From 4f2c3edf5b6b2bc7e7468eb992faf0e42ec139b7 Mon Sep 17 00:00:00 2001 From: Rohit Grover Date: Fri, 22 Jul 2016 09:12:50 +0100 Subject: [PATCH 1/8] salvaging the changes from PR#2150 which are useful in spite of fix to RWW The RWW fix is controversial because it requires holding off interrupts for periods of around 5ms at a time. But there were still some minor improvements around that change which could be retained. This commit contains these changes. --- .../TARGET_K64F/storage_driver.c | 36 ++++++++++++------- 1 file changed, 24 insertions(+), 12 deletions(-) diff --git a/hal/targets/hal/TARGET_Freescale/TARGET_KSDK2_MCUS/TARGET_K64F/storage_driver.c b/hal/targets/hal/TARGET_Freescale/TARGET_KSDK2_MCUS/TARGET_K64F/storage_driver.c index b955784eebc..00bbd3d042b 100644 --- a/hal/targets/hal/TARGET_Freescale/TARGET_KSDK2_MCUS/TARGET_K64F/storage_driver.c +++ b/hal/targets/hal/TARGET_Freescale/TARGET_KSDK2_MCUS/TARGET_K64F/storage_driver.c @@ -146,7 +146,6 @@ extern volatile uint32_t *const kFCCOBx; #define SIZEOF_DOUBLE_PHRASE (16) #endif /* #ifdef USING_KSDK2 */ - /* * forward declarations */ @@ -369,6 +368,8 @@ static inline void clearErrorStatusBits() } } +/* The following functions are only needed if using interrupt-driven operation. */ +#if ASYNC_OPS static inline void enableCommandCompletionInterrupt(void) { #ifdef USING_KSDK2 @@ -410,6 +411,23 @@ static inline void launchCommand(void) #endif } +#else /* #if !ASYNC_OPS */ + +static void launchCommandAndWaitForCompletion() +{ + // It contains the inlined equivalent of the following code snippet: + // launchCommand(); + // while (controllerCurrentlyBusy()) { + // /* Spin waiting for the command execution to complete. */ + // } + + FTFx->FSTAT = FTFx_FSTAT_CCIF_MASK; /* launchcommand() */ + while ((FTFx->FSTAT & FTFx_FSTAT_CCIF_MASK) == 0) { + /* Spin waiting for the command execution to complete. */ + } +} +#endif /* #if !ASYNC_OPS */ + #ifndef USING_KSDK2 static inline void setupAddressInCCOB123(uint64_t addr) { @@ -547,17 +565,14 @@ static inline void setupNextErase(struct mtd_k64f_data *context) static int32_t executeCommand(struct mtd_k64f_data *context) { +#if ASYNC_OPS + /* Asynchronous operation */ + (void)context; /* avoid compiler warning about un-used variables */ launchCommand(); /* At this point, The FTFE reads the command code and performs a series of * parameter checks and protection checks, if applicable, which are unique * to each command. */ - -#if ASYNC_OPS - /* Asynchronous operation */ - - (void)context; /* avoid compiler warning about un-used variables */ - /* Spin waiting for the command execution to begin. */ while (!controllerCurrentlyBusy() && !failedWithAccessError() && !failedWithProtectionError()); if (failedWithAccessError() || failedWithProtectionError()) { @@ -572,8 +587,7 @@ static int32_t executeCommand(struct mtd_k64f_data *context) /* Synchronous operation. */ while (1) { - /* Spin waiting for the command execution to complete. */ - while (controllerCurrentlyBusy()); + launchCommandAndWaitForCompletion(); /* Execution may result in failure. Check for errors */ if (failedWithAccessError() || failedWithProtectionError()) { @@ -593,7 +607,6 @@ static int32_t executeCommand(struct mtd_k64f_data *context) /* start the successive program operation */ setupNextProgramData(context); - launchCommand(); /* continue on to the next iteration of the parent loop */ break; @@ -603,7 +616,6 @@ static int32_t executeCommand(struct mtd_k64f_data *context) } setupNextErase(context); /* start the successive erase operation */ - launchCommand(); /* continue on to the next iteration of the parent loop */ break; @@ -831,7 +843,7 @@ static int32_t readData(uint64_t addr, void *data, uint32_t size) return ARM_DRIVER_ERROR_PARAMETER; /* illegal address range */ } - context->currentCommand = ARM_STORAGE_OPERATION_READ_DATA; + context->currentCommand = ARM_STORAGE_OPERATION_READ_DATA; memcpy(data, (const void *)(uintptr_t)addr, size); return size; /* signal synchronous completion. */ } From 9014777a31e733c909813cbb0528ffbd6e831af8 Mon Sep 17 00:00:00 2001 From: Rohit Grover Date: Fri, 22 Jul 2016 09:17:44 +0100 Subject: [PATCH 2/8] remove an un-necessary comment header --- .../TARGET_KSDK2_MCUS/TARGET_K64F/storage_driver.c | 4 ---- 1 file changed, 4 deletions(-) diff --git a/hal/targets/hal/TARGET_Freescale/TARGET_KSDK2_MCUS/TARGET_K64F/storage_driver.c b/hal/targets/hal/TARGET_Freescale/TARGET_KSDK2_MCUS/TARGET_K64F/storage_driver.c index 00bbd3d042b..1e6a780c244 100644 --- a/hal/targets/hal/TARGET_Freescale/TARGET_KSDK2_MCUS/TARGET_K64F/storage_driver.c +++ b/hal/targets/hal/TARGET_Freescale/TARGET_KSDK2_MCUS/TARGET_K64F/storage_driver.c @@ -15,10 +15,6 @@ * limitations under the License. */ -/** - * This is a mock driver using the flash abstraction layer. It allows for writing tests. - */ - #if DEVICE_STORAGE #include From c82e7775b12c8b8f282149eb6b05457cdcbc1107 Mon Sep 17 00:00:00 2001 From: Rohit Grover Date: Fri, 22 Jul 2016 09:21:58 +0100 Subject: [PATCH 3/8] minor fixes to include headers --- .../TARGET_KSDK2_MCUS/TARGET_K64F/storage_driver.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/hal/targets/hal/TARGET_Freescale/TARGET_KSDK2_MCUS/TARGET_K64F/storage_driver.c b/hal/targets/hal/TARGET_Freescale/TARGET_KSDK2_MCUS/TARGET_K64F/storage_driver.c index 1e6a780c244..e8496421050 100644 --- a/hal/targets/hal/TARGET_Freescale/TARGET_KSDK2_MCUS/TARGET_K64F/storage_driver.c +++ b/hal/targets/hal/TARGET_Freescale/TARGET_KSDK2_MCUS/TARGET_K64F/storage_driver.c @@ -17,8 +17,6 @@ #if DEVICE_STORAGE -#include - #include "Driver_Storage.h" #include "cmsis_nvic.h" #include "MK64F12.h" @@ -30,9 +28,11 @@ #ifndef USING_KSDK2 #include "device/MK64F12/MK64F12_ftfe.h" #else -#include "drivers/fsl_flash.h" +#include "fsl_flash.h" #endif +#include + #ifdef USING_KSDK2 /*! * @name Misc utility defines From 81ab477abc712d6dcc7387dcb0feaee51c49aad1 Mon Sep 17 00:00:00 2001 From: Rohit Grover Date: Fri, 22 Jul 2016 09:31:38 +0100 Subject: [PATCH 4/8] switch to using more specific names in DEVICE_STORAGE_CONFIG_* This should help avoid conflicts with configs for other Storage devices in the future. --- .../TARGET_K64F/storage_driver.c | 18 +++++++++--------- 1 file changed, 9 insertions(+), 9 deletions(-) diff --git a/hal/targets/hal/TARGET_Freescale/TARGET_KSDK2_MCUS/TARGET_K64F/storage_driver.c b/hal/targets/hal/TARGET_Freescale/TARGET_KSDK2_MCUS/TARGET_K64F/storage_driver.c index e8496421050..166bda23869 100644 --- a/hal/targets/hal/TARGET_Freescale/TARGET_KSDK2_MCUS/TARGET_K64F/storage_driver.c +++ b/hal/targets/hal/TARGET_Freescale/TARGET_KSDK2_MCUS/TARGET_K64F/storage_driver.c @@ -169,16 +169,16 @@ struct mtd_k64f_data { static const ARM_STORAGE_BLOCK blockTable[] = { { /**< This is the start address of the flash block. */ -#ifdef DEVICE_STORAGE_CONFIG_HARDWARE_MTD_START_ADDR - .addr = DEVICE_STORAGE_CONFIG_HARDWARE_MTD_START_ADDR, +#ifdef DEVICE_STORAGE_CONFIG_HARDWARE_MTD_K64F_START_ADDR + .addr = DEVICE_STORAGE_CONFIG_HARDWARE_MTD_K64F_START_ADDR, #else .addr = BLOCK1_START_ADDR, #endif /**< This is the size of the flash block, in units of bytes. * Together with addr, it describes a range [addr, addr+size). */ -#ifdef DEVICE_STORAGE_CONFIG_HARDWARE_MTD_SIZE - .size = DEVICE_STORAGE_CONFIG_HARDWARE_MTD_SIZE, +#ifdef DEVICE_STORAGE_CONFIG_HARDWARE_MTD_K64F_SIZE + .size = DEVICE_STORAGE_CONFIG_HARDWARE_MTD_K64F_SIZE, #else .size = BLOCK1_SIZE, #endif @@ -200,7 +200,7 @@ static const ARM_DRIVER_VERSION version = { }; -#if (!defined(DEVICE_STORAGE_CONFIG_HARDWARE_MTD_ASYNC_OPS) || DEVICE_STORAGE_CONFIG_HARDWARE_MTD_ASYNC_OPS) +#if (!defined(DEVICE_STORAGE_CONFIG_HARDWARE_MTD_K64F_ASYNC_OPS) || DEVICE_STORAGE_CONFIG_HARDWARE_MTD_K64F_ASYNC_OPS) #define ASYNC_OPS 1 #else #define ASYNC_OPS 0 @@ -219,8 +219,8 @@ static const ARM_STORAGE_CAPABILITIES caps = { .asynchronous_ops = ASYNC_OPS, /* Enable chip-erase functionality if we own all of block-1. */ - #if ((!defined (DEVICE_STORAGE_CONFIG_HARDWARE_MTD_START_ADDR) || (DEVICE_STORAGE_CONFIG_HARDWARE_MTD_START_ADDR == BLOCK1_START_ADDR)) && \ - (!defined (DEVICE_STORAGE_CONFIG_HARDWARE_MTD_SIZE) || (DEVICE_STORAGE_CONFIG_HARDWARE_MTD_SIZE == BLOCK1_SIZE))) + #if ((!defined (DEVICE_STORAGE_CONFIG_HARDWARE_MTD_K64F_START_ADDR) || (DEVICE_STORAGE_CONFIG_HARDWARE_MTD_K64F_START_ADDR == BLOCK1_START_ADDR)) && \ + (!defined (DEVICE_STORAGE_CONFIG_HARDWARE_MTD_K64F_SIZE) || (DEVICE_STORAGE_CONFIG_HARDWARE_MTD_K64F_SIZE == BLOCK1_SIZE))) .erase_all = 1, /**< Supports EraseChip operation. */ #else .erase_all = 0, /**< Supports EraseChip operation. */ @@ -228,8 +228,8 @@ static const ARM_STORAGE_CAPABILITIES caps = { }; static const ARM_STORAGE_INFO info = { -#ifdef DEVICE_STORAGE_CONFIG_HARDWARE_MTD_SIZE - .total_storage = DEVICE_STORAGE_CONFIG_HARDWARE_MTD_SIZE, /**< Total available storage, in units of octets. */ +#ifdef DEVICE_STORAGE_CONFIG_HARDWARE_MTD_K64F_SIZE + .total_storage = DEVICE_STORAGE_CONFIG_HARDWARE_MTD_K64F_SIZE, /**< Total available storage, in units of octets. */ #else .total_storage = BLOCK1_SIZE, /**< Total available storage, in units of octets. By default, BLOCK0 is reserved to hold program code. */ #endif From 8396aafb5a23c4c038b62c8ae316a52806e6a877 Mon Sep 17 00:00:00 2001 From: Rohit Grover Date: Fri, 22 Jul 2016 09:38:11 +0100 Subject: [PATCH 5/8] add missing include for stdint.h to Driver_Storage.h --- hal/hal/storage_abstraction/Driver_Storage.h | 2 ++ 1 file changed, 2 insertions(+) diff --git a/hal/hal/storage_abstraction/Driver_Storage.h b/hal/hal/storage_abstraction/Driver_Storage.h index d0ca583bd57..8b5410ff59f 100644 --- a/hal/hal/storage_abstraction/Driver_Storage.h +++ b/hal/hal/storage_abstraction/Driver_Storage.h @@ -18,6 +18,8 @@ #ifndef __DRIVER_STORAGE_H #define __DRIVER_STORAGE_H +#include + #ifdef __cplusplus extern "C" { #endif // __cplusplus From 02738b7af6ab01cd8f37472918498a2888bb8b95 Mon Sep 17 00:00:00 2001 From: Rohit Grover Date: Fri, 22 Jul 2016 09:51:11 +0100 Subject: [PATCH 6/8] Add a separate error code for runtime/intergrity-check failures --- hal/hal/storage_abstraction/Driver_Storage.h | 1 + .../TARGET_KSDK2_MCUS/TARGET_K64F/storage_driver.c | 4 ++-- 2 files changed, 3 insertions(+), 2 deletions(-) diff --git a/hal/hal/storage_abstraction/Driver_Storage.h b/hal/hal/storage_abstraction/Driver_Storage.h index 8b5410ff59f..5d8c9012fff 100644 --- a/hal/hal/storage_abstraction/Driver_Storage.h +++ b/hal/hal/storage_abstraction/Driver_Storage.h @@ -42,6 +42,7 @@ extern "C" { #define ARM_STORAGE_ERROR_NOT_ERASABLE (ARM_DRIVER_ERROR_SPECIFIC - 1) ///< Part (or all) of the range provided to Erase() isn't erasable. #define ARM_STORAGE_ERROR_NOT_PROGRAMMABLE (ARM_DRIVER_ERROR_SPECIFIC - 2) ///< Part (or all) of the range provided to ProgramData() isn't programmable. #define ARM_STORAGE_ERROR_PROTECTED (ARM_DRIVER_ERROR_SPECIFIC - 3) ///< Part (or all) of the range to Erase() or ProgramData() is protected. +#define ARM_STORAGE_ERROR_RUNTIME_OR_INTEGRITY_FAILURE (ARM_DRIVER_ERROR_SPECIFIC - 4) ///< Runtime or sanity-check failure. /** * \brief Attributes of the storage range within a storage block. diff --git a/hal/targets/hal/TARGET_Freescale/TARGET_KSDK2_MCUS/TARGET_K64F/storage_driver.c b/hal/targets/hal/TARGET_Freescale/TARGET_KSDK2_MCUS/TARGET_K64F/storage_driver.c index 166bda23869..2eb5e87ae49 100644 --- a/hal/targets/hal/TARGET_Freescale/TARGET_KSDK2_MCUS/TARGET_K64F/storage_driver.c +++ b/hal/targets/hal/TARGET_Freescale/TARGET_KSDK2_MCUS/TARGET_K64F/storage_driver.c @@ -591,7 +591,7 @@ static int32_t executeCommand(struct mtd_k64f_data *context) return ARM_DRIVER_ERROR_PARAMETER; } if (failedWithRunTimeError()) { - return ARM_DRIVER_ERROR; /* unspecified runtime error. */ + return ARM_STORAGE_ERROR_RUNTIME_OR_INTEGRITY_FAILURE; } /* signal synchronous completion. */ @@ -638,7 +638,7 @@ static void ftfe_ccie_irq_handler(void) } if (failedWithRunTimeError()) { if (context->commandCompletionCallback) { - context->commandCompletionCallback(ARM_DRIVER_ERROR, context->currentCommand); + context->commandCompletionCallback(ARM_STORAGE_ERROR_RUNTIME_OR_INTEGRITY_FAILURE, context->currentCommand); } return; } From 1efb48f4b19115f20c2c49476bfb29f0d43b0c35 Mon Sep 17 00:00:00 2001 From: Rohit Grover Date: Fri, 22 Jul 2016 09:57:28 +0100 Subject: [PATCH 7/8] add helper function launchCommandFromIRQ() --- .../TARGET_K64F/storage_driver.c | 42 ++++++++----------- 1 file changed, 18 insertions(+), 24 deletions(-) diff --git a/hal/targets/hal/TARGET_Freescale/TARGET_KSDK2_MCUS/TARGET_K64F/storage_driver.c b/hal/targets/hal/TARGET_Freescale/TARGET_KSDK2_MCUS/TARGET_K64F/storage_driver.c index 2eb5e87ae49..9736ec8f2c6 100644 --- a/hal/targets/hal/TARGET_Freescale/TARGET_KSDK2_MCUS/TARGET_K64F/storage_driver.c +++ b/hal/targets/hal/TARGET_Freescale/TARGET_KSDK2_MCUS/TARGET_K64F/storage_driver.c @@ -623,6 +623,22 @@ static int32_t executeCommand(struct mtd_k64f_data *context) } #if ASYNC_OPS +static inline void launchCommandFromIRQ(const struct mtd_k64f_data *context) +{ + launchCommand(); + + while (!controllerCurrentlyBusy() && !failedWithAccessError() && !failedWithProtectionError()); + if (failedWithAccessError() || failedWithProtectionError()) { + clearErrorStatusBits(); + if (context->commandCompletionCallback) { + context->commandCompletionCallback(ARM_DRIVER_ERROR_PARAMETER, context->currentCommand); + } + return; + } + + enableCommandCompletionInterrupt(); +} + static void ftfe_ccie_irq_handler(void) { disbleCommandCompletionInterrupt(); @@ -654,18 +670,7 @@ static void ftfe_ccie_irq_handler(void) /* start the successive program operation */ setupNextProgramData(context); - launchCommand(); - - while (!controllerCurrentlyBusy() && !failedWithAccessError() && !failedWithProtectionError()); - if (failedWithAccessError() || failedWithProtectionError()) { - clearErrorStatusBits(); - if (context->commandCompletionCallback) { - context->commandCompletionCallback(ARM_DRIVER_ERROR_PARAMETER, ARM_STORAGE_OPERATION_PROGRAM_DATA); - } - return; - } - - enableCommandCompletionInterrupt(); + launchCommandFromIRQ(context); break; case ARM_STORAGE_OPERATION_ERASE: @@ -677,18 +682,7 @@ static void ftfe_ccie_irq_handler(void) } setupNextErase(context); - launchCommand(); - - while (!controllerCurrentlyBusy() && !failedWithAccessError() && !failedWithProtectionError()); - if (failedWithAccessError() || failedWithProtectionError()) { - clearErrorStatusBits(); - if (context->commandCompletionCallback) { - context->commandCompletionCallback(ARM_DRIVER_ERROR_PARAMETER, ARM_STORAGE_OPERATION_ERASE); - } - return; - } - - enableCommandCompletionInterrupt(); + launchCommandFromIRQ(context); break; default: From 9182b6d57dadc1dd32b72441feba7e1c7d01f527 Mon Sep 17 00:00:00 2001 From: Rohit Grover Date: Fri, 22 Jul 2016 10:08:35 +0100 Subject: [PATCH 8/8] erase-optimization: check sectors for all-1s before launching erase With this change, we check for all-1s before executing erase. This means that the cost of erasing a range is now proportional to the amount of sectors which have been programmed. This should result in latency improvements in our use of containers based on flash storage. --- .../TARGET_K64F/storage_driver.c | 94 +++++++++++++++++-- 1 file changed, 84 insertions(+), 10 deletions(-) diff --git a/hal/targets/hal/TARGET_Freescale/TARGET_KSDK2_MCUS/TARGET_K64F/storage_driver.c b/hal/targets/hal/TARGET_Freescale/TARGET_KSDK2_MCUS/TARGET_K64F/storage_driver.c index 9736ec8f2c6..a832e239be6 100644 --- a/hal/targets/hal/TARGET_Freescale/TARGET_KSDK2_MCUS/TARGET_K64F/storage_driver.c +++ b/hal/targets/hal/TARGET_Freescale/TARGET_KSDK2_MCUS/TARGET_K64F/storage_driver.c @@ -262,6 +262,7 @@ static const ARM_STORAGE_INFO info = { * This is the command code written into the first FCCOB register, FCCOB0. */ enum FlashCommandOps { + RD1SEC = (uint8_t)0x01, /* read 1s section */ PGM8 = (uint8_t)0x07, /* program phrase */ ERSBLK = (uint8_t)0x08, /* erase block */ ERSSCR = (uint8_t)0x09, /* erase flash sector */ @@ -433,6 +434,34 @@ static inline void setupAddressInCCOB123(uint64_t addr) } #endif /* ifndef USING_KSDK2 */ +static inline void setupRead1sSection(uint64_t addr, size_t cnt) +{ +#ifdef USING_KSDK2 + kFCCOBx[0] = BYTES_JOIN_TO_WORD_1_3(RD1SEC, addr); + kFCCOBx[1] = BYTES_JOIN_TO_WORD_2_1_1(cnt >> 4, 0 /* normal read level */, 0); +#else + BW_FTFE_FCCOB0_CCOBn((uintptr_t)FTFE, RD1SEC); + setupAddressInCCOB123(addr); + BW_FTFE_FCCOB4_CCOBn((uintptr_t)FTFE, ((cnt >> 4) >> 8) & 0xFFUL); /* bits [15:8] of cnt in units of 128-bits. */ + BW_FTFE_FCCOB5_CCOBn((uintptr_t)FTFE, ((cnt >> 4) >> 0) & 0xFFUL); /* bits [7:0] of cnt in units of 128-bits. */ + BW_FTFE_FCCOB6_CCOBn((uintptr_t)FTFE, 0); /* use normal read level for 1s. */ +#endif +} + +static inline bool currentCommandByteIsRD1SEC(void) +{ +#ifdef USING_KSDK2 + return ((kFCCOBx[0] >> 24) == RD1SEC); +#else + return (BR_FTFE_FCCOB0_CCOBn((uintptr_t)FTFE) == RD1SEC); +#endif +} + +static inline bool currentCommandSetupIsAnEraseCheck(const struct mtd_k64f_data *context) +{ + return ((context->currentCommand == ARM_STORAGE_OPERATION_ERASE) && currentCommandByteIsRD1SEC()); +} + static inline void setupEraseSector(uint64_t addr) { #ifdef USING_KSDK2 @@ -547,6 +576,25 @@ static inline void setupNextProgramData(struct mtd_k64f_data *context) } } +/* Setup a command to determine if erase is needed for the range + * [context->currentOperatingStorageAddress, context->currentOperatingStorageAddress + ERASE_UNIT). + * If any byte within the range isn't 0xFF, this command results in a run-time + * error. + * + * Upon launch, if any byte within the given range isn't 0xFF then this command + * will terminate in a run-time error. + */ +static inline void setupNextEraseCheck(const struct mtd_k64f_data *context) +{ + setupRead1sSection(context->currentOperatingStorageAddress, ERASE_UNIT); /* setup check for erased */ +} + +static inline void progressEraseContextByEraseUnit(struct mtd_k64f_data *context) +{ + context->amountLeftToOperate -= ERASE_UNIT; + context->currentOperatingStorageAddress += ERASE_UNIT; +} + /** * Advance the state machine for erase. This function is called only if * amountLeftToOperate is non-zero. @@ -554,9 +602,7 @@ static inline void setupNextProgramData(struct mtd_k64f_data *context) static inline void setupNextErase(struct mtd_k64f_data *context) { setupEraseSector(context->currentOperatingStorageAddress); /* Program FCCOB to load the required command parameters. */ - - context->amountLeftToOperate -= ERASE_UNIT; - context->currentOperatingStorageAddress += ERASE_UNIT; + progressEraseContextByEraseUnit(context); } static int32_t executeCommand(struct mtd_k64f_data *context) @@ -591,7 +637,10 @@ static int32_t executeCommand(struct mtd_k64f_data *context) return ARM_DRIVER_ERROR_PARAMETER; } if (failedWithRunTimeError()) { - return ARM_STORAGE_ERROR_RUNTIME_OR_INTEGRITY_FAILURE; + /* filter away run-time errors which may legitimately arise from an erase-check operation. */ + if (!currentCommandSetupIsAnEraseCheck(context)) { + return ARM_STORAGE_ERROR_RUNTIME_OR_INTEGRITY_FAILURE; + } } /* signal synchronous completion. */ @@ -607,11 +656,22 @@ static int32_t executeCommand(struct mtd_k64f_data *context) break; case ARM_STORAGE_OPERATION_ERASE: + if (currentCommandSetupIsAnEraseCheck(context)) { + if (failedWithRunTimeError()) { + /* a run-time failure from an erase-check indicates at an erase operation is necessary */ + setupNextErase(context); + /* continue on to the next iteration of the parent loop */ + break; + } else { + /* erase can be skipped since this sector is already erased. */ + progressEraseContextByEraseUnit(context); + } + } if (context->amountLeftToOperate == 0) { return context->sizeofCurrentOperation; } - setupNextErase(context); /* start the successive erase operation */ + setupNextEraseCheck(context); /* start the erase check on the successive erase sector */ /* continue on to the next iteration of the parent loop */ break; @@ -653,10 +713,13 @@ static void ftfe_ccie_irq_handler(void) return; } if (failedWithRunTimeError()) { - if (context->commandCompletionCallback) { - context->commandCompletionCallback(ARM_STORAGE_ERROR_RUNTIME_OR_INTEGRITY_FAILURE, context->currentCommand); + /* filter away run-time errors which may legitimately arise from an erase-check operation. */ + if (!currentCommandSetupIsAnEraseCheck(context)) { + if (context->commandCompletionCallback) { + context->commandCompletionCallback(ARM_STORAGE_ERROR_RUNTIME_OR_INTEGRITY_FAILURE, context->currentCommand); + } + return; } - return; } switch (context->currentCommand) { @@ -674,6 +737,17 @@ static void ftfe_ccie_irq_handler(void) break; case ARM_STORAGE_OPERATION_ERASE: + if (currentCommandSetupIsAnEraseCheck(context)) { + if (failedWithRunTimeError()) { + /* a run-time failure from an erase-check indicates at an erase operation is necessary */ + setupNextErase(context); + launchCommandFromIRQ(context); + break; + } else { + /* erase can be skipped since this sector is already erased. */ + progressEraseContextByEraseUnit(context); + } + } if (context->amountLeftToOperate == 0) { if (context->commandCompletionCallback) { context->commandCompletionCallback(context->sizeofCurrentOperation, ARM_STORAGE_OPERATION_ERASE); @@ -681,7 +755,7 @@ static void ftfe_ccie_irq_handler(void) return; } - setupNextErase(context); + setupNextEraseCheck(context); /* start the erase check on the successive erase sector */ launchCommandFromIRQ(context); break; @@ -915,7 +989,7 @@ static int32_t erase(uint64_t addr, uint32_t size) context->amountLeftToOperate = size; clearErrorStatusBits(); - setupNextErase(context); + setupNextEraseCheck(context); return executeCommand(context); }