aboutsummaryrefslogtreecommitdiffstats
path: root/os/ex
diff options
context:
space:
mode:
authorGiovanni Di Sirio <gdisirio@gmail.com>2017-11-10 09:28:50 +0000
committerGiovanni Di Sirio <gdisirio@gmail.com>2017-11-10 09:28:50 +0000
commit4ba55d0c38d9c62fddf888be02521ec88714bdbd (patch)
treecd0dc740d46465a45f1d0d6e2e49c2cca22390d0 /os/ex
parentf16a0581cec5a807fa09b3ac15fbe75c447536a6 (diff)
downloadChibiOS-4ba55d0c38d9c62fddf888be02521ec88714bdbd.tar.gz
ChibiOS-4ba55d0c38d9c62fddf888be02521ec88714bdbd.tar.bz2
ChibiOS-4ba55d0c38d9c62fddf888be02521ec88714bdbd.zip
More MFS code.
git-svn-id: svn://svn.code.sf.net/p/chibios/svn/trunk@10979 35acf78f-673a-0410-8e92-d51de3d6d3f4
Diffstat (limited to 'os/ex')
-rw-r--r--os/ex/subsystems/mfs/mfs.c234
-rw-r--r--os/ex/subsystems/mfs/mfs.h139
2 files changed, 285 insertions, 88 deletions
diff --git a/os/ex/subsystems/mfs/mfs.c b/os/ex/subsystems/mfs/mfs.c
index 5fce43e1b..2228e8ea6 100644
--- a/os/ex/subsystems/mfs/mfs.c
+++ b/os/ex/subsystems/mfs/mfs.c
@@ -62,6 +62,16 @@
/* Driver local variables and types. */
/*===========================================================================*/
+/**
+ * @brief Type of a records scan callback function.
+ */
+typedef void (*foundrec_t)(mfs_data_header_t *dhdrp);
+
+/**
+ * @brief Type of a records scan callback function.
+ */
+typedef void (*endrec_t)(mfs_data_header_t *dhdrp);
+
const uint16_t crc16_table[256] = {
0x0000, 0x1021, 0x2042, 0x3063, 0x4084, 0x50A5, 0x60C6, 0x70E7,
0x8108, 0x9129, 0xA14A, 0xB16B, 0xC18C, 0xD1AD, 0xE1CE, 0xF1EF,
@@ -112,7 +122,8 @@ uint16_t crc16(uint16_t crc, const uint8_t *data, size_t n) {
return crc;
}
-static flash_offset_t mfs_get_bank_offset(MFSDriver *mfsp, mfs_bank_t bank) {
+static flash_offset_t mfs_flash_get_bank_offset(MFSDriver *mfsp,
+ mfs_bank_t bank) {
return bank == MFS_BANK_0 ? flashGetSectorOffset(mfsp->config->flashp,
mfsp->config->bank0_start) :
@@ -126,7 +137,7 @@ static flash_offset_t mfs_get_bank_offset(MFSDriver *mfsp, mfs_bank_t bank) {
* @param[in] mfsp pointer to the @p MFSDriver object
* @param[in] offset flash offset
* @param[in] n number of bytes to be read
- * @param[in] rp pointer to the data buffer
+ * @param[out] rp pointer to the data buffer
* @return The operation status.
* @retval MFS_NO_ERROR if the operation has been successfully completed.
* @retval MFS_ERR_FLASH_FAILURE if the flash memory is unusable because HW
@@ -135,7 +146,7 @@ static flash_offset_t mfs_get_bank_offset(MFSDriver *mfsp, mfs_bank_t bank) {
* @notapi
*/
static mfs_error_t mfs_flash_read(MFSDriver *mfsp, flash_offset_t offset,
- size_t n, const uint8_t *rp) {
+ size_t n, uint8_t *rp) {
flash_error_t ferr;
ferr = flashRead(mfsp->config->flashp, offset, n, rp);
@@ -154,7 +165,7 @@ static mfs_error_t mfs_flash_read(MFSDriver *mfsp, flash_offset_t offset,
* @param[in] mfsp pointer to the @p MFSDriver object
* @param[in] offset flash offset
* @param[in] n number of bytes to be writen
- * @param[out] wp pointer to the data buffer
+ * @param[in] wp pointer to the data buffer
* @return The operation status.
* @retval MFS_NO_ERROR if the operation has been successfully completed.
* @retval MFS_ERR_FLASH_FAILURE if the flash memory is unusable because HW
@@ -165,7 +176,7 @@ static mfs_error_t mfs_flash_read(MFSDriver *mfsp, flash_offset_t offset,
static mfs_error_t mfs_flash_write(MFSDriver *mfsp,
flash_offset_t offset,
size_t n,
- uint8_t *wp) {
+ const uint8_t *wp) {
flash_error_t ferr;
ferr = flashProgram(mfsp->config->flashp, offset, n, wp);
@@ -277,11 +288,11 @@ static mfs_error_t mfs_bank_verify_erase(MFSDriver *mfsp, mfs_bank_t bank) {
*
* @notapi
*/
-static mfs_error_t mfs_bank_set_header(MFSDriver *mfsp,
- mfs_bank_t bank,
- uint32_t cnt) {
+static mfs_error_t mfs_bank_write_header(MFSDriver *mfsp,
+ mfs_bank_t bank,
+ uint32_t cnt) {
flash_sector_t sector;
- mfs_bank_header_t header;
+ mfs_bank_header_t bhdr;
if (bank == MFS_BANK_0) {
sector = mfsp->config->bank0_start;
@@ -290,18 +301,17 @@ static mfs_error_t mfs_bank_set_header(MFSDriver *mfsp,
sector = mfsp->config->bank1_start;
}
- header.magic1 = MFS_BANK_MAGIC_1;
- header.magic1 = MFS_BANK_MAGIC_1;
- header.counter = cnt;
- header.next = sizeof (mfs_bank_header_t);
- header.crc = crc16(0xFFFFU,
- (const uint8_t *)&header,
- sizeof (flash_sector_t) - sizeof (uint16_t));
+ bhdr.fields.magic1 = MFS_BANK_MAGIC_1;
+ bhdr.fields.magic1 = MFS_BANK_MAGIC_1;
+ bhdr.fields.counter = cnt;
+ bhdr.fields.reserved1 = (uint16_t)mfsp->config->erased;
+ bhdr.fields.crc = crc16(0xFFFFU, bhdr.hdr8,
+ sizeof (mfs_bank_header_t) - sizeof (uint16_t));
return mfs_flash_write(mfsp,
flashGetSectorOffset(mfsp->config->flashp, sector),
sizeof (mfs_bank_header_t),
- (const uint8_t *)&header);
+ bhdr.hdr8);
}
/**
@@ -346,17 +356,160 @@ static mfs_error_t mfs_bank_mount(MFSDriver *mfsp, mfs_bank_t bank) {
return MFS_NO_ERROR;
}
+static mfs_error_t mfs_check_record(MFSDriver *mfsp,
+ mfs_data_header_t *dhdrp,
+ flash_offset_t offset,
+ flash_offset_t limit,
+ mfs_record_state_t *sts) {
+ unsigned i;
+
+ for (i = 0; i < 3; i++) {
+ if (dhdrp->hdr32[i] != mfsp->config->erased) {
+ /* Not erased must verify the header.*/
+ if ((dhdrp->fields.magic != MFS_HEADER_MAGIC) ||
+ (dhdrp->fields.id >= (uint16_t)MFS_CFG_MAX_RECORDS) ||
+ (dhdrp->fields.size + sizeof (mfs_data_header_t) > limit - offset)) {
+ *sts = MFS_RECORD_GARBAGE;
+ return MFS_NO_ERROR;
+ }
+#if MFS_CFG_STRONG_CHECKING == TRUE
+ {
+ /* Checking the CRC while reading the record data.*/
+ (void)mfsp;
+ }
+#else
+ (void)mfsp;
+#endif
+ }
+ }
+
+ /* It is fully erased.*/
+ *sts = MFS_RECORD_ERASED;
+ return MFS_NO_ERROR;
+}
+
+/**
+ * @brief Scans blocks searching for records.
+ * @note The block integrity is strongly checked.
+ *
+ * @param[in] mfsp pointer to the @p MFSDriver object
+ * @param[in] bank the bank identifier
+ * @param[out] statep bank state
+ * @param[out] cntp bank counter value, only valid if the bank is not
+ * in the @p MFS_BANK_GARBAGE state.
+ * @param[in] foundcb callback to be called for each found record or @p NULL
+ * @param[in] endcb callback to be called after scanning or @p NULL
+ *
+ * @return The operation status.
+ * @retval MFS_NO_ERROR if the operation has been successfully completed.
+ * @retval MFS_ERR_FLASH_FAILURE if the flash memory is unusable because HW
+ * failures.
+ */
+static mfs_error_t mfs_scan_records(MFSDriver *mfsp,
+ mfs_bank_t bank,
+ mfs_bank_state_t *statep,
+ uint32_t *cntp,
+ foundrec_t foundcb,
+ endrec_t endcb) {
+ flash_offset_t hdr_offset, start_offset, end_offset;
+ mfs_record_state_t sts;
+ uint16_t crc;
+ bool warning = false;
+
+ /* Default state.*/
+ *statep = MFS_BANK_GARBAGE;
+
+ start_offset = mfs_flash_get_bank_offset(mfsp, bank);
+ end_offset = start_offset + mfsp->config->bank_size;
+
+ /* Reading the current bank header.*/
+ RET_ON_ERROR(mfs_flash_read(mfsp, start_offset,
+ sizeof (mfs_bank_header_t),
+ (void *)&mfsp->buffer.bhdr));
+
+ /* Checking fields integrity.*/
+ if ((mfsp->buffer.bhdr.fields.magic1 != MFS_BANK_MAGIC_1) ||
+ (mfsp->buffer.bhdr.fields.magic2 != MFS_BANK_MAGIC_2) ||
+ (mfsp->buffer.bhdr.fields.counter == mfsp->config->erased) ||
+ (mfsp->buffer.bhdr.fields.reserved1 != (uint16_t)mfsp->config->erased)) {
+ return MFS_NO_ERROR;
+ }
+
+ /* Verifying CRC.*/
+ crc = crc16(0xFFFFU, mfsp->buffer.bhdr.hdr8,
+ sizeof (mfs_bank_header_t) - sizeof (uint16_t));
+ if (crc != mfsp->buffer.bhdr.fields.crc) {
+ return MFS_NO_ERROR;
+ }
+
+ /* Returning the counter value.*/
+ if (cntp != NULL) {
+ *cntp = mfsp->buffer.bhdr.fields.counter;
+ }
+
+ /* Scanning records.*/
+ hdr_offset = start_offset + (flash_offset_t)sizeof(mfs_bank_header_t);
+ while (hdr_offset < end_offset) {
+ /* Reading the current record header.*/
+ RET_ON_ERROR(mfs_flash_read(mfsp, start_offset,
+ sizeof (mfs_data_header_t),
+ (void *)&mfsp->buffer.dhdr));
+
+ /* Checking header/data integrity.*/
+ RET_ON_ERROR(mfs_check_record(mfsp, &mfsp->buffer.dhdr,
+ hdr_offset, end_offset, &sts));
+ if (sts == MFS_RECORD_ERASED) {
+ /* Record area fully erased, stopping scan.*/
+ break;
+ }
+ else if (sts == MFS_RECORD_OK) {
+ /* Record OK.*/
+ if (foundcb != NULL) {
+ foundcb(&mfsp->buffer.dhdr);
+ }
+ }
+ else if (sts == MFS_RECORD_CRC) {
+ /* Record payload corrupted, scan can continue because the header
+ is OK.*/
+ warning = true;
+ }
+ else {
+ /* Unrecognized header, scanning cannot continue.*/
+ warning = true;
+ break;
+ }
+ }
+
+ if (hdr_offset > end_offset) {
+ return MFS_ERR_INTERNAL;
+ }
+
+ /* Final callback.*/
+ if (endcb != NULL) {
+ endcb(&mfsp->buffer.dhdr);
+ }
+
+ if (warning) {
+ *statep = MFS_BANK_PARTIAL;
+ }
+ else {
+ *statep = MFS_BANK_OK;
+ }
+
+ return MFS_NO_ERROR;
+}
+
/**
* @brief Determines the state of a flash bank.
*
* @param[in] mfsp pointer to the @p MFSDriver object
- * @param[in] bank the bank identifier
- * @param[out[ statep bank state
- * @param[out] cntp bank counter value, only valid if the bank is not
- * in the @p MFS_BANK_GARBAGE or @p MFS_BANK_ERASED
- * states.
+ * @param[in] bank the bank identifier
+ * @param[out] statep bank state
+ * @param[out] cntp bank counter value, only valid if the bank is not
+ * in the @p MFS_BANK_GARBAGE or @p MFS_BANK_ERASED
+ * states.
*
- * @return The bank state.
+ * @return The operation status.
* @retval MFS_NO_ERROR if the operation has been successfully completed.
* @retval MFS_ERR_FLASH_FAILURE if the flash memory is unusable because HW
* failures.
@@ -374,13 +527,10 @@ static mfs_error_t mfs_get_bank_state(MFSDriver *mfsp,
return MFS_BANK_OK;
}
- /* Reading the header of the current bank into the transient buffer.*/
- RET_ON_ERROR(mfs_flash_read(mfsp,
- mfs_get_bank_offset(mfsp, bank),
- sizeof (mfs_bank_header_t),
- (void *)&mfsp->buffer.bhdr));
-
- return MFS_BANK_OK;
+ return mfs_scan_records(mfsp, bank,
+ statep, cntp,
+ NULL,
+ NULL);
}
/**
@@ -410,7 +560,7 @@ static mfs_error_t mfs_try_mount(MFSDriver *mfsp) {
case PAIR(MFS_BANK_ERASED, MFS_BANK_ERASED):
/* Both banks erased, first initialization.*/
- RET_ON_ERROR(mfs_bank_set_header(mfsp, MFS_BANK_0, 1));
+ RET_ON_ERROR(mfs_bank_write_header(mfsp, MFS_BANK_0, 1));
RET_ON_ERROR(mfs_bank_mount(mfsp, MFS_BANK_0));
return MFS_NO_ERROR;
@@ -422,7 +572,7 @@ static mfs_error_t mfs_try_mount(MFSDriver *mfsp) {
case PAIR(MFS_BANK_ERASED, MFS_BANK_PARTIAL):
/* Bank zero is erased, bank one has problems.*/
RET_ON_ERROR(mfs_bank_copy(mfsp, MFS_BANK_1, MFS_BANK_0));
- RET_ON_ERROR(mfs_bank_set_header(mfsp, MFS_BANK_0, cnt1 + 1));
+ RET_ON_ERROR(mfs_bank_write_header(mfsp, MFS_BANK_0, cnt1 + 1));
RET_ON_ERROR(mfs_bank_erase(mfsp, MFS_BANK_1));
RET_ON_ERROR(mfs_bank_mount(mfsp, MFS_BANK_0));
return MFS_WARN_REPAIR;
@@ -430,7 +580,7 @@ static mfs_error_t mfs_try_mount(MFSDriver *mfsp) {
case PAIR(MFS_BANK_ERASED, MFS_BANK_GARBAGE):
/* Bank zero is erased, bank one is not readable.*/
RET_ON_ERROR(mfs_bank_erase(mfsp, MFS_BANK_1));
- RET_ON_ERROR(mfs_bank_set_header(mfsp, MFS_BANK_0, 1));
+ RET_ON_ERROR(mfs_bank_write_header(mfsp, MFS_BANK_0, 1));
RET_ON_ERROR(mfs_bank_mount(mfsp, MFS_BANK_0));
return MFS_WARN_REPAIR;
@@ -466,7 +616,7 @@ static mfs_error_t mfs_try_mount(MFSDriver *mfsp) {
/* Partial bank one is more recent than the normal bank zero.*/
RET_ON_ERROR(mfs_bank_erase(mfsp, MFS_BANK_0));
RET_ON_ERROR(mfs_bank_copy(mfsp, MFS_BANK_1, MFS_BANK_0));
- RET_ON_ERROR(mfs_bank_set_header(mfsp, MFS_BANK_0, cnt1 + 1));
+ RET_ON_ERROR(mfs_bank_write_header(mfsp, MFS_BANK_0, cnt1 + 1));
RET_ON_ERROR(mfs_bank_erase(mfsp, MFS_BANK_1));
RET_ON_ERROR(mfs_bank_mount(mfsp, MFS_BANK_0));
}
@@ -481,7 +631,7 @@ static mfs_error_t mfs_try_mount(MFSDriver *mfsp) {
case PAIR(MFS_BANK_PARTIAL, MFS_BANK_ERASED):
/* Bank zero has problems, bank one is erased.*/
RET_ON_ERROR(mfs_bank_copy(mfsp, MFS_BANK_0, MFS_BANK_1));
- RET_ON_ERROR(mfs_bank_set_header(mfsp, MFS_BANK_1, cnt0 + 1));
+ RET_ON_ERROR(mfs_bank_write_header(mfsp, MFS_BANK_1, cnt0 + 1));
RET_ON_ERROR(mfs_bank_erase(mfsp, MFS_BANK_0));
RET_ON_ERROR(mfs_bank_mount(mfsp, MFS_BANK_1));
return MFS_WARN_REPAIR;
@@ -498,7 +648,7 @@ static mfs_error_t mfs_try_mount(MFSDriver *mfsp) {
/* Partial bank zero is more recent than the normal bank one.*/
RET_ON_ERROR(mfs_bank_erase(mfsp, MFS_BANK_1));
RET_ON_ERROR(mfs_bank_copy(mfsp, MFS_BANK_0, MFS_BANK_1));
- RET_ON_ERROR(mfs_bank_set_header(mfsp, MFS_BANK_1, cnt0 + 1));
+ RET_ON_ERROR(mfs_bank_write_header(mfsp, MFS_BANK_1, cnt0 + 1));
RET_ON_ERROR(mfs_bank_erase(mfsp, MFS_BANK_0));
RET_ON_ERROR(mfs_bank_mount(mfsp, MFS_BANK_1));
}
@@ -510,7 +660,7 @@ static mfs_error_t mfs_try_mount(MFSDriver *mfsp) {
/* Bank zero is newer, copying in bank one and using it.*/
RET_ON_ERROR(mfs_bank_erase(mfsp, MFS_BANK_1));
RET_ON_ERROR(mfs_bank_copy(mfsp, MFS_BANK_0, MFS_BANK_1));
- RET_ON_ERROR(mfs_bank_set_header(mfsp, MFS_BANK_1, cnt0 + 1));
+ RET_ON_ERROR(mfs_bank_write_header(mfsp, MFS_BANK_1, cnt0 + 1));
RET_ON_ERROR(mfs_bank_erase(mfsp, MFS_BANK_0));
RET_ON_ERROR(mfs_bank_mount(mfsp, MFS_BANK_1));
}
@@ -518,7 +668,7 @@ static mfs_error_t mfs_try_mount(MFSDriver *mfsp) {
/* Bank one is newer, copying in bank zero and using it.*/
RET_ON_ERROR(mfs_bank_erase(mfsp, MFS_BANK_0));
RET_ON_ERROR(mfs_bank_copy(mfsp, MFS_BANK_1, MFS_BANK_0));
- RET_ON_ERROR(mfs_bank_set_header(mfsp, MFS_BANK_0, cnt1 + 1));
+ RET_ON_ERROR(mfs_bank_write_header(mfsp, MFS_BANK_0, cnt1 + 1));
RET_ON_ERROR(mfs_bank_erase(mfsp, MFS_BANK_1));
RET_ON_ERROR(mfs_bank_mount(mfsp, MFS_BANK_0));
}
@@ -528,7 +678,7 @@ static mfs_error_t mfs_try_mount(MFSDriver *mfsp) {
/* Bank zero has problems, bank one is unreadable.*/
RET_ON_ERROR(mfs_bank_erase(mfsp, MFS_BANK_1));
RET_ON_ERROR(mfs_bank_copy(mfsp, MFS_BANK_0, MFS_BANK_1));
- RET_ON_ERROR(mfs_bank_set_header(mfsp, MFS_BANK_1, cnt0 + 1));
+ RET_ON_ERROR(mfs_bank_write_header(mfsp, MFS_BANK_1, cnt0 + 1));
RET_ON_ERROR(mfs_bank_erase(mfsp, MFS_BANK_0));
RET_ON_ERROR(mfs_bank_mount(mfsp, MFS_BANK_1));
return MFS_WARN_REPAIR;
@@ -536,7 +686,7 @@ static mfs_error_t mfs_try_mount(MFSDriver *mfsp) {
case PAIR(MFS_BANK_GARBAGE, MFS_BANK_ERASED):
/* Bank zero is unreadable, bank one is erased.*/
RET_ON_ERROR(mfs_bank_erase(mfsp, MFS_BANK_1));
- RET_ON_ERROR(mfs_bank_set_header(mfsp, MFS_BANK_0, 1));
+ RET_ON_ERROR(mfs_bank_write_header(mfsp, MFS_BANK_0, 1));
RET_ON_ERROR(mfs_bank_mount(mfsp, MFS_BANK_0));
return MFS_WARN_REPAIR;
@@ -550,7 +700,7 @@ static mfs_error_t mfs_try_mount(MFSDriver *mfsp) {
/* Bank zero is unreadable, bank one has problems.*/
RET_ON_ERROR(mfs_bank_erase(mfsp, MFS_BANK_0));
RET_ON_ERROR(mfs_bank_copy(mfsp, MFS_BANK_1, MFS_BANK_0));
- RET_ON_ERROR(mfs_bank_set_header(mfsp, MFS_BANK_0, cnt0 + 1));
+ RET_ON_ERROR(mfs_bank_write_header(mfsp, MFS_BANK_0, cnt0 + 1));
RET_ON_ERROR(mfs_bank_erase(mfsp, MFS_BANK_1));
RET_ON_ERROR(mfs_bank_mount(mfsp, MFS_BANK_0));
return MFS_WARN_REPAIR;
@@ -559,7 +709,7 @@ static mfs_error_t mfs_try_mount(MFSDriver *mfsp) {
/* Both banks are unreadable, reinitializing.*/
RET_ON_ERROR(mfs_bank_erase(mfsp, MFS_BANK_0));
RET_ON_ERROR(mfs_bank_erase(mfsp, MFS_BANK_1));
- RET_ON_ERROR(mfs_bank_set_header(mfsp, MFS_BANK_0, 1));
+ RET_ON_ERROR(mfs_bank_write_header(mfsp, MFS_BANK_0, 1));
RET_ON_ERROR(mfs_bank_mount(mfsp, MFS_BANK_0));
return MFS_WARN_REPAIR;
diff --git a/os/ex/subsystems/mfs/mfs.h b/os/ex/subsystems/mfs/mfs.h
index 8dd05a48f..033b7652c 100644
--- a/os/ex/subsystems/mfs/mfs.h
+++ b/os/ex/subsystems/mfs/mfs.h
@@ -66,6 +66,16 @@
#if !defined(MFS_CFG_WRITE_VERIFY) || defined(__DOXYGEN__)
#define MFS_CFG_WRITE_VERIFY TRUE
#endif
+
+/**
+ * @brief Enables a stronger and slower check procedure on mount.
+ * @details Strong checking requires reading of the whole written data and
+ * this can be slow, normal checking only checks integrity of
+ * metadata, data errors would be detected on read.
+ */
+#if !defined(MFS_CFG_STRONG_CHECKING) || defined(__DOXYGEN__)
+#define MFS_CFG_STRONG_CHECKING TRUE
+#endif
/** @} */
/*===========================================================================*/
@@ -80,6 +90,10 @@
#error "invalid MFS_MAX_REPAIR_ATTEMPTS value"
#endif
+#if (MFS_CFG_MAX_REPAIR_ATTEMPTS < 1) || (MFS_CFG_MAX_REPAIR_ATTEMPTS > 10)
+#error "invalid MFS_MAX_REPAIR_ATTEMPTS value"
+#endif
+
/*===========================================================================*/
/* Driver data structures and types. */
/*===========================================================================*/
@@ -130,33 +144,46 @@ typedef enum {
} mfs_bank_state_t;
/**
+ * @brief Type of a record state assessment.
+ */
+typedef enum {
+ MFS_RECORD_ERASED = 0,
+ MFS_RECORD_OK = 1,
+ MFS_RECORD_CRC = 2,
+ MFS_RECORD_GARBAGE = 3
+} mfs_record_state_t;
+
+/**
* @brief Type of a bank header.
- * @note The header resides in the first 16 bytes of a bank extending
- * to the next page boundary.
+ * @note The header resides in the first 16 bytes of a bank.
*/
-typedef struct {
- /**
- * @brief Bank magic 1.
- */
- uint32_t magic1;
- /**
- * @brief Bank magic 2.
- */
- uint32_t magic2;
- /**
- * @brief Usage counter of the bank.
- * @details This value is increased each time a bank swap is performed. It
- * indicates how much wearing the flash has already endured.
- */
- uint32_t counter;
- /**
- * @brief First data element.
- */
- flash_offset_t next;
- /**
- * @brief Header CRC.
- */
- uint16_t crc;
+typedef union {
+ struct {
+ /**
+ * @brief Bank magic 1.
+ */
+ uint32_t magic1;
+ /**
+ * @brief Bank magic 2.
+ */
+ uint32_t magic2;
+ /**
+ * @brief Usage counter of the bank.
+ * @details This value is increased each time a bank swap is performed. It
+ * indicates how much wearing the flash has already endured.
+ */
+ uint32_t counter;
+ /**
+ * @brief Reserved field.
+ */
+ uint16_t reserved1;
+ /**
+ * @brief Header CRC.
+ */
+ uint16_t crc;
+ } fields;
+ uint8_t hdr8[16];
+ uint32_t hdr32[4];
} mfs_bank_header_t;
/**
@@ -164,26 +191,30 @@ typedef struct {
* @details This structure is placed before each written data block.
*/
typedef struct {
- /**
- * @brief Data header magic.
- */
- uint16_t magic;
- /**
- * @brief Data CRC.
- */
- uint16_t crc;
- /**
- * @brief Data identifier.
- */
- uint16_t id;
- /**
- * @brief Data attributes.
- */
- uint16_t flags;
- /**
- * @brief Data size.
- */
- uint32_t size;
+ struct {
+ /**
+ * @brief Data header magic.
+ */
+ uint16_t magic;
+ /**
+ * @brief Data CRC.
+ */
+ uint16_t crc;
+ /**
+ * @brief Data identifier.
+ */
+ uint16_t id;
+ /**
+ * @brief Data attributes.
+ */
+ uint16_t flags;
+ /**
+ * @brief Data size.
+ */
+ uint32_t size;
+ } fields;
+ uint8_t hdr8[12];
+ uint32_t hdr32[3];
} mfs_data_header_t;
/**
@@ -195,11 +226,21 @@ typedef struct {
*/
BaseFlash *flashp;
/**
+ * @brief Erased value.
+ */
+ uint32_t erased;
+ /**
+ * @brief Banks size.
+ */
+ flash_offset_t bank_size;
+ /**
* @brief Base sector index for bank 0.
*/
flash_sector_t bank0_start;
/**
- * #brief Number of sectors for bank 0.
+ * @brief Number of sectors for bank 0.
+ * @note The total size of bank0 sectors must be greater or equal to
+ * @p bank_size.
*/
flash_sector_t bank0_sectors;
/**
@@ -208,6 +249,8 @@ typedef struct {
flash_sector_t bank1_start;
/**
* @brief Number of sectors for bank 1.
+ * @note The total size of bank1 sectors must be greater or equal to
+ * @p bank_size.
*/
flash_sector_t bank1_sectors;
} MFSConfig;
@@ -231,6 +274,10 @@ typedef struct {
*/
mfs_bank_t current_bank;
/**
+ * @brief Usage counter of the current bank.
+ */
+ uint32_t current_counter;
+ /**
* @brief Size in bytes of banks.
*/
uint32_t banks_size;