50 #define ALIGNED_REC_SIZE(n) \ 51 (flash_offset_t)MFS_ALIGN_NEXT(sizeof (mfs_data_header_t) + (size_t)(n)) 56 #define ALIGNED_DHDR_SIZE \ 62 #define ALIGNED_SIZEOF(t) \ 63 (((sizeof (t) - 1U) | MFS_ALIGN_MASK) + 1U) 68 #define PAIR(a, b) (((unsigned)(a) << 2U) | (unsigned)(b)) 73 #define RET_ON_ERROR(err) do { \ 74 mfs_error_t e = (err); \ 75 if (e != MFS_NO_ERROR) { \ 88 static const uint16_t crc16_table[256] = {
89 0x0000, 0x1021, 0x2042, 0x3063, 0x4084, 0x50A5, 0x60C6, 0x70E7,
90 0x8108, 0x9129, 0xA14A, 0xB16B, 0xC18C, 0xD1AD, 0xE1CE, 0xF1EF,
91 0x1231, 0x0210, 0x3273, 0x2252, 0x52B5, 0x4294, 0x72F7, 0x62D6,
92 0x9339, 0x8318, 0xB37B, 0xA35A, 0xD3BD, 0xC39C, 0xF3FF, 0xE3DE,
93 0x2462, 0x3443, 0x0420, 0x1401, 0x64E6, 0x74C7, 0x44A4, 0x5485,
94 0xA56A, 0xB54B, 0x8528, 0x9509, 0xE5EE, 0xF5CF, 0xC5AC, 0xD58D,
95 0x3653, 0x2672, 0x1611, 0x0630, 0x76D7, 0x66F6, 0x5695, 0x46B4,
96 0xB75B, 0xA77A, 0x9719, 0x8738, 0xF7DF, 0xE7FE, 0xD79D, 0xC7BC,
97 0x48C4, 0x58E5, 0x6886, 0x78A7, 0x0840, 0x1861, 0x2802, 0x3823,
98 0xC9CC, 0xD9ED, 0xE98E, 0xF9AF, 0x8948, 0x9969, 0xA90A, 0xB92B,
99 0x5AF5, 0x4AD4, 0x7AB7, 0x6A96, 0x1A71, 0x0A50, 0x3A33, 0x2A12,
100 0xDBFD, 0xCBDC, 0xFBBF, 0xEB9E, 0x9B79, 0x8B58, 0xBB3B, 0xAB1A,
101 0x6CA6, 0x7C87, 0x4CE4, 0x5CC5, 0x2C22, 0x3C03, 0x0C60, 0x1C41,
102 0xEDAE, 0xFD8F, 0xCDEC, 0xDDCD, 0xAD2A, 0xBD0B, 0x8D68, 0x9D49,
103 0x7E97, 0x6EB6, 0x5ED5, 0x4EF4, 0x3E13, 0x2E32, 0x1E51, 0x0E70,
104 0xFF9F, 0xEFBE, 0xDFDD, 0xCFFC, 0xBF1B, 0xAF3A, 0x9F59, 0x8F78,
105 0x9188, 0x81A9, 0xB1CA, 0xA1EB, 0xD10C, 0xC12D, 0xF14E, 0xE16F,
106 0x1080, 0x00A1, 0x30C2, 0x20E3, 0x5004, 0x4025, 0x7046, 0x6067,
107 0x83B9, 0x9398, 0xA3FB, 0xB3DA, 0xC33D, 0xD31C, 0xE37F, 0xF35E,
108 0x02B1, 0x1290, 0x22F3, 0x32D2, 0x4235, 0x5214, 0x6277, 0x7256,
109 0xB5EA, 0xA5CB, 0x95A8, 0x8589, 0xF56E, 0xE54F, 0xD52C, 0xC50D,
110 0x34E2, 0x24C3, 0x14A0, 0x0481, 0x7466, 0x6447, 0x5424, 0x4405,
111 0xA7DB, 0xB7FA, 0x8799, 0x97B8, 0xE75F, 0xF77E, 0xC71D, 0xD73C,
112 0x26D3, 0x36F2, 0x0691, 0x16B0, 0x6657, 0x7676, 0x4615, 0x5634,
113 0xD94C, 0xC96D, 0xF90E, 0xE92F, 0x99C8, 0x89E9, 0xB98A, 0xA9AB,
114 0x5844, 0x4865, 0x7806, 0x6827, 0x18C0, 0x08E1, 0x3882, 0x28A3,
115 0xCB7D, 0xDB5C, 0xEB3F, 0xFB1E, 0x8BF9, 0x9BD8, 0xABBB, 0xBB9A,
116 0x4A75, 0x5A54, 0x6A37, 0x7A16, 0x0AF1, 0x1AD0, 0x2AB3, 0x3A92,
117 0xFD2E, 0xED0F, 0xDD6C, 0xCD4D, 0xBDAA, 0xAD8B, 0x9DE8, 0x8DC9,
118 0x7C26, 0x6C07, 0x5C64, 0x4C45, 0x3CA2, 0x2C83, 0x1CE0, 0x0CC1,
119 0xEF1F, 0xFF3E, 0xCF5D, 0xDF7C, 0xAF9B, 0xBFBA, 0x8FD9, 0x9FF8,
120 0x6E17, 0x7E36, 0x4E55, 0x5E74, 0x2E93, 0x3EB2, 0x0ED1, 0x1EF0
127 uint16_t crc16(uint16_t crc,
const uint8_t *data,
size_t n) {
130 crc = (crc << 8U) ^ crc16_table[(crc >> 8U) ^ (uint16_t)*data];
138 static void mfs_state_reset(
MFSDriver *mfsp) {
173 size_t n, uint8_t *rp) {
177 if (ferr != FLASH_NO_ERROR) {
178 mfsp->
state = MFS_ERROR;
179 return MFS_ERR_FLASH_FAILURE;
205 if (ferr != FLASH_NO_ERROR) {
206 mfsp->
state = MFS_ERROR;
207 return MFS_ERR_FLASH_FAILURE;
210 #if MFS_CFG_WRITE_VERIFY == TRUE 217 if (memcmp((
void *)mfsp->
buffer.data8, (
void *)wp, chunk)) {
218 mfsp->
state = MFS_ERROR;
219 return MFS_ERR_FLASH_FAILURE;
282 if (bank == MFS_BANK_0) {
291 while (sector < end) {
295 if (ferr != FLASH_NO_ERROR) {
296 mfsp->
state = MFS_ERROR;
297 return MFS_ERR_FLASH_FAILURE;
300 if (ferr != FLASH_NO_ERROR) {
301 mfsp->
state = MFS_ERROR;
302 return MFS_ERR_FLASH_FAILURE;
305 if (ferr != FLASH_NO_ERROR) {
306 mfsp->
state = MFS_ERROR;
307 return MFS_ERR_FLASH_FAILURE;
328 if (bank == MFS_BANK_0) {
337 while (sector < end) {
341 if (ferr == FLASH_ERROR_VERIFY) {
342 return MFS_ERR_NOT_ERASED;
344 if (ferr != FLASH_NO_ERROR) {
345 mfsp->
state = MFS_ERROR;
346 return MFS_ERR_FLASH_FAILURE;
371 if (bank == MFS_BANK_0) {
378 bhdr.fields.
magic1 = MFS_BANK_MAGIC_1;
379 bhdr.fields.
magic2 = MFS_BANK_MAGIC_2;
382 bhdr.fields.
crc = crc16(0xFFFFU, bhdr.hdr8,
406 return MFS_BANK_ERASED;
410 if ((mfsp->
buffer.bhdr.fields.
magic1 != MFS_BANK_MAGIC_1) ||
411 (mfsp->
buffer.bhdr.fields.
magic2 != MFS_BANK_MAGIC_2) ||
414 return MFS_BANK_GARBAGE;
418 crc = crc16(0xFFFFU, mfsp->
buffer.bhdr.hdr8,
420 if (crc != mfsp->
buffer.bhdr.fields.
crc) {
421 return MFS_BANK_GARBAGE;
448 start_offset = mfs_flash_get_bank_offset(mfsp, bank);
474 if ((u.dhdr.fields.magic1 != MFS_HEADER_MAGIC_1) ||
475 (u.dhdr.fields.magic2 != MFS_HEADER_MAGIC_2) ||
476 (u.dhdr.fields.id < 1U) ||
478 (u.dhdr.fields.size > end_offset - hdr_offset)) {
486 if (u.dhdr.fields.size > 0U) {
488 uint32_t total = u.dhdr.fields.size;
498 crc = crc16(crc, &mfsp->
buffer.data8[0], chunk);
505 if (crc != u.dhdr.fields.crc) {
512 if (u.dhdr.fields.size == 0U) {
513 mfsp->
descriptors[u.dhdr.fields.id - 1U].offset = 0U;
514 mfsp->
descriptors[u.dhdr.fields.id - 1U].size = 0U;
517 mfsp->
descriptors[u.dhdr.fields.id - 1U].offset = hdr_offset;
518 mfsp->
descriptors[u.dhdr.fields.id - 1U].size = u.dhdr.fields.size;
565 if (*statep == MFS_BANK_ERASED) {
570 if (err == MFS_ERR_NOT_ERASED) {
571 *statep = MFS_BANK_GARBAGE;
593 if (sbank == MFS_BANK_0) {
601 dest_offset = mfs_flash_get_bank_offset(mfsp, dbank) +
612 dest_offset += totsize;
641 uint32_t cnt0 = 0, cnt1 = 0;
642 bool w1 =
false, w2 =
false;
645 mfs_state_reset(mfsp);
653 switch (
PAIR(sts0, sts1)) {
655 case PAIR(MFS_BANK_ERASED, MFS_BANK_ERASED):
661 case PAIR(MFS_BANK_OK, MFS_BANK_OK):
677 case PAIR(MFS_BANK_GARBAGE, MFS_BANK_GARBAGE):
686 case PAIR(MFS_BANK_ERASED, MFS_BANK_OK):
691 case PAIR(MFS_BANK_OK, MFS_BANK_ERASED):
696 case PAIR(MFS_BANK_ERASED, MFS_BANK_GARBAGE):
704 case PAIR(MFS_BANK_GARBAGE, MFS_BANK_ERASED):
712 case PAIR(MFS_BANK_OK, MFS_BANK_GARBAGE):
719 case PAIR(MFS_BANK_GARBAGE, MFS_BANK_OK):
727 return MFS_ERR_INTERNAL;
741 return MFS_ERR_INTERNAL;
766 return (w1 || w2) ? MFS_WARN_REPAIR : MFS_NO_ERROR;
789 mfs_state_reset(mfsp);
796 if (err == MFS_ERR_INTERNAL) {
799 mfsp->
state = MFS_ERROR;
802 if (!MFS_IS_ERROR(err)) {
803 mfsp->
state = MFS_READY;
809 mfsp->
state = MFS_ERROR;
810 return MFS_ERR_FLASH_FAILURE;
828 mfsp->
state = MFS_STOP;
853 (mfsp->
state == MFS_ERROR),
"invalid state");
872 (mfsp->
state == MFS_ERROR),
"invalid state");
875 mfsp->
state = MFS_STOP;
898 if (mfsp->
state != MFS_READY) {
899 return MFS_ERR_INV_STATE;
933 size_t *np, uint8_t *buffer) {
938 (np != NULL) && (*np > 0U) && (buffer != NULL));
940 if ((mfsp->
state != MFS_READY) && (mfsp->
state != MFS_TRANSACTION)) {
941 return MFS_ERR_INV_STATE;
946 return MFS_ERR_NOT_FOUND;
950 if (*np < mfsp->descriptors[
id - 1U].size) {
951 return MFS_ERR_INV_SIZE;
968 crc = crc16(0xFFFFU, buffer, *np);
969 if (crc != mfsp->
buffer.dhdr.fields.
crc) {
970 mfsp->
state = MFS_ERROR;
971 return MFS_ERR_FLASH_FAILURE;
1006 size_t n,
const uint8_t *buffer) {
1011 (n > 0U) && (buffer != NULL));
1017 if (mfsp->
state == MFS_READY) {
1018 bool warning =
false;
1026 return MFS_ERR_OUT_OF_MEM;
1030 free = (mfs_flash_get_bank_offset(mfsp, mfsp->
current_bank) +
1032 if (rspace > free) {
1040 mfsp->
buffer.dhdr.fields.
id = (uint16_t)
id;
1042 mfsp->
buffer.dhdr.fields.
crc = crc16(0xFFFFU, buffer, n);
1046 mfsp->
buffer.data8 + (sizeof (uint32_t) * 2U)));
1055 mfsp->
buffer.dhdr.fields.
magic1 = (uint32_t)MFS_HEADER_MAGIC_1;
1056 mfsp->
buffer.dhdr.fields.
magic2 = (uint32_t)MFS_HEADER_MAGIC_2;
1059 sizeof (uint32_t) * 2U,
1074 return warning ? MFS_WARN_GC : MFS_NO_ERROR;
1077 #if MFS_CFG_TRANSACTION_MAX > 0 1079 if (mfsp->
state == MFS_TRANSACTION) {
1085 return MFS_ERR_TRANSACTION_NUM;
1092 return MFS_ERR_TRANSACTION_SIZE;
1096 mfsp->
buffer.dhdr.fields.
id = (uint16_t)
id;
1098 mfsp->
buffer.dhdr.fields.
crc = crc16(0xFFFFU, buffer, n);
1102 mfsp->
buffer.data8 + (sizeof (uint32_t) * 2U)));
1120 return MFS_NO_ERROR;
1125 return MFS_ERR_INV_STATE;
1164 if (mfsp->
state == MFS_READY) {
1165 bool warning =
false;
1169 return MFS_ERR_NOT_FOUND;
1176 return MFS_ERR_INTERNAL;
1180 free = (mfs_flash_get_bank_offset(mfsp, mfsp->
current_bank) +
1182 if (rspace > free) {
1191 mfsp->
buffer.dhdr.fields.
magic1 = (uint32_t)MFS_HEADER_MAGIC_1;
1192 mfsp->
buffer.dhdr.fields.
magic2 = (uint32_t)MFS_HEADER_MAGIC_2;
1193 mfsp->
buffer.dhdr.fields.
id = (uint16_t)
id;
1195 mfsp->
buffer.dhdr.fields.
crc = (uint16_t)0xFFFF;
1207 return warning ? MFS_WARN_GC : MFS_NO_ERROR;
1210 #if MFS_CFG_TRANSACTION_MAX > 0 1212 if (mfsp->
state == MFS_TRANSACTION) {
1217 return MFS_ERR_NOT_FOUND;
1223 return MFS_ERR_TRANSACTION_NUM;
1230 return MFS_ERR_TRANSACTION_SIZE;
1235 mfsp->
buffer.dhdr.fields.
id = (uint16_t)
id;
1237 mfsp->
buffer.dhdr.fields.
crc = (uint16_t)0xFFFF;
1241 mfsp->
buffer.data8 + (sizeof (uint32_t) * 2U)));
1253 return MFS_NO_ERROR;
1257 return MFS_ERR_INV_STATE;
1282 if (mfsp->
state != MFS_READY) {
1283 return MFS_ERR_INV_STATE;
1289 #if (MFS_CFG_TRANSACTION_MAX > 0) || defined(__DOXYGEN__) 1326 if (mfsp->
state != MFS_READY) {
1327 return MFS_ERR_INV_STATE;
1337 return MFS_ERR_OUT_OF_MEM;
1341 free = (mfs_flash_get_bank_offset(mfsp, mfsp->
current_bank) +
1343 if (rspace > free) {
1350 mfsp->
state = MFS_TRANSACTION;
1357 return MFS_NO_ERROR;
1382 if (mfsp->
state != MFS_TRANSACTION) {
1383 return MFS_ERR_INV_STATE;
1387 mfsp->
buffer.dhdr.fields.
magic1 = (uint32_t)MFS_HEADER_MAGIC_1;
1388 mfsp->
buffer.dhdr.fields.
magic2 = (uint32_t)MFS_HEADER_MAGIC_2;
1390 while (top > &mfsp->
tr_ops[0]) {
1397 sizeof (uint32_t) * 2U,
1404 while (top < &mfsp->tr_ops[mfsp->
tr_nops]) {
1405 unsigned i = (unsigned)top->
id - 1U;
1409 if (top->
size > 0U) {
1434 mfsp->
state = MFS_READY;
1436 return MFS_NO_ERROR;
1462 if (mfsp->
state != MFS_TRANSACTION) {
1463 return MFS_ERR_INV_STATE;
1467 mfsp->
state = MFS_READY;
mfs_error_t mfsReadRecord(MFSDriver *mfsp, mfs_id_t id, size_t *np, uint8_t *buffer)
Retrieves and reads a data record.
void mfsObjectInit(MFSDriver *mfsp)
Initializes an instance.
Type of a buffered write/erase operation within a transaction.
uint32_t flash_sector_t
Type of a flash sector number.
uint32_t erased
Erased value.
union MFSDriver::@2 buffer
Transient buffer.
static mfs_error_t mfs_try_mount(MFSDriver *mfsp)
Performs a flash partition mount attempt.
static mfs_error_t mfs_garbage_collect(MFSDriver *mfsp)
Enforces a garbage collection.
#define MFS_CFG_TRANSACTION_MAX
Maximum number of objects writable in a single transaction.
mfs_record_descriptor_t descriptors[MFS_CFG_MAX_RECORDS]
Offsets of the most recent instance of the records.
#define ALIGNED_SIZEOF(t)
Aligned size of a type.
mfs_state_t state
Driver state.
#define flashProgram(ip, offset, n, pp)
Program operation.
mfs_id_t id
Record identifier.
static mfs_error_t mfs_bank_get_state(MFSDriver *mfsp, mfs_bank_t bank, mfs_bank_state_t *statep, uint32_t *cntp)
Determines the state of a bank.
size_t size
Written data size.
#define flashVerifyErase(ip, sector)
Returns the erase state of a sector.
Type of a MFS configuration structure.
uint32_t mfs_id_t
Type of a record identifier.
void mfsStop(MFSDriver *mfsp)
Deactivates a MFS driver.
mfs_transaction_op_t tr_ops[MFS_CFG_TRANSACTION_MAX]
Buffered operations in current transaction.
flash_offset_t used_space
Used space in the current bank without considering erased records.
mfs_error_t mfsRollbackTransaction(MFSDriver *mfsp)
A transaction is rolled back atomically.
static mfs_bank_state_t mfs_bank_check_header(MFSDriver *mfsp)
Checks integrity of the header in the shared buffer.
uint32_t tr_nops
Number of buffered operations in current transaction.
flash_offset_t tr_next_offset
Next write offset for current transaction.
mfs_error_t mfsPerformGarbageCollection(MFSDriver *mfsp)
Enforces a garbage collection operation.
mfs_bank_state_t
Type of a bank state assessment.
mfs_error_t mfsStart(MFSDriver *mfsp, const MFSConfig *config)
Configures and activates a MFS driver.
mfs_error_t mfsCommitTransaction(MFSDriver *mfsp)
A transaction is committed and finalized atomically.
static mfs_error_t mfs_bank_verify_erase(MFSDriver *mfsp, mfs_bank_t bank)
Erases and verifies all sectors belonging to a bank.
flash_offset_t bank_size
Banks size.
#define ALIGNED_DHDR_SIZE
Data record header size aligned.
flash_offset_t offset
Written header offset.
#define MFS_CFG_MAX_REPAIR_ATTEMPTS
Maximum number of repair attempts on partition mount.
#define ALIGNED_REC_SIZE(n)
Data record size aligned.
#define MFS_CFG_BUFFER_SIZE
Size of the buffer used for data copying.
mfs_error_t mfsEraseRecord(MFSDriver *mfsp, mfs_id_t id)
Erases a data record.
#define RET_ON_ERROR(err)
Error check helper.
mfs_error_t mfs_mount(MFSDriver *mfsp)
Configures and activates a MFS driver.
static mfs_error_t mfs_bank_erase(MFSDriver *mfsp, mfs_bank_t bank)
Erases and verifies all sectors belonging to a bank.
flash_sector_t bank1_start
Base sector index for bank 1.
#define flashRead(ip, offset, n, rp)
Read operation.
flash_error_t
Type of a flash error code.
#define osalDbgCheck(c)
Function parameters check.
flash_sector_t bank0_sectors
Number of sectors for bank 0.
flash_error_t flashWaitErase(BaseFlash *devp)
Waits until the current erase operation is finished.
mfs_error_t mfsStartTransaction(MFSDriver *mfsp, size_t size)
Puts the driver in transaction mode.
#define flashStartEraseSector(ip, sector)
Starts an sector erase operation.
flash_sector_t bank1_sectors
Number of sectors for bank 1.
flash_offset_t next_offset
Pointer to the next free position in the current bank.
mfs_error_t mfsErase(MFSDriver *mfsp)
Destroys the state of the managed storage by erasing the flash.
uint32_t flash_offset_t
Type of a flash offset.
#define MFS_CFG_MAX_RECORDS
Maximum number of indexed records in the managed storage.
Managed Flash Storage module header.
mfs_error_t mfsWriteRecord(MFSDriver *mfsp, mfs_id_t id, size_t n, const uint8_t *buffer)
Creates or updates a data record.
mfs_error_t
Type of an MFS error code.
mfs_bank_t current_bank
Bank currently in use.
static mfs_error_t mfs_bank_write_header(MFSDriver *mfsp, mfs_bank_t bank, uint32_t cnt)
Writes the validation header in a bank.
static mfs_error_t mfs_flash_copy(MFSDriver *mfsp, flash_offset_t doffset, flash_offset_t soffset, uint32_t n)
Flash copy.
uint32_t current_counter
Usage counter of the current bank.
#define osalDbgAssert(c, remark)
Condition assertion.
flash_offset_t flashGetSectorOffset(BaseFlash *devp, flash_sector_t sector)
Returns the offset of a sector.
flash_sector_t bank0_start
Base sector index for bank 0.
BaseFlash * flashp
Flash driver associated to this MFS instance.
static mfs_error_t mfs_bank_scan_records(MFSDriver *mfsp, mfs_bank_t bank, bool *wflagp)
Scans blocks searching for records.
mfs_bank_t
Type of a flash bank.
static mfs_error_t mfs_flash_read(MFSDriver *mfsp, flash_offset_t offset, size_t n, uint8_t *rp)
Flash read.
#define PAIR(a, b)
Combines two values (0..3) in one (0..15).
flash_offset_t tr_limit_offet
Maximum offset for the transaction.
static mfs_error_t mfs_flash_write(MFSDriver *mfsp, flash_offset_t offset, size_t n, const uint8_t *wp)
Flash write.
const MFSConfig * config
Current configuration data.