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] }