diff --git a/demos/STM32/RT-STM32H743I-NUCLEO144/cfg/mcuconf.h b/demos/STM32/RT-STM32H743I-NUCLEO144/cfg/mcuconf.h
index a0c330e73..798385198 100644
--- a/demos/STM32/RT-STM32H743I-NUCLEO144/cfg/mcuconf.h
+++ b/demos/STM32/RT-STM32H743I-NUCLEO144/cfg/mcuconf.h
@@ -33,6 +33,7 @@
#define STM32H7xx_MCUCONF
#define STM32H743_MCUCONF
+#define STM32H753_MCUCONF
/*
* General settings.
diff --git a/demos/STM32/RT-STM32L476RG-NUCLEO64/debug/RT-STM32L476RG-NUCLEO64 (OpenOCD, Flash and Run).launch b/demos/STM32/RT-STM32L476RG-NUCLEO64/debug/RT-STM32L476RG-NUCLEO64 (OpenOCD, Flash and Run).launch
index b9f5693fe..d7ddaf929 100644
--- a/demos/STM32/RT-STM32L476RG-NUCLEO64/debug/RT-STM32L476RG-NUCLEO64 (OpenOCD, Flash and Run).launch
+++ b/demos/STM32/RT-STM32L476RG-NUCLEO64/debug/RT-STM32L476RG-NUCLEO64 (OpenOCD, Flash and Run).launch
@@ -1,52 +1,52 @@
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/demos/STM32/RT-STM32L496ZG-NUCLEO144/debug/RT-STM32L496ZG-NUCLEO144 (OpenOCD, Flash and Run).launch b/demos/STM32/RT-STM32L496ZG-NUCLEO144/debug/RT-STM32L496ZG-NUCLEO144 (OpenOCD, Flash and Run).launch
index e94eb65d4..a17c58a13 100644
--- a/demos/STM32/RT-STM32L496ZG-NUCLEO144/debug/RT-STM32L496ZG-NUCLEO144 (OpenOCD, Flash and Run).launch
+++ b/demos/STM32/RT-STM32L496ZG-NUCLEO144/debug/RT-STM32L496ZG-NUCLEO144 (OpenOCD, Flash and Run).launch
@@ -1,52 +1,52 @@
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/demos/STM32/RT-STM32L4R5ZI-NUCLEO144/debug/RT-STM32L4R5ZI-NUCLEO144 (OpenOCD, Flash and Run).launch b/demos/STM32/RT-STM32L4R5ZI-NUCLEO144/debug/RT-STM32L4R5ZI-NUCLEO144 (OpenOCD, Flash and Run).launch
index c9b1eb6f5..2d30add31 100644
--- a/demos/STM32/RT-STM32L4R5ZI-NUCLEO144/debug/RT-STM32L4R5ZI-NUCLEO144 (OpenOCD, Flash and Run).launch
+++ b/demos/STM32/RT-STM32L4R5ZI-NUCLEO144/debug/RT-STM32L4R5ZI-NUCLEO144 (OpenOCD, Flash and Run).launch
@@ -1,52 +1,52 @@
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/demos/STM32/RT-STM32L4R9-DISCOVERY/debug/RT-STM32L4R9-DISCOVERY (OpenOCD, Flash and Run).launch b/demos/STM32/RT-STM32L4R9-DISCOVERY/debug/RT-STM32L4R9-DISCOVERY (OpenOCD, Flash and Run).launch
index 039bf68c4..b04c92897 100644
--- a/demos/STM32/RT-STM32L4R9-DISCOVERY/debug/RT-STM32L4R9-DISCOVERY (OpenOCD, Flash and Run).launch
+++ b/demos/STM32/RT-STM32L4R9-DISCOVERY/debug/RT-STM32L4R9-DISCOVERY (OpenOCD, Flash and Run).launch
@@ -1,52 +1,52 @@
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/os/hal/boards/ST_STM32L4R9I_DISCOVERY/board.h b/os/hal/boards/ST_STM32L4R9I_DISCOVERY/board.h
index 07a5d09bd..15f5c0430 100644
--- a/os/hal/boards/ST_STM32L4R9I_DISCOVERY/board.h
+++ b/os/hal/boards/ST_STM32L4R9I_DISCOVERY/board.h
@@ -611,7 +611,7 @@
* PC10 - SDMMC_1_D2 (alternate 12).
* PC11 - SDMMC_1_D3 (alternate 12).
* PC12 - SDMMC_1_CK (alternate 12).
- * PC13 - JOY_SEL BUTTON (input floating).
+ * PC13 - JOY_SEL BUTTON (input pulldown).
* PC14 - PIN14 (analog).
* PC15 - PIN15 (analog).
*/
@@ -676,7 +676,7 @@
PIN_PUPDR_FLOATING(GPIOC_SDMMC_1_D2) | \
PIN_PUPDR_FLOATING(GPIOC_SDMMC_1_D3) | \
PIN_PUPDR_FLOATING(GPIOC_SDMMC_1_CK) | \
- PIN_PUPDR_FLOATING(GPIOC_JOY_SEL) | \
+ PIN_PUPDR_PULLDOWN(GPIOC_JOY_SEL) | \
PIN_PUPDR_FLOATING(GPIOC_PIN14) | \
PIN_PUPDR_FLOATING(GPIOC_PIN15))
#define VAL_GPIOC_ODR (PIN_ODR_LOW(GPIOC_PIN0) | \
diff --git a/os/hal/boards/ST_STM32L4R9I_DISCOVERY/cfg/board.chcfg b/os/hal/boards/ST_STM32L4R9I_DISCOVERY/cfg/board.chcfg
index 716a19662..08e16415a 100644
--- a/os/hal/boards/ST_STM32L4R9I_DISCOVERY/cfg/board.chcfg
+++ b/os/hal/boards/ST_STM32L4R9I_DISCOVERY/cfg/board.chcfg
@@ -483,7 +483,7 @@
PinLock="Disabled"
Alternate="0"
ID="JOY_SEL BUTTON"
- Resistor="Floating"
+ Resistor="PullDown"
Mode="Input"
Level="Low" />
0U) {
size_t chunk = n <= MFS_CFG_BUFFER_SIZE ? n : MFS_CFG_BUFFER_SIZE;
+
RET_ON_ERROR(mfs_flash_read(mfsp, offset, chunk, mfsp->buffer.data8));
+
if (memcmp((void *)mfsp->buffer.data8, (void *)wp, chunk)) {
mfsp->state = MFS_ERROR;
return MFS_ERR_FLASH_FAILURE;
@@ -244,52 +267,6 @@ static mfs_error_t mfs_flash_copy(MFSDriver *mfsp,
return MFS_NO_ERROR;
}
-/**
- * @brief Verifies integrity of a record.
- *
- * @param[in] mfsp pointer to the @p MFSDriver object
- * @param[in] dhdrp pointer to the header to be checked
- * @param[in] offset flash offset of the header to be checked
- * @param[in] limit flash limit offset
- * @param[out] sts assessed record state
- * @return The operation status.
- *
- * @notapi
- */
-static mfs_error_t mfs_record_check(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)1) ||
- (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
- {
- /* TODO: Checking the CRC while reading the record data.*/
-/* *sts = MFS_RECORD_CRC;
- return MFS_NO_ERROR;*/
- }
-#endif
- *sts = MFS_RECORD_OK;
- return MFS_NO_ERROR;
- }
- }
-
- /* It is fully erased.*/
- *sts = MFS_RECORD_ERASED;
- return MFS_NO_ERROR;
-}
-
/**
* @brief Erases and verifies all sectors belonging to a bank.
*
@@ -382,7 +359,6 @@ static mfs_error_t mfs_bank_verify_erase(MFSDriver *mfsp, mfs_bank_t bank) {
* @param[in] bank bank to be validated
* @param[in] cnt value for the flash usage counter
* @return The operation status.
- * @retval MFS_NO_ERROR if the operation has been successfully completed.
*
* @notapi
*/
@@ -412,16 +388,50 @@ static mfs_error_t mfs_bank_write_header(MFSDriver *mfsp,
bhdr.hdr8);
}
+/**
+ * @brief Checks integrity of the header in the shared buffer.
+ *
+ * @param[in] mfsp pointer to the @p MFSDriver object
+ * @param[in] bank bank identifier
+ * @return The header state.
+ *
+ * @notapi
+ */
+static mfs_bank_state_t mfs_bank_check_header(MFSDriver *mfsp) {
+ uint16_t crc;
+
+ if ((mfsp->buffer.bhdr.hdr32[0] == mfsp->config->erased) &&
+ (mfsp->buffer.bhdr.hdr32[1] == mfsp->config->erased) &&
+ (mfsp->buffer.bhdr.hdr32[2] == mfsp->config->erased) &&
+ (mfsp->buffer.bhdr.hdr32[3] == mfsp->config->erased)) {
+ return MFS_BANK_ERASED;
+ }
+
+ /* 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_BANK_GARBAGE;
+ }
+
+ /* 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_BANK_GARBAGE;
+ }
+
+ return MFS_BANK_OK;
+}
+
/**
* @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, it can be:
- * - MFS_BANK_PARTIAL
- * - MFS_BANK_OK
- * .
+ * @param[out] wflagp warning flag on anomalies
*
* @return The operation status.
*
@@ -429,75 +439,93 @@ static mfs_error_t mfs_bank_write_header(MFSDriver *mfsp,
*/
static mfs_error_t mfs_bank_scan_records(MFSDriver *mfsp,
mfs_bank_t bank,
- mfs_bank_state_t *statep) {
+ bool *wflagp) {
flash_offset_t hdr_offset, start_offset, end_offset;
- mfs_record_state_t sts;
- bool warning = false;
+ /* No warning by default.*/
+ *wflagp = false;
+
+ /* Boundaries.*/
start_offset = mfs_flash_get_bank_offset(mfsp, bank);
+ hdr_offset = start_offset + (flash_offset_t)ALIGNED_SIZEOF(mfs_bank_header_t);
end_offset = start_offset + mfsp->config->bank_size;
- /* Scanning records.*/
- hdr_offset = start_offset + (flash_offset_t)sizeof(mfs_bank_header_t);
- while (hdr_offset < end_offset) {
- uint32_t size;
+ /* Scanning records until there is there is not enough space left for an
+ header.*/
+ while (hdr_offset < end_offset - ALIGNED_DHDR_SIZE) {
+ union {
+ mfs_data_header_t dhdr;
+ uint8_t data8[ALIGNED_SIZEOF(mfs_data_header_t)];
+ } u;
+ uint16_t crc;
/* Reading the current record header.*/
RET_ON_ERROR(mfs_flash_read(mfsp, hdr_offset,
sizeof (mfs_data_header_t),
- (void *)&mfsp->buffer.dhdr));
+ u.data8));
- /* Checking header/data integrity.*/
- RET_ON_ERROR(mfs_record_check(mfsp, &mfsp->buffer.dhdr,
- hdr_offset, end_offset, &sts));
- if (sts == MFS_RECORD_ERASED) {
- /* Record area fully erased, stopping scan.*/
+ /* Checking if the found header is in erased state.*/
+ if ((u.dhdr.hdr32[0] == mfsp->config->erased) &&
+ (u.dhdr.hdr32[1] == mfsp->config->erased) &&
+ (u.dhdr.hdr32[2] == mfsp->config->erased)) {
break;
}
- else if (sts == MFS_RECORD_OK) {
- /* Record OK.*/
- size = mfsp->buffer.dhdr.fields.size;
- /* Zero-sized records are erase markers.*/
- if (size == 0U) {
- mfsp->descriptors[mfsp->buffer.dhdr.fields.id - 1U].offset = 0U;
- mfsp->descriptors[mfsp->buffer.dhdr.fields.id - 1U].size = 0U;
- }
- else {
- mfsp->descriptors[mfsp->buffer.dhdr.fields.id - 1U].offset = hdr_offset;
- mfsp->descriptors[mfsp->buffer.dhdr.fields.id - 1U].size = size;
+ /* It is not erased so checking for integrity.*/
+ if ((u.dhdr.fields.magic != MFS_HEADER_MAGIC) ||
+ (u.dhdr.fields.id < 1U) ||
+ (u.dhdr.fields.id > (uint32_t)MFS_CFG_MAX_RECORDS) ||
+ (u.dhdr.fields.size > end_offset - hdr_offset)) {
+ *wflagp = true;
+ break;
+ }
+
+ /* Finally checking the CRC, we need to perform it in chunks because
+ we have a limited buffer.*/
+ crc = 0xFFFFU;
+ if (u.dhdr.fields.size > 0U) {
+ flash_offset_t data = hdr_offset + sizeof (mfs_data_header_t);
+ uint32_t total = u.dhdr.fields.size;
+
+ while (total > 0U) {
+ uint32_t chunk = total > MFS_CFG_BUFFER_SIZE ? MFS_CFG_BUFFER_SIZE :
+ total;
+
+ /* Reading the data chunk.*/
+ RET_ON_ERROR(mfs_flash_read(mfsp, data, chunk, mfsp->buffer.data8));
+
+ /* CRC on the read data chunk.*/
+ crc = crc16(crc, &mfsp->buffer.data8[0], chunk);
+
+ /* Next chunk.*/
+ data += chunk;
+ total -= chunk;
}
}
- else if (sts == MFS_RECORD_CRC) {
- /* Record payload corrupted, scan can continue because the header
- is OK.*/
- size = mfsp->buffer.dhdr.fields.size;
- warning = true;
+ if (crc != u.dhdr.fields.crc) {
+ /* If the CRC is invalid then this record is ignored but scanning
+ continues because there could be more valid records afterward.*/
+ *wflagp = true;
}
else {
- /* Unrecognized header, scanning cannot continue.*/
- warning = true;
- break;
+ /* Zero-sized records are erase markers.*/
+ if (u.dhdr.fields.size == 0U) {
+ mfsp->descriptors[u.dhdr.fields.id - 1U].offset = 0U;
+ mfsp->descriptors[u.dhdr.fields.id - 1U].size = 0U;
+ }
+ else {
+ mfsp->descriptors[u.dhdr.fields.id - 1U].offset = hdr_offset;
+ mfsp->descriptors[u.dhdr.fields.id - 1U].size = u.dhdr.fields.size;
+ }
}
- hdr_offset = hdr_offset +
- (flash_offset_t)sizeof(mfs_data_header_t) +
- (flash_offset_t)size;
+
+ /* On the next header.*/
+ hdr_offset = hdr_offset + ALIGNED_REC_SIZE(u.dhdr.fields.size);
}
- if (hdr_offset > end_offset) {
- return MFS_ERR_INTERNAL;
- }
-
- /* Final.*/
+ /* Next writable offset.*/
mfsp->next_offset = hdr_offset;
- if (warning) {
- *statep = MFS_BANK_PARTIAL;
- }
- else {
- *statep = MFS_BANK_OK;
- }
-
return MFS_NO_ERROR;
}
@@ -521,89 +549,26 @@ static mfs_error_t mfs_bank_scan_records(MFSDriver *mfsp,
static mfs_error_t mfs_bank_get_state(MFSDriver *mfsp,
mfs_bank_t bank,
mfs_bank_state_t *statep,
- uint32_t * cntp) {
- unsigned i;
- mfs_error_t err;
- uint16_t crc;
-
- /* Worst case is default.*/
- *statep = MFS_BANK_GARBAGE;
- *cntp = 0U;
+ uint32_t *cntp) {
/* 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));
+ mfsp->buffer.data8));
- /* Checking the special case where the header is erased.*/
- for (i = 0; i < 4; i++) {
- if (mfsp->buffer.bhdr.hdr32[i] != mfsp->config->erased) {
+ /* Getting the counter regardless of the bank state, it is only valid if
+ the state is MFS_BANK_OK.*/
+ *cntp = mfsp->buffer.bhdr.fields.counter;
- /* 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;
- }
+ /* Checking just the header.*/
+ *statep = mfs_bank_check_header(mfsp);
+ if (*statep == MFS_BANK_ERASED) {
+ mfs_error_t err;
- /* 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;
- }
-
- *statep = MFS_BANK_OK;
- *cntp = mfsp->buffer.bhdr.fields.counter;
-
- return MFS_NO_ERROR;
- }
- }
-
- /* If the header is erased then it could be the whole block erased.*/
- err = mfs_bank_verify_erase(mfsp, bank);
- if (err == MFS_NO_ERROR) {
- *statep = MFS_BANK_ERASED;
- }
-
- return err;
-}
-
-/**
- * @brief Selects a bank as current.
- * @note The bank header is assumed to be valid.
- *
- * @param[in] mfsp pointer to the @p MFSDriver object
- * @param[in] bank bank to be scanned
- * @param[out] statep bank state, it can be:
- * - MFS_BANK_ERASED
- * - MFS_BANK_GARBAGE
- * - MFS_BANK_PARTIAL
- * - MFS_BANK_OK
- * .
- * @return The operation status.
- *
- * @notapi
- */
-static mfs_error_t mfs_bank_mount(MFSDriver *mfsp,
- mfs_bank_t bank,
- mfs_bank_state_t *statep) {
- unsigned i;
-
- /* Resetting the bank state, then reading the required header data.*/
- mfs_state_reset(mfsp);
- RET_ON_ERROR(mfs_bank_get_state(mfsp, bank, statep, &mfsp->current_counter));
- mfsp->current_bank = bank;
-
- /* Scanning for the most recent instance of all records.*/
- RET_ON_ERROR(mfs_bank_scan_records(mfsp, bank, statep));
-
- /* Calculating the effective used size.*/
- mfsp->used_space = sizeof (mfs_bank_header_t);
- 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);
+ /* Checking if the bank is really all erased.*/
+ err = mfs_bank_verify_erase(mfsp, bank);
+ if (err == MFS_ERR_NOT_ERASED) {
+ *statep = MFS_BANK_GARBAGE;
}
}
@@ -634,11 +599,11 @@ static mfs_error_t mfs_garbage_collect(MFSDriver *mfsp) {
/* Write address.*/
dest_offset = mfs_flash_get_bank_offset(mfsp, dbank) +
- sizeof (mfs_bank_header_t);
+ ALIGNED_SIZEOF(mfs_bank_header_t);
/* Copying the most recent record instances only.*/
for (i = 0; i < MFS_CFG_MAX_RECORDS; i++) {
- uint32_t totsize = mfsp->descriptors[i].size + sizeof (mfs_data_header_t);
+ uint32_t totsize = ALIGNED_REC_SIZE(mfsp->descriptors[i].size);
if (mfsp->descriptors[i].offset != 0) {
RET_ON_ERROR(mfs_flash_copy(mfsp, dest_offset,
mfsp->descriptors[i].offset,
@@ -671,10 +636,13 @@ static mfs_error_t mfs_garbage_collect(MFSDriver *mfsp) {
* @api
*/
static mfs_error_t mfs_try_mount(MFSDriver *mfsp) {
- mfs_bank_state_t sts, sts0, sts1;
+ mfs_bank_state_t sts0, sts1;
mfs_bank_t bank;
uint32_t cnt0 = 0, cnt1 = 0;
- bool warning = false;
+ bool w1 = false, w2 = false;
+
+ /* Resetting the bank state.*/
+ mfs_state_reset(mfsp);
/* Assessing the state of the two banks.*/
RET_ON_ERROR(mfs_bank_get_state(mfsp, MFS_BANK_0, &sts0, &cnt0));
@@ -703,7 +671,7 @@ static mfs_error_t mfs_try_mount(MFSDriver *mfsp) {
RET_ON_ERROR(mfs_bank_erase(mfsp, MFS_BANK_0));
bank = MFS_BANK_1;
}
- warning = true;
+ w1 = true;
break;
case PAIR(MFS_BANK_GARBAGE, MFS_BANK_GARBAGE):
@@ -712,7 +680,7 @@ static mfs_error_t mfs_try_mount(MFSDriver *mfsp) {
RET_ON_ERROR(mfs_bank_erase(mfsp, MFS_BANK_1));
RET_ON_ERROR(mfs_bank_write_header(mfsp, MFS_BANK_0, 1));
bank = MFS_BANK_0;
- warning = true;
+ w1 = true;
break;
case PAIR(MFS_BANK_ERASED, MFS_BANK_OK):
@@ -730,7 +698,7 @@ static mfs_error_t mfs_try_mount(MFSDriver *mfsp) {
RET_ON_ERROR(mfs_bank_erase(mfsp, MFS_BANK_1));
RET_ON_ERROR(mfs_bank_write_header(mfsp, MFS_BANK_0, 1));
bank = MFS_BANK_0;
- warning = true;
+ w1 = true;
break;
case PAIR(MFS_BANK_GARBAGE, MFS_BANK_ERASED):
@@ -738,21 +706,21 @@ static mfs_error_t mfs_try_mount(MFSDriver *mfsp) {
RET_ON_ERROR(mfs_bank_erase(mfsp, MFS_BANK_0));
RET_ON_ERROR(mfs_bank_write_header(mfsp, MFS_BANK_1, 1));
bank = MFS_BANK_1;
- warning = true;
+ w1 = true;
break;
case PAIR(MFS_BANK_OK, MFS_BANK_GARBAGE):
/* Bank zero is normal, bank one is unreadable.*/
RET_ON_ERROR(mfs_bank_erase(mfsp, MFS_BANK_1));
bank = MFS_BANK_0;
- warning = true;
+ w1 = true;
break;
case PAIR(MFS_BANK_GARBAGE, MFS_BANK_OK):
/* Bank zero is unreadable, bank one is normal.*/
RET_ON_ERROR(mfs_bank_erase(mfsp, MFS_BANK_0));
bank = MFS_BANK_1;
- warning = true;
+ w1 = true;
break;
default:
@@ -760,21 +728,42 @@ static mfs_error_t mfs_try_mount(MFSDriver *mfsp) {
}
/* Mounting the bank.*/
- RET_ON_ERROR(mfs_bank_mount(mfsp, bank, &sts));
+ {
+ unsigned i;
- /* This condition should not occur, the bank has just been repaired.*/
- if ((sts == MFS_BANK_ERASED) || (sts == MFS_BANK_GARBAGE)) {
- return MFS_ERR_INTERNAL;
+ /* Reading the bank header again.*/
+ RET_ON_ERROR(mfs_flash_read(mfsp, mfs_flash_get_bank_offset(mfsp, bank),
+ sizeof (mfs_bank_header_t),
+ mfsp->buffer.data8));
+
+ /* Checked again for extra safety.*/
+ if (mfs_bank_check_header(mfsp) != MFS_BANK_OK) {
+ return MFS_ERR_INTERNAL;
+ }
+
+ /* Storing the bank data.*/
+ 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, &w2));
+
+ /* Calculating the effective used size.*/
+ mfsp->used_space = ALIGNED_SIZEOF(mfs_bank_header_t);
+ for (i = 0; i < MFS_CFG_MAX_RECORDS; i++) {
+ if (mfsp->descriptors[i].offset != 0U) {
+ mfsp->used_space += ALIGNED_REC_SIZE(mfsp->descriptors[i].size);
+ }
+ }
}
/* In case of detected problems then a garbage collection is performed in
order to repair/remove anomalies.*/
- if (sts == MFS_BANK_PARTIAL) {
+ if (w2) {
RET_ON_ERROR(mfs_garbage_collect(mfsp));
- warning = true;
}
- return warning ? MFS_WARN_REPAIR : MFS_NO_ERROR;
+ return (w1 || w2) ? MFS_WARN_REPAIR : MFS_NO_ERROR;
}
/**
@@ -782,11 +771,14 @@ static mfs_error_t mfs_try_mount(MFSDriver *mfsp) {
*
* @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_GC if the operation triggered a garbage collection.
- * @retval MFS_ERR_FLASH_FAILURE if the flash memory is unusable because HW
- * failures. Makes the driver enter the @p MFS_ERROR state.
- * @retval MFS_ERR_INTERNAL if an internal logic failure is detected.
+ * @retval MFS_NO_ERROR if the operation has been successfully
+ * completed.
+ * @retval MFS_WARN_GC if the operation triggered a garbage
+ * collection.
+ * @retval MFS_ERR_FLASH_FAILURE if the flash memory is unusable because HW
+ * failures. Makes the driver enter the
+ * @p MFS_ERROR state.
+ * @retval MFS_ERR_INTERNAL if an internal logic failure is detected.
*
* @api
*/
@@ -843,11 +835,14 @@ void mfsObjectInit(MFSDriver *mfsp) {
* @param[in] mfsp pointer to the @p MFSDriver object
* @param[in] config pointer to the configuration
* @return The operation status.
- * @retval MFS_NO_ERROR if the operation has been successfully completed.
- * @retval MFS_WARN_GC if the operation triggered a garbage collection.
- * @retval MFS_ERR_FLASH_FAILURE if the flash memory is unusable because HW
- * failures. Makes the driver enter the @p MFS_ERROR state.
- * @retval MFS_ERR_INTERNAL if an internal logic failure is detected.
+ * @retval MFS_NO_ERROR if the operation has been
+ * completed.
+ * @retval MFS_WARN_GC if the operation triggered a garbage
+ * collection.
+ * @retval MFS_ERR_FLASH_FAILURE if the flash memory is unusable because HW
+ * failures. Makes the driver enter the
+ * @p MFS_ERROR state.
+ * @retval MFS_ERR_INTERNAL if an internal logic failure is detected.
*
* @api
*/
@@ -885,11 +880,14 @@ void mfsStop(MFSDriver *mfsp) {
*
* @param[in] mfsp pointer to the @p MFSDriver object
* @return The operation status.
- * @retval MFS_ERR_INV_STATE if the driver is in not in @p MSG_READY state.
- * @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. Makes the driver enter the @p MFS_ERROR state.
- * @retval MFS_ERR_INTERNAL if an internal logic failure is detected.
+ * @retval MFS_ERR_INV_STATE if the driver is in not in @p MFS_READY
+ * state.
+ * @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. Makes the driver enter the
+ * @p MFS_ERROR state.
+ * @retval MFS_ERR_INTERNAL if an internal logic failure is detected.
*
* @api
*/
@@ -917,14 +915,17 @@ mfs_error_t mfsErase(MFSDriver *mfsp) {
* the size of the data copied into the buffer
* @param[out] buffer pointer to a buffer for record data
* @return The operation status.
- * @retval MFS_NO_ERROR if the operation has been successfully completed.
- * @retval MFS_ERR_INV_STATE if the driver is in not in @p MSG_READY state.
- * @retval MFS_ERR_INV_SIZE if the passed buffer is not large enough to
- * contain the record data.
- * @retval MFS_ERR_NOT_FOUND if the specified id does not exists.
- * @retval MFS_ERR_FLASH_FAILURE if the flash memory is unusable because HW
- * failures. Makes the driver enter the @p MFS_ERROR state.
- * @retval MFS_ERR_INTERNAL if an internal logic failure is detected.
+ * @retval MFS_NO_ERROR if the operation has been successfully
+ * completed.
+ * @retval MFS_ERR_INV_STATE if the driver is in not in @p MFS_READY
+ * state.
+ * @retval MFS_ERR_INV_SIZE if the passed buffer is not large enough to
+ * contain the record data.
+ * @retval MFS_ERR_NOT_FOUND if the specified id does not exists.
+ * @retval MFS_ERR_FLASH_FAILURE if the flash memory is unusable because HW
+ * failures. Makes the driver enter the
+ * @p MFS_ERROR state.
+ * @retval MFS_ERR_INTERNAL if an internal logic failure is detected.
*
* @api
*/
@@ -934,9 +935,9 @@ mfs_error_t mfsReadRecord(MFSDriver *mfsp, mfs_id_t id,
osalDbgCheck((mfsp != NULL) &&
(id >= 1U) && (id <= (mfs_id_t)MFS_CFG_MAX_RECORDS) &&
- (np != NULL) && (buffer != NULL));
+ (np != NULL) && (*np > 0U) && (buffer != NULL));
- if (mfsp->state != MFS_READY) {
+ if ((mfsp->state != MFS_READY) && (mfsp->state != MFS_TRANSACTION)) {
return MFS_ERR_INV_STATE;
}
@@ -982,87 +983,147 @@ mfs_error_t mfsReadRecord(MFSDriver *mfsp, mfs_id_t id,
* @param[in] n size of data to be written, it cannot be zero
* @param[in] buffer pointer to a buffer for record data
* @return The operation status.
- * @retval MFS_NO_ERROR if the operation has been successfully completed.
- * @retval MFS_WARN_GC if the operation triggered a garbage collection.
- * @retval MFS_ERR_INV_STATE if the driver is in not in @p MSG_READY state.
- * @retval MFS_ERR_OUT_OF_MEM if there is not enough flash space for the
- * operation.
- * @retval MFS_ERR_FLASH_FAILURE if the flash memory is unusable because HW
- * failures. Makes the driver enter the @p MFS_ERROR state.
- * @retval MFS_ERR_INTERNAL if an internal logic failure is detected.
+ * @retval MFS_NO_ERROR if the operation has been successfully
+ * completed.
+ * @retval MFS_WARN_GC if the operation triggered a garbage
+ * collection.
+ * @retval MFS_ERR_INV_STATE if the driver is in not in @p MFS_READY
+ * state.
+ * @retval MFS_ERR_OUT_OF_MEM if there is not enough flash space for the
+ * operation.
+ * @retval MFS_ERR_TRANSACTION_NUM if the transaction operations buffer space
+ * has been exceeded.
+ * @retval MFS_ERR_TRANSACTION_SIZE if the transaction allocated space
+ * has been exceeded.
+ * @retval MFS_ERR_FLASH_FAILURE if the flash memory is unusable because HW
+ * failures. Makes the driver enter the
+ * @p MFS_ERROR state.
+ * @retval MFS_ERR_INTERNAL if an internal logic failure is detected.
*
* @api
*/
mfs_error_t mfsWriteRecord(MFSDriver *mfsp, mfs_id_t id,
size_t n, const uint8_t *buffer) {
- flash_offset_t free, required;
- bool warning = false;
+ flash_offset_t free, asize, rspace;
osalDbgCheck((mfsp != NULL) &&
(id >= 1U) && (id <= (mfs_id_t)MFS_CFG_MAX_RECORDS) &&
(n > 0U) && (buffer != NULL));
- if (mfsp->state != MFS_READY) {
- return MFS_ERR_INV_STATE;
+ /* Aligned record size.*/
+ asize = ALIGNED_REC_SIZE(n);
+
+ /* Normal mode code path.*/
+ if (mfsp->state == MFS_READY) {
+ bool warning = false;
+
+ /* If the required space is beyond the available (compacted) block
+ size then an error is returned.
+ NOTE: The space for one extra header is reserved in order to allow
+ for an erase operation after the space has been fully allocated.*/
+ rspace = ALIGNED_DHDR_SIZE + asize;
+ if (rspace > mfsp->config->bank_size - mfsp->used_space) {
+ return MFS_ERR_OUT_OF_MEM;
+ }
+
+ /* Checking for immediately (not compacted) available space.*/
+ free = (mfs_flash_get_bank_offset(mfsp, mfsp->current_bank) +
+ mfsp->config->bank_size) - mfsp->next_offset;
+ if (rspace > free) {
+ /* We need to perform a garbage collection, there is enough space
+ but it has to be freed.*/
+ warning = true;
+ RET_ON_ERROR(mfs_garbage_collect(mfsp));
+ }
+
+ /* Writing the data header without the magic, it will be written last.*/
+ mfsp->buffer.dhdr.fields.magic = (uint32_t)mfsp->config->erased;
+ mfsp->buffer.dhdr.fields.id = (uint16_t)id;
+ mfsp->buffer.dhdr.fields.size = (uint32_t)n;
+ mfsp->buffer.dhdr.fields.crc = crc16(0xFFFFU, buffer, n);
+ RET_ON_ERROR(mfs_flash_write(mfsp,
+ mfsp->next_offset,
+ sizeof (mfs_data_header_t),
+ mfsp->buffer.data8));
+
+ /* Writing the data part.*/
+ RET_ON_ERROR(mfs_flash_write(mfsp,
+ mfsp->next_offset + sizeof (mfs_data_header_t),
+ n,
+ buffer));
+
+ /* Finally writing the magic number, it seals the operation.*/
+ mfsp->buffer.dhdr.fields.magic = (uint32_t)MFS_HEADER_MAGIC;
+ RET_ON_ERROR(mfs_flash_write(mfsp,
+ mfsp->next_offset,
+ sizeof (uint32_t),
+ mfsp->buffer.data8));
+
+ /* The size of the old record instance, if present, must be subtracted
+ to the total used size.*/
+ if (mfsp->descriptors[id - 1U].offset != 0U) {
+ mfsp->used_space -= ALIGNED_REC_SIZE(mfsp->descriptors[id - 1U].size);
+ }
+
+ /* Adjusting bank-related metadata.*/
+ mfsp->descriptors[id - 1U].offset = mfsp->next_offset;
+ mfsp->descriptors[id - 1U].size = (uint32_t)n;
+ mfsp->next_offset += asize;
+ mfsp->used_space += asize;
+
+ return warning ? MFS_WARN_GC : MFS_NO_ERROR;
}
- /* If the required space is beyond the available (compacted) block
- size then an error is returned.
- NOTE: The space for one extra header is reserved in order to allow
- for an erase operation after the space has been fully allocated.*/
- required = ((flash_offset_t)sizeof (mfs_data_header_t) * 2U) +
- (flash_offset_t)n;
- if (required > mfsp->config->bank_size - mfsp->used_space) {
- return MFS_ERR_OUT_OF_MEM;
+#if MFS_CFG_TRANSACTION_MAX > 0
+ /* Transaction mode code path.*/
+ if (mfsp->state == MFS_TRANSACTION) {
+ mfs_transaction_op_t *top;
+
+ /* Checking if the maximum number of operations in a transaction is
+ Exceeded.*/
+ if (mfsp->tr_nops >= MFS_CFG_TRANSACTION_MAX) {
+ return MFS_ERR_TRANSACTION_NUM;
+ }
+
+ /* If the required space is greater than the space allocated for the
+ transaction then error.*/
+ rspace = asize;
+ if (rspace > mfsp->tr_limit_offet - mfsp->tr_next_offset) {
+ return MFS_ERR_TRANSACTION_SIZE;
+ }
+
+ /* Writing the data header without the magic, it will be written last.*/
+ mfsp->buffer.dhdr.fields.magic = (uint32_t)mfsp->config->erased;
+ mfsp->buffer.dhdr.fields.id = (uint16_t)id;
+ mfsp->buffer.dhdr.fields.size = (uint32_t)n;
+ mfsp->buffer.dhdr.fields.crc = crc16(0xFFFFU, buffer, n);
+ RET_ON_ERROR(mfs_flash_write(mfsp,
+ mfsp->tr_next_offset,
+ sizeof (mfs_data_header_t),
+ mfsp->buffer.data8));
+
+ /* Writing the data part.*/
+ RET_ON_ERROR(mfs_flash_write(mfsp,
+ mfsp->tr_next_offset + sizeof (mfs_data_header_t),
+ n,
+ buffer));
+
+ /* Adding a transaction operation record.*/
+ top = &mfsp->tr_ops[mfsp->tr_nops];
+ top->offset = mfsp->tr_next_offset;
+ top->size = n;
+ top->id = id;
+
+ /* Number of records and next write position updated.*/
+ mfsp->tr_nops++;
+ mfsp->tr_next_offset += asize;
+
+ return MFS_NO_ERROR;
}
+#endif /* MFS_CFG_TRANSACTION_MAX > 0 */
- /* Checking for immediately (not compacted) available space.*/
- free = (mfs_flash_get_bank_offset(mfsp, mfsp->current_bank) +
- mfsp->config->bank_size) - mfsp->next_offset;
- if (required > free) {
- /* We need to perform a garbage collection, there is enough space
- but it has to be freed.*/
- warning = true;
- RET_ON_ERROR(mfs_garbage_collect(mfsp));
- }
-
- /* Writing the data header without the magic, it will be written last.*/
- mfsp->buffer.dhdr.fields.magic = (uint32_t)mfsp->config->erased;
- mfsp->buffer.dhdr.fields.id = (uint16_t)id;
- mfsp->buffer.dhdr.fields.size = (uint32_t)n;
- mfsp->buffer.dhdr.fields.crc = crc16(0xFFFFU, buffer, n);
- RET_ON_ERROR(mfs_flash_write(mfsp,
- mfsp->next_offset,
- sizeof (mfs_data_header_t),
- mfsp->buffer.data8));
-
- /* Writing the data part.*/
- RET_ON_ERROR(mfs_flash_write(mfsp,
- mfsp->next_offset + sizeof (mfs_data_header_t),
- n,
- buffer));
-
- /* Finally writing the magic number, it seals the transaction.*/
- mfsp->buffer.dhdr.fields.magic = (uint32_t)MFS_HEADER_MAGIC;
- RET_ON_ERROR(mfs_flash_write(mfsp,
- mfsp->next_offset,
- sizeof (uint32_t),
- mfsp->buffer.data8));
-
- /* The size of the old record instance, if present, must be subtracted
- to the total used size.*/
- if (mfsp->descriptors[id - 1U].offset != 0U) {
- mfsp->used_space -= sizeof (mfs_data_header_t) +
- mfsp->descriptors[id - 1U].size;
- }
-
- /* Adjusting bank-related metadata.*/
- mfsp->descriptors[id - 1U].offset = mfsp->next_offset;
- mfsp->descriptors[id - 1U].size = (uint32_t)n;
- mfsp->next_offset += sizeof (mfs_data_header_t) + n;
- mfsp->used_space += sizeof (mfs_data_header_t) + n;
-
- return warning ? MFS_WARN_GC : MFS_NO_ERROR;
+ /* Invalid state.*/
+ return MFS_ERR_INV_STATE;
}
/**
@@ -1072,67 +1133,129 @@ mfs_error_t mfsWriteRecord(MFSDriver *mfsp, mfs_id_t id,
* @param[in] id record numeric identifier, the valid range is between
* @p 1 and @p MFS_CFG_MAX_RECORDS
* @return The operation status.
- * @retval MFS_NO_ERROR if the operation has been successfully completed.
- * @retval MFS_WARN_GC if the operation triggered a garbage collection.
- * @retval MFS_ERR_INV_STATE if the driver is in not in @p MSG_READY state.
- * @retval MFS_ERR_FLASH_FAILURE if the flash memory is unusable because HW
- * failures. Makes the driver enter the @p MFS_ERROR state.
- * @retval MFS_ERR_INTERNAL if an internal logic failure is detected.
+ * @retval MFS_NO_ERROR if the operation has been successfully
+ * completed.
+ * @retval MFS_WARN_GC if the operation triggered a garbage
+ * collection.
+ * @retval MFS_ERR_INV_STATE if the driver is in not in @p MFS_READY
+ * state.
+ * @retval MFS_ERR_OUT_OF_MEM if there is not enough flash space for the
+ * operation.
+ * @retval MFS_ERR_TRANSACTION_NUM if the transaction operations buffer space
+ * has been exceeded.
+ * @retval MFS_ERR_TRANSACTION_SIZE if the transaction allocated space
+ * has been exceeded.
+ * @retval MFS_ERR_FLASH_FAILURE if the flash memory is unusable because HW
+ * failures. Makes the driver enter the
+ * @p MFS_ERROR state.
+ * @retval MFS_ERR_INTERNAL if an internal logic failure is detected.
*
* @api
*/
mfs_error_t mfsEraseRecord(MFSDriver *mfsp, mfs_id_t id) {
- flash_offset_t free, required;
- bool warning = false;
+ flash_offset_t free, asize, rspace;
osalDbgCheck((mfsp != NULL) &&
(id >= 1U) && (id <= (mfs_id_t)MFS_CFG_MAX_RECORDS));
- if (mfsp->state != MFS_READY) {
- return MFS_ERR_INV_STATE;
+ /* Aligned record size.*/
+ asize = ALIGNED_DHDR_SIZE;
+
+ /* Normal mode code path.*/
+ if (mfsp->state == MFS_READY) {
+ bool warning = false;
+
+ /* Checking if the requested record actually exists.*/
+ if (mfsp->descriptors[id - 1U].offset == 0U) {
+ return MFS_ERR_NOT_FOUND;
+ }
+
+ /* If the required space is beyond the available (compacted) block
+ size then an internal error is returned, it should never happen.*/
+ rspace = asize;
+ if (rspace > mfsp->config->bank_size - mfsp->used_space) {
+ return MFS_ERR_INTERNAL;
+ }
+
+ /* Checking for immediately (not compacted) available space.*/
+ free = (mfs_flash_get_bank_offset(mfsp, mfsp->current_bank) +
+ mfsp->config->bank_size) - mfsp->next_offset;
+ if (rspace > free) {
+ /* We need to perform a garbage collection, there is enough space
+ but it has to be freed.*/
+ warning = true;
+ RET_ON_ERROR(mfs_garbage_collect(mfsp));
+ }
+
+ /* Writing the data header with size set to zero, it means that the
+ record is logically erased.*/
+ mfsp->buffer.dhdr.fields.magic = (uint32_t)MFS_HEADER_MAGIC;
+ mfsp->buffer.dhdr.fields.id = (uint16_t)id;
+ mfsp->buffer.dhdr.fields.size = (uint32_t)0;
+ mfsp->buffer.dhdr.fields.crc = (uint16_t)0xFFFF;
+ RET_ON_ERROR(mfs_flash_write(mfsp,
+ mfsp->next_offset,
+ sizeof (mfs_data_header_t),
+ mfsp->buffer.data8));
+
+ /* Adjusting bank-related metadata.*/
+ mfsp->used_space -= ALIGNED_REC_SIZE(mfsp->descriptors[id - 1U].size);
+ mfsp->next_offset += sizeof (mfs_data_header_t);
+ mfsp->descriptors[id - 1U].offset = 0U;
+ mfsp->descriptors[id - 1U].size = 0U;
+
+ return warning ? MFS_WARN_GC : MFS_NO_ERROR;
}
- /* Checking if the requested record actually exists.*/
- if (mfsp->descriptors[id - 1U].offset == 0U) {
- return MFS_ERR_NOT_FOUND;
+#if MFS_CFG_TRANSACTION_MAX > 0
+ /* Transaction mode code path.*/
+ if (mfsp->state == MFS_TRANSACTION) {
+ mfs_transaction_op_t *top;
+
+ /* Checking if the requested record actually exists.*/
+ if (mfsp->descriptors[id - 1U].offset == 0U) {
+ return MFS_ERR_NOT_FOUND;
+ }
+
+ /* Checking if the maximum number of operations in a transaction is
+ Exceeded.*/
+ if (mfsp->tr_nops >= MFS_CFG_TRANSACTION_MAX) {
+ return MFS_ERR_TRANSACTION_NUM;
+ }
+
+ /* If the required space is greater than the space allocated for the
+ transaction then error.*/
+ rspace = asize;
+ if (rspace > mfsp->tr_limit_offet - mfsp->tr_next_offset) {
+ return MFS_ERR_TRANSACTION_SIZE;
+ }
+
+ /* Writing the data header with size set to zero, it means that the
+ record is logically erased. Note, the magic number is not set.*/
+ mfsp->buffer.dhdr.fields.magic = mfsp->config->erased;
+ mfsp->buffer.dhdr.fields.id = (uint16_t)id;
+ mfsp->buffer.dhdr.fields.size = (uint32_t)0;
+ mfsp->buffer.dhdr.fields.crc = (uint16_t)0xFFFF;
+ RET_ON_ERROR(mfs_flash_write(mfsp,
+ mfsp->next_offset,
+ sizeof (mfs_data_header_t),
+ mfsp->buffer.data8));
+
+ /* Adding a transaction operation record.*/
+ top = &mfsp->tr_ops[mfsp->tr_nops];
+ top->offset = mfsp->tr_next_offset;
+ top->size = 0U;
+ top->id = id;
+
+ /* Number of records and next write position updated.*/
+ mfsp->tr_nops++;
+ mfsp->tr_next_offset += asize;
+
+ return MFS_NO_ERROR;
}
+#endif /* MFS_CFG_TRANSACTION_MAX > 0 */
- /* If the required space is beyond the available (compacted) block
- size then an internal error is returned, it should never happen.*/
- required = (flash_offset_t)sizeof (mfs_data_header_t);
- if (required > mfsp->config->bank_size - mfsp->used_space) {
- return MFS_ERR_INTERNAL;
- }
-
- /* Checking for immediately (not compacted) available space.*/
- free = (mfs_flash_get_bank_offset(mfsp, mfsp->current_bank) +
- mfsp->config->bank_size) - mfsp->next_offset;
- if (required > free) {
- /* We need to perform a garbage collection, there is enough space
- but it has to be freed.*/
- warning = true;
- RET_ON_ERROR(mfs_garbage_collect(mfsp));
- }
-
- /* Writing the data header with size set to zero, it means that the
- record is logically erased.*/
- mfsp->buffer.dhdr.fields.magic = (uint32_t)MFS_HEADER_MAGIC;
- mfsp->buffer.dhdr.fields.id = (uint16_t)id;
- mfsp->buffer.dhdr.fields.size = (uint32_t)0;
- mfsp->buffer.dhdr.fields.crc = (uint16_t)0;
- RET_ON_ERROR(mfs_flash_write(mfsp,
- mfsp->next_offset,
- sizeof (mfs_data_header_t),
- mfsp->buffer.data8));
-
- /* Adjusting bank-related metadata.*/
- mfsp->used_space -= sizeof (mfs_data_header_t) +
- mfsp->descriptors[id - 1U].size;
- mfsp->next_offset += sizeof (mfs_data_header_t);
- mfsp->descriptors[id - 1U].offset = 0U;
- mfsp->descriptors[id - 1U].size = 0U;
-
- return warning ? MFS_WARN_GC : MFS_NO_ERROR;
+ return MFS_ERR_INV_STATE;
}
/**
@@ -1142,11 +1265,14 @@ mfs_error_t mfsEraseRecord(MFSDriver *mfsp, mfs_id_t id) {
*
* @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_ERR_INV_STATE if the driver is in not in @p MSG_READY state.
- * @retval MFS_ERR_FLASH_FAILURE if the flash memory is unusable because HW
- * failures. Makes the driver enter the @p MFS_ERROR state.
- * @retval MFS_ERR_INTERNAL if an internal logic failure is detected.
+ * @retval MFS_NO_ERROR if the operation has been successfully
+ * completed.
+ * @retval MFS_ERR_INV_STATE if the driver is in not in @p MFS_READY
+ * state.
+ * @retval MFS_ERR_FLASH_FAILURE if the flash memory is unusable because HW
+ * failures. Makes the driver enter the
+ * @p MFS_ERROR state.
+ * @retval MFS_ERR_INTERNAL if an internal logic failure is detected.
*
* @api
*/
@@ -1161,4 +1287,196 @@ mfs_error_t mfsPerformGarbageCollection(MFSDriver *mfsp) {
return mfs_garbage_collect(mfsp);
}
+#if (MFS_CFG_TRANSACTION_MAX > 0) || defined(__DOXYGEN__)
+/**
+ * @brief Puts the driver in transaction mode.
+ * @note The parameters @p n and @p size are used to make an
+ * estimation of the space required for the transaction to succeed.
+ * Note that the estimated size must include also the extra space
+ * required by alignment enforcement option. If the estimated size
+ * is wrong (by defect) what could happen is that there is a failure
+ * in the middle of a transaction and a roll-back would be required.
+ * @note The conditions for starting a transaction are:
+ * - The driver must be started.
+ * - There must be enough compacted storage to accommodate the whole
+ * transaction. If the required space is available but it is not
+ * compacted then a garbage collect operation is performed.
+ * .
+ *
+ * @param[in] mfsp pointer to the @p MFSDriver object
+ * @param[in] size estimated total size of written records in transaction,
+ * this includes, data, headers and alignment gaps
+ * @return The operation status.
+ * @retval MFS_NO_ERROR if the operation has been successfully
+ * completed.
+ * @retval MFS_ERR_INV_STATE if the driver is in not in @p MFS_READY
+ * state.
+ * @retval MFS_ERR_FLASH_FAILURE if the flash memory is unusable because HW
+ * failures. Makes the driver enter the
+ * @p MFS_ERROR state.
+ * @retval MFS_ERR_INTERNAL if an internal logic failure is detected.
+ *
+ * @api
+ */
+mfs_error_t mfsStartTransaction(MFSDriver *mfsp, size_t size) {
+ flash_offset_t free, tspace, rspace;
+
+ osalDbgCheck((mfsp != NULL) && (size > ALIGNED_DHDR_SIZE));
+
+ /* The driver must be in ready mode.*/
+ if (mfsp->state != MFS_READY) {
+ return MFS_ERR_INV_STATE;
+ }
+
+ /* Estimating the required contiguous compacted space.*/
+ tspace = (flash_offset_t)MFS_ALIGN_NEXT(size);
+ rspace = tspace + ALIGNED_DHDR_SIZE;
+
+ /* If the required space is beyond the available (compacted) block
+ size then an error is returned.*/
+ if (rspace > mfsp->config->bank_size - mfsp->used_space) {
+ return MFS_ERR_OUT_OF_MEM;
+ }
+
+ /* Checking for immediately (not compacted) available space.*/
+ free = (mfs_flash_get_bank_offset(mfsp, mfsp->current_bank) +
+ mfsp->config->bank_size) - mfsp->next_offset;
+ if (rspace > free) {
+ /* We need to perform a garbage collection, there is enough space
+ but it has to be freed.*/
+ RET_ON_ERROR(mfs_garbage_collect(mfsp));
+ }
+
+ /* Entering transaction mode.*/
+ mfsp->state = MFS_TRANSACTION;
+
+ /* Initializing transaction state.*/
+ mfsp->tr_next_offset = mfsp->next_offset;
+ mfsp->tr_nops = 0U;
+ mfsp->tr_limit_offet = mfsp->tr_next_offset + tspace;
+
+ return MFS_NO_ERROR;
+}
+
+/**
+ * @brief A transaction is committed and finalized atomically.
+ *
+ * @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_ERR_INV_STATE if the driver is in not in @p MFS_TRANSACTION
+ * state.
+ * @retval MFS_ERR_FLASH_FAILURE if the flash memory is unusable because HW
+ * failures. Makes the driver enter the
+ * @p MFS_ERROR state.
+ * @retval MFS_ERR_INTERNAL if an internal logic failure is detected.
+ *
+ * @api
+ */
+mfs_error_t mfsCommitTransaction(MFSDriver *mfsp) {
+ mfs_transaction_op_t *top;
+
+ osalDbgCheck(mfsp != NULL);
+
+ /* The driver must be in transaction mode.*/
+ if (mfsp->state != MFS_TRANSACTION) {
+ return MFS_ERR_INV_STATE;
+ }
+
+ /* Scanning all buffered operations in reverse order.*/
+ mfsp->buffer.dhdr.fields.magic = (uint32_t)MFS_HEADER_MAGIC;
+ top = &mfsp->tr_ops[mfsp->tr_nops];
+ while (top > &mfsp->tr_ops[0]) {
+ /* On the previous element.*/
+ top--;
+
+ /* Finalizing the operation by writing the magic number.*/
+ RET_ON_ERROR(mfs_flash_write(mfsp,
+ top->offset,
+ sizeof (uint32_t),
+ mfsp->buffer.data8));
+ }
+
+ /* Transaction fully committed by writing the last (first in transaction)
+ magic number, now updating the internal state using the buffered data.*/
+ mfsp->next_offset = mfsp->tr_next_offset;
+ while (top < &mfsp->tr_ops[mfsp->tr_nops]) {
+ unsigned i = (unsigned)top->id - 1U;
+
+ /* The calculation is a bit different depending on write or erase record
+ operations.*/
+ if (top->size > 0U) {
+ /* It is a write.*/
+ if (mfsp->descriptors[i].offset != 0U) {
+ /* The size of the old record instance, if present, must be subtracted
+ to the total used size.*/
+ mfsp->used_space -= ALIGNED_REC_SIZE(mfsp->descriptors[i].size);
+ }
+
+ /* Adjusting bank-related metadata.*/
+ mfsp->used_space += ALIGNED_REC_SIZE(top->size);
+ mfsp->descriptors[i].offset = top->offset;
+ mfsp->descriptors[i].size = top->size;
+ }
+ else {
+ /* It is an erase.*/
+ mfsp->used_space -= ALIGNED_REC_SIZE(mfsp->descriptors[i].size);
+ mfsp->descriptors[i].offset = 0U;
+ mfsp->descriptors[i].size = 0U;
+ }
+
+ /* On the next element.*/
+ top++;
+ }
+
+ /* Returning to ready mode.*/
+ mfsp->state = MFS_READY;
+
+ return MFS_NO_ERROR;
+}
+
+/**
+ * @brief A transaction is rolled back atomically.
+ * @details This function performs a garbage collection in order to discard
+ * all written data that has not been finalized.
+ *
+ * @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_ERR_INV_STATE if the driver is in not in @p MFS_TRANSACTION
+ * state.
+ * @retval MFS_ERR_FLASH_FAILURE if the flash memory is unusable because HW
+ * failures. Makes the driver enter the
+ * @p MFS_ERROR state.
+ * @retval MFS_ERR_INTERNAL if an internal logic failure is detected.
+ *
+ * @api
+ */
+mfs_error_t mfsRollbackTransaction(MFSDriver *mfsp) {
+ mfs_error_t err;
+
+ osalDbgCheck(mfsp != NULL);
+
+ if (mfsp->state != MFS_TRANSACTION) {
+ return MFS_ERR_INV_STATE;
+ }
+
+ /* Returning to ready mode.*/
+ mfsp->state = MFS_READY;
+
+ /* If no operations have been performed then there is no need to perform
+ a garbage collection.*/
+ if (mfsp->tr_nops > 0U) {
+ err = mfs_garbage_collect(mfsp);
+ }
+ else {
+ err = MFS_NO_ERROR;
+ }
+
+ return err;
+}
+#endif /* MFS_CFG_TRANSACTION_MAX > 0 */
+
/** @} */
diff --git a/os/hal/lib/complex/mfs/hal_mfs.h b/os/hal/lib/complex/mfs/hal_mfs.h
index 56ff0b966..14dfc75ee 100644
--- a/os/hal/lib/complex/mfs/hal_mfs.h
+++ b/os/hal/lib/complex/mfs/hal_mfs.h
@@ -48,7 +48,7 @@
*/
/**
* @brief Maximum number of indexed records in the managed storage.
- * @note Record indexes go from 0 to @p MFS_CFG_MAX_RECORDS - 1.
+ * @note Record indexes go from 1 to @p MFS_CFG_MAX_RECORDS.
*/
#if !defined(MFS_CFG_MAX_RECORDS) || defined(__DOXYGEN__)
#define MFS_CFG_MAX_RECORDS 32
@@ -95,15 +95,16 @@
* for records in the flash array. This is required when alignment
* constraints exist, for example when using a DTR mode on OSPI
* devices.
- * @note When enforcing an alignment you need to use buffers with size
- * aligned to the specified value. For example, if you need to
- * write a 5 bytes object with alignment of 4 then you need to
- * use a 8 bytes data buffer, the last 3 bytes are used as filler
- * so ==initialize== those to zero (buffer->DDDDD000) or garbage
- * will be written after data.
*/
#if !defined(MFS_CFG_MEMORY_ALIGNMENT) || defined(__DOXYGEN__)
-#define MFS_CFG_MEMORY_ALIGNMENT 1
+#define MFS_CFG_MEMORY_ALIGNMENT 2
+#endif
+
+/**
+ * @brief Maximum number of objects writable in a single transaction.
+ */
+#if !defined(MFS_CFG_TRANSACTION_MAX) || defined(__DOXYGEN__)
+#define MFS_CFG_TRANSACTION_MAX 16
#endif
/** @} */
@@ -115,7 +116,8 @@
#error "invalid MFS_CFG_MAX_RECORDS value"
#endif
-#if (MFS_CFG_MAX_REPAIR_ATTEMPTS < 1) || (MFS_CFG_MAX_REPAIR_ATTEMPTS > 10)
+#if (MFS_CFG_MAX_REPAIR_ATTEMPTS < 1) || \
+ (MFS_CFG_MAX_REPAIR_ATTEMPTS > 10)
#error "invalid MFS_MAX_REPAIR_ATTEMPTS value"
#endif
@@ -127,7 +129,8 @@
#error "MFS_CFG_BUFFER_SIZE is not a power of two"
#endif
-#if MFS_CFG_MEMORY_ALIGNMENT < 1
+#if (MFS_CFG_MEMORY_ALIGNMENT < 1) || \
+ (MFS_CFG_MEMORY_ALIGNMENT > MFS_CFG_BUFFER_SIZE)
#error "invalid MFS_CFG_MEMORY_ALIGNMENT value"
#endif
@@ -135,6 +138,11 @@
#error "MFS_CFG_MEMORY_ALIGNMENT is not a power of two"
#endif
+#if (MFS_CFG_TRANSACTION_MAX < 0) || \
+ (MFS_CFG_TRANSACTION_MAX > MFS_CFG_MAX_RECORDS)
+#error "invalid MFS_CFG_TRANSACTION_MAX value"
+#endif
+
/*===========================================================================*/
/* Driver data structures and types. */
/*===========================================================================*/
@@ -154,7 +162,8 @@ typedef enum {
MFS_UNINIT = 0,
MFS_STOP = 1,
MFS_READY = 2,
- MFS_ERROR = 3
+ MFS_TRANSACTION = 3,
+ MFS_ERROR = 4
} mfs_state_t;
/**
@@ -170,9 +179,11 @@ typedef enum {
MFS_ERR_INV_SIZE = -2,
MFS_ERR_NOT_FOUND = -3,
MFS_ERR_OUT_OF_MEM = -4,
- MFS_ERR_NOT_ERASED = -5,
- MFS_ERR_FLASH_FAILURE = -6,
- MFS_ERR_INTERNAL = -7
+ MFS_ERR_TRANSACTION_NUM = -5,
+ MFS_ERR_TRANSACTION_SIZE = -6,
+ MFS_ERR_NOT_ERASED = -7,
+ MFS_ERR_FLASH_FAILURE = -8,
+ MFS_ERR_INTERNAL = -9
} mfs_error_t;
/**
@@ -181,20 +192,9 @@ typedef enum {
typedef enum {
MFS_BANK_ERASED = 0,
MFS_BANK_OK = 1,
- MFS_BANK_PARTIAL = 2,
- MFS_BANK_GARBAGE = 3
+ MFS_BANK_GARBAGE = 2
} 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 record identifier.
*/
@@ -244,7 +244,7 @@ typedef union {
*/
uint32_t magic;
/**
- * @brief Data identifier.
+ * @brief Record identifier.
*/
uint16_t id;
/**
@@ -311,8 +311,24 @@ typedef struct {
} MFSConfig;
/**
- * @extends BaseFlash
- *
+ * @brief Type of a buffered write/erase operation within a transaction.
+ */
+typedef struct {
+ /**
+ * @brief Written header offset.
+ */
+ flash_offset_t offset;
+ /**
+ * @brief Written data size.
+ */
+ size_t size;
+ /**
+ * @brief Record identifier.
+ */
+ mfs_id_t id;
+} mfs_transaction_op_t;
+
+/**
* @brief Type of an MFS instance.
*/
typedef struct {
@@ -345,6 +361,24 @@ typedef struct {
* @note Zero means that there is not a record with that id.
*/
mfs_record_descriptor_t descriptors[MFS_CFG_MAX_RECORDS];
+#if (MFS_CFG_TRANSACTION_MAX > 0) || defined(__DOXYGEN__)
+ /**
+ * @brief Next write offset for current transaction.
+ */
+ flash_offset_t tr_next_offset;
+ /**
+ * @brief Maximum offset for the transaction.
+ */
+ flash_offset_t tr_limit_offet;
+ /**
+ * @brief Number of buffered operations in current transaction.
+ */
+ uint32_t tr_nops;
+ /**
+ * @brief Buffered operations in current transaction.
+ */
+ mfs_transaction_op_t tr_ops[MFS_CFG_TRANSACTION_MAX];
+#endif
/**
* @brief Transient buffer.
*/
@@ -376,7 +410,8 @@ typedef struct {
#define MFS_ALIGN_MASK ((uint32_t)MFS_CFG_MEMORY_ALIGNMENT - 1U)
#define MFS_IS_ALIGNED(v) (((uint32_t)(v) & MFS_ALIGN_MASK) == 0U)
#define MFS_ALIGN_PREV(v) ((uint32_t)(v) & ~MFS_ALIGN_MASK)
-#define MFS_ALIGN_NEXT(v) MFS_ALIGN_PREV((size_t)(v) + MFS_ALIGN_MASK)
+#define MFS_ALIGN_NEXT(v) (MFS_ALIGN_PREV(((uint32_t)(v) - 1U)) + \
+ MFS_CFG_MEMORY_ALIGNMENT)
/** @} */
/*===========================================================================*/
@@ -396,6 +431,11 @@ extern "C" {
size_t n, const uint8_t *buffer);
mfs_error_t mfsEraseRecord(MFSDriver *devp, mfs_id_t id);
mfs_error_t mfsPerformGarbageCollection(MFSDriver *mfsp);
+#if MFS_CFG_TRANSACTION_MAX > 0
+ mfs_error_t mfsStartTransaction(MFSDriver *mfsp, size_t size);
+ mfs_error_t mfsCommitTransaction(MFSDriver *mfsp);
+ mfs_error_t mfsRollbackTransaction(MFSDriver *mfsp);
+#endif /* MFS_CFG_TRANSACTION_MAX > 0 */
#ifdef __cplusplus
}
#endif
diff --git a/os/hal/ports/STM32/LLD/ADCv3/hal_adc_lld.c b/os/hal/ports/STM32/LLD/ADCv3/hal_adc_lld.c
index 1991ccb5b..790af8a49 100644
--- a/os/hal/ports/STM32/LLD/ADCv3/hal_adc_lld.c
+++ b/os/hal/ports/STM32/LLD/ADCv3/hal_adc_lld.c
@@ -496,7 +496,7 @@ void adc_lld_init(void) {
#if defined(ADC3_4_COMMON)
ADCD3.adcc = ADC3_4_COMMON;
#elif defined(ADC123_COMMON)
- ADCD1.adcc = ADC123_COMMON;
+ ADCD3.adcc = ADC123_COMMON;
#else
ADCD3.adcc = ADC3_COMMON;
#endif
diff --git a/os/hal/ports/STM32/LLD/EXTIv1/stm32_exti.h b/os/hal/ports/STM32/LLD/EXTIv1/stm32_exti.h
index 046eec162..63f192ee2 100644
--- a/os/hal/ports/STM32/LLD/EXTIv1/stm32_exti.h
+++ b/os/hal/ports/STM32/LLD/EXTIv1/stm32_exti.h
@@ -45,7 +45,7 @@
/** @} */
/* Handling differences in ST headers.*/
-#if !defined(STM32L4XX) && !defined(STM32L4XXP)
+#if !defined(STM32H7XX) && !defined(STM32L4XX) && !defined(STM32L4XXP)
#define EMR1 EMR
#define IMR1 IMR
#define PR1 PR
diff --git a/os/hal/ports/STM32/LLD/GPIOv2/hal_pal_lld.c b/os/hal/ports/STM32/LLD/GPIOv2/hal_pal_lld.c
index a8ce78f87..78d52b94d 100644
--- a/os/hal/ports/STM32/LLD/GPIOv2/hal_pal_lld.c
+++ b/os/hal/ports/STM32/LLD/GPIOv2/hal_pal_lld.c
@@ -160,13 +160,8 @@ void _pal_lld_enablepadevent(ioportid_t port,
/* Multiple channel setting of the same channel not allowed, first disable
it. This is done because on STM32 the same channel cannot be mapped on
multiple ports.*/
-#if defined(STM32_EXTI_ENHANCED)
osalDbgAssert(((EXTI->RTSR1 & padmask) == 0U) &&
((EXTI->FTSR1 & padmask) == 0U), "channel already in use");
-#else
- osalDbgAssert(((EXTI->RTSR & padmask) == 0U) &&
- ((EXTI->FTSR & padmask) == 0U), "channel already in use");
-#endif
/* Index and mask of the SYSCFG CR register to be used.*/
cridx = (uint32_t)pad >> 2U;
@@ -181,7 +176,6 @@ void _pal_lld_enablepadevent(ioportid_t port,
SYSCFG->EXTICR[cridx] = (SYSCFG->EXTICR[cridx] & crmask) | (portidx << croff);
/* Programming edge registers.*/
-#if defined(STM32_EXTI_ENHANCED)
if (mode & PAL_EVENT_MODE_RISING_EDGE)
EXTI->RTSR1 |= padmask;
else
@@ -192,21 +186,12 @@ void _pal_lld_enablepadevent(ioportid_t port,
EXTI->FTSR1 &= ~padmask;
/* Programming interrupt and event registers.*/
+#if defined(STM32_EXTI_ENHANCED)
EXTI_D1->IMR1 |= padmask;
EXTI_D1->EMR1 &= ~padmask;
#else
- if (mode & PAL_EVENT_MODE_RISING_EDGE)
- EXTI->RTSR |= padmask;
- else
- EXTI->RTSR &= ~padmask;
- if (mode & PAL_EVENT_MODE_FALLING_EDGE)
- EXTI->FTSR |= padmask;
- else
- EXTI->FTSR &= ~padmask;
-
- /* Programming interrupt and event registers.*/
- EXTI->IMR |= padmask;
- EXTI->EMR &= ~padmask;
+ EXTI->IMR1 |= padmask;
+ EXTI->EMR1 &= ~padmask;
#endif
}
@@ -222,13 +207,8 @@ void _pal_lld_enablepadevent(ioportid_t port,
void _pal_lld_disablepadevent(ioportid_t port, iopadid_t pad) {
uint32_t padmask, rtsr1, ftsr1;
-#if defined(STM32_EXTI_ENHANCED)
rtsr1 = EXTI->RTSR1;
ftsr1 = EXTI->FTSR1;
-#else
- rtsr1 = EXTI->RTSR;
- ftsr1 = EXTI->FTSR;
-#endif
/* Mask of the pad.*/
padmask = 1U << (uint32_t)pad;
@@ -258,11 +238,11 @@ void _pal_lld_disablepadevent(ioportid_t port, iopadid_t pad) {
EXTI_D1->PR1 = padmask;
#else
/* Disabling channel.*/
- EXTI->IMR &= ~padmask;
- EXTI->EMR &= ~padmask;
- EXTI->RTSR = rtsr1 & ~padmask;
- EXTI->FTSR = ftsr1 & ~padmask;
- EXTI->PR = padmask;
+ EXTI->IMR1 &= ~padmask;
+ EXTI->EMR1 &= ~padmask;
+ EXTI->RTSR1 = rtsr1 & ~padmask;
+ EXTI->FTSR1 = ftsr1 & ~padmask;
+ EXTI->PR1 = padmask;
#endif
#if PAL_USE_CALLBACKS || PAL_USE_WAIT
diff --git a/os/hal/ports/STM32/LLD/GPIOv3/hal_pal_lld.c b/os/hal/ports/STM32/LLD/GPIOv3/hal_pal_lld.c
index 9ca51f5b9..92b61b52b 100644
--- a/os/hal/ports/STM32/LLD/GPIOv3/hal_pal_lld.c
+++ b/os/hal/ports/STM32/LLD/GPIOv3/hal_pal_lld.c
@@ -30,15 +30,6 @@
/* Driver local definitions. */
/*===========================================================================*/
-/* Handling a difference in ST headers.*/
-#if defined(STM32L4XX)
-#define EMR EMR1
-#define IMR IMR1
-#define PR PR1
-#define RTSR RTSR1
-#define FTSR FTSR1
-#endif
-
/*===========================================================================*/
/* Driver exported variables. */
/*===========================================================================*/
@@ -174,8 +165,8 @@ void _pal_lld_enablepadevent(ioportid_t port,
/* Multiple channel setting of the same channel not allowed, first disable
it. This is done because on STM32 the same channel cannot be mapped on
multiple ports.*/
- osalDbgAssert(((EXTI->RTSR & padmask) == 0U) &&
- ((EXTI->FTSR & padmask) == 0U), "channel already in use");
+ osalDbgAssert(((EXTI->RTSR1 & padmask) == 0U) &&
+ ((EXTI->FTSR1 & padmask) == 0U), "channel already in use");
/* Index and mask of the SYSCFG CR register to be used.*/
cridx = (uint32_t)pad >> 2U;
@@ -191,17 +182,17 @@ void _pal_lld_enablepadevent(ioportid_t port,
/* Programming edge registers.*/
if (mode & PAL_EVENT_MODE_RISING_EDGE)
- EXTI->RTSR |= padmask;
+ EXTI->RTSR1 |= padmask;
else
- EXTI->RTSR &= ~padmask;
+ EXTI->RTSR1 &= ~padmask;
if (mode & PAL_EVENT_MODE_FALLING_EDGE)
- EXTI->FTSR |= padmask;
+ EXTI->FTSR1 |= padmask;
else
- EXTI->FTSR &= ~padmask;
+ EXTI->FTSR1 &= ~padmask;
/* Programming interrupt and event registers.*/
- EXTI->IMR |= padmask;
- EXTI->EMR &= ~padmask;
+ EXTI->IMR1 |= padmask;
+ EXTI->EMR1 &= ~padmask;
}
/**
@@ -216,8 +207,8 @@ void _pal_lld_enablepadevent(ioportid_t port,
void _pal_lld_disablepadevent(ioportid_t port, iopadid_t pad) {
uint32_t padmask, rtsr1, ftsr1;
- rtsr1 = EXTI->RTSR;
- ftsr1 = EXTI->FTSR;
+ rtsr1 = EXTI->RTSR1;
+ ftsr1 = EXTI->FTSR1;
/* Mask of the pad.*/
padmask = 1U << (uint32_t)pad;
@@ -239,11 +230,11 @@ void _pal_lld_disablepadevent(ioportid_t port, iopadid_t pad) {
osalDbgAssert(crport == portidx, "channel mapped on different port");
/* Disabling channel.*/
- EXTI->IMR &= ~padmask;
- EXTI->EMR &= ~padmask;
- EXTI->RTSR = rtsr1 & ~padmask;
- EXTI->FTSR = ftsr1 & ~padmask;
- EXTI->PR = padmask;
+ EXTI->IMR1 &= ~padmask;
+ EXTI->EMR1 &= ~padmask;
+ EXTI->RTSR1 = rtsr1 & ~padmask;
+ EXTI->FTSR1 = ftsr1 & ~padmask;
+ EXTI->PR1 = padmask;
#if PAL_USE_CALLBACKS || PAL_USE_WAIT
/* Callback cleared and/or thread reset.*/
diff --git a/os/hal/ports/STM32/LLD/I2Cv3/hal_i2c_lld.c b/os/hal/ports/STM32/LLD/I2Cv3/hal_i2c_lld.c
index 30abebadb..b7e0b480b 100644
--- a/os/hal/ports/STM32/LLD/I2Cv3/hal_i2c_lld.c
+++ b/os/hal/ports/STM32/LLD/I2Cv3/hal_i2c_lld.c
@@ -981,8 +981,8 @@ void i2c_lld_stop(I2CDriver *i2cp) {
#endif
#if defined(STM32_I2C_BDMA_REQUIRED)
{
- bdmaStreamRelease(i2cp->rx.bdma);
- bdmaStreamRelease(i2cp->tx.bdma);
+ bdmaStreamFreeI(i2cp->rx.bdma);
+ bdmaStreamFreeI(i2cp->tx.bdma);
}
#endif
#if defined(STM32_I2C_DMA_REQUIRED) && defined(STM32_I2C_BDMA_REQUIRED)
@@ -990,8 +990,8 @@ void i2c_lld_stop(I2CDriver *i2cp) {
#endif
#if defined(STM32_I2C_DMA_REQUIRED)
{
- dmaStreamRelease(i2cp->rx.dma);
- dmaStreamRelease(i2cp->tx.dma);
+ dmaStreamFreeI(i2cp->rx.dma);
+ dmaStreamFreeI(i2cp->tx.dma);
}
#endif
diff --git a/os/hal/ports/STM32/LLD/SPIv3/hal_spi_lld.c b/os/hal/ports/STM32/LLD/SPIv3/hal_spi_lld.c
index 333789b5b..8ad8fb927 100644
--- a/os/hal/ports/STM32/LLD/SPIv3/hal_spi_lld.c
+++ b/os/hal/ports/STM32/LLD/SPIv3/hal_spi_lld.c
@@ -1081,6 +1081,10 @@ uint32_t spi_lld_polled_exchange(SPIDriver *spip, uint32_t frame) {
spip->spi->CR1 |= SPI_CR1_CSTART;
+ /* wait for room in TX FIFO.*/
+ while ((spip->spi->SR & SPI_SR_TXP) == 0U)
+ ;
+
/* Data register must be accessed with the appropriate data size.
Byte size access (uint8_t *) for transactions that are <= 8-bit etc.*/
if (dsize <= 8U) {
diff --git a/os/hal/ports/STM32/LLD/TIMv1/hal_st_lld.c b/os/hal/ports/STM32/LLD/TIMv1/hal_st_lld.c
index b99ebdde8..c00c973dd 100644
--- a/os/hal/ports/STM32/LLD/TIMv1/hal_st_lld.c
+++ b/os/hal/ports/STM32/LLD/TIMv1/hal_st_lld.c
@@ -42,6 +42,9 @@
#if !STM32_HAS_TIM2
#error "TIM2 not present in the selected device"
#endif
+#if defined(STM32_TIM2_IS_USED)
+#error "ST requires TIM2 but the timer is already used"
+#endif
#if (OSAL_ST_RESOLUTION == 32) && !STM32_TIM2_IS_32BITS
#error "TIM2 is not a 32bits timer"
#endif
@@ -64,6 +67,9 @@
#if !STM32_HAS_TIM3
#error "TIM3 not present in the selected device"
#endif
+#if defined(STM32_TIM3_IS_USED)
+#error "ST requires TIM3 but the timer is already used"
+#endif
#if (OSAL_ST_RESOLUTION == 32) && !STM32_TIM3_IS_32BITS
#error "TIM3 is not a 32bits timer"
#endif
@@ -86,6 +92,9 @@
#if !STM32_HAS_TIM4
#error "TIM4 not present in the selected device"
#endif
+#if defined(STM32_TIM4_IS_USED)
+#error "ST requires TIM4 but the timer is already used"
+#endif
#if (OSAL_ST_RESOLUTION == 32) && !STM32_TIM4_IS_32BITS
#error "TIM4 is not a 32bits timer"
#endif
@@ -108,6 +117,9 @@
#if !STM32_HAS_TIM5
#error "TIM5 not present in the selected device"
#endif
+#if defined(STM32_TIM5_IS_USED)
+#error "ST requires TIM5 but the timer is already used"
+#endif
#if (OSAL_ST_RESOLUTION == 32) && !STM32_TIM5_IS_32BITS
#error "TIM5 is not a 32bits timer"
#endif
@@ -130,6 +142,9 @@
#if !STM32_HAS_TIM21
#error "TIM21 not present in the selected device"
#endif
+#if defined(STM32_TIM21_IS_USED)
+#error "ST requires TIM21 but the timer is already used"
+#endif
#if (OSAL_ST_RESOLUTION == 32) && !STM32_TIM21_IS_32BITS
#error "TIM21 is not a 32bits timer"
#endif
@@ -144,6 +159,9 @@
#if !STM32_HAS_TIM22
#error "TIM22 not present in the selected device"
#endif
+#if defined(STM32_TIM22_IS_USED)
+#error "ST requires TIM22 but the timer is already used"
+#endif
#if (OSAL_ST_RESOLUTION == 32) && !STM32_TIM22_IS_32BITS
#error "TIM21 is not a 32bits timer"
#endif
diff --git a/os/hal/ports/STM32/STM32F37x/hal_lld.h b/os/hal/ports/STM32/STM32F37x/hal_lld.h
index 7dbdfbf57..82e46b8cc 100644
--- a/os/hal/ports/STM32/STM32F37x/hal_lld.h
+++ b/os/hal/ports/STM32/STM32F37x/hal_lld.h
@@ -993,6 +993,7 @@
#include "stm32_registry.h"
#include "stm32_isr.h"
#include "stm32_dma.h"
+#include "stm32_exti.h"
#include "stm32_rcc.h"
#ifdef __cplusplus
diff --git a/os/hal/ports/STM32/STM32F37x/platform.mk b/os/hal/ports/STM32/STM32F37x/platform.mk
index 6fa673330..f807d3dae 100644
--- a/os/hal/ports/STM32/STM32F37x/platform.mk
+++ b/os/hal/ports/STM32/STM32F37x/platform.mk
@@ -32,6 +32,7 @@ endif
include $(CHIBIOS)/os/hal/ports/STM32/LLD/CANv1/driver.mk
include $(CHIBIOS)/os/hal/ports/STM32/LLD/DACv1/driver.mk
include $(CHIBIOS)/os/hal/ports/STM32/LLD/DMAv1/driver.mk
+include $(CHIBIOS)/os/hal/ports/STM32/LLD/EXTIv1/driver.mk
include $(CHIBIOS)/os/hal/ports/STM32/LLD/GPIOv2/driver.mk
include $(CHIBIOS)/os/hal/ports/STM32/LLD/I2Cv2/driver.mk
include $(CHIBIOS)/os/hal/ports/STM32/LLD/RTCv2/driver.mk
diff --git a/os/hal/ports/STM32/STM32F37x/stm32_registry.h b/os/hal/ports/STM32/STM32F37x/stm32_registry.h
index c2729188a..b5fe4f32a 100644
--- a/os/hal/ports/STM32/STM32F37x/stm32_registry.h
+++ b/os/hal/ports/STM32/STM32F37x/stm32_registry.h
@@ -103,7 +103,7 @@
/* EXTI attributes.*/
#define STM32_EXTI_NUM_LINES 23
-#define STM32_EXTI_IMR_MASK 0x1F800000U
+#define STM32_EXTI_IMR1_MASK 0x1F800000U
/* GPIO attributes.*/
#define STM32_HAS_GPIOA TRUE
@@ -356,7 +356,7 @@
/* EXTI attributes.*/
#define STM32_EXTI_NUM_LINES 23
-#define STM32_EXTI_IMR_MASK 0x1F800000U
+#define STM32_EXTI_IMR1_MASK 0x1F800000U
/* GPIO attributes.*/
#define STM32_HAS_GPIOA TRUE
diff --git a/os/hal/ports/STM32/STM32H7xx/hal_lld.c b/os/hal/ports/STM32/STM32H7xx/hal_lld.c
index 60ce00310..df3e2f478 100644
--- a/os/hal/ports/STM32/STM32H7xx/hal_lld.c
+++ b/os/hal/ports/STM32/STM32H7xx/hal_lld.c
@@ -206,7 +206,7 @@ void stm32_clock_init(void) {
/* Fix for errata 2.2.15: Reading from AXI SRAM might lead to data
read corruption.
AXI->TARG7_FN_MOD.*/
- *((volatile uint32_t *)0x51000000 + 0x1108 + 0x7000) = 0x00000001U;
+ *((volatile uint32_t *)(0x51000000 + 0x1108 + 0x7000)) = 0x00000001U;
#endif
/* PWR initialization.*/
diff --git a/os/hal/ports/STM32/STM32H7xx/hal_lld.h b/os/hal/ports/STM32/STM32H7xx/hal_lld.h
index 926630588..c465a3910 100644
--- a/os/hal/ports/STM32/STM32H7xx/hal_lld.h
+++ b/os/hal/ports/STM32/STM32H7xx/hal_lld.h
@@ -494,9 +494,9 @@
#define STM32_SAI4ASEL_PER_CK RCC_D3CCIPR_SAI4ASEL_VALUE(4U)
#define STM32_ADCSEL_PLL2_P_CK RCC_D3CCIPR_ADCSEL_VALUE(0U)
-#define STM32_ADCSEL_PLL3_R_CK RCC_D3CCIPR_ADCSEL_VALUE(0U)
-#define STM32_ADCSEL_PER_CK RCC_D3CCIPR_ADCSEL_VALUE(0U)
-#define STM32_ADCSEL_DISABLE RCC_D3CCIPR_ADCSEL_VALUE(0U)
+#define STM32_ADCSEL_PLL3_R_CK RCC_D3CCIPR_ADCSEL_VALUE(1U)
+#define STM32_ADCSEL_PER_CK RCC_D3CCIPR_ADCSEL_VALUE(2U)
+#define STM32_ADCSEL_DISABLE RCC_D3CCIPR_ADCSEL_VALUE(3U)
#define STM32_LPTIM345SEL_PCLK4 RCC_D3CCIPR_LPTIM345SEL_VALUE(0U)
#define STM32_LPTIM345SEL_PLL2_P_CK RCC_D3CCIPR_LPTIM345SEL_VALUE(1U)
@@ -2432,58 +2432,58 @@
/**
* @brief USART4 clock.
*/
-#define STM32_USART4CLK STM32_PCLK1
+#define STM32_UART4CLK STM32_PCLK1
/**
* @brief USART5 clock.
*/
-#define STM32_USART5CLK STM32_PCLK1
+#define STM32_UART5CLK STM32_PCLK1
/**
* @brief USART7 clock.
*/
-#define STM32_USART7CLK STM32_PCLK1
+#define STM32_UART7CLK STM32_PCLK1
/**
* @brief USART8 clock.
*/
-#define STM32_USART8CLK STM32_PCLK2
+#define STM32_UART8CLK STM32_PCLK1
#elif STM32_USART234578SEL == STM32_USART234578SEL_PLL2_Q_CK
#define STM32_USART2CLK STM32_PLL2_Q_CK
#define STM32_USART3CLK STM32_PLL2_Q_CK
-#define STM32_USART4CLK STM32_PLL2_Q_CK
-#define STM32_USART5CLK STM32_PLL2_Q_CK
-#define STM32_USART7CLK STM32_PLL2_Q_CK
-#define STM32_USART8CLK STM32_PLL2_Q_CK
+#define STM32_UART4CLK STM32_PLL2_Q_CK
+#define STM32_UART5CLK STM32_PLL2_Q_CK
+#define STM32_UART7CLK STM32_PLL2_Q_CK
+#define STM32_UART8CLK STM32_PLL2_Q_CK
#elif STM32_USART234578SEL == STM32_USART234578SEL_PLL3_Q_CK
#define STM32_USART2CLK STM32_PLL3_Q_CK
#define STM32_USART3CLK STM32_PLL3_Q_CK
-#define STM32_USART4CLK STM32_PLL3_Q_CK
-#define STM32_USART5CLK STM32_PLL3_Q_CK
-#define STM32_USART7CLK STM32_PLL3_Q_CK
-#define STM32_USART8CLK STM32_PLL3_Q_CK
+#define STM32_UART4CLK STM32_PLL3_Q_CK
+#define STM32_UART5CLK STM32_PLL3_Q_CK
+#define STM32_UART7CLK STM32_PLL3_Q_CK
+#define STM32_UART8CLK STM32_PLL3_Q_CK
#elif STM32_USART234578SEL == STM32_USART234578SEL_HSI_KER_CK
#define STM32_USART2CLK STM32_HSI_CK
#define STM32_USART3CLK STM32_HSI_CK
-#define STM32_USART4CLK STM32_HSI_CK
-#define STM32_USART5CLK STM32_HSI_CK
-#define STM32_USART7CLK STM32_HSI_CK
-#define STM32_USART8CLK STM32_HSI_CK
+#define STM32_UART4CLK STM32_HSI_CK
+#define STM32_UART5CLK STM32_HSI_CK
+#define STM32_UART7CLK STM32_HSI_CK
+#define STM32_UART8CLK STM32_HSI_CK
#elif STM32_USART234578SEL == STM32_USART234578SEL_CSI_KER_CK
#define STM32_USART2CLK STM32_CSI_CK
#define STM32_USART3CLK STM32_CSI_CK
-#define STM32_USART4CLK STM32_CSI_CK
-#define STM32_USART5CLK STM32_CSI_CK
-#define STM32_USART7CLK STM32_CSI_CK
-#define STM32_USART8CLK STM32_CSI_CK
+#define STM32_UART4CLK STM32_CSI_CK
+#define STM32_UART5CLK STM32_CSI_CK
+#define STM32_UART7CLK STM32_CSI_CK
+#define STM32_UART8CLK STM32_CSI_CK
#elif STM32_USART234578SEL == STM32_USART234578SEL_LSE_CK
#define STM32_USART2CLK STM32_LSE_CK
#define STM32_USART3CLK STM32_LSE_CK
-#define STM32_USART4CLK STM32_LSE_CK
-#define STM32_USART6CLK STM32_LSE_CK
-#define STM32_USART7CLK STM32_LSE_CK
-#define STM32_USART8CLK STM32_LSE_CK
+#define STM32_UART4CLK STM32_LSE_CK
+#define STM32_UART6CLK STM32_LSE_CK
+#define STM32_UART7CLK STM32_LSE_CK
+#define STM32_UART8CLK STM32_LSE_CK
#else
#error "invalid source selected for STM32_USART234578SEL clock"
#endif
@@ -2905,6 +2905,7 @@
#include "stm32_isr.h"
#include "stm32_dma.h"
#include "stm32_bdma.h"
+#include "stm32_exti.h"
#include "stm32_rcc.h"
#ifdef __cplusplus
diff --git a/os/hal/ports/STM32/STM32H7xx/platform.mk b/os/hal/ports/STM32/STM32H7xx/platform.mk
index 9853db181..2fd49d0df 100644
--- a/os/hal/ports/STM32/STM32H7xx/platform.mk
+++ b/os/hal/ports/STM32/STM32H7xx/platform.mk
@@ -30,6 +30,7 @@ include $(CHIBIOS)/os/hal/ports/STM32/LLD/BDMAv1/driver.mk
include $(CHIBIOS)/os/hal/ports/STM32/LLD/CRYPv1/driver.mk
include $(CHIBIOS)/os/hal/ports/STM32/LLD/DACv1/driver.mk
include $(CHIBIOS)/os/hal/ports/STM32/LLD/DMAv2/driver.mk
+include $(CHIBIOS)/os/hal/ports/STM32/LLD/EXTIv1/driver.mk
include $(CHIBIOS)/os/hal/ports/STM32/LLD/GPIOv2/driver.mk
include $(CHIBIOS)/os/hal/ports/STM32/LLD/I2Cv3/driver.mk
include $(CHIBIOS)/os/hal/ports/STM32/LLD/OTGv1/driver.mk
diff --git a/os/hal/ports/STM32/STM32H7xx/stm32_registry.h b/os/hal/ports/STM32/STM32H7xx/stm32_registry.h
index 8c99d5f84..9dcdd99a2 100644
--- a/os/hal/ports/STM32/STM32H7xx/stm32_registry.h
+++ b/os/hal/ports/STM32/STM32H7xx/stm32_registry.h
@@ -133,6 +133,7 @@
#define STM32_ETH_NUMBER 61
/* EXTI attributes.*/
+#define STM32_EXTI_ENHANCED
#define STM32_EXTI_NUM_LINES 34
#define STM32_EXTI_IMR1_MASK 0x1F800000U
#define STM32_EXTI_IMR2_MASK 0xFFFFFFFCU
diff --git a/os/hal/ports/STM32/STM32L1xx/hal_lld.h b/os/hal/ports/STM32/STM32L1xx/hal_lld.h
index cd0342a42..ea239aa12 100644
--- a/os/hal/ports/STM32/STM32L1xx/hal_lld.h
+++ b/os/hal/ports/STM32/STM32L1xx/hal_lld.h
@@ -845,6 +845,7 @@
#include "mpu_v7m.h"
#include "stm32_isr.h"
#include "stm32_dma.h"
+#include "stm32_exti.h"
#include "stm32_rcc.h"
#ifdef __cplusplus
diff --git a/os/hal/ports/STM32/STM32L1xx/platform.mk b/os/hal/ports/STM32/STM32L1xx/platform.mk
index 813b1a200..43e7d1b0a 100644
--- a/os/hal/ports/STM32/STM32L1xx/platform.mk
+++ b/os/hal/ports/STM32/STM32L1xx/platform.mk
@@ -31,6 +31,7 @@ endif
# Drivers compatible with the platform.
include $(CHIBIOS)/os/hal/ports/STM32/LLD/DACv1/driver.mk
include $(CHIBIOS)/os/hal/ports/STM32/LLD/DMAv1/driver.mk
+include $(CHIBIOS)/os/hal/ports/STM32/LLD/EXTIv1/driver.mk
include $(CHIBIOS)/os/hal/ports/STM32/LLD/GPIOv2/driver.mk
include $(CHIBIOS)/os/hal/ports/STM32/LLD/I2Cv1/driver.mk
include $(CHIBIOS)/os/hal/ports/STM32/LLD/RTCv2/driver.mk
diff --git a/os/hal/ports/STM32/STM32L1xx/stm32_registry.h b/os/hal/ports/STM32/STM32L1xx/stm32_registry.h
index bc5485ab3..d227aa1e3 100644
--- a/os/hal/ports/STM32/STM32L1xx/stm32_registry.h
+++ b/os/hal/ports/STM32/STM32L1xx/stm32_registry.h
@@ -53,6 +53,12 @@
#error "STM32L1xx device not specified"
#endif
+#if defined(STM32L100xB) || defined(STM32L100xBA) || defined(STM32L100xC)
+#define STM32L1XX_VALUE_LINE TRUE
+#else
+#define STM32L1XX_VALUE_LINE FALSE
+#endif
+
/*===========================================================================*/
/* Platform capabilities. */
/*===========================================================================*/
@@ -130,7 +136,7 @@
#else
#define STM32_EXTI_NUM_LINES 24
#endif
-#define STM32_EXTI_IMR_MASK 0x00000000U
+#define STM32_EXTI_IMR1_MASK 0x00000000U
#if (STM32L1XX_PROD_CAT == 1) || (STM32L1XX_PROD_CAT == 2) || \
(STM32L1XX_PROD_CAT == 3) || defined(__DOXYGEN__)
@@ -197,7 +203,27 @@
#endif
#define STM32_RTC_HAS_PERIODIC_WAKEUPS TRUE
#define STM32_RTC_NUM_ALARMS 2
-#define STM32_RTC_HAS_INTERRUPTS FALSE
+#if STM32L1XX_VALUE_LINE || defined(__DOXYGEN__)
+#define STM32_RTC_STORAGE_SIZE 20
+#elif (STM32L1XX_PROD_CAT == 1) || (STM32L1XX_PROD_CAT == 2)
+#define STM32_RTC_STORAGE_SIZE 80
+#else
+#define STM32_RTC_STORAGE_SIZE 128
+#endif
+#define STM32_RTC_TAMP_STAMP_HANDLER Vector48
+#define STM32_RTC_WKUP_HANDLER Vector4C
+#define STM32_RTC_ALARM_HANDLER VectorE4
+#define STM32_RTC_TAMP_STAMP_NUMBER 3
+#define STM32_RTC_WKUP_NUMBER 1
+#define STM32_RTC_ALARM_NUMBER 2
+#define STM32_RTC_ALARM_EXTI 17
+#define STM32_RTC_TAMP_STAMP_EXTI 19
+#define STM32_RTC_WKUP_EXTI 20
+#define STM32_RTC_IRQ_ENABLE() do { \
+ nvicEnableVector(STM32_RTC_TAMP_STAMP_NUMBER, STM32_IRQ_EXTI19_PRIORITY); \
+ nvicEnableVector(STM32_RTC_WKUP_NUMBER, STM32_IRQ_EXTI20_PRIORITY); \
+ nvicEnableVector(STM32_RTC_ALARM_NUMBER, STM32_IRQ_EXTI18_PRIORITY); \
+} while (false)
/* SDIO attributes.*/
#define STM32_HAS_SDIO TRUE
diff --git a/os/oslib/include/chmempools.h b/os/oslib/include/chmempools.h
index 6e5a45277..427ba9fb1 100644
--- a/os/oslib/include/chmempools.h
+++ b/os/oslib/include/chmempools.h
@@ -248,6 +248,19 @@ static inline void chGuardedPoolObjectInit(guarded_memory_pool_t *gmp,
chGuardedPoolObjectInitAligned(gmp, size, PORT_NATURAL_ALIGN);
}
+/**
+ * @brief Gets the count of objects in a guarded memory pool.
+ * @pre The guarded memory pool must be already been initialized.
+ *
+ * @param[in] gmp pointer to a @p guarded_memory_pool_t structure
+ *
+ * @iclass
+ */
+static inline cnt_t chGuardedPoolGetCounterI(guarded_memory_pool_t *gmp) {
+
+ return chSemGetCounterI(&gmp->sem);
+}
+
/**
* @brief Allocates an object from a guarded memory pool.
* @pre The guarded memory pool must be already been initialized.
diff --git a/os/oslib/include/chobjfifos.h b/os/oslib/include/chobjfifos.h
index a50ed121f..38564379f 100644
--- a/os/oslib/include/chobjfifos.h
+++ b/os/oslib/include/chobjfifos.h
@@ -119,7 +119,7 @@ extern "C" {
* @param[in] objalign required objects alignment
* @param[in] objbuf pointer to the buffer of objects, it must be able
* to hold @p objn objects of @p objsize size with
- * @p objealign alignment
+ * @p objalign alignment
* @param[in] msgbuf pointer to the buffer of messages, it must be able
* to hold @p objn messages
*
@@ -145,8 +145,7 @@ static inline void chFifoObjectInitAligned(objects_fifo_t *ofp, size_t objsize,
* @param[in] objsize size of objects
* @param[in] objn number of objects available
* @param[in] objbuf pointer to the buffer of objects, it must be able
- * to hold @p objn objects of @p objsize size with
- * @p objealign alignment
+ * to hold @p objn objects of @p objsize size
* @param[in] msgbuf pointer to the buffer of messages, it must be able
* to hold @p objn messages
*
diff --git a/os/rt/include/chtime.h b/os/rt/include/chtime.h
index 264ebcde3..39bd137fd 100644
--- a/os/rt/include/chtime.h
+++ b/os/rt/include/chtime.h
@@ -482,7 +482,8 @@ static inline bool chTimeIsInRangeX(systime_t time,
systime_t start,
systime_t end) {
- return (bool)((time - start) < (end - start));
+ return (bool)((systime_t)((systime_t)time - (systime_t)start) <
+ (systime_t)((systime_t)end - (systime_t)start));
}
/** @} */
diff --git a/readme.txt b/readme.txt
index b66b3fdb8..29402c38f 100644
--- a/readme.txt
+++ b/readme.txt
@@ -74,9 +74,13 @@
*****************************************************************************
*** Next ***
+- HAL: Added H753 to all H7 mcuconf.h files.
+- NEW: Added transactional updates to MFS.
- VAR: Modified syscalls.c to allocate memory from bottom upward, ChibiOS
allocators take memory from top downward. This way the memory taken
using _sbrk_r() does not contain "holes" caused by other allocators.
+- LIB: Re-introduced missing chGuardedPoolGetCounterI() function to guarded
+ pools allocator.
- LIB: Modified core allocator to be able to get blocks starting from bottom
or top of the available memory range.
Removed alignment enforcement for requested block size. Alignment is
@@ -85,15 +89,39 @@
- HAL: Added a new interface for range-finder devices (used by EX).
- HAL: Added mcuconf.h updater tool for STM32F407 (backported to 19.1.1).
- NIL: Integrated NIL 4.0.
+- FIX: Fixed missing RTC definitions in STM32L1xx registry (bug #1023)
+ (backported to 19.1.1).
+- FIX: Fixed missing EXTI driver integration on some platforms (bug #1022)
+ (backported to 19.1.1).
+- FIX: Fixed various UART clock naming errors in STM32H7 HAL (bug #1021)
+ (backported to 19.1.1)(backported to 18.2.3).
+- FIX: Fixed missing STM32L4+ check in GPIOv3 driver (bug #1020)
+ (backported to 19.1.1)(backported to 18.2.3).
+- FIX: Fixed call to obsolete dmaStreamRelease() in STM32 I2Cv3 driver
+ (bug #1019)(backported to 19.1.1).
+- FIX: Fixed misconfiguration in STM32L4R9I DIscovery board files (bug #1018)
+ (backported to 19.1.1).
+- FIX: Fixed wrong Debug launch configuration in STM32L4Rx demos (bug #1017)
+ (backported to 19.1.1).
+- FIX: Fixed wrong ADCSEL definitions in STM32H7 HAL (bug #1016)
+ (backported to 19.1.1)(backported to 18.2.3).
+- FIX: Fixed chTimeIsInRangeX() failing under some configurations (bug #1015)
+ (backported to 19.1.1)(backported to 18.2.3).
+- FIX: Fixed invalid AXI errata fix for STM32H7xx (bug #1014)
+ (backported to 19.1.1)(backported to 18.2.3).
+- FIX: Fixed invalid ADCD3 initialization in STM32 ADCv3 driver (bug #1013)
+ (backported to 19.1.1)(backported to 18.2.3).
+- FIX: Fixed invalid call to dmaStreamRelease() in STM32 SDIOv1 driver
+ (bug #1012)(backported to 19.1.1).
- FIX: Fixed wrong license restriction check in Nil (bug #1011)
(backported to 19.1.1)(backported to 18.2.3).
- FIX: Fixed uninitialized variables in STM32 DMA drivers (bug #1010)
(backported to 19.1.1).
- FIX: Fixed wrong mcuconf.h in some testex demos related to STM32F407
- (bug #1008)(backported to 19.1.1)(backported to 18.2.3).
+ (bug #1008)(backported to 19.1.1)(backported to 18.2.3).
- FIX: Fixed problem in STM32 mcuconf.h template files (bug #1007)
- (backported to 19.1.1)(backported to 18.2.3).
+ (backported to 19.1.1)(backported to 18.2.3).
- EX: Fixed I2C Acquire bus called twice in the HTS221 initialization
- (bug #1006)(backported to 19.1.1)(backported to 18.2.3).
+ (bug #1006)(backported to 19.1.1)(backported to 18.2.3).
- EX: Fixed missing I2C release bus in LPS22HB initialization (bug #1005)
- (backported to 19.1.1).
+ (backported to 19.1.1).
diff --git a/test/lib/ch_test.h b/test/lib/ch_test.h
index b78591689..3b51085cb 100644
--- a/test/lib/ch_test.h
+++ b/test/lib/ch_test.h
@@ -104,6 +104,13 @@ typedef struct {
*/
#define test_set_step(step) test_step = (step)
+/**
+ * @brief End step marker.
+ *
+ * @param[in] step the step number
+ */
+#define test_end_step(step) (void)(step);
+
/**
* @brief Test failure enforcement.
* @note This function can only be called from test_case execute context.
diff --git a/test/mfs/configuration.xml b/test/mfs/configuration.xml
index efc7b5b04..070066b52 100644
--- a/test/mfs/configuration.xml
+++ b/test/mfs/configuration.xml
@@ -47,6 +47,10 @@
extern const MFSConfig mfscfg1;
extern MFSDriver mfs1;
extern uint8_t mfs_buffer[512];
+extern const uint8_t mfs_pattern16[16];
+extern const uint8_t mfs_pattern32[32];
+extern const uint8_t mfs_pattern10[10];
+extern const uint8_t mfs_pattern512[512];
flash_error_t bank_erase(mfs_bank_t bank);
flash_error_t bank_verify_erased(mfs_bank_t bank);
@@ -57,6 +61,54 @@ void test_print_mfs_info(void);]]>
MFSDriver mfs1;
uint8_t mfs_buffer[512];
+
+const uint8_t mfs_pattern16[16] = {
+ 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15
+};
+
+const uint8_t mfs_pattern32[32] = {
+ 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31,
+ 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47
+};
+
+const uint8_t mfs_pattern10[10] = {
+ 48, 49, 50, 51, 52, 53, 54, 55, 56, 57
+};
+
+const uint8_t mfs_pattern512[512] = {
+ 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15,
+ 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31,
+ 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47,
+ 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 62, 63,
+ 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15,
+ 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31,
+ 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47,
+ 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 62, 63,
+ 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15,
+ 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31,
+ 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47,
+ 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 62, 63,
+ 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15,
+ 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31,
+ 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47,
+ 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 62, 63,
+ 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15,
+ 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31,
+ 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47,
+ 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 62, 63,
+ 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15,
+ 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31,
+ 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47,
+ 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 62, 63,
+ 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15,
+ 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31,
+ 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47,
+ 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 62, 63,
+ 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15,
+ 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31,
+ 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47,
+ 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 62, 63
+};
void test_print_mfs_info(void) {
@@ -128,55 +180,7 @@ flash_error_t bank_verify_erased(mfs_bank_t bank) {
-#include "hal_mfs.h"
-
-static const uint8_t pattern1[] = {
- 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15
-};
-
-static const uint8_t pattern2[] = {
- 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31,
- 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47
-};
-
-static const uint8_t pattern3[] = {
- 48, 49, 50, 51, 52, 53, 54, 55, 56, 57
-};
-
-static const uint8_t pattern512[] = {
- 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15,
- 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31,
- 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47,
- 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 62, 63,
- 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15,
- 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31,
- 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47,
- 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 62, 63,
- 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15,
- 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31,
- 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47,
- 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 62, 63,
- 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15,
- 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31,
- 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47,
- 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 62, 63,
- 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15,
- 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31,
- 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47,
- 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 62, 63,
- 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15,
- 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31,
- 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47,
- 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 62, 63,
- 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15,
- 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31,
- 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47,
- 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 62, 63,
- 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15,
- 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31,
- 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47,
- 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 62, 63
-};]]>
+#include "hal_mfs.h"]]>
@@ -336,13 +340,13 @@ test_assert(err == MFS_ERR_NOT_FOUND , "record was already present");]]>
+test_assert(size == sizeof mfs_pattern16, "unexpected record length");
+test_assert(memcmp(mfs_pattern16, mfs_buffer, size) == 0, "wrong record content");]]>
@@ -355,13 +359,13 @@ test_assert(memcmp(pattern1, mfs_buffer, size) == 0, "wrong record content");]]>
+test_assert(size == sizeof mfs_pattern32, "unexpected record length");
+test_assert(memcmp(mfs_pattern32, mfs_buffer, size) == 0, "wrong record content");]]>
@@ -417,11 +421,11 @@ mfsStart(&mfs1, &mfscfg1);]]>
@@ -530,21 +534,21 @@ mfsErase(&mfs1);]]>
@@ -559,9 +563,9 @@ for (id = 1; id <= id_max; id++) {
@@ -583,7 +587,7 @@ test_assert(remaining >= sizeof (mfs_data_header_t), "not enough space");
if (remaining > sizeof (mfs_data_header_t) * 2) {
err = mfsWriteRecord(&mfs1, MFS_CFG_MAX_RECORDS,
remaining - (sizeof (mfs_data_header_t) * 2),
- pattern512);
+ mfs_pattern512);
test_assert(err == MFS_NO_ERROR, "error filling remaining space");
err = mfsEraseRecord(&mfs1, MFS_CFG_MAX_RECORDS);
test_assert(err == MFS_NO_ERROR, "error filling remaining space");
@@ -641,21 +645,21 @@ mfsErase(&mfs1);]]>
@@ -690,14 +694,15 @@ test_assert(err == MFS_ERR_NOT_FOUND, "record not erased");]]>
size_t size;
test_assert(mfs1.current_counter == 1, "not first instance");
-err = mfsWriteRecord(&mfs1, 1, sizeof pattern512, pattern512);
+err = mfsWriteRecord(&mfs1, 1, sizeof mfs_pattern512, mfs_pattern512);
test_assert(err == MFS_WARN_GC, "error creating the record");
test_assert(mfs1.current_counter == 2, "not second instance");
size = sizeof mfs_buffer;
err = mfsReadRecord(&mfs1, 1, &size, mfs_buffer);
test_assert(err == MFS_NO_ERROR, "record not found");
-test_assert(size == sizeof pattern512, "unexpected record length");
-test_assert(memcmp(pattern512, mfs_buffer, size) == 0, "wrong record content");
+test_assert(size == sizeof mfs_pattern512, "unexpected record length");
+test_assert(memcmp(mfs_pattern512, mfs_buffer, size) == 0,
+ "wrong record content");
test_assert(mfs1.current_bank == MFS_BANK_1, "unexpected bank");
test_assert(bank_verify_erased(MFS_BANK_0) == FLASH_NO_ERROR, "bank 0 not erased");]]>
@@ -712,7 +717,7 @@ test_assert(bank_verify_erased(MFS_BANK_0) == FLASH_NO_ERROR, "bank 0 not erased
size_t size;
test_assert(mfs1.current_counter == 2, "not second instance");
-err = mfsWriteRecord(&mfs1, 1, sizeof pattern512, pattern512);
+err = mfsWriteRecord(&mfs1, 1, sizeof mfs_pattern512, mfs_pattern512);
test_assert(err == MFS_WARN_GC, "error creating the record");
test_assert(mfs1.current_counter == 3, "not third instance");
size = sizeof mfs_buffer;
err = mfsReadRecord(&mfs1, 1, &size, mfs_buffer);
test_assert(err == MFS_NO_ERROR, "record not found");
-test_assert(size == sizeof pattern512, "unexpected record length");
-test_assert(memcmp(pattern512, mfs_buffer, size) == 0, "wrong record content");
+test_assert(size == sizeof mfs_pattern512, "unexpected record length");
+test_assert(memcmp(mfs_pattern512, mfs_buffer, size) == 0,
+ "wrong record content");
test_assert(mfs1.current_bank == MFS_BANK_0, "unexpected bank");
test_assert(bank_verify_erased(MFS_BANK_1) == FLASH_NO_ERROR, "bank 1 not erased");]]>
@@ -785,7 +792,7 @@ test_assert(bank_verify_erased(MFS_BANK_1) == FLASH_NO_ERROR, "bank 1 not erased
@@ -869,9 +878,9 @@ for (id = 1; id <= id_max; id++) {
size_t size;
mfs_id_t id;
mfs_id_t id_max = (mfscfg1.bank_size - sizeof (mfs_bank_header_t)) /
- (sizeof (mfs_data_header_t) + (sizeof pattern512 / 2));
+ (sizeof (mfs_data_header_t) + (sizeof mfs_pattern512 / 2));
mfs_id_t n = ((mfscfg1.bank_size - sizeof (mfs_bank_header_t)) -
- (id_max * (sizeof (mfs_data_header_t) + (sizeof pattern512 / 2)))) /
+ (id_max * (sizeof (mfs_data_header_t) + (sizeof mfs_pattern512 / 2)))) /
sizeof (mfs_data_header_t);
for (id = 1; id <= n; id++) {
@@ -894,7 +903,7 @@ for (id = 1; id <= n; id++) {
+
+
+ Internal Tests
+
+
+ Transaction Mode tests.
+
+
+ This sequence tests the MFS behavior when used in transaction mode, correct cases and expected error cases are tested.
+
+
+
+
+
+
+#include "hal_mfs.h"]]>
+
+
+
+
+ Committing a transaction
+
+
+ A set of new/existing records are written/erased within a transaction then the transaction is committed, the state is checked afterward.
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ Records 1, 2 and 3 are created, MFS_NO_ERROR is expected.
+
+
+
+
+
+
+
+
+
+
+ Presence of records 1, 2 and 3 is verified, MFS_NO_ERROR is expected.
+
+
+
+
+
+
+
+
+
+
+ Starting a transaction with sufficient pre-allocated space, MFS_NO_ERROR is expected.
+
+
+
+
+
+
+
+
+
+
+ Atomically erasing record 1, updating record 2, reading record 3.
+
+
+
+
+
+
+
+
+
+
+ Committing the transaction, MFS_NO_ERROR is expected.
+
+
+
+
+
+
+
+
+
+
+ Testing outcome, records 1 must not be present, record 2 must contain the new value and record 3 must be unchanged.
+
+
+
+
+
+
+
+
+
+
+ Re-mounting the manage storage, MFS_NO_ERROR is expected.
+
+
+
+
+
+
+
+
+
+
+ Testing outcome again after re-start.
+
+
+
+
+
+
+
+
+
+
+ Performing a garbage collection, the result must
+ not change.
+
+
+
+
+
+
+
+
+
+
+ Testing outcome again after garbage collection.
+
+
+
+
+
+
+
+
+
+
+
+
+ Rolling back a transaction.
+
+
+ A set of new/existing records are written/erased within a transaction then the transaction is rolled back, the state is checked afterward.
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ Records 1, 2 and 3 are created, MFS_NO_ERROR is expected.
+
+
+
+
+
+
+
+
+
+
+ Presence of records 1, 2 and 3 is verified, MFS_NO_ERROR is expected.
+
+
+
+
+
+
+
+
+
+
+ Starting a transaction with sufficient pre-allocated space, MFS_NO_ERROR is expected..
+
+
+
+
+
+
+
+
+
+
+ Atomically erasing record 1, updating record 2, reading record 3.
+
+
+
+
+
+
+
+
+
+
+ Rolling back the transaction, MFS_NO_ERROR is expected.
+
+
+
+
+
+
+
+
+
+
+ State must not have changed, records 1, 2 and 3 must still be there unchanged.
+
+
+
+
+
+
+
+
+
+
+
+
+ Transaction triggering an early garbage collect.
+
+
+ A transaction is started with sufficient space but not contiguous, a garbage collection is triggered.
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ Filling up the storage by writing records with increasing IDs, MFS_NO_ERROR is expected.
+
+
+
+
+
+
+
+
+
+
+ Erasing one record, MFS_NO_ERROR is expected.
+
+
+
+
+
+
+
+
+
+
+ Starting a transaction with the whole remaining space, MFS_ERR_OUT_OF_MEM is expected.
+
+
+
+
+
+ bank_size - mfs1.used_space;
+
+err = mfsStartTransaction(&mfs1, size);
+test_assert(err == MFS_ERR_OUT_OF_MEM, "invalid error code");]]>
+
+
+
+
+ Starting a transaction with insufficient space for one more header, MFS_ERR_OUT_OF_MEM is expected.
+
+
+
+
+
+ bank_size - mfs1.used_space) - sizeof (mfs_data_header_t)) + 1;
+
+err = mfsStartTransaction(&mfs1, size);
+test_assert(err == MFS_ERR_OUT_OF_MEM, "invalid error code");]]>
+
+
+
+
+ Starting a transaction with just enough space for one more header, MFS_NO_ERROR is expected.
+
+
+
+
+
+ bank_size - mfs1.used_space) - sizeof (mfs_data_header_t);
+
+err = mfsStartTransaction(&mfs1, size);
+test_assert(err == MFS_NO_ERROR, "error starting transaction");]]>
+
+
+
+
+ Rolling back, MFS_NO_ERROR is expected.
+
+
+
+
+
+
+
+
+
+
+
+
Internal Tests
diff --git a/test/mfs/mfs_test.mk b/test/mfs/mfs_test.mk
index ae6fbf6a2..499ebb47b 100644
--- a/test/mfs/mfs_test.mk
+++ b/test/mfs/mfs_test.mk
@@ -1,7 +1,8 @@
# List of all the ChibiOS/HAL MFS test files.
TESTSRC += ${CHIBIOS}/test/mfs/source/test/mfs_test_root.c \
${CHIBIOS}/test/mfs/source/test/mfs_test_sequence_001.c \
- ${CHIBIOS}/test/mfs/source/test/mfs_test_sequence_002.c
+ ${CHIBIOS}/test/mfs/source/test/mfs_test_sequence_002.c \
+ ${CHIBIOS}/test/mfs/source/test/mfs_test_sequence_003.c
# Required include directories
TESTINC += ${CHIBIOS}/test/mfs/source/test
diff --git a/test/mfs/source/test/mfs_test_root.c b/test/mfs/source/test/mfs_test_root.c
index 447278610..422a41f06 100644
--- a/test/mfs/source/test/mfs_test_root.c
+++ b/test/mfs/source/test/mfs_test_root.c
@@ -23,6 +23,7 @@
* Test Sequences
* - @subpage mfs_test_sequence_001
* - @subpage mfs_test_sequence_002
+ * - @subpage mfs_test_sequence_003
* .
*/
@@ -46,6 +47,7 @@
const testsequence_t * const mfs_test_suite_array[] = {
&mfs_test_sequence_001,
&mfs_test_sequence_002,
+ &mfs_test_sequence_003,
NULL
};
@@ -66,6 +68,54 @@ const testsuite_t mfs_test_suite = {
MFSDriver mfs1;
uint8_t mfs_buffer[512];
+const uint8_t mfs_pattern16[16] = {
+ 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15
+};
+
+const uint8_t mfs_pattern32[32] = {
+ 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31,
+ 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47
+};
+
+const uint8_t mfs_pattern10[10] = {
+ 48, 49, 50, 51, 52, 53, 54, 55, 56, 57
+};
+
+const uint8_t mfs_pattern512[512] = {
+ 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15,
+ 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31,
+ 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47,
+ 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 62, 63,
+ 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15,
+ 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31,
+ 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47,
+ 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 62, 63,
+ 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15,
+ 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31,
+ 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47,
+ 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 62, 63,
+ 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15,
+ 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31,
+ 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47,
+ 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 62, 63,
+ 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15,
+ 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31,
+ 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47,
+ 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 62, 63,
+ 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15,
+ 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31,
+ 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47,
+ 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 62, 63,
+ 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15,
+ 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31,
+ 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47,
+ 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 62, 63,
+ 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15,
+ 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31,
+ 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47,
+ 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 62, 63
+};
+
void test_print_mfs_info(void) {
}
diff --git a/test/mfs/source/test/mfs_test_root.h b/test/mfs/source/test/mfs_test_root.h
index 672b7da80..22f85634f 100644
--- a/test/mfs/source/test/mfs_test_root.h
+++ b/test/mfs/source/test/mfs_test_root.h
@@ -26,6 +26,7 @@
#include "mfs_test_sequence_001.h"
#include "mfs_test_sequence_002.h"
+#include "mfs_test_sequence_003.h"
#if !defined(__DOXYGEN__)
@@ -55,6 +56,10 @@ extern "C" {
extern const MFSConfig mfscfg1;
extern MFSDriver mfs1;
extern uint8_t mfs_buffer[512];
+extern const uint8_t mfs_pattern16[16];
+extern const uint8_t mfs_pattern32[32];
+extern const uint8_t mfs_pattern10[10];
+extern const uint8_t mfs_pattern512[512];
flash_error_t bank_erase(mfs_bank_t bank);
flash_error_t bank_verify_erased(mfs_bank_t bank);
diff --git a/test/mfs/source/test/mfs_test_sequence_001.c b/test/mfs/source/test/mfs_test_sequence_001.c
index 20b4d8d89..7c6d929ee 100644
--- a/test/mfs/source/test/mfs_test_sequence_001.c
+++ b/test/mfs/source/test/mfs_test_sequence_001.c
@@ -47,54 +47,6 @@
#include
#include "hal_mfs.h"
-static const uint8_t pattern1[] = {
- 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15
-};
-
-static const uint8_t pattern2[] = {
- 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31,
- 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47
-};
-
-static const uint8_t pattern3[] = {
- 48, 49, 50, 51, 52, 53, 54, 55, 56, 57
-};
-
-static const uint8_t pattern512[] = {
- 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15,
- 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31,
- 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47,
- 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 62, 63,
- 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15,
- 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31,
- 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47,
- 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 62, 63,
- 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15,
- 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31,
- 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47,
- 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 62, 63,
- 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15,
- 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31,
- 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47,
- 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 62, 63,
- 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15,
- 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31,
- 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47,
- 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 62, 63,
- 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15,
- 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31,
- 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47,
- 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 62, 63,
- 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15,
- 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31,
- 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47,
- 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 62, 63,
- 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15,
- 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31,
- 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47,
- 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 62, 63
-};
-
/****************************************************************************
* Test cases.
****************************************************************************/
@@ -136,6 +88,7 @@ static void mfs_test_001_001_execute(void) {
ferr = bank_erase(MFS_BANK_1);
test_assert(ferr == FLASH_NO_ERROR, "Bank 1 erase failure");
}
+ test_end_step(1);
/* [1.1.2] Calling mfsStart() on an uninitialized flash array,
MFS_NO_ERROR is expected.*/
@@ -146,6 +99,7 @@ static void mfs_test_001_001_execute(void) {
err = mfsStart(&mfs1, &mfscfg1);
test_assert(err == MFS_NO_ERROR, "initialization error with erased flash");
}
+ test_end_step(2);
/* [1.1.3] Calling mfsStart() on a newly initialized flash array,
MFS_NO_ERROR is expected.*/
@@ -156,6 +110,7 @@ static void mfs_test_001_001_execute(void) {
err = mfsStart(&mfs1, &mfscfg1);
test_assert(err == MFS_NO_ERROR, "initialization error with initialized flash");
}
+ test_end_step(3);
}
static const testcase_t mfs_test_001_001 = {
@@ -203,6 +158,7 @@ static void mfs_test_001_002_execute(void) {
"found a record that should not exists");
}
}
+ test_end_step(1);
}
static const testcase_t mfs_test_001_002 = {
@@ -253,6 +209,7 @@ static void mfs_test_001_003_execute(void) {
mfs_error_t err = mfsReadRecord(&mfs1, 1, &size, mfs_buffer);
test_assert(err == MFS_ERR_NOT_FOUND , "record was already present");
}
+ test_end_step(1);
/* [1.3.2] Creating the record then retrieving it again, MFS_NO_ERROR
is expected, record content and size are compared with the
@@ -261,14 +218,15 @@ static void mfs_test_001_003_execute(void) {
{
mfs_error_t err;
- err = mfsWriteRecord(&mfs1, 1, sizeof pattern1, pattern1);
+ err = mfsWriteRecord(&mfs1, 1, sizeof mfs_pattern16, mfs_pattern16);
test_assert(err == MFS_NO_ERROR, "error creating the record");
size = sizeof mfs_buffer;
err = mfsReadRecord(&mfs1, 1, &size, mfs_buffer);
test_assert(err == MFS_NO_ERROR, "record not found");
- test_assert(size == sizeof pattern1, "unexpected record length");
- test_assert(memcmp(pattern1, mfs_buffer, size) == 0, "wrong record content");
+ test_assert(size == sizeof mfs_pattern16, "unexpected record length");
+ test_assert(memcmp(mfs_pattern16, mfs_buffer, size) == 0, "wrong record content");
}
+ test_end_step(2);
/* [1.3.3] Updating the record then retrieving it again, MFS_NO_ERROR
is expected, record content and size are compared with the
@@ -277,14 +235,15 @@ static void mfs_test_001_003_execute(void) {
{
mfs_error_t err;
- err = mfsWriteRecord(&mfs1, 1, sizeof pattern2, pattern2);
+ err = mfsWriteRecord(&mfs1, 1, sizeof mfs_pattern32, mfs_pattern32);
test_assert(err == MFS_NO_ERROR, "error updating the record");
size = sizeof mfs_buffer;
err = mfsReadRecord(&mfs1, 1, &size, mfs_buffer);
test_assert(err == MFS_NO_ERROR, "record not found");
- test_assert(size == sizeof pattern2, "unexpected record length");
- test_assert(memcmp(pattern2, mfs_buffer, size) == 0, "wrong record content");
+ test_assert(size == sizeof mfs_pattern32, "unexpected record length");
+ test_assert(memcmp(mfs_pattern32, mfs_buffer, size) == 0, "wrong record content");
}
+ test_end_step(3);
/* [1.3.4] Erasing the record then trying to retrieve it again,
MFS_NO_ERROR is expected on erase, MFS_ERR_NOT_FOUND is expected
@@ -299,6 +258,7 @@ static void mfs_test_001_003_execute(void) {
err = mfsReadRecord(&mfs1, 1, &size, mfs_buffer);
test_assert(err == MFS_ERR_NOT_FOUND, "record not erased");
}
+ test_end_step(4);
}
static const testcase_t mfs_test_001_003 = {
@@ -341,13 +301,14 @@ static void mfs_test_001_004_execute(void) {
{
mfs_error_t err;
- err = mfsWriteRecord(&mfs1, 1, sizeof pattern1, pattern1);
+ err = mfsWriteRecord(&mfs1, 1, sizeof mfs_pattern16, mfs_pattern16);
test_assert(err == MFS_NO_ERROR, "error creating record 1");
- err = mfsWriteRecord(&mfs1, 2, sizeof pattern2, pattern2);
+ err = mfsWriteRecord(&mfs1, 2, sizeof mfs_pattern32, mfs_pattern32);
test_assert(err == MFS_NO_ERROR, "error creating record 2");
- err = mfsWriteRecord(&mfs1, 3, sizeof pattern3, pattern3);
+ err = mfsWriteRecord(&mfs1, 3, sizeof mfs_pattern10, mfs_pattern10);
test_assert(err == MFS_NO_ERROR, "error creating record 3");
}
+ test_end_step(1);
/* [1.4.2] Records must exist.*/
test_set_step(2);
@@ -365,6 +326,7 @@ static void mfs_test_001_004_execute(void) {
err = mfsReadRecord(&mfs1, 3, &size, mfs_buffer);
test_assert(err == MFS_NO_ERROR, "record 2 not present");
}
+ test_end_step(2);
/* [1.4.3] Re-mounting, records must still exist.*/
test_set_step(3);
@@ -384,6 +346,7 @@ static void mfs_test_001_004_execute(void) {
err = mfsReadRecord(&mfs1, 3, &size, mfs_buffer);
test_assert(err == MFS_NO_ERROR, "record 2 not present");
}
+ test_end_step(3);
/* [1.4.4] Erasing storage and verify that the records have been
removed, MFS_NO_ERROR is expected on erase, MFS_ERR_NOT_FOUND is
@@ -405,6 +368,7 @@ static void mfs_test_001_004_execute(void) {
err = mfsReadRecord(&mfs1, 3, &size, mfs_buffer);
test_assert(err == MFS_ERR_NOT_FOUND, "record 2 still present");
}
+ test_end_step(4);
}
static const testcase_t mfs_test_001_004 = {
@@ -448,24 +412,25 @@ static void mfs_test_001_005_execute(void) {
{
mfs_id_t id;
mfs_id_t id_max = (mfscfg1.bank_size - sizeof (mfs_bank_header_t)) /
- (sizeof (mfs_data_header_t) + sizeof pattern512);
+ (sizeof (mfs_data_header_t) + sizeof mfs_pattern512);
for (id = 1; id <= id_max; id++) {
mfs_error_t err;
size_t size;
- err = mfsWriteRecord(&mfs1, id, sizeof pattern512, pattern512);
+ err = mfsWriteRecord(&mfs1, id, sizeof mfs_pattern512, mfs_pattern512);
test_assert(err == MFS_NO_ERROR, "error creating the record");
size = sizeof mfs_buffer;
err = mfsReadRecord(&mfs1, id, &size, mfs_buffer);
test_assert(err == MFS_NO_ERROR,
"record not found");
- test_assert(size == sizeof pattern512,
+ test_assert(size == sizeof mfs_pattern512,
"unexpected record length");
- test_assert(memcmp(pattern512, mfs_buffer, size) == 0,
+ test_assert(memcmp(mfs_pattern512, mfs_buffer, size) == 0,
"wrong record content");
}
}
+ test_end_step(1);
/* [1.5.2] Creating one more record, should fail, MFS_ERR_OUT_OF_MEM
is expected.*/
@@ -473,11 +438,12 @@ static void mfs_test_001_005_execute(void) {
{
mfs_error_t err;
mfs_id_t id_max = (mfscfg1.bank_size - sizeof (mfs_bank_header_t)) /
- (sizeof (mfs_data_header_t) + sizeof pattern512);
+ (sizeof (mfs_data_header_t) + sizeof mfs_pattern512);
- err = mfsWriteRecord(&mfs1, id_max, sizeof pattern512 , pattern512);
+ err = mfsWriteRecord(&mfs1, id_max, sizeof mfs_pattern512 , mfs_pattern512);
test_assert(err == MFS_ERR_OUT_OF_MEM, "creation didn't fail");
}
+ test_end_step(2);
/* [1.5.3] Adding a smaller record to fill the final gap. A
reinitialization is performed and MFS_NO_ERROR is expected.*/
@@ -493,7 +459,7 @@ static void mfs_test_001_005_execute(void) {
if (remaining > sizeof (mfs_data_header_t) * 2) {
err = mfsWriteRecord(&mfs1, MFS_CFG_MAX_RECORDS,
remaining - (sizeof (mfs_data_header_t) * 2),
- pattern512);
+ mfs_pattern512);
test_assert(err == MFS_NO_ERROR, "error filling remaining space");
err = mfsEraseRecord(&mfs1, MFS_CFG_MAX_RECORDS);
test_assert(err == MFS_NO_ERROR, "error filling remaining space");
@@ -515,6 +481,7 @@ static void mfs_test_001_005_execute(void) {
err = mfsStart(&mfs1, &mfscfg1);
test_assert(err == MFS_NO_ERROR, "initialization error");
}
+ test_end_step(3);
}
static const testcase_t mfs_test_001_005 = {
@@ -566,24 +533,25 @@ static void mfs_test_001_006_execute(void) {
{
mfs_id_t id;
mfs_id_t id_max = (mfscfg1.bank_size - sizeof (mfs_bank_header_t)) /
- (sizeof (mfs_data_header_t) + sizeof pattern512);
+ (sizeof (mfs_data_header_t) + sizeof mfs_pattern512);
for (id = 1; id <= id_max; id++) {
mfs_error_t err;
size_t size;
- err = mfsWriteRecord(&mfs1, id, sizeof pattern512, pattern512);
+ err = mfsWriteRecord(&mfs1, id, sizeof mfs_pattern512, mfs_pattern512);
test_assert(err == MFS_NO_ERROR, "error creating the record");
size = sizeof mfs_buffer;
err = mfsReadRecord(&mfs1, id, &size, mfs_buffer);
test_assert(err == MFS_NO_ERROR,
"record not found");
- test_assert(size == sizeof pattern512,
+ test_assert(size == sizeof mfs_pattern512,
"unexpected record length");
- test_assert(memcmp(pattern512, mfs_buffer, size) == 0,
+ test_assert(memcmp(mfs_pattern512, mfs_buffer, size) == 0,
"wrong record content");
}
}
+ test_end_step(1);
/* [1.6.2] Erasing one record, MFS_NO_ERROR is expected.*/
test_set_step(2);
@@ -597,6 +565,7 @@ static void mfs_test_001_006_execute(void) {
err = mfsReadRecord(&mfs1, 1, &size, mfs_buffer);
test_assert(err == MFS_ERR_NOT_FOUND, "record not erased");
}
+ test_end_step(2);
/* [1.6.3] Writing one more record triggers garbage collection,
MFS_WARN_GC is expected, KS state is checked for correctness after
@@ -607,17 +576,19 @@ static void mfs_test_001_006_execute(void) {
size_t size;
test_assert(mfs1.current_counter == 1, "not first instance");
- err = mfsWriteRecord(&mfs1, 1, sizeof pattern512, pattern512);
+ err = mfsWriteRecord(&mfs1, 1, sizeof mfs_pattern512, mfs_pattern512);
test_assert(err == MFS_WARN_GC, "error creating the record");
test_assert(mfs1.current_counter == 2, "not second instance");
size = sizeof mfs_buffer;
err = mfsReadRecord(&mfs1, 1, &size, mfs_buffer);
test_assert(err == MFS_NO_ERROR, "record not found");
- test_assert(size == sizeof pattern512, "unexpected record length");
- test_assert(memcmp(pattern512, mfs_buffer, size) == 0, "wrong record content");
+ test_assert(size == sizeof mfs_pattern512, "unexpected record length");
+ test_assert(memcmp(mfs_pattern512, mfs_buffer, size) == 0,
+ "wrong record content");
test_assert(mfs1.current_bank == MFS_BANK_1, "unexpected bank");
test_assert(bank_verify_erased(MFS_BANK_0) == FLASH_NO_ERROR, "bank 0 not erased");
}
+ test_end_step(3);
/* [1.6.4] Checking for all records in the new bank, MFS_NOERROR is
expected for each record.*/
@@ -625,7 +596,7 @@ static void mfs_test_001_006_execute(void) {
{
mfs_id_t id;
mfs_id_t id_max = (mfscfg1.bank_size - sizeof (mfs_bank_header_t)) /
- (sizeof (mfs_data_header_t) + sizeof pattern512);
+ (sizeof (mfs_data_header_t) + sizeof mfs_pattern512);
for (id = 1; id <= MFS_CFG_MAX_RECORDS; id++) {
mfs_error_t err;
@@ -635,8 +606,9 @@ static void mfs_test_001_006_execute(void) {
size = sizeof mfs_buffer;
err = mfsReadRecord(&mfs1, id, &size, mfs_buffer);
test_assert(err == MFS_NO_ERROR, "record not found");
- test_assert(size == sizeof pattern512, "unexpected record length");
- test_assert(memcmp(pattern512, mfs_buffer, size) == 0, "wrong record content");
+ test_assert(size == sizeof mfs_pattern512, "unexpected record length");
+ test_assert(memcmp(mfs_pattern512, mfs_buffer, size) == 0,
+ "wrong record content");
}
else {
size = sizeof mfs_buffer;
@@ -645,6 +617,7 @@ static void mfs_test_001_006_execute(void) {
}
}
}
+ test_end_step(4);
/* [1.6.5] Erasing one record, MFS_NO_ERROR is expected.*/
test_set_step(5);
@@ -658,6 +631,7 @@ static void mfs_test_001_006_execute(void) {
err = mfsReadRecord(&mfs1, 1, &size, mfs_buffer);
test_assert(err == MFS_ERR_NOT_FOUND, "record not erased");
}
+ test_end_step(5);
/* [1.6.6] Writing one more record triggers garbage collection,
MFS_WARN_GC is expected, MFS object state is checked for
@@ -668,17 +642,19 @@ static void mfs_test_001_006_execute(void) {
size_t size;
test_assert(mfs1.current_counter == 2, "not second instance");
- err = mfsWriteRecord(&mfs1, 1, sizeof pattern512, pattern512);
+ err = mfsWriteRecord(&mfs1, 1, sizeof mfs_pattern512, mfs_pattern512);
test_assert(err == MFS_WARN_GC, "error creating the record");
test_assert(mfs1.current_counter == 3, "not third instance");
size = sizeof mfs_buffer;
err = mfsReadRecord(&mfs1, 1, &size, mfs_buffer);
test_assert(err == MFS_NO_ERROR, "record not found");
- test_assert(size == sizeof pattern512, "unexpected record length");
- test_assert(memcmp(pattern512, mfs_buffer, size) == 0, "wrong record content");
+ test_assert(size == sizeof mfs_pattern512, "unexpected record length");
+ test_assert(memcmp(mfs_pattern512, mfs_buffer, size) == 0,
+ "wrong record content");
test_assert(mfs1.current_bank == MFS_BANK_0, "unexpected bank");
test_assert(bank_verify_erased(MFS_BANK_1) == FLASH_NO_ERROR, "bank 1 not erased");
}
+ test_end_step(6);
/* [1.6.7] Checking for all records in the new bank, MFS_NO_ERROR is
expected for each record.*/
@@ -686,7 +662,7 @@ static void mfs_test_001_006_execute(void) {
{
mfs_id_t id;
mfs_id_t id_max = (mfscfg1.bank_size - sizeof (mfs_bank_header_t)) /
- (sizeof (mfs_data_header_t) + sizeof pattern512);
+ (sizeof (mfs_data_header_t) + sizeof mfs_pattern512);
for (id = 1; id <= MFS_CFG_MAX_RECORDS; id++) {
mfs_error_t err;
@@ -696,8 +672,9 @@ static void mfs_test_001_006_execute(void) {
size = sizeof mfs_buffer;
err = mfsReadRecord(&mfs1, id, &size, mfs_buffer);
test_assert(err == MFS_NO_ERROR, "record not found");
- test_assert(size == sizeof pattern512, "unexpected record length");
- test_assert(memcmp(pattern512, mfs_buffer, size) == 0, "wrong record content");
+ test_assert(size == sizeof mfs_pattern512, "unexpected record length");
+ test_assert(memcmp(mfs_pattern512, mfs_buffer, size) == 0,
+ "wrong record content");
}
else {
size = sizeof mfs_buffer;
@@ -706,6 +683,7 @@ static void mfs_test_001_006_execute(void) {
}
}
}
+ test_end_step(7);
}
static const testcase_t mfs_test_001_006 = {
@@ -749,21 +727,23 @@ static void mfs_test_001_007_execute(void) {
{
mfs_id_t id;
mfs_id_t id_max = (mfscfg1.bank_size - sizeof (mfs_bank_header_t)) /
- (sizeof (mfs_data_header_t) + (sizeof pattern512 / 2));
+ (sizeof (mfs_data_header_t) + (sizeof mfs_pattern512 / 2));
for (id = 1; id <= id_max; id++) {
mfs_error_t err;
size_t size;
- err = mfsWriteRecord(&mfs1, id, (sizeof pattern512 / 2), pattern512);
+ err = mfsWriteRecord(&mfs1, id, (sizeof mfs_pattern512 / 2), mfs_pattern512);
test_assert(err == MFS_NO_ERROR, "error creating the record");
size = sizeof mfs_buffer;
err = mfsReadRecord(&mfs1, id, &size, mfs_buffer);
test_assert(err == MFS_NO_ERROR, "record not found");
- test_assert(size == (sizeof pattern512 / 2), "unexpected record length");
- test_assert(memcmp(pattern512, mfs_buffer, size) == 0, "wrong record content");
+ test_assert(size == (sizeof mfs_pattern512 / 2), "unexpected record length");
+ test_assert(memcmp(mfs_pattern512, mfs_buffer, size) == 0,
+ "wrong record content");
}
}
+ test_end_step(1);
/* [1.7.2] Erase records until the flash bank is filled entirely.*/
test_set_step(2);
@@ -772,9 +752,9 @@ static void mfs_test_001_007_execute(void) {
size_t size;
mfs_id_t id;
mfs_id_t id_max = (mfscfg1.bank_size - sizeof (mfs_bank_header_t)) /
- (sizeof (mfs_data_header_t) + (sizeof pattern512 / 2));
+ (sizeof (mfs_data_header_t) + (sizeof mfs_pattern512 / 2));
mfs_id_t n = ((mfscfg1.bank_size - sizeof (mfs_bank_header_t)) -
- (id_max * (sizeof (mfs_data_header_t) + (sizeof pattern512 / 2)))) /
+ (id_max * (sizeof (mfs_data_header_t) + (sizeof mfs_pattern512 / 2)))) /
sizeof (mfs_data_header_t);
for (id = 1; id <= n; id++) {
@@ -785,6 +765,7 @@ static void mfs_test_001_007_execute(void) {
test_assert(err == MFS_ERR_NOT_FOUND, "record not erased");
}
}
+ test_end_step(2);
/* [1.7.3] Erasing one more record triggers garbage collection,
MFS_WARN_GC is expected, KS state is checked for correctness after
@@ -794,7 +775,7 @@ static void mfs_test_001_007_execute(void) {
mfs_error_t err;
size_t size;
mfs_id_t id_max = (mfscfg1.bank_size - sizeof (mfs_bank_header_t)) /
- (sizeof (mfs_data_header_t) + (sizeof pattern512 / 2));
+ (sizeof (mfs_data_header_t) + (sizeof mfs_pattern512 / 2));
test_assert(mfs1.current_counter == 1, "not first instance");
err = mfsEraseRecord(&mfs1, id_max);
@@ -806,6 +787,7 @@ static void mfs_test_001_007_execute(void) {
test_assert(mfs1.current_bank == MFS_BANK_1, "unexpected bank");
test_assert(bank_verify_erased(MFS_BANK_0) == FLASH_NO_ERROR, "bank 0 not erased");
}
+ test_end_step(3);
}
static const testcase_t mfs_test_001_007 = {
diff --git a/test/mfs/source/test/mfs_test_sequence_002.c b/test/mfs/source/test/mfs_test_sequence_002.c
index 735b359df..c75858ea2 100644
--- a/test/mfs/source/test/mfs_test_sequence_002.c
+++ b/test/mfs/source/test/mfs_test_sequence_002.c
@@ -21,17 +21,18 @@
* @file mfs_test_sequence_002.c
* @brief Test Sequence 002 code.
*
- * @page mfs_test_sequence_002 [2] API Invalid Cases tests
+ * @page mfs_test_sequence_002 [2] Transaction Mode tests
*
* File: @ref mfs_test_sequence_002.c
*
* Description
- * This test sequence tests the error coded returned by the various
- * APIs when called when the system is not initialized.
+ * This sequence tests the MFS behavior when used in transaction mode,
+ * correct cases and expected error cases are tested.
*
* Test Cases
* - @subpage mfs_test_002_001
* - @subpage mfs_test_002_002
+ * - @subpage mfs_test_002_003
* .
*/
@@ -39,6 +40,7 @@
* Shared code.
****************************************************************************/
+#include
#include "hal_mfs.h"
/****************************************************************************
@@ -46,91 +48,277 @@
****************************************************************************/
/**
- * @page mfs_test_002_001 [2.1] Initialization error from APIs
+ * @page mfs_test_002_001 [2.1] Committing a transaction
*
* Description
- * The API functions are invoked without prior initialization.
+ * A set of new/existing records are written/erased within a
+ * transaction then the transaction is committed, the state is checked
+ * afterward.
*
* Test Steps
- * - [2.1.1] The function mfsErase() is called, MFS_ERR_INV_STATE is
- * expected.
- * - [2.1.2] The function mfsWriteRecord() is called, MFS_ERR_INV_STATE
+ * - [2.1.1] Records 1, 2 and 3 are created, MFS_NO_ERROR is expected.
+ * - [2.1.2] Presence of records 1, 2 and 3 is verified, MFS_NO_ERROR
* is expected.
- * - [2.1.3] The function mfsEraseRecord() is called, MFS_ERR_INV_STATE
- * is expected.
- * - [2.1.4] The function mfsReadRecord() is called, MFS_ERR_INV_STATE
- * is expected.
- * - [2.1.5] The function mfsPerformGarbageCollection() is called,
- * MFS_ERR_INV_STATE is expected.
+ * - [2.1.3] Starting a transaction with sufficient pre-allocated
+ * space, MFS_NO_ERROR is expected.
+ * - [2.1.4] Atomically erasing record 1, updating record 2, reading
+ * record 3.
+ * - [2.1.5] Committing the transaction, MFS_NO_ERROR is expected.
+ * - [2.1.6] Testing outcome, records 1 must not be present, record 2
+ * must contain the new value and record 3 must be unchanged.
+ * - [2.1.7] Re-mounting the manage storage, MFS_NO_ERROR is expected.
+ * - [2.1.8] Testing outcome again after re-start.
+ * - [2.1.9] Performing a garbage collection, the result must not
+ * change.
+ * - [2.1.10] Testing outcome again after garbage collection.
* .
*/
-static void mfs_test_002_001_execute(void) {
+static void mfs_test_002_001_setup(void) {
+ bank_erase(MFS_BANK_0);
+ bank_erase(MFS_BANK_1);
+ mfsStart(&mfs1, &mfscfg1);
+}
- /* [2.1.1] The function mfsErase() is called, MFS_ERR_INV_STATE is
+static void mfs_test_002_001_teardown(void) {
+ mfsStop(&mfs1);
+}
+
+static void mfs_test_002_001_execute(void) {
+ uint32_t current_counter;
+ uint32_t used_space;
+
+ /* [2.1.1] Records 1, 2 and 3 are created, MFS_NO_ERROR is
expected.*/
test_set_step(1);
{
- mfs_error_t err = mfsErase(&mfs1);
- test_assert(err == MFS_ERR_INV_STATE, "mfsErase() returned wrong status");
- }
+ mfs_error_t err;
- /* [2.1.2] The function mfsWriteRecord() is called, MFS_ERR_INV_STATE
+ err = mfsWriteRecord(&mfs1, 1, sizeof mfs_pattern16, mfs_pattern16);
+ test_assert(err == MFS_NO_ERROR, "error creating record 1");
+ err = mfsWriteRecord(&mfs1, 2, sizeof mfs_pattern16, mfs_pattern16);
+ test_assert(err == MFS_NO_ERROR, "error creating record 2");
+ err = mfsWriteRecord(&mfs1, 3, sizeof mfs_pattern16, mfs_pattern16);
+ test_assert(err == MFS_NO_ERROR, "error creating record 3");
+ }
+ test_end_step(1);
+
+ /* [2.1.2] Presence of records 1, 2 and 3 is verified, MFS_NO_ERROR
is expected.*/
test_set_step(2);
{
- mfs_error_t err = mfsWriteRecord(&mfs1, 1, 16, mfs_buffer);
- test_assert(err == MFS_ERR_INV_STATE, "mfsWriteRecord() returned wrong status");
- }
+ mfs_error_t err;
+ size_t size;
- /* [2.1.3] The function mfsEraseRecord() is called, MFS_ERR_INV_STATE
- is expected.*/
+ size = sizeof mfs_buffer;
+ err = mfsReadRecord(&mfs1, 1, &size, mfs_buffer);
+ test_assert(err == MFS_NO_ERROR, "record not found");
+ size = sizeof mfs_buffer;
+ err = mfsReadRecord(&mfs1, 2, &size, mfs_buffer);
+ test_assert(err == MFS_NO_ERROR, "record not found");
+ size = sizeof mfs_buffer;
+ err = mfsReadRecord(&mfs1, 3, &size, mfs_buffer);
+ test_assert(err == MFS_NO_ERROR, "record not found");
+ }
+ test_end_step(2);
+
+ /* [2.1.3] Starting a transaction with sufficient pre-allocated
+ space, MFS_NO_ERROR is expected.*/
test_set_step(3);
{
- mfs_error_t err = mfsEraseRecord(&mfs1, 1);
- test_assert(err == MFS_ERR_INV_STATE, "mfsEraseRecord() returned wrong status");
- }
+ mfs_error_t err;
- /* [2.1.4] The function mfsReadRecord() is called, MFS_ERR_INV_STATE
- is expected.*/
+ err = mfsStartTransaction(&mfs1, 1024U);
+ test_assert(err == MFS_NO_ERROR, "error starting transaction");
+ }
+ test_end_step(3);
+
+ /* [2.1.4] Atomically erasing record 1, updating record 2, reading
+ record 3.*/
test_set_step(4);
{
- size_t size = sizeof mfs_buffer;
- mfs_error_t err = mfsReadRecord(&mfs1, 1, &size, mfs_buffer);
- test_assert(err == MFS_ERR_INV_STATE, "mfsReadRecord() returned wrong status");
- }
+ mfs_error_t err;
+ size_t size;
- /* [2.1.5] The function mfsPerformGarbageCollection() is called,
- MFS_ERR_INV_STATE is expected.*/
+ err = mfsEraseRecord(&mfs1, 1);
+ test_assert(err == MFS_NO_ERROR, "error erasing record 1");
+ err = mfsWriteRecord(&mfs1, 2, sizeof mfs_pattern32, mfs_pattern32);
+ test_assert(err == MFS_NO_ERROR, "error writing record 2");
+ size = sizeof mfs_buffer;
+ err = mfsReadRecord(&mfs1, 3, &size, mfs_buffer);
+ test_assert(err == MFS_NO_ERROR, "record not found");
+ test_assert(size == sizeof mfs_pattern16, "unexpected record length");
+ test_assert(memcmp(mfs_pattern16, mfs_buffer, size) == 0, "wrong record content");
+ }
+ test_end_step(4);
+
+ /* [2.1.5] Committing the transaction, MFS_NO_ERROR is expected.*/
test_set_step(5);
{
- mfs_error_t err = mfsPerformGarbageCollection(&mfs1);
- test_assert(err == MFS_ERR_INV_STATE, "mfsPerformGarbageCollection() returned wrong status");
+ mfs_error_t err;
+
+ err = mfsCommitTransaction(&mfs1);
+ test_assert(err == MFS_NO_ERROR, "error committing transaction");
+
+ /* Saving some internal state for successive checks.*/
+ current_counter = mfs1.current_counter;
+ used_space = mfs1.used_space;
}
+ test_end_step(5);
+
+ /* [2.1.6] Testing outcome, records 1 must not be present, record 2
+ must contain the new value and record 3 must be unchanged.*/
+ test_set_step(6);
+ {
+ mfs_error_t err;
+ size_t size;
+
+ /* Record 1 must not be present.*/
+ size = sizeof mfs_buffer;
+ err = mfsReadRecord(&mfs1, 1, &size, mfs_buffer);
+ test_assert(err == MFS_ERR_NOT_FOUND, "record found");
+
+ /* Record 2 must contain the new value.*/
+ size = sizeof mfs_buffer;
+ err = mfsReadRecord(&mfs1, 2, &size, mfs_buffer);
+ test_assert(err == MFS_NO_ERROR, "record not found");
+ test_assert(size == sizeof mfs_pattern32, "unexpected record length");
+ test_assert(memcmp(mfs_pattern32, mfs_buffer, size) == 0, "wrong record content");
+
+ /* Record 3 must be unchanged.*/
+ size = sizeof mfs_buffer;
+ err = mfsReadRecord(&mfs1, 3, &size, mfs_buffer);
+ test_assert(err == MFS_NO_ERROR, "record not found");
+ test_assert(size == sizeof mfs_pattern16, "unexpected record length");
+ test_assert(memcmp(mfs_pattern16, mfs_buffer, size) == 0, "wrong record content");
+
+ /* Checking internal data.*/
+ test_assert(MFS_BANK_0 == mfs1.current_bank, "internal data mismatch");
+ test_assert(current_counter == mfs1.current_counter, "internal data mismatch");
+ test_assert(used_space == mfs1.used_space, "internal data mismatch");
+ }
+ test_end_step(6);
+
+ /* [2.1.7] Re-mounting the manage storage, MFS_NO_ERROR is
+ expected.*/
+ test_set_step(7);
+ {
+ mfs_error_t err;
+
+ err = mfsStart(&mfs1, &mfscfg1);
+ test_assert(err == MFS_NO_ERROR, "re-start failed");
+ }
+ test_end_step(7);
+
+ /* [2.1.8] Testing outcome again after re-start.*/
+ test_set_step(8);
+ {
+ mfs_error_t err;
+ size_t size;
+
+ /* Record 1 must not be present.*/
+ size = sizeof mfs_buffer;
+ err = mfsReadRecord(&mfs1, 1, &size, mfs_buffer);
+ test_assert(err == MFS_ERR_NOT_FOUND, "record found");
+
+ /* Record 2 must contain the new value.*/
+ size = sizeof mfs_buffer;
+ err = mfsReadRecord(&mfs1, 2, &size, mfs_buffer);
+ test_assert(err == MFS_NO_ERROR, "record not found");
+ test_assert(size == sizeof mfs_pattern32, "unexpected record length");
+ test_assert(memcmp(mfs_pattern32, mfs_buffer, size) == 0, "wrong record content");
+
+ /* Record 3 must be unchanged.*/
+ size = sizeof mfs_buffer;
+ err = mfsReadRecord(&mfs1, 3, &size, mfs_buffer);
+ test_assert(err == MFS_NO_ERROR, "record not found");
+ test_assert(size == sizeof mfs_pattern16, "unexpected record length");
+ test_assert(memcmp(mfs_pattern16, mfs_buffer, size) == 0, "wrong record content");
+
+ /* Checking internal data.*/
+ test_assert(MFS_BANK_0 == mfs1.current_bank, "internal data mismatch");
+ test_assert(current_counter == mfs1.current_counter, "internal data mismatch");
+ test_assert(used_space == mfs1.used_space, "internal data mismatch");
+ }
+ test_end_step(8);
+
+ /* [2.1.9] Performing a garbage collection, the result must not
+ change.*/
+ test_set_step(9);
+ {
+ mfs_error_t err;
+
+ err = mfsPerformGarbageCollection(&mfs1);
+ test_assert(err == MFS_NO_ERROR, "garbage collection failed");
+ }
+ test_end_step(9);
+
+ /* [2.1.10] Testing outcome again after garbage collection.*/
+ test_set_step(10);
+ {
+ mfs_error_t err;
+ size_t size;
+
+ /* Record 1 must not be present.*/
+ size = sizeof mfs_buffer;
+ err = mfsReadRecord(&mfs1, 1, &size, mfs_buffer);
+ test_assert(err == MFS_ERR_NOT_FOUND, "record found");
+
+ /* Record 2 must contain the new value.*/
+ size = sizeof mfs_buffer;
+ err = mfsReadRecord(&mfs1, 2, &size, mfs_buffer);
+ test_assert(err == MFS_NO_ERROR, "record not found");
+ test_assert(size == sizeof mfs_pattern32, "unexpected record length");
+ test_assert(memcmp(mfs_pattern32, mfs_buffer, size) == 0, "wrong record content");
+
+ /* Record 3 must be unchanged.*/
+ size = sizeof mfs_buffer;
+ err = mfsReadRecord(&mfs1, 3, &size, mfs_buffer);
+ test_assert(err == MFS_NO_ERROR, "record not found");
+ test_assert(size == sizeof mfs_pattern16, "unexpected record length");
+ test_assert(memcmp(mfs_pattern16, mfs_buffer, size) == 0, "wrong record content");
+
+ /* Checking internal data.*/
+ test_assert(MFS_BANK_1 == mfs1.current_bank, "internal data mismatch");
+ test_assert(current_counter == mfs1.current_counter - 1, "internal data mismatch");
+ test_assert(used_space == mfs1.used_space, "internal data mismatch");
+ }
+ test_end_step(10);
}
static const testcase_t mfs_test_002_001 = {
- "Initialization error from APIs",
- NULL,
- NULL,
+ "Committing a transaction",
+ mfs_test_002_001_setup,
+ mfs_test_002_001_teardown,
mfs_test_002_001_execute
};
/**
- * @page mfs_test_002_002 [2.2] Erasing non existing record
+ * @page mfs_test_002_002 [2.2] Rolling back a transaction
*
* Description
- * An erase operation is attempted on an non-existing record.
+ * A set of new/existing records are written/erased within a
+ * transaction then the transaction is rolled back, the state is
+ * checked afterward.
*
* Test Steps
- * - [2.2.1] Record one is erased, the error MFS_ERR_NOT_FOUND is
- * expected.
+ * - [2.2.1] Records 1, 2 and 3 are created, MFS_NO_ERROR is expected.
+ * - [2.2.2] Presence of records 1, 2 and 3 is verified, MFS_NO_ERROR
+ * is expected.
+ * - [2.2.3] Starting a transaction with sufficient pre-allocated
+ * space, MFS_NO_ERROR is expected..
+ * - [2.2.4] Atomically erasing record 1, updating record 2, reading
+ * record 3.
+ * - [2.2.5] Rolling back the transaction, MFS_NO_ERROR is expected.
+ * - [2.2.6] State must not have changed, records 1, 2 and 3 must still
+ * be there unchanged.
* .
*/
static void mfs_test_002_002_setup(void) {
+ bank_erase(MFS_BANK_0);
+ bank_erase(MFS_BANK_1);
mfsStart(&mfs1, &mfscfg1);
- mfsErase(&mfs1);
}
static void mfs_test_002_002_teardown(void) {
@@ -138,26 +326,249 @@ static void mfs_test_002_002_teardown(void) {
}
static void mfs_test_002_002_execute(void) {
+ uint32_t current_counter;
+ uint32_t used_space;
- /* [2.2.1] Record one is erased, the error MFS_ERR_NOT_FOUND is
+ /* [2.2.1] Records 1, 2 and 3 are created, MFS_NO_ERROR is
expected.*/
test_set_step(1);
{
mfs_error_t err;
- err = mfsEraseRecord(&mfs1, 1);
- test_assert(err != MFS_NO_ERROR, "record was present");
- test_assert(err == MFS_ERR_NOT_FOUND, "invalid error code");
+ err = mfsWriteRecord(&mfs1, 1, sizeof mfs_pattern16, mfs_pattern16);
+ test_assert(err == MFS_NO_ERROR, "error creating record 1");
+ err = mfsWriteRecord(&mfs1, 2, sizeof mfs_pattern16, mfs_pattern16);
+ test_assert(err == MFS_NO_ERROR, "error creating record 2");
+ err = mfsWriteRecord(&mfs1, 3, sizeof mfs_pattern16, mfs_pattern16);
+ test_assert(err == MFS_NO_ERROR, "error creating record 3");
}
+ test_end_step(1);
+
+ /* [2.2.2] Presence of records 1, 2 and 3 is verified, MFS_NO_ERROR
+ is expected.*/
+ test_set_step(2);
+ {
+ mfs_error_t err;
+ size_t size;
+
+ size = sizeof mfs_buffer;
+ err = mfsReadRecord(&mfs1, 1, &size, mfs_buffer);
+ test_assert(err == MFS_NO_ERROR, "record not found");
+ size = sizeof mfs_buffer;
+ err = mfsReadRecord(&mfs1, 2, &size, mfs_buffer);
+ test_assert(err == MFS_NO_ERROR, "record not found");
+ size = sizeof mfs_buffer;
+ err = mfsReadRecord(&mfs1, 3, &size, mfs_buffer);
+ test_assert(err == MFS_NO_ERROR, "record not found");
+ }
+ test_end_step(2);
+
+ /* [2.2.3] Starting a transaction with sufficient pre-allocated
+ space, MFS_NO_ERROR is expected..*/
+ test_set_step(3);
+ {
+ mfs_error_t err;
+
+ err = mfsStartTransaction(&mfs1, 1024U);
+ test_assert(err == MFS_NO_ERROR, "error starting transaction");
+ }
+ test_end_step(3);
+
+ /* [2.2.4] Atomically erasing record 1, updating record 2, reading
+ record 3.*/
+ test_set_step(4);
+ {
+ mfs_error_t err;
+ size_t size;
+
+ err = mfsEraseRecord(&mfs1, 1);
+ test_assert(err == MFS_NO_ERROR, "error erasing record 1");
+ err = mfsWriteRecord(&mfs1, 2, sizeof mfs_pattern32, mfs_pattern32);
+ test_assert(err == MFS_NO_ERROR, "error writing record 2");
+ size = sizeof mfs_buffer;
+ err = mfsReadRecord(&mfs1, 3, &size, mfs_buffer);
+ test_assert(err == MFS_NO_ERROR, "record not found");
+ test_assert(size == sizeof mfs_pattern16, "unexpected record length");
+ test_assert(memcmp(mfs_pattern16, mfs_buffer, size) == 0, "wrong record content");
+
+ /* Saving some internal state for successive checks.*/
+ current_counter = mfs1.current_counter;
+ used_space = mfs1.used_space;
+ }
+ test_end_step(4);
+
+ /* [2.2.5] Rolling back the transaction, MFS_NO_ERROR is expected.*/
+ test_set_step(5);
+ {
+ mfs_error_t err;
+
+ err = mfsRollbackTransaction(&mfs1);
+ test_assert(err == MFS_NO_ERROR, "error rolling back transaction");
+ }
+ test_end_step(5);
+
+ /* [2.2.6] State must not have changed, records 1, 2 and 3 must still
+ be there unchanged.*/
+ test_set_step(6);
+ {
+ mfs_error_t err;
+ size_t size;
+
+ size = sizeof mfs_buffer;
+ err = mfsReadRecord(&mfs1, 1, &size, mfs_buffer);
+ test_assert(err == MFS_NO_ERROR, "record not found");
+ test_assert(size == sizeof mfs_pattern16, "size changed");
+ size = sizeof mfs_buffer;
+ err = mfsReadRecord(&mfs1, 2, &size, mfs_buffer);
+ test_assert(err == MFS_NO_ERROR, "record not found");
+ test_assert(size == sizeof mfs_pattern16, "size changed");
+ size = sizeof mfs_buffer;
+ err = mfsReadRecord(&mfs1, 3, &size, mfs_buffer);
+ test_assert(err == MFS_NO_ERROR, "record not found");
+ test_assert(size == sizeof mfs_pattern16, "size changed");
+
+ /* Checking internal data.*/
+ test_assert(MFS_BANK_1 == mfs1.current_bank, "internal data mismatch");
+ test_assert(current_counter == mfs1.current_counter - 1, "internal data mismatch");
+ test_assert(used_space == mfs1.used_space, "internal data mismatch");
+ }
+ test_end_step(6);
}
static const testcase_t mfs_test_002_002 = {
- "Erasing non existing record",
+ "Rolling back a transaction",
mfs_test_002_002_setup,
mfs_test_002_002_teardown,
mfs_test_002_002_execute
};
+/**
+ * @page mfs_test_002_003 [2.3] Transaction triggering an early garbage collect
+ *
+ * Description
+ * A transaction is started with sufficient space but not contiguous, a
+ * garbage collection is triggered.
+ *
+ * Test Steps
+ * - [2.3.1] Filling up the storage by writing records with increasing
+ * IDs, MFS_NO_ERROR is expected.
+ * - [2.3.2] Erasing one record, MFS_NO_ERROR is expected.
+ * - [2.3.3] Starting a transaction with the whole remaining space,
+ * MFS_ERR_OUT_OF_MEM is expected.
+ * - [2.3.4] Starting a transaction with insufficient space for one
+ * more header, MFS_ERR_OUT_OF_MEM is expected.
+ * - [2.3.5] Starting a transaction with just enough space for one more
+ * header, MFS_NO_ERROR is expected.
+ * - [2.3.6] Rolling back, MFS_NO_ERROR is expected.
+ * .
+ */
+
+static void mfs_test_002_003_setup(void) {
+ bank_erase(MFS_BANK_0);
+ bank_erase(MFS_BANK_1);
+ mfsStart(&mfs1, &mfscfg1);
+}
+
+static void mfs_test_002_003_teardown(void) {
+ mfsStop(&mfs1);
+}
+
+static void mfs_test_002_003_execute(void) {
+
+ /* [2.3.1] Filling up the storage by writing records with increasing
+ IDs, MFS_NO_ERROR is expected.*/
+ test_set_step(1);
+ {
+ mfs_id_t id;
+ mfs_id_t id_max = (mfscfg1.bank_size - sizeof (mfs_bank_header_t)) /
+ (sizeof (mfs_data_header_t) + sizeof mfs_pattern512);
+
+ for (id = 1; id <= id_max; id++) {
+ mfs_error_t err;
+ size_t size;
+
+ err = mfsWriteRecord(&mfs1, id, sizeof mfs_pattern512, mfs_pattern512);
+ test_assert(err == MFS_NO_ERROR, "error creating the record");
+ size = sizeof mfs_buffer;
+ err = mfsReadRecord(&mfs1, id, &size, mfs_buffer);
+ test_assert(err == MFS_NO_ERROR,
+ "record not found");
+ test_assert(size == sizeof mfs_pattern512,
+ "unexpected record length");
+ test_assert(memcmp(mfs_pattern512, mfs_buffer, size) == 0,
+ "wrong record content");
+ }
+ }
+ test_end_step(1);
+
+ /* [2.3.2] Erasing one record, MFS_NO_ERROR is expected.*/
+ test_set_step(2);
+ {
+ mfs_error_t err;
+ size_t size;
+
+ err = mfsEraseRecord(&mfs1, 1);
+ test_assert(err == MFS_NO_ERROR, "error erasing the record");
+ size = sizeof mfs_buffer;
+ err = mfsReadRecord(&mfs1, 1, &size, mfs_buffer);
+ test_assert(err == MFS_ERR_NOT_FOUND, "record not erased");
+ }
+ test_end_step(2);
+
+ /* [2.3.3] Starting a transaction with the whole remaining space,
+ MFS_ERR_OUT_OF_MEM is expected.*/
+ test_set_step(3);
+ {
+ mfs_error_t err;
+ size_t size = mfs1.config->bank_size - mfs1.used_space;
+
+ err = mfsStartTransaction(&mfs1, size);
+ test_assert(err == MFS_ERR_OUT_OF_MEM, "invalid error code");
+ }
+ test_end_step(3);
+
+ /* [2.3.4] Starting a transaction with insufficient space for one
+ more header, MFS_ERR_OUT_OF_MEM is expected.*/
+ test_set_step(4);
+ {
+ mfs_error_t err;
+ size_t size = ((mfs1.config->bank_size - mfs1.used_space) - sizeof (mfs_data_header_t)) + 1;
+
+ err = mfsStartTransaction(&mfs1, size);
+ test_assert(err == MFS_ERR_OUT_OF_MEM, "invalid error code");
+ }
+ test_end_step(4);
+
+ /* [2.3.5] Starting a transaction with just enough space for one more
+ header, MFS_NO_ERROR is expected.*/
+ test_set_step(5);
+ {
+ mfs_error_t err;
+ size_t size = (mfs1.config->bank_size - mfs1.used_space) - sizeof (mfs_data_header_t);
+
+ err = mfsStartTransaction(&mfs1, size);
+ test_assert(err == MFS_NO_ERROR, "error starting transaction");
+ }
+ test_end_step(5);
+
+ /* [2.3.6] Rolling back, MFS_NO_ERROR is expected.*/
+ test_set_step(6);
+ {
+ mfs_error_t err;
+
+ err = mfsRollbackTransaction(&mfs1);
+ test_assert(err == MFS_NO_ERROR, "error rolling back transaction");
+ }
+ test_end_step(6);
+}
+
+static const testcase_t mfs_test_002_003 = {
+ "Transaction triggering an early garbage collect",
+ mfs_test_002_003_setup,
+ mfs_test_002_003_teardown,
+ mfs_test_002_003_execute
+};
+
/****************************************************************************
* Exported data.
****************************************************************************/
@@ -168,13 +579,14 @@ static const testcase_t mfs_test_002_002 = {
const testcase_t * const mfs_test_sequence_002_array[] = {
&mfs_test_002_001,
&mfs_test_002_002,
+ &mfs_test_002_003,
NULL
};
/**
- * @brief API Invalid Cases tests.
+ * @brief Transaction Mode tests.
*/
const testsequence_t mfs_test_sequence_002 = {
- "API Invalid Cases tests",
+ "Transaction Mode tests",
mfs_test_sequence_002_array
};
diff --git a/test/mfs/source/test/mfs_test_sequence_003.c b/test/mfs/source/test/mfs_test_sequence_003.c
new file mode 100644
index 000000000..e31f53bab
--- /dev/null
+++ b/test/mfs/source/test/mfs_test_sequence_003.c
@@ -0,0 +1,186 @@
+/*
+ ChibiOS - Copyright (C) 2006..2018 Giovanni Di Sirio
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+*/
+
+#include "hal.h"
+#include "mfs_test_root.h"
+
+/**
+ * @file mfs_test_sequence_003.c
+ * @brief Test Sequence 003 code.
+ *
+ * @page mfs_test_sequence_003 [3] API Invalid Cases tests
+ *
+ * File: @ref mfs_test_sequence_003.c
+ *
+ * Description
+ * This test sequence tests the error coded returned by the various
+ * APIs when called when the system is not initialized.
+ *
+ * Test Cases
+ * - @subpage mfs_test_003_001
+ * - @subpage mfs_test_003_002
+ * .
+ */
+
+/****************************************************************************
+ * Shared code.
+ ****************************************************************************/
+
+#include "hal_mfs.h"
+
+/****************************************************************************
+ * Test cases.
+ ****************************************************************************/
+
+/**
+ * @page mfs_test_003_001 [3.1] Initialization error from APIs
+ *
+ * Description
+ * The API functions are invoked without prior initialization.
+ *
+ * Test Steps
+ * - [3.1.1] The function mfsErase() is called, MFS_ERR_INV_STATE is
+ * expected.
+ * - [3.1.2] The function mfsWriteRecord() is called, MFS_ERR_INV_STATE
+ * is expected.
+ * - [3.1.3] The function mfsEraseRecord() is called, MFS_ERR_INV_STATE
+ * is expected.
+ * - [3.1.4] The function mfsReadRecord() is called, MFS_ERR_INV_STATE
+ * is expected.
+ * - [3.1.5] The function mfsPerformGarbageCollection() is called,
+ * MFS_ERR_INV_STATE is expected.
+ * .
+ */
+
+static void mfs_test_003_001_execute(void) {
+
+ /* [3.1.1] The function mfsErase() is called, MFS_ERR_INV_STATE is
+ expected.*/
+ test_set_step(1);
+ {
+ mfs_error_t err = mfsErase(&mfs1);
+ test_assert(err == MFS_ERR_INV_STATE, "mfsErase() returned wrong status");
+ }
+ test_end_step(1);
+
+ /* [3.1.2] The function mfsWriteRecord() is called, MFS_ERR_INV_STATE
+ is expected.*/
+ test_set_step(2);
+ {
+ mfs_error_t err = mfsWriteRecord(&mfs1, 1, 16, mfs_buffer);
+ test_assert(err == MFS_ERR_INV_STATE, "mfsWriteRecord() returned wrong status");
+ }
+ test_end_step(2);
+
+ /* [3.1.3] The function mfsEraseRecord() is called, MFS_ERR_INV_STATE
+ is expected.*/
+ test_set_step(3);
+ {
+ mfs_error_t err = mfsEraseRecord(&mfs1, 1);
+ test_assert(err == MFS_ERR_INV_STATE, "mfsEraseRecord() returned wrong status");
+ }
+ test_end_step(3);
+
+ /* [3.1.4] The function mfsReadRecord() is called, MFS_ERR_INV_STATE
+ is expected.*/
+ test_set_step(4);
+ {
+ size_t size = sizeof mfs_buffer;
+ mfs_error_t err = mfsReadRecord(&mfs1, 1, &size, mfs_buffer);
+ test_assert(err == MFS_ERR_INV_STATE, "mfsReadRecord() returned wrong status");
+ }
+ test_end_step(4);
+
+ /* [3.1.5] The function mfsPerformGarbageCollection() is called,
+ MFS_ERR_INV_STATE is expected.*/
+ test_set_step(5);
+ {
+ mfs_error_t err = mfsPerformGarbageCollection(&mfs1);
+ test_assert(err == MFS_ERR_INV_STATE, "mfsPerformGarbageCollection() returned wrong status");
+ }
+ test_end_step(5);
+}
+
+static const testcase_t mfs_test_003_001 = {
+ "Initialization error from APIs",
+ NULL,
+ NULL,
+ mfs_test_003_001_execute
+};
+
+/**
+ * @page mfs_test_003_002 [3.2] Erasing non existing record
+ *
+ * Description
+ * An erase operation is attempted on an non-existing record.
+ *
+ * Test Steps
+ * - [3.2.1] Record one is erased, the error MFS_ERR_NOT_FOUND is
+ * expected.
+ * .
+ */
+
+static void mfs_test_003_002_setup(void) {
+ mfsStart(&mfs1, &mfscfg1);
+ mfsErase(&mfs1);
+}
+
+static void mfs_test_003_002_teardown(void) {
+ mfsStop(&mfs1);
+}
+
+static void mfs_test_003_002_execute(void) {
+
+ /* [3.2.1] Record one is erased, the error MFS_ERR_NOT_FOUND is
+ expected.*/
+ test_set_step(1);
+ {
+ mfs_error_t err;
+
+ err = mfsEraseRecord(&mfs1, 1);
+ test_assert(err != MFS_NO_ERROR, "record was present");
+ test_assert(err == MFS_ERR_NOT_FOUND, "invalid error code");
+ }
+ test_end_step(1);
+}
+
+static const testcase_t mfs_test_003_002 = {
+ "Erasing non existing record",
+ mfs_test_003_002_setup,
+ mfs_test_003_002_teardown,
+ mfs_test_003_002_execute
+};
+
+/****************************************************************************
+ * Exported data.
+ ****************************************************************************/
+
+/**
+ * @brief Array of test cases.
+ */
+const testcase_t * const mfs_test_sequence_003_array[] = {
+ &mfs_test_003_001,
+ &mfs_test_003_002,
+ NULL
+};
+
+/**
+ * @brief API Invalid Cases tests.
+ */
+const testsequence_t mfs_test_sequence_003 = {
+ "API Invalid Cases tests",
+ mfs_test_sequence_003_array
+};
diff --git a/test/mfs/source/test/mfs_test_sequence_003.h b/test/mfs/source/test/mfs_test_sequence_003.h
new file mode 100644
index 000000000..336f8bff6
--- /dev/null
+++ b/test/mfs/source/test/mfs_test_sequence_003.h
@@ -0,0 +1,27 @@
+/*
+ ChibiOS - Copyright (C) 2006..2018 Giovanni Di Sirio
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+*/
+
+/**
+ * @file mfs_test_sequence_003.h
+ * @brief Test Sequence 003 header.
+ */
+
+#ifndef MFS_TEST_SEQUENCE_003_H
+#define MFS_TEST_SEQUENCE_003_H
+
+extern const testsequence_t mfs_test_sequence_003;
+
+#endif /* MFS_TEST_SEQUENCE_003_H */
diff --git a/testhal/STM32/multi/ADC/cfg/stm32h743_nucleo144/mcuconf.h b/testhal/STM32/multi/ADC/cfg/stm32h743_nucleo144/mcuconf.h
index bc4eed683..057857cab 100644
--- a/testhal/STM32/multi/ADC/cfg/stm32h743_nucleo144/mcuconf.h
+++ b/testhal/STM32/multi/ADC/cfg/stm32h743_nucleo144/mcuconf.h
@@ -33,6 +33,7 @@
#define STM32H7xx_MCUCONF
#define STM32H743_MCUCONF
+#define STM32H753_MCUCONF
/*
* General settings.
diff --git a/testhal/STM32/multi/DAC/cfg/stm32h743_nucleo144/mcuconf.h b/testhal/STM32/multi/DAC/cfg/stm32h743_nucleo144/mcuconf.h
index b692bf59e..547a50654 100644
--- a/testhal/STM32/multi/DAC/cfg/stm32h743_nucleo144/mcuconf.h
+++ b/testhal/STM32/multi/DAC/cfg/stm32h743_nucleo144/mcuconf.h
@@ -33,6 +33,7 @@
#define STM32H7xx_MCUCONF
#define STM32H743_MCUCONF
+#define STM32H753_MCUCONF
/*
* General settings.
diff --git a/testhal/STM32/multi/SPI/cfg/stm32h743_nucleo144/mcuconf.h b/testhal/STM32/multi/SPI/cfg/stm32h743_nucleo144/mcuconf.h
index 79a0ac12e..18fb9c84c 100644
--- a/testhal/STM32/multi/SPI/cfg/stm32h743_nucleo144/mcuconf.h
+++ b/testhal/STM32/multi/SPI/cfg/stm32h743_nucleo144/mcuconf.h
@@ -33,6 +33,7 @@
#define STM32H7xx_MCUCONF
#define STM32H743_MCUCONF
+#define STM32H753_MCUCONF
/*
* General settings.
diff --git a/testhal/STM32/multi/USB_CDC/cfg/stm32h743_nucleo144/mcuconf.h b/testhal/STM32/multi/USB_CDC/cfg/stm32h743_nucleo144/mcuconf.h
index 3500ef385..990bf245f 100644
--- a/testhal/STM32/multi/USB_CDC/cfg/stm32h743_nucleo144/mcuconf.h
+++ b/testhal/STM32/multi/USB_CDC/cfg/stm32h743_nucleo144/mcuconf.h
@@ -33,6 +33,7 @@
#define STM32H7xx_MCUCONF
#define STM32H743_MCUCONF
+#define STM32H753_MCUCONF
/*
* General settings.
diff --git a/testhal/STM32/multi/WSPI-MFS/.project b/testhal/STM32/multi/WSPI-MFS/.project
index 1ea006f99..68106fb4f 100644
--- a/testhal/STM32/multi/WSPI-MFS/.project
+++ b/testhal/STM32/multi/WSPI-MFS/.project
@@ -86,5 +86,15 @@
2
CHIBIOS/test/mfs
+
+ test/lib
+ 2
+ CHIBIOS/test/lib
+
+
+ test/mfs
+ 2
+ CHIBIOS/test/mfs
+
diff --git a/testhal/STM32/multi/WSPI-MFS/debug/STM32-WSPI-MFS (Select ELF file)(OpenOCD, Just Run).launch b/testhal/STM32/multi/WSPI-MFS/debug/STM32-WSPI-MFS (Select ELF file)(OpenOCD, Just Run).launch
index 71e2e7e7b..8324a522c 100644
--- a/testhal/STM32/multi/WSPI-MFS/debug/STM32-WSPI-MFS (Select ELF file)(OpenOCD, Just Run).launch
+++ b/testhal/STM32/multi/WSPI-MFS/debug/STM32-WSPI-MFS (Select ELF file)(OpenOCD, Just Run).launch
@@ -33,7 +33,7 @@
-
+
diff --git a/tools/ftl/processors/conf/mcuconf_stm32h743xx/mcuconf.h.ftl b/tools/ftl/processors/conf/mcuconf_stm32h743xx/mcuconf.h.ftl
index 25acd2076..7e1e9e252 100644
--- a/tools/ftl/processors/conf/mcuconf_stm32h743xx/mcuconf.h.ftl
+++ b/tools/ftl/processors/conf/mcuconf_stm32h743xx/mcuconf.h.ftl
@@ -44,6 +44,7 @@
#define STM32H7xx_MCUCONF
#define STM32H743_MCUCONF
+#define STM32H753_MCUCONF
/*
* General settings.
diff --git a/tools/ftl/processors/unittest/test/test_sequence.c.ftl b/tools/ftl/processors/unittest/test/test_sequence.c.ftl
index b6217a55d..abbbc174f 100755
--- a/tools/ftl/processors/unittest/test/test_sequence.c.ftl
+++ b/tools/ftl/processors/unittest/test/test_sequence.c.ftl
@@ -179,6 +179,7 @@ static void ${prefix_lower}test_${(sequence_index + 1)?string("000")}_${(case_in
[@utils.EmitIndentedCCode " " 2 step.code.value[0] /]
[/#if]
}
+ test_end_step(${(step_index + 1)?string});
[/#list]
}