2017-10-25 00:55:23 +02:00
|
|
|
/**
|
|
|
|
* Marlin 3D Printer Firmware
|
|
|
|
*
|
2019-06-28 06:57:50 +02:00
|
|
|
* Copyright (c) 2019 MarlinFirmware [https://github.com/MarlinFirmware/Marlin]
|
2018-08-14 03:13:59 +02:00
|
|
|
* Copyright (c) 2016 Bob Cousins bobcousins42@googlemail.com
|
|
|
|
* Copyright (c) 2015-2016 Nico Tonnhofer wurstnase.reprap@gmail.com
|
|
|
|
* Copyright (c) 2016 Victor Perez victor_pv@hotmail.com
|
2017-10-25 00:55:23 +02:00
|
|
|
*
|
|
|
|
* This program is free software: you can redistribute it and/or modify
|
|
|
|
* it under the terms of the GNU General Public License as published by
|
|
|
|
* the Free Software Foundation, either version 3 of the License, or
|
|
|
|
* (at your option) any later version.
|
|
|
|
*
|
|
|
|
* This program is distributed in the hope that it will be useful,
|
|
|
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
|
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
|
|
* GNU General Public License for more details.
|
|
|
|
*
|
|
|
|
* You should have received a copy of the GNU General Public License
|
|
|
|
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
|
|
|
*
|
|
|
|
*/
|
2017-08-01 18:19:23 +02:00
|
|
|
#ifdef TARGET_LPC1768
|
2017-06-17 23:19:42 +02:00
|
|
|
|
2018-08-14 08:19:34 +02:00
|
|
|
#include "../../inc/MarlinConfigPre.h"
|
2017-06-17 23:19:42 +02:00
|
|
|
|
2017-09-06 13:28:32 +02:00
|
|
|
#if ENABLED(EEPROM_SETTINGS)
|
2017-06-17 23:19:42 +02:00
|
|
|
|
2018-08-15 00:54:12 +02:00
|
|
|
#include "../../inc/MarlinConfig.h"
|
2018-08-14 08:19:34 +02:00
|
|
|
#include "persistent_store_api.h"
|
|
|
|
|
2019-02-20 11:35:58 +01:00
|
|
|
#if DISABLED(FLASH_EEPROM_EMULATION)
|
2017-08-01 18:19:23 +02:00
|
|
|
|
2018-08-14 00:30:26 +02:00
|
|
|
#include <chanfs/diskio.h>
|
|
|
|
#include <chanfs/ff.h>
|
2017-06-17 23:19:42 +02:00
|
|
|
|
2017-10-04 22:40:54 +02:00
|
|
|
extern uint32_t MSC_Aquire_Lock();
|
|
|
|
extern uint32_t MSC_Release_Lock();
|
|
|
|
|
2017-06-17 23:19:42 +02:00
|
|
|
FATFS fat_fs;
|
|
|
|
FIL eeprom_file;
|
2018-08-14 00:30:26 +02:00
|
|
|
bool eeprom_file_open = false;
|
2017-06-17 23:19:42 +02:00
|
|
|
|
2018-08-14 00:30:26 +02:00
|
|
|
bool PersistentStore::access_start() {
|
2017-10-19 17:44:45 +02:00
|
|
|
const char eeprom_erase_value = 0xFF;
|
2017-10-04 22:40:54 +02:00
|
|
|
MSC_Aquire_Lock();
|
Update LPC persistent store to initialize eeprom.dat with FF
This change initialize any data in eeprom.dat beyond the current file size to FF.
That way if eeprom.dat is deleted and created again, it doesn't take the old values or random ones, but rather starts with FF in all positions as a real brand new or erased eeprom.dat
Currently if you delete eeprom.dat and restart the board, the new file is created in the same sector with the same content, since FAT does not actually delete the data, just marks the sector as free. I tested by deleting the file, and then rebooting the board, and checking the file content.
The change can be tested in the same way, deleting, rebooting the board, and then the new content should be all FF.
If an eeprom file already exist with data on it, but smaller than E2END, it will be padded with FF on first access, so it will not have random or old content appended.
2017-09-28 03:43:43 +02:00
|
|
|
if (f_mount(&fat_fs, "", 1)) {
|
2017-10-04 22:40:54 +02:00
|
|
|
MSC_Release_Lock();
|
|
|
|
return false;
|
|
|
|
}
|
2017-06-17 23:19:42 +02:00
|
|
|
FRESULT res = f_open(&eeprom_file, "eeprom.dat", FA_OPEN_ALWAYS | FA_WRITE | FA_READ);
|
Update LPC persistent store to initialize eeprom.dat with FF
This change initialize any data in eeprom.dat beyond the current file size to FF.
That way if eeprom.dat is deleted and created again, it doesn't take the old values or random ones, but rather starts with FF in all positions as a real brand new or erased eeprom.dat
Currently if you delete eeprom.dat and restart the board, the new file is created in the same sector with the same content, since FAT does not actually delete the data, just marks the sector as free. I tested by deleting the file, and then rebooting the board, and checking the file content.
The change can be tested in the same way, deleting, rebooting the board, and then the new content should be all FF.
If an eeprom file already exist with data on it, but smaller than E2END, it will be padded with FF on first access, so it will not have random or old content appended.
2017-09-28 03:43:43 +02:00
|
|
|
if (res) MSC_Release_Lock();
|
|
|
|
|
|
|
|
if (res == FR_OK) {
|
2017-10-26 20:37:26 +02:00
|
|
|
UINT bytes_written;
|
|
|
|
FSIZE_t file_size = f_size(&eeprom_file);
|
Update LPC persistent store to initialize eeprom.dat with FF
This change initialize any data in eeprom.dat beyond the current file size to FF.
That way if eeprom.dat is deleted and created again, it doesn't take the old values or random ones, but rather starts with FF in all positions as a real brand new or erased eeprom.dat
Currently if you delete eeprom.dat and restart the board, the new file is created in the same sector with the same content, since FAT does not actually delete the data, just marks the sector as free. I tested by deleting the file, and then rebooting the board, and checking the file content.
The change can be tested in the same way, deleting, rebooting the board, and then the new content should be all FF.
If an eeprom file already exist with data on it, but smaller than E2END, it will be padded with FF on first access, so it will not have random or old content appended.
2017-09-28 03:43:43 +02:00
|
|
|
f_lseek(&eeprom_file, file_size);
|
2018-08-14 00:30:26 +02:00
|
|
|
while (file_size < capacity() && res == FR_OK) {
|
2017-10-19 17:44:45 +02:00
|
|
|
res = f_write(&eeprom_file, &eeprom_erase_value, 1, &bytes_written);
|
Update LPC persistent store to initialize eeprom.dat with FF
This change initialize any data in eeprom.dat beyond the current file size to FF.
That way if eeprom.dat is deleted and created again, it doesn't take the old values or random ones, but rather starts with FF in all positions as a real brand new or erased eeprom.dat
Currently if you delete eeprom.dat and restart the board, the new file is created in the same sector with the same content, since FAT does not actually delete the data, just marks the sector as free. I tested by deleting the file, and then rebooting the board, and checking the file content.
The change can be tested in the same way, deleting, rebooting the board, and then the new content should be all FF.
If an eeprom file already exist with data on it, but smaller than E2END, it will be padded with FF on first access, so it will not have random or old content appended.
2017-09-28 03:43:43 +02:00
|
|
|
file_size++;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
if (res == FR_OK) {
|
|
|
|
f_lseek(&eeprom_file, 0);
|
|
|
|
f_sync(&eeprom_file);
|
2018-08-14 00:30:26 +02:00
|
|
|
eeprom_file_open = true;
|
Update LPC persistent store to initialize eeprom.dat with FF
This change initialize any data in eeprom.dat beyond the current file size to FF.
That way if eeprom.dat is deleted and created again, it doesn't take the old values or random ones, but rather starts with FF in all positions as a real brand new or erased eeprom.dat
Currently if you delete eeprom.dat and restart the board, the new file is created in the same sector with the same content, since FAT does not actually delete the data, just marks the sector as free. I tested by deleting the file, and then rebooting the board, and checking the file content.
The change can be tested in the same way, deleting, rebooting the board, and then the new content should be all FF.
If an eeprom file already exist with data on it, but smaller than E2END, it will be padded with FF on first access, so it will not have random or old content appended.
2017-09-28 03:43:43 +02:00
|
|
|
}
|
|
|
|
return res == FR_OK;
|
2017-06-17 23:19:42 +02:00
|
|
|
}
|
|
|
|
|
2018-08-14 00:30:26 +02:00
|
|
|
bool PersistentStore::access_finish() {
|
2017-06-17 23:19:42 +02:00
|
|
|
f_close(&eeprom_file);
|
|
|
|
f_unmount("");
|
2017-10-04 22:40:54 +02:00
|
|
|
MSC_Release_Lock();
|
2018-08-14 00:30:26 +02:00
|
|
|
eeprom_file_open = false;
|
2017-06-17 23:19:42 +02:00
|
|
|
return true;
|
|
|
|
}
|
|
|
|
|
2018-08-14 08:19:34 +02:00
|
|
|
// This extra chit-chat goes away soon, but is helpful for now
|
|
|
|
// to see errors that are happening in read_data / write_data
|
|
|
|
static void debug_rw(const bool write, int &pos, const uint8_t *value, const size_t size, const FRESULT s, const size_t total=0) {
|
2018-10-01 06:44:33 +02:00
|
|
|
PGM_P const rw_str = write ? PSTR("write") : PSTR("read");
|
2018-11-29 23:58:58 +01:00
|
|
|
SERIAL_CHAR(' ');
|
2018-08-15 00:54:12 +02:00
|
|
|
serialprintPGM(rw_str);
|
2018-11-29 23:58:58 +01:00
|
|
|
SERIAL_ECHOPAIR("_data(", pos);
|
|
|
|
SERIAL_ECHOPAIR(",", (int)value);
|
|
|
|
SERIAL_ECHOPAIR(",", (int)size);
|
|
|
|
SERIAL_ECHOLNPGM(", ...)");
|
2018-08-14 08:19:34 +02:00
|
|
|
if (total) {
|
2018-11-29 23:58:58 +01:00
|
|
|
SERIAL_ECHOPGM(" f_");
|
2018-08-15 00:54:12 +02:00
|
|
|
serialprintPGM(rw_str);
|
2018-11-29 23:58:58 +01:00
|
|
|
SERIAL_ECHOPAIR("()=", (int)s);
|
|
|
|
SERIAL_ECHOPAIR("\n size=", size);
|
|
|
|
SERIAL_ECHOPGM("\n bytes_");
|
2018-08-15 00:54:12 +02:00
|
|
|
serialprintPGM(write ? PSTR("written=") : PSTR("read="));
|
2018-11-29 23:58:58 +01:00
|
|
|
SERIAL_ECHOLN(total);
|
2018-08-14 08:19:34 +02:00
|
|
|
}
|
|
|
|
else
|
2018-11-29 23:58:58 +01:00
|
|
|
SERIAL_ECHOLNPAIR(" f_lseek()=", (int)s);
|
2018-08-14 08:19:34 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
// File function return codes for type FRESULT. This goes away soon, but
|
|
|
|
// is helpful right now to see any errors in read_data and write_data.
|
2017-10-18 21:00:29 +02:00
|
|
|
//
|
2017-10-25 00:55:23 +02:00
|
|
|
// typedef enum {
|
|
|
|
// FR_OK = 0, /* (0) Succeeded */
|
|
|
|
// FR_DISK_ERR, /* (1) A hard error occurred in the low level disk I/O layer */
|
|
|
|
// FR_INT_ERR, /* (2) Assertion failed */
|
|
|
|
// FR_NOT_READY, /* (3) The physical drive cannot work */
|
|
|
|
// FR_NO_FILE, /* (4) Could not find the file */
|
|
|
|
// FR_NO_PATH, /* (5) Could not find the path */
|
|
|
|
// FR_INVALID_NAME, /* (6) The path name format is invalid */
|
|
|
|
// FR_DENIED, /* (7) Access denied due to prohibited access or directory full */
|
|
|
|
// FR_EXIST, /* (8) Access denied due to prohibited access */
|
|
|
|
// FR_INVALID_OBJECT, /* (9) The file/directory object is invalid */
|
|
|
|
// FR_WRITE_PROTECTED, /* (10) The physical drive is write protected */
|
|
|
|
// FR_INVALID_DRIVE, /* (11) The logical drive number is invalid */
|
|
|
|
// FR_NOT_ENABLED, /* (12) The volume has no work area */
|
|
|
|
// FR_NO_FILESYSTEM, /* (13) There is no valid FAT volume */
|
|
|
|
// FR_MKFS_ABORTED, /* (14) The f_mkfs() aborted due to any problem */
|
|
|
|
// FR_TIMEOUT, /* (15) Could not get a grant to access the volume within defined period */
|
|
|
|
// FR_LOCKED, /* (16) The operation is rejected according to the file sharing policy */
|
|
|
|
// FR_NOT_ENOUGH_CORE, /* (17) LFN working buffer could not be allocated */
|
|
|
|
// FR_TOO_MANY_OPEN_FILES, /* (18) Number of open files > FF_FS_LOCK */
|
|
|
|
// FR_INVALID_PARAMETER /* (19) Given parameter is invalid */
|
|
|
|
// } FRESULT;
|
2017-10-18 21:00:29 +02:00
|
|
|
|
2018-08-14 03:13:59 +02:00
|
|
|
bool PersistentStore::write_data(int &pos, const uint8_t *value, const size_t size, uint16_t *crc) {
|
|
|
|
if (!eeprom_file_open) return true;
|
2017-10-18 21:00:29 +02:00
|
|
|
FRESULT s;
|
2017-10-26 20:37:26 +02:00
|
|
|
UINT bytes_written = 0;
|
2017-10-25 00:55:23 +02:00
|
|
|
|
2017-10-18 21:00:29 +02:00
|
|
|
s = f_lseek(&eeprom_file, pos);
|
2017-10-25 00:55:23 +02:00
|
|
|
if (s) {
|
2018-08-14 08:19:34 +02:00
|
|
|
debug_rw(true, pos, value, size, s);
|
|
|
|
return s;
|
2017-10-18 21:00:29 +02:00
|
|
|
}
|
2017-10-25 00:55:23 +02:00
|
|
|
|
2018-08-14 03:13:59 +02:00
|
|
|
s = f_write(&eeprom_file, (void*)value, size, &bytes_written);
|
2017-10-25 00:55:23 +02:00
|
|
|
if (s) {
|
2018-08-14 08:19:34 +02:00
|
|
|
debug_rw(true, pos, value, size, s, bytes_written);
|
|
|
|
return s;
|
2017-10-18 21:00:29 +02:00
|
|
|
}
|
2017-06-17 23:19:42 +02:00
|
|
|
crc16(crc, value, size);
|
2018-08-14 08:19:34 +02:00
|
|
|
pos += size;
|
|
|
|
return bytes_written != size; // return true for any error
|
2017-06-17 23:19:42 +02:00
|
|
|
}
|
|
|
|
|
2018-08-14 03:13:59 +02:00
|
|
|
bool PersistentStore::read_data(int &pos, uint8_t* value, const size_t size, uint16_t *crc, const bool writing/*=true*/) {
|
|
|
|
if (!eeprom_file_open) return true;
|
2017-10-26 20:37:26 +02:00
|
|
|
UINT bytes_read = 0;
|
2017-10-18 21:00:29 +02:00
|
|
|
FRESULT s;
|
|
|
|
s = f_lseek(&eeprom_file, pos);
|
2018-08-14 03:13:59 +02:00
|
|
|
|
2018-03-10 10:02:53 +01:00
|
|
|
if (s) {
|
2018-08-14 08:19:34 +02:00
|
|
|
debug_rw(false, pos, value, size, s);
|
|
|
|
return true;
|
2017-10-18 21:00:29 +02:00
|
|
|
}
|
2018-08-14 03:13:59 +02:00
|
|
|
|
2018-01-05 02:51:18 +01:00
|
|
|
if (writing) {
|
2018-08-14 03:13:59 +02:00
|
|
|
s = f_read(&eeprom_file, (void*)value, size, &bytes_read);
|
2018-01-05 02:51:18 +01:00
|
|
|
crc16(crc, value, size);
|
|
|
|
}
|
|
|
|
else {
|
|
|
|
uint8_t temp[size];
|
2018-08-14 03:13:59 +02:00
|
|
|
s = f_read(&eeprom_file, (void*)temp, size, &bytes_read);
|
2018-01-05 02:51:18 +01:00
|
|
|
crc16(crc, temp, size);
|
|
|
|
}
|
2018-08-14 03:13:59 +02:00
|
|
|
|
2017-10-25 00:55:23 +02:00
|
|
|
if (s) {
|
2018-08-14 08:19:34 +02:00
|
|
|
debug_rw(false, pos, value, size, s, bytes_read);
|
|
|
|
return true;
|
2017-10-18 21:00:29 +02:00
|
|
|
}
|
2018-08-14 03:13:59 +02:00
|
|
|
|
2018-08-14 08:19:34 +02:00
|
|
|
pos += size;
|
2017-10-18 21:00:29 +02:00
|
|
|
return bytes_read != size; // return true for any error
|
2017-06-17 23:19:42 +02:00
|
|
|
}
|
|
|
|
|
2018-08-14 08:04:11 +02:00
|
|
|
size_t PersistentStore::capacity() { return 4096; } // 4KiB of Emulated EEPROM
|
2017-06-17 23:19:42 +02:00
|
|
|
|
2019-02-20 11:35:58 +01:00
|
|
|
#endif // !FLASH_EEPROM_EMULATION
|
2017-06-17 23:19:42 +02:00
|
|
|
#endif // EEPROM_SETTINGS
|
2017-09-06 13:28:32 +02:00
|
|
|
#endif // TARGET_LPC1768
|