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 09f151e988..b955784eeb 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 @@ -126,28 +126,8 @@ /*! @brief Access to FTFx->FCCOB */ extern volatile uint32_t *const kFCCOBx; -static flash_config_t privateDeviceConfig; #endif /* #ifdef USING_KSDK2 */ -/* - * forward declarations - */ -static int32_t getBlock(uint64_t addr, ARM_STORAGE_BLOCK *blockP); -static int32_t nextBlock(const ARM_STORAGE_BLOCK* prevP, ARM_STORAGE_BLOCK *nextP); - -/* - * Global state for the driver. - */ -ARM_Storage_Callback_t commandCompletionCallback; -static bool initialized = false; -ARM_POWER_STATE powerState = ARM_POWER_OFF; - -ARM_STORAGE_OPERATION currentCommand; -uint64_t currentOperatingStorageAddress; -size_t sizeofCurrentOperation; -size_t amountLeftToOperate; -const uint8_t *currentOperatingData; - #ifdef USING_KSDK2 #define ERASE_UNIT (FSL_FEATURE_FLASH_PFLASH_BLOCK_SECTOR_SIZE) #define BLOCK1_START_ADDR (FSL_FEATURE_FLASH_PFLASH_BLOCK_SIZE) @@ -166,22 +146,44 @@ const uint8_t *currentOperatingData; #define SIZEOF_DOUBLE_PHRASE (16) #endif /* #ifdef USING_KSDK2 */ + +/* + * forward declarations + */ +static int32_t getBlock(uint64_t addr, ARM_STORAGE_BLOCK *blockP); +static int32_t nextBlock(const ARM_STORAGE_BLOCK* prevP, ARM_STORAGE_BLOCK *nextP); + +/* + * Global state for the driver. + */ +struct mtd_k64f_data { + ARM_Storage_Callback_t commandCompletionCallback; + bool initialized; + ARM_POWER_STATE powerState; + + ARM_STORAGE_OPERATION currentCommand; + uint64_t currentOperatingStorageAddress; + size_t sizeofCurrentOperation; + size_t amountLeftToOperate; + const uint8_t *currentOperatingData; +} mtd_k64f_data; + /* * Static configuration. */ static const ARM_STORAGE_BLOCK blockTable[] = { { /**< This is the start address of the flash block. */ -#ifdef YOTTA_CFG_CONFIG_HARDWARE_MTD_START_ADDR - .addr = YOTTA_CFG_CONFIG_HARDWARE_MTD_START_ADDR, +#ifdef DEVICE_STORAGE_CONFIG_HARDWARE_MTD_START_ADDR + .addr = DEVICE_STORAGE_CONFIG_HARDWARE_MTD_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 YOTTA_CFG_CONFIG_HARDWARE_MTD_SIZE - .size = YOTTA_CFG_CONFIG_HARDWARE_MTD_SIZE, +#ifdef DEVICE_STORAGE_CONFIG_HARDWARE_MTD_SIZE + .size = DEVICE_STORAGE_CONFIG_HARDWARE_MTD_SIZE, #else .size = BLOCK1_SIZE, #endif @@ -202,6 +204,13 @@ static const ARM_DRIVER_VERSION version = { .drv = ARM_DRIVER_VERSION_MAJOR_MINOR(1,00) }; + +#if (!defined(DEVICE_STORAGE_CONFIG_HARDWARE_MTD_ASYNC_OPS) || DEVICE_STORAGE_CONFIG_HARDWARE_MTD_ASYNC_OPS) +#define ASYNC_OPS 1 +#else +#define ASYNC_OPS 0 +#endif + static const ARM_STORAGE_CAPABILITIES caps = { /**< Signal Flash Ready event. In other words, can APIs like initialize, * read, erase, program, etc. operate in asynchronous mode? @@ -212,15 +221,11 @@ static const ARM_STORAGE_CAPABILITIES caps = { * 1, drivers may still complete asynchronous operations synchronously as * necessary--in which case they return a positive error code to indicate * synchronous completion. */ -#ifndef YOTTA_CFG_CONFIG_HARDWARE_MTD_ASYNC_OPS - .asynchronous_ops = 1, -#else - .asynchronous_ops = YOTTA_CFG_CONFIG_HARDWARE_MTD_ASYNC_OPS, -#endif + .asynchronous_ops = ASYNC_OPS, /* Enable chip-erase functionality if we own all of block-1. */ - #if ((!defined (YOTTA_CFG_CONFIG_HARDWARE_MTD_START_ADDR) || (YOTTA_CFG_CONFIG_HARDWARE_MTD_START_ADDR == BLOCK1_START_ADDR)) && \ - (!defined (YOTTA_CFG_CONFIG_HARDWARE_MTD_SIZE) || (YOTTA_CFG_CONFIG_HARDWARE_MTD_SIZE == BLOCK1_SIZE))) + #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))) .erase_all = 1, /**< Supports EraseChip operation. */ #else .erase_all = 0, /**< Supports EraseChip operation. */ @@ -228,7 +233,11 @@ 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. */ +#else .total_storage = BLOCK1_SIZE, /**< Total available storage, in units of octets. By default, BLOCK0 is reserved to hold program code. */ +#endif .program_unit = PROGRAM_UNIT, .optimal_program_unit = OPTIMAL_PROGRAM_UNIT, @@ -265,7 +274,6 @@ enum FlashCommandOps { SETRAM = (uint8_t)0x81, /* Set FlexRAM. (unused for now) */ }; - /** * Read out the CCIF (Command Complete Interrupt Flag) to ensure all previous * operations have completed. @@ -388,11 +396,6 @@ static inline bool commandCompletionInterruptEnabled(void) #endif } -static inline bool asyncOperationsEnabled(void) -{ - return caps.asynchronous_ops; -} - /** * Once all relevant command parameters have been loaded, the user launches the * command by clearing the FSTAT[CCIF] bit by writing a '1' to it. The CCIF flag @@ -511,22 +514,22 @@ static inline size_t sizeofLargestProgramSection(uint64_t addr, size_t size) * Advance the state machine for program-data. This function is called only if * amountLeftToOperate is non-zero. */ -static inline void setupNextProgramData(void) +static inline void setupNextProgramData(struct mtd_k64f_data *context) { - if ((amountLeftToOperate == PROGRAM_PHRASE_SIZEOF_INLINE_DATA) || - ((currentOperatingStorageAddress % SIZEOF_DOUBLE_PHRASE) == PROGRAM_PHRASE_SIZEOF_INLINE_DATA)) { - setup8ByteWrite(currentOperatingStorageAddress, currentOperatingData); + if ((context->amountLeftToOperate == PROGRAM_PHRASE_SIZEOF_INLINE_DATA) || + ((context->currentOperatingStorageAddress % SIZEOF_DOUBLE_PHRASE) == PROGRAM_PHRASE_SIZEOF_INLINE_DATA)) { + setup8ByteWrite(context->currentOperatingStorageAddress, context->currentOperatingData); - amountLeftToOperate -= PROGRAM_PHRASE_SIZEOF_INLINE_DATA; - currentOperatingStorageAddress += PROGRAM_PHRASE_SIZEOF_INLINE_DATA; - currentOperatingData += PROGRAM_PHRASE_SIZEOF_INLINE_DATA; + context->amountLeftToOperate -= PROGRAM_PHRASE_SIZEOF_INLINE_DATA; + context->currentOperatingStorageAddress += PROGRAM_PHRASE_SIZEOF_INLINE_DATA; + context->currentOperatingData += PROGRAM_PHRASE_SIZEOF_INLINE_DATA; } else { - size_t amount = sizeofLargestProgramSection(currentOperatingStorageAddress, amountLeftToOperate); - setupProgramSection(currentOperatingStorageAddress, currentOperatingData, amount); + size_t amount = sizeofLargestProgramSection(context->currentOperatingStorageAddress, context->amountLeftToOperate); + setupProgramSection(context->currentOperatingStorageAddress, context->currentOperatingData, amount); - amountLeftToOperate -= amount; - currentOperatingStorageAddress += amount; - currentOperatingData += amount; + context->amountLeftToOperate -= amount; + context->currentOperatingStorageAddress += amount; + context->currentOperatingData += amount; } } @@ -534,15 +537,15 @@ static inline void setupNextProgramData(void) * Advance the state machine for erase. This function is called only if * amountLeftToOperate is non-zero. */ -static inline void setupNextErase(void) +static inline void setupNextErase(struct mtd_k64f_data *context) { - setupEraseSector(currentOperatingStorageAddress); /* Program FCCOB to load the required command parameters. */ + setupEraseSector(context->currentOperatingStorageAddress); /* Program FCCOB to load the required command parameters. */ - amountLeftToOperate -= ERASE_UNIT; - currentOperatingStorageAddress += ERASE_UNIT; + context->amountLeftToOperate -= ERASE_UNIT; + context->currentOperatingStorageAddress += ERASE_UNIT; } -static int32_t executeCommand(void) +static int32_t executeCommand(struct mtd_k64f_data *context) { launchCommand(); @@ -550,104 +553,106 @@ static int32_t executeCommand(void) * parameter checks and protection checks, if applicable, which are unique * to each command. */ - if (asyncOperationsEnabled()) { - /* Asynchronous operation */ +#if ASYNC_OPS + /* Asynchronous operation */ - /* Spin waiting for the command execution to begin. */ - while (!controllerCurrentlyBusy() && !failedWithAccessError() && !failedWithProtectionError()); + (void)context; /* avoid compiler warning about un-used variables */ + + /* Spin waiting for the command execution to begin. */ + while (!controllerCurrentlyBusy() && !failedWithAccessError() && !failedWithProtectionError()); + if (failedWithAccessError() || failedWithProtectionError()) { + clearErrorStatusBits(); + return ARM_DRIVER_ERROR_PARAMETER; + } + + enableCommandCompletionInterrupt(); + + return ARM_DRIVER_OK; /* signal asynchronous completion. An interrupt will signal completion later. */ +#else /* #if ASYNC_OPS */ + /* Synchronous operation. */ + + while (1) { + /* Spin waiting for the command execution to complete. */ + while (controllerCurrentlyBusy()); + + /* Execution may result in failure. Check for errors */ if (failedWithAccessError() || failedWithProtectionError()) { clearErrorStatusBits(); return ARM_DRIVER_ERROR_PARAMETER; } + if (failedWithRunTimeError()) { + return ARM_DRIVER_ERROR; /* unspecified runtime error. */ + } - enableCommandCompletionInterrupt(); + /* signal synchronous completion. */ + switch (context->currentCommand) { + case ARM_STORAGE_OPERATION_PROGRAM_DATA: + if (context->amountLeftToOperate == 0) { + return context->sizeofCurrentOperation; + } - return ARM_DRIVER_OK; /* signal asynchronous completion. An interrupt will signal completion later. */ - } else { - /* Synchronous operation. */ + /* start the successive program operation */ + setupNextProgramData(context); + launchCommand(); + /* continue on to the next iteration of the parent loop */ + break; - while (1) { + case ARM_STORAGE_OPERATION_ERASE: + if (context->amountLeftToOperate == 0) { + return context->sizeofCurrentOperation; + } - /* Spin waiting for the command execution to complete. */ - while (controllerCurrentlyBusy()); + setupNextErase(context); /* start the successive erase operation */ + launchCommand(); + /* continue on to the next iteration of the parent loop */ + break; - /* Execution may result in failure. Check for errors */ - if (failedWithAccessError() || failedWithProtectionError()) { - clearErrorStatusBits(); - return ARM_DRIVER_ERROR_PARAMETER; - } - if (failedWithRunTimeError()) { - return ARM_DRIVER_ERROR; /* unspecified runtime error. */ - } - - /* signal synchronous completion. */ - switch (currentCommand) { - case ARM_STORAGE_OPERATION_PROGRAM_DATA: - if (amountLeftToOperate == 0) { - return sizeofCurrentOperation; - } - - /* start the successive program operation */ - setupNextProgramData(); - launchCommand(); - /* continue on to the next iteration of the parent loop */ - break; - - case ARM_STORAGE_OPERATION_ERASE: - if (amountLeftToOperate == 0) { - return sizeofCurrentOperation; - } - - setupNextErase(); /* start the successive erase operation */ - launchCommand(); - /* continue on to the next iteration of the parent loop */ - break; - - default: - return 1; - } + default: + return 1; } } +#endif /* #ifdef ASYNC_OPS */ } +#if ASYNC_OPS static void ftfe_ccie_irq_handler(void) { - NVIC_ClearPendingIRQ(FTFE_IRQn); disbleCommandCompletionInterrupt(); + struct mtd_k64f_data *context = &mtd_k64f_data; /* check for errors */ if (failedWithAccessError() || failedWithProtectionError()) { clearErrorStatusBits(); - if (commandCompletionCallback) { - commandCompletionCallback(ARM_DRIVER_ERROR_PARAMETER, currentCommand); + if (context->commandCompletionCallback) { + context->commandCompletionCallback(ARM_DRIVER_ERROR_PARAMETER, context->currentCommand); } return; } if (failedWithRunTimeError()) { - if (commandCompletionCallback) { - commandCompletionCallback(ARM_DRIVER_ERROR, currentCommand); + if (context->commandCompletionCallback) { + context->commandCompletionCallback(ARM_DRIVER_ERROR, context->currentCommand); } return; } - switch (currentCommand) { + switch (context->currentCommand) { case ARM_STORAGE_OPERATION_PROGRAM_DATA: - if (amountLeftToOperate == 0) { - if (commandCompletionCallback) { - commandCompletionCallback(sizeofCurrentOperation, ARM_STORAGE_OPERATION_PROGRAM_DATA); + if (context->amountLeftToOperate == 0) { + if (context->commandCompletionCallback) { + context->commandCompletionCallback(context->sizeofCurrentOperation, ARM_STORAGE_OPERATION_PROGRAM_DATA); } return; } /* start the successive program operation */ - setupNextProgramData(); + setupNextProgramData(context); launchCommand(); while (!controllerCurrentlyBusy() && !failedWithAccessError() && !failedWithProtectionError()); if (failedWithAccessError() || failedWithProtectionError()) { clearErrorStatusBits(); - if (commandCompletionCallback) { - commandCompletionCallback(ARM_DRIVER_ERROR_PARAMETER, ARM_STORAGE_OPERATION_PROGRAM_DATA); + if (context->commandCompletionCallback) { + context->commandCompletionCallback(ARM_DRIVER_ERROR_PARAMETER, ARM_STORAGE_OPERATION_PROGRAM_DATA); } return; } @@ -656,21 +661,21 @@ static void ftfe_ccie_irq_handler(void) break; case ARM_STORAGE_OPERATION_ERASE: - if (amountLeftToOperate == 0) { - if (commandCompletionCallback) { - commandCompletionCallback(sizeofCurrentOperation, ARM_STORAGE_OPERATION_ERASE); + if (context->amountLeftToOperate == 0) { + if (context->commandCompletionCallback) { + context->commandCompletionCallback(context->sizeofCurrentOperation, ARM_STORAGE_OPERATION_ERASE); } return; } - setupNextErase(); + setupNextErase(context); launchCommand(); while (!controllerCurrentlyBusy() && !failedWithAccessError() && !failedWithProtectionError()); if (failedWithAccessError() || failedWithProtectionError()) { clearErrorStatusBits(); - if (commandCompletionCallback) { - commandCompletionCallback(ARM_DRIVER_ERROR_PARAMETER, ARM_STORAGE_OPERATION_ERASE); + if (context->commandCompletionCallback) { + context->commandCompletionCallback(ARM_DRIVER_ERROR_PARAMETER, ARM_STORAGE_OPERATION_ERASE); } return; } @@ -679,12 +684,13 @@ static void ftfe_ccie_irq_handler(void) break; default: - if (commandCompletionCallback) { - commandCompletionCallback(ARM_DRIVER_OK, currentCommand); + if (context->commandCompletionCallback) { + context->commandCompletionCallback(ARM_DRIVER_OK, context->currentCommand); } break; } } +#endif /* #if ASYNC_OPS */ /** * This is a helper function which can be used to do arbitrary sanity checking @@ -707,7 +713,6 @@ static int32_t checkForEachBlockInRange(uint64_t startAddr, uint32_t size, int32 return rc; } - /* move on to the following block */ if (nextBlock(&block, &block) != ARM_DRIVER_OK) { break; @@ -746,21 +751,16 @@ static ARM_STORAGE_CAPABILITIES getCapabilities(void) static int32_t initialize(ARM_Storage_Callback_t callback) { - currentCommand = ARM_STORAGE_OPERATION_INITIALIZE; + struct mtd_k64f_data *context = &mtd_k64f_data; + memset(context, 0, sizeof(mtd_k64f_data)); + context->currentCommand = ARM_STORAGE_OPERATION_INITIALIZE; - if (initialized) { - commandCompletionCallback = callback; + if (context->initialized) { + context->commandCompletionCallback = callback; return 1; /* synchronous completion. */ } -#ifdef USING_KSDK2 - status_t rc = FLASH_Init(&privateDeviceConfig); - if (rc != kStatus_FLASH_Success) { - return ARM_DRIVER_ERROR; - } -#endif /* ifdef USING_KSDK2 */ - if (controllerCurrentlyBusy()) { /* The user cannot initiate any further FTFE commands until notified that the * current command has completed.*/ @@ -769,52 +769,57 @@ static int32_t initialize(ARM_Storage_Callback_t callback) clearErrorStatusBits(); - commandCompletionCallback = callback; + context->commandCompletionCallback = callback; /* Enable the command-completion interrupt. */ - if (asyncOperationsEnabled()) { - NVIC_SetVector(FTFE_IRQn, (uint32_t)ftfe_ccie_irq_handler); - NVIC_ClearPendingIRQ(FTFE_IRQn); - NVIC_EnableIRQ(FTFE_IRQn); - } +#if ASYNC_OPS + NVIC_SetVector(FTFE_IRQn, (uint32_t)ftfe_ccie_irq_handler); + NVIC_ClearPendingIRQ(FTFE_IRQn); + NVIC_EnableIRQ(FTFE_IRQn); +#endif - initialized = true; + context->initialized = true; return 1; /* synchronous completion. */ } static int32_t uninitialize(void) { - currentCommand = ARM_STORAGE_OPERATION_UNINITIALIZE; + struct mtd_k64f_data *context = &mtd_k64f_data; + context->currentCommand = ARM_STORAGE_OPERATION_UNINITIALIZE; - if (!initialized) { + if (!context->initialized) { return ARM_DRIVER_ERROR; } /* Disable the command-completion interrupt. */ - if (asyncOperationsEnabled() && commandCompletionInterruptEnabled()) { +#if ASYNC_OPS + if (commandCompletionInterruptEnabled()) { disbleCommandCompletionInterrupt(); NVIC_DisableIRQ(FTFE_IRQn); NVIC_ClearPendingIRQ(FTFE_IRQn); } +#endif - commandCompletionCallback = NULL; - initialized = false; + context->commandCompletionCallback = NULL; + context->initialized = false; return 1; /* synchronous completion. */ } static int32_t powerControl(ARM_POWER_STATE state) { - currentCommand = ARM_STORAGE_OPERATION_POWER_CONTROL; + struct mtd_k64f_data *context = &mtd_k64f_data; + context->currentCommand = ARM_STORAGE_OPERATION_POWER_CONTROL; - powerState = state; + context->powerState = state; return 1; /* signal synchronous completion. */ } static int32_t readData(uint64_t addr, void *data, uint32_t size) { - currentCommand = ARM_STORAGE_OPERATION_READ_DATA; + struct mtd_k64f_data *context = &mtd_k64f_data; + context->currentCommand = ARM_STORAGE_OPERATION_READ_DATA; - if (!initialized) { + if (!context->initialized) { return ARM_DRIVER_ERROR; /* illegal */ } @@ -826,13 +831,15 @@ 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; memcpy(data, (const void *)(uintptr_t)addr, size); return size; /* signal synchronous completion. */ } static int32_t programData(uint64_t addr, const void *data, uint32_t size) { - if (!initialized) { + struct mtd_k64f_data *context = &mtd_k64f_data; + if (!context->initialized) { return (int32_t)ARM_DRIVER_ERROR; /* illegal */ } @@ -853,27 +860,28 @@ static int32_t programData(uint64_t addr, const void *data, uint32_t size) return ARM_STORAGE_ERROR_NOT_PROGRAMMABLE; } - currentCommand = ARM_STORAGE_OPERATION_PROGRAM_DATA; - if (controllerCurrentlyBusy()) { /* The user cannot initiate any further FTFE commands until notified that the * current command has completed.*/ return ARM_DRIVER_ERROR_BUSY; } - sizeofCurrentOperation = size; - amountLeftToOperate = size; - currentOperatingData = data; - currentOperatingStorageAddress = addr; + context->currentCommand = ARM_STORAGE_OPERATION_PROGRAM_DATA; + context->sizeofCurrentOperation = size; + context->amountLeftToOperate = size; + context->currentOperatingData = data; + context->currentOperatingStorageAddress = addr; clearErrorStatusBits(); - setupNextProgramData(); - return executeCommand(); + setupNextProgramData(context); + return executeCommand(context); } static int32_t erase(uint64_t addr, uint32_t size) { - if (!initialized) { + struct mtd_k64f_data *context = &mtd_k64f_data; + + if (!context->initialized) { return (int32_t)ARM_DRIVER_ERROR; /* illegal */ } /* argument validation */ @@ -893,28 +901,27 @@ static int32_t erase(uint64_t addr, uint32_t size) return ARM_STORAGE_ERROR_NOT_ERASABLE; } - currentCommand = ARM_STORAGE_OPERATION_ERASE; - - currentOperatingStorageAddress = addr; - sizeofCurrentOperation = size; - amountLeftToOperate = size; - if (controllerCurrentlyBusy()) { /* The user cannot initiate any further FTFE commands until notified that the * current command has completed.*/ return (int32_t)ARM_DRIVER_ERROR_BUSY; } + context->currentCommand = ARM_STORAGE_OPERATION_ERASE; + context->currentOperatingStorageAddress = addr; + context->sizeofCurrentOperation = size; + context->amountLeftToOperate = size; + clearErrorStatusBits(); - setupNextErase(); - return executeCommand(); + setupNextErase(context); + return executeCommand(context); } static int32_t eraseAll(void) { - currentCommand = ARM_STORAGE_OPERATION_ERASE_ALL; + struct mtd_k64f_data *context = &mtd_k64f_data; - if (!initialized) { + if (!context->initialized) { return (int32_t)ARM_DRIVER_ERROR; /* illegal */ } @@ -932,22 +939,25 @@ static int32_t eraseAll(void) return (int32_t)ARM_DRIVER_ERROR_BUSY; } + context->currentCommand = ARM_STORAGE_OPERATION_ERASE_ALL; + clearErrorStatusBits(); /* Program FCCOB to load the required command parameters. */ setupEraseBlock(BLOCK1_START_ADDR); - - return executeCommand(); + return executeCommand(context); } static ARM_STORAGE_STATUS getStatus(void) { + struct mtd_k64f_data *context = &mtd_k64f_data; + ARM_STORAGE_STATUS status = { .busy = 0, .error = 0, }; - if (!initialized) { + if (!context->initialized) { status.error = 1; return status; }