aboutsummaryrefslogtreecommitdiffstats
path: root/os/ex
diff options
context:
space:
mode:
authorGiovanni Di Sirio <gdisirio@gmail.com>2017-11-12 16:19:33 +0000
committerGiovanni Di Sirio <gdisirio@gmail.com>2017-11-12 16:19:33 +0000
commitbabdb259ec6bc32d841990890be98684ea6d4949 (patch)
treeb73a3c131ce356af583ed3e005466f23509affca /os/ex
parent66fc4a31eb9a8bfcb26b5e6d5ffed92f58b00cec (diff)
downloadChibiOS-babdb259ec6bc32d841990890be98684ea6d4949.tar.gz
ChibiOS-babdb259ec6bc32d841990890be98684ea6d4949.tar.bz2
ChibiOS-babdb259ec6bc32d841990890be98684ea6d4949.zip
Simplified code.
git-svn-id: svn://svn.code.sf.net/p/chibios/svn/trunk@10985 35acf78f-673a-0410-8e92-d51de3d6d3f4
Diffstat (limited to 'os/ex')
-rw-r--r--os/ex/subsystems/mfs/mfs.c202
1 files changed, 72 insertions, 130 deletions
diff --git a/os/ex/subsystems/mfs/mfs.c b/os/ex/subsystems/mfs/mfs.c
index e4dbf77d7..38db34839 100644
--- a/os/ex/subsystems/mfs/mfs.c
+++ b/os/ex/subsystems/mfs/mfs.c
@@ -418,53 +418,6 @@ static mfs_error_t mfs_bank_write_header(MFSDriver *mfsp,
}
/**
- * @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] cntp bank counter value, only valid if the bank header is
- * correct.
- *
- * @return The operation status.
- * @retval MFS_NO_ERROR if the operation has been successfully completed.
- * @retval MFS_ERR_HEADER if the header is corrupt or missing.
- * @retval MFS_ERR_FLASH_FAILURE if the flash memory is unusable because HW
- * failures.
- */
-static mfs_error_t mfs_bank_verify_header(MFSDriver *mfsp,
- mfs_bank_t bank,
- uint32_t *cntp) {
- uint16_t crc;
-
- /* Reading the current bank header.*/
- RET_ON_ERROR(mfs_flash_read(mfsp, mfs_flash_get_bank_offset(mfsp, bank),
- 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_ERR_HEADER;
- }
-
- /* 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_ERR_HEADER;
- }
-
- /* Returning the counter value.*/
- if (cntp != NULL) {
- *cntp = mfsp->buffer.bhdr.fields.counter;
- }
-
- return MFS_NO_ERROR;
-}
-
-/**
* @brief Scans blocks searching for records.
* @note The block integrity is strongly checked.
*
@@ -481,9 +434,7 @@ static mfs_error_t mfs_bank_verify_header(MFSDriver *mfsp,
*/
static mfs_error_t mfs_bank_scan_records(MFSDriver *mfsp,
mfs_bank_t bank,
- mfs_bank_state_t *statep,
- mfs_scan_cb_t foundcb,
- mfs_scan_cb_t endcb) {
+ mfs_bank_state_t *statep) {
flash_offset_t hdr_offset, start_offset, end_offset;
mfs_record_state_t sts;
bool warning = false;
@@ -508,8 +459,16 @@ static mfs_error_t mfs_bank_scan_records(MFSDriver *mfsp,
}
else if (sts == MFS_RECORD_OK) {
/* Record OK.*/
- if (foundcb != NULL) {
- foundcb(mfsp, hdr_offset);
+ uint32_t size = mfsp->buffer.dhdr.fields.size;
+
+ /* Zero-sized records are erase markers.*/
+ if (size == 0U) {
+ mfsp->descriptors[mfsp->buffer.dhdr.fields.id - 1].offset = 0U;
+ mfsp->descriptors[mfsp->buffer.dhdr.fields.id - 1].size = 0U;
+ }
+ else {
+ mfsp->descriptors[mfsp->buffer.dhdr.fields.id - 1].offset = hdr_offset;
+ mfsp->descriptors[mfsp->buffer.dhdr.fields.id - 1].size = size;
}
}
else if (sts == MFS_RECORD_CRC) {
@@ -528,10 +487,8 @@ static mfs_error_t mfs_bank_scan_records(MFSDriver *mfsp,
return MFS_ERR_INTERNAL;
}
- /* Final callback.*/
- if (endcb != NULL) {
- endcb(mfsp, hdr_offset);
- }
+ /* Final.*/
+ mfsp->next_offset = hdr_offset;
if (warning) {
*statep = MFS_BANK_PARTIAL;
@@ -544,66 +501,6 @@ static mfs_error_t mfs_bank_scan_records(MFSDriver *mfsp,
}
/**
- * @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.
- *
- * @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_bank_get_state(MFSDriver *mfsp,
- mfs_bank_t bank,
- mfs_bank_state_t *statep,
- uint32_t *cntp) {
- mfs_error_t err;
-
- /* Special case where the block is fully erased.*/
- err = mfs_bank_verify_erase(mfsp, bank);
- if (err == MFS_NO_ERROR) {
- *statep = MFS_BANK_ERASED;
- return MFS_BANK_OK;
- }
-
- /* Bank header verification.*/
- *statep = MFS_BANK_GARBAGE;
- RET_ON_ERROR(mfs_bank_verify_header(mfsp, bank, cntp));
-
- return mfs_bank_scan_records(mfsp, bank, statep, NULL, NULL);
-}
-
-/**
- * @brief Private callback of @p mfs_bank_mount().
- */
-static void mfs_bank_mount_found_cb(MFSDriver *mfsp, flash_offset_t offset) {
- uint32_t size = mfsp->buffer.dhdr.fields.size;
-
- /* Zero-sized records are erase markers.*/
- if (size == 0U) {
- mfsp->descriptors[mfsp->buffer.dhdr.fields.id - 1].offset = 0U;
- mfsp->descriptors[mfsp->buffer.dhdr.fields.id - 1].size = 0U;
- }
- else {
- mfsp->descriptors[mfsp->buffer.dhdr.fields.id - 1].offset = offset;
- mfsp->descriptors[mfsp->buffer.dhdr.fields.id - 1].size = size;
- }
-}
-
-/**
- * @brief Private callback of @p mfs_bank_mount().
- */
-static void mfs_bank_mount_end_cb(MFSDriver *mfsp, flash_offset_t offset) {
-
- mfsp->next_offset = offset;
-}
-
-/**
* @brief Selects a bank as current.
*
* @param[in] mfsp pointer to the @p MFSDriver object
@@ -620,21 +517,62 @@ static mfs_error_t mfs_bank_mount(MFSDriver *mfsp,
mfs_bank_t bank,
mfs_bank_state_t *statep) {
unsigned i;
+ bool dirty;
+ mfs_error_t err;
+ uint16_t crc;
- /* Resetting previous state.*/
+ /* Resetting the bank state.*/
mfs_state_reset(mfsp);
- /* Bank header verification.*/
+ /* Worst case is default.*/
*statep = MFS_BANK_GARBAGE;
- RET_ON_ERROR(mfs_bank_verify_header(mfsp, bank, &mfsp->current_counter));
+
+ /* Reading the current bank header.*/
+ RET_ON_ERROR(mfs_flash_read(mfsp, mfs_flash_get_bank_offset(mfsp, bank),
+ sizeof (mfs_bank_header_t),
+ (void *)&mfsp->buffer.bhdr));
+
+ /* Checking the special case where the header is erased.*/
+ dirty = false;
+ for (i = 0; i < 4; i++) {
+ if (mfsp->buffer.bhdr.hdr32[i] != mfsp->config->erased) {
+ dirty = true;
+ break;
+ }
+ }
+
+ /* If the header is erased then it could be the whole block erased.*/
+ if (!dirty) {
+ err = mfs_bank_verify_erase(mfsp, bank);
+ if (err == MFS_NO_ERROR) {
+ *statep = MFS_BANK_ERASED;
+ }
+ return MFS_NO_ERROR;
+ }
+
+ /* Checking header 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 header 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;
+ }
+
+ /* Header is OK, storing metadata.*/
+ mfsp->current_bank = bank;
+ mfsp->current_counter = mfsp->buffer.bhdr.fields.counter;
/* Scanning for the most recent instance of all records.*/
- RET_ON_ERROR(mfs_bank_scan_records(mfsp, bank, statep,
- mfs_bank_mount_found_cb,
- mfs_bank_mount_end_cb));
+ RET_ON_ERROR(mfs_bank_scan_records(mfsp, bank, statep));
/* Calculating the effective used size.*/
- mfsp->current_bank = bank;
for (i = 0; i < MFS_CFG_MAX_RECORDS; i++) {
if (mfsp->descriptors[i].offset != 0U) {
mfsp->used_space += mfsp->descriptors[i].size + sizeof (mfs_data_header_t);
@@ -701,9 +639,11 @@ static mfs_error_t mfs_try_mount(MFSDriver *mfsp) {
uint32_t cnt0 = 0, cnt1 = 0;
mfs_error_t err;
- /* Assessing the state of the two banks.*/
- RET_ON_ERROR(mfs_bank_get_state(mfsp, MFS_BANK_0, &sts0, &cnt0));
- RET_ON_ERROR(mfs_bank_get_state(mfsp, MFS_BANK_1, &sts1, &cnt1));
+ /* Assessing the state of the two banks by trying to mount them.*/
+ RET_ON_ERROR(mfs_bank_mount(mfsp, MFS_BANK_0, &sts0));
+ cnt0 = mfsp->current_counter;
+ RET_ON_ERROR(mfs_bank_mount(mfsp, MFS_BANK_1, &sts1));
+ cnt1 = mfsp->current_counter;
/* Handling all possible scenarios, each one requires its own recovery
strategy.*/
@@ -718,7 +658,7 @@ static mfs_error_t mfs_try_mount(MFSDriver *mfsp) {
case PAIR(MFS_BANK_ERASED, MFS_BANK_OK):
/* Normal situation, bank one is used.*/
- RET_ON_ERROR(mfs_bank_mount(mfsp, MFS_BANK_1, &sts));
+ RET_ON_ERROR(mfs_bank_mount(mfsp, MFS_BANK_1, &sts)); /* Not necessary.*/
err = MFS_NO_ERROR;
break;
@@ -989,7 +929,7 @@ mfs_error_t mfsMount(MFSDriver *mfsp) {
}
/**
- * @brief Unmounts a manage flash storage.
+ * @brief Unmounts a managed flash storage.
*/
mfs_error_t mfsUnmount(MFSDriver *mfsp) {
@@ -1100,12 +1040,14 @@ mfs_error_t mfsEraseRecord(MFSDriver *mfsp, uint32_t id) {
/**
* @brief Enforces a garbage collection operation.
- * @details Garbage collection is usually performed on mount, it involves:
- * integrity check, removal of obsolete data and a flash bank swap.
+ * @details Garbage collection involves: integrity check, optionally repairs,
+ * obsolete data removal, data compaction and a flash bank swap.
*
* @param[in] mfsp pointer to the @p MFSDriver object
* @return The operation status.
* @retval MFS_NO_ERROR if the operation has been successfully completed.
+ * @retval MFS_WARN_REPAIR if the operation has been completed but a
+ * repair has been performed.
* @retval MFS_ERR_FLASH_FAILURE if the flash memory is unusable because HW
* failures.
*