fsl_ftfx_controller.c 47 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164116511661167116811691170117111721173117411751176117711781179118011811182118311841185118611871188118911901191119211931194119511961197119811991200120112021203120412051206120712081209121012111212121312141215121612171218121912201221122212231224122512261227122812291230123112321233123412351236123712381239124012411242124312441245124612471248124912501251125212531254125512561257125812591260126112621263126412651266126712681269127012711272127312741275127612771278127912801281128212831284128512861287128812891290129112921293129412951296129712981299130013011302130313041305130613071308130913101311131213131314131513161317131813191320132113221323132413251326132713281329133013311332133313341335133613371338133913401341134213431344134513461347134813491350135113521353135413551356135713581359136013611362136313641365136613671368136913701371137213731374137513761377137813791380138113821383138413851386138713881389139013911392139313941395139613971398139914001401140214031404
  1. /*
  2. * The Clear BSD License
  3. * Copyright 2013-2016 Freescale Semiconductor, Inc.
  4. * Copyright 2016-2018 NXP
  5. * All rights reserved.
  6. *
  7. * Redistribution and use in source and binary forms, with or without
  8. * modification, are permitted (subject to the limitations in the
  9. * disclaimer below) provided that the following conditions are met:
  10. *
  11. * * Redistributions of source code must retain the above copyright
  12. * notice, this list of conditions and the following disclaimer.
  13. *
  14. * * Redistributions in binary form must reproduce the above copyright
  15. * notice, this list of conditions and the following disclaimer in the
  16. * documentation and/or other materials provided with the distribution.
  17. *
  18. * * Neither the name of the copyright holder nor the names of its
  19. * contributors may be used to endorse or promote products derived from
  20. * this software without specific prior written permission.
  21. *
  22. * NO EXPRESS OR IMPLIED LICENSES TO ANY PARTY'S PATENT RIGHTS ARE
  23. * GRANTED BY THIS LICENSE. THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT
  24. * HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED
  25. * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
  26. * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
  27. * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
  28. * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
  29. * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
  30. * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
  31. * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
  32. * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE
  33. * OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
  34. * IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
  35. *
  36. */
  37. #include "fsl_ftfx_controller.h"
  38. /*******************************************************************************
  39. * Definitions
  40. ******************************************************************************/
  41. /*!
  42. * @name Flash controller command numbers
  43. * @{
  44. */
  45. #define FTFx_VERIFY_BLOCK 0x00U /*!< RD1BLK*/
  46. #define FTFx_VERIFY_SECTION 0x01U /*!< RD1SEC*/
  47. #define FTFx_PROGRAM_CHECK 0x02U /*!< PGMCHK*/
  48. #define FTFx_READ_RESOURCE 0x03U /*!< RDRSRC*/
  49. #define FTFx_PROGRAM_LONGWORD 0x06U /*!< PGM4*/
  50. #define FTFx_PROGRAM_PHRASE 0x07U /*!< PGM8*/
  51. #define FTFx_ERASE_BLOCK 0x08U /*!< ERSBLK*/
  52. #define FTFx_ERASE_SECTOR 0x09U /*!< ERSSCR*/
  53. #define FTFx_PROGRAM_SECTION 0x0BU /*!< PGMSEC*/
  54. #define FTFx_GENERATE_CRC 0x0CU /*!< CRCGEN*/
  55. #define FTFx_VERIFY_ALL_BLOCK 0x40U /*!< RD1ALL*/
  56. #define FTFx_READ_ONCE 0x41U /*!< RDONCE or RDINDEX*/
  57. #define FTFx_PROGRAM_ONCE 0x43U /*!< PGMONCE or PGMINDEX*/
  58. #define FTFx_ERASE_ALL_BLOCK 0x44U /*!< ERSALL*/
  59. #define FTFx_SECURITY_BY_PASS 0x45U /*!< VFYKEY*/
  60. #define FTFx_SWAP_CONTROL 0x46U /*!< SWAP*/
  61. #define FTFx_ERASE_ALL_BLOCK_UNSECURE 0x49U /*!< ERSALLU*/
  62. #define FTFx_VERIFY_ALL_EXECUTE_ONLY_SEGMENT 0x4AU /*!< RD1XA*/
  63. #define FTFx_ERASE_ALL_EXECUTE_ONLY_SEGMENT 0x4BU /*!< ERSXA*/
  64. #define FTFx_PROGRAM_PARTITION 0x80U /*!< PGMPART*/
  65. #define FTFx_SET_FLEXRAM_FUNCTION 0x81U /*!< SETRAM*/
  66. /*@}*/
  67. /*!
  68. * @brief Constants for execute-in-RAM flash function.
  69. */
  70. enum _ftfx_ram_func_constants
  71. {
  72. kFTFx_RamFuncMaxSizeInWords = 16U, /*!< The maximum size of execute-in-RAM function.*/
  73. };
  74. /*! @brief A function pointer used to point to relocated flash_run_command() */
  75. typedef void (*callFtfxRunCommand_t)(FTFx_REG8_ACCESS_TYPE ftfx_fstat);
  76. /*!
  77. * @name Enumeration for Flash security register code
  78. * @{
  79. */
  80. enum _ftfx_fsec_register_code
  81. {
  82. kFTFx_FsecRegCode_KEYEN_Enabled = 0x80U,
  83. kFTFx_FsecRegCode_SEC_Unsecured = 0x02U
  84. };
  85. /*@}*/
  86. /*!
  87. * @brief Enumeration for flash config area.
  88. */
  89. enum _ftfx_pflash_config_area_range
  90. {
  91. kFTFx_PflashConfigAreaStart = 0x400U,
  92. kFTFx_PflashConfigAreaEnd = 0x40FU
  93. };
  94. /*******************************************************************************
  95. * Prototypes
  96. ******************************************************************************/
  97. /*! @brief Init IFR memory related info */
  98. static status_t ftfx_init_ifr(ftfx_config_t *config);
  99. #if FTFx_DRIVER_IS_FLASH_RESIDENT
  100. /*! @brief Copy flash_run_command() to RAM*/
  101. static void ftfx_copy_run_command_to_ram(uint32_t *ftfxRunCommand);
  102. #endif /* FTFx_DRIVER_IS_FLASH_RESIDENT */
  103. /*! @brief Internal function Flash command sequence. Called by driver APIs only*/
  104. static status_t ftfx_command_sequence(ftfx_config_t *config);
  105. /*! @brief Validates the range and alignment of the given address range.*/
  106. static status_t ftfx_check_mem_range(ftfx_config_t *config,
  107. uint32_t startAddress,
  108. uint32_t lengthInBytes,
  109. uint8_t alignmentBaseline);
  110. /*! @brief Validates the given user key for flash erase APIs.*/
  111. static status_t ftfx_check_user_key(uint32_t key);
  112. /*! @brief Reads word from byte address.*/
  113. static uint32_t ftfx_read_word_from_byte_address(const uint8_t *src);
  114. /*! @brief Writes word to byte address.*/
  115. static void ftfx_write_word_to_byte_address(uint8_t *dst, uint32_t word);
  116. #if defined(FSL_FEATURE_FLASH_HAS_READ_RESOURCE_CMD) && FSL_FEATURE_FLASH_HAS_READ_RESOURCE_CMD
  117. /*! @brief Validates the range of the given resource address.*/
  118. static status_t ftfx_check_resource_range(ftfx_config_t *config,
  119. uint32_t start,
  120. uint32_t lengthInBytes,
  121. uint32_t alignmentBaseline,
  122. ftfx_read_resource_opt_t option);
  123. #endif /* FSL_FEATURE_FLASH_HAS_READ_RESOURCE_CMD */
  124. #if defined(FSL_FEATURE_FLASH_HAS_SET_FLEXRAM_FUNCTION_CMD) && FSL_FEATURE_FLASH_HAS_SET_FLEXRAM_FUNCTION_CMD
  125. /*! @brief Validates the gived flexram function option.*/
  126. static inline status_t ftfx_check_flexram_function_option(ftfx_flexram_func_opt_t option);
  127. #endif /* FSL_FEATURE_FLASH_HAS_SET_FLEXRAM_FUNCTION_CMD */
  128. #if defined(FSL_FEATURE_FLASH_HAS_SWAP_CONTROL_CMD) && FSL_FEATURE_FLASH_HAS_SWAP_CONTROL_CMD
  129. /*! @brief Validates the gived swap control option.*/
  130. static status_t ftfx_check_swap_control_option(ftfx_swap_control_opt_t option);
  131. #endif /* FSL_FEATURE_FLASH_HAS_SWAP_CONTROL_CMD */
  132. /*******************************************************************************
  133. * Variables
  134. ******************************************************************************/
  135. #if FTFx_DRIVER_IS_FLASH_RESIDENT
  136. /*!
  137. * @brief Position independent code of flash_run_command()
  138. *
  139. * Note1: The prototype of C function is shown as below:
  140. * @code
  141. * void flash_run_command(FTFx_REG8_ACCESS_TYPE ftfx_fstat)
  142. * {
  143. * // clear CCIF bit
  144. * *ftfx_fstat = FTFx_FSTAT_CCIF_MASK;
  145. *
  146. * // Check CCIF bit of the flash status register, wait till it is set.
  147. * // IP team indicates that this loop will always complete.
  148. * while (!((*ftfx_fstat) & FTFx_FSTAT_CCIF_MASK))
  149. * {
  150. * }
  151. * }
  152. * @endcode
  153. * Note2: The binary code is generated by IAR 7.70.1
  154. */
  155. static const uint16_t s_ftfxRunCommandFunctionCode[] = {
  156. 0x2180, /* MOVS R1, #128 ; 0x80 */
  157. 0x7001, /* STRB R1, [R0] */
  158. /* @4: */
  159. 0x7802, /* LDRB R2, [R0] */
  160. 0x420a, /* TST R2, R1 */
  161. 0xd0fc, /* BEQ.N @4 */
  162. 0x4770 /* BX LR */
  163. };
  164. #if (!FTFx_DRIVER_IS_EXPORTED)
  165. /*! @brief A static buffer used to hold flash_run_command() */
  166. static uint32_t s_ftfxRunCommand[kFTFx_RamFuncMaxSizeInWords];
  167. #endif /* (!FTFx_DRIVER_IS_EXPORTED) */
  168. #endif /* FTFx_DRIVER_IS_FLASH_RESIDENT */
  169. /*! @brief Access to FTFx Registers */
  170. static volatile uint32_t *const kFCCOBx = (volatile uint32_t *)&FTFx_FCCOB3_REG;
  171. #if FSL_FEATURE_FLASH_HAS_FLEX_NVM
  172. /*! @brief Table of eeprom sizes. */
  173. static const uint16_t kEepromDensities[16] = {
  174. FSL_FEATURE_FLASH_FLEX_NVM_EEPROM_SIZE_FOR_EEESIZE_0000,
  175. FSL_FEATURE_FLASH_FLEX_NVM_EEPROM_SIZE_FOR_EEESIZE_0001,
  176. FSL_FEATURE_FLASH_FLEX_NVM_EEPROM_SIZE_FOR_EEESIZE_0010,
  177. FSL_FEATURE_FLASH_FLEX_NVM_EEPROM_SIZE_FOR_EEESIZE_0011,
  178. FSL_FEATURE_FLASH_FLEX_NVM_EEPROM_SIZE_FOR_EEESIZE_0100,
  179. FSL_FEATURE_FLASH_FLEX_NVM_EEPROM_SIZE_FOR_EEESIZE_0101,
  180. FSL_FEATURE_FLASH_FLEX_NVM_EEPROM_SIZE_FOR_EEESIZE_0110,
  181. FSL_FEATURE_FLASH_FLEX_NVM_EEPROM_SIZE_FOR_EEESIZE_0111,
  182. FSL_FEATURE_FLASH_FLEX_NVM_EEPROM_SIZE_FOR_EEESIZE_1000,
  183. FSL_FEATURE_FLASH_FLEX_NVM_EEPROM_SIZE_FOR_EEESIZE_1001,
  184. FSL_FEATURE_FLASH_FLEX_NVM_EEPROM_SIZE_FOR_EEESIZE_1010,
  185. FSL_FEATURE_FLASH_FLEX_NVM_EEPROM_SIZE_FOR_EEESIZE_1011,
  186. FSL_FEATURE_FLASH_FLEX_NVM_EEPROM_SIZE_FOR_EEESIZE_1100,
  187. FSL_FEATURE_FLASH_FLEX_NVM_EEPROM_SIZE_FOR_EEESIZE_1101,
  188. FSL_FEATURE_FLASH_FLEX_NVM_EEPROM_SIZE_FOR_EEESIZE_1110,
  189. FSL_FEATURE_FLASH_FLEX_NVM_EEPROM_SIZE_FOR_EEESIZE_1111
  190. };
  191. /*! @brief Table of dflash sizes. */
  192. static const uint32_t kDflashDensities[16] = {
  193. FSL_FEATURE_FLASH_FLEX_NVM_DFLASH_SIZE_FOR_DEPART_0000,
  194. FSL_FEATURE_FLASH_FLEX_NVM_DFLASH_SIZE_FOR_DEPART_0001,
  195. FSL_FEATURE_FLASH_FLEX_NVM_DFLASH_SIZE_FOR_DEPART_0010,
  196. FSL_FEATURE_FLASH_FLEX_NVM_DFLASH_SIZE_FOR_DEPART_0011,
  197. FSL_FEATURE_FLASH_FLEX_NVM_DFLASH_SIZE_FOR_DEPART_0100,
  198. FSL_FEATURE_FLASH_FLEX_NVM_DFLASH_SIZE_FOR_DEPART_0101,
  199. FSL_FEATURE_FLASH_FLEX_NVM_DFLASH_SIZE_FOR_DEPART_0110,
  200. FSL_FEATURE_FLASH_FLEX_NVM_DFLASH_SIZE_FOR_DEPART_0111,
  201. FSL_FEATURE_FLASH_FLEX_NVM_DFLASH_SIZE_FOR_DEPART_1000,
  202. FSL_FEATURE_FLASH_FLEX_NVM_DFLASH_SIZE_FOR_DEPART_1001,
  203. FSL_FEATURE_FLASH_FLEX_NVM_DFLASH_SIZE_FOR_DEPART_1010,
  204. FSL_FEATURE_FLASH_FLEX_NVM_DFLASH_SIZE_FOR_DEPART_1011,
  205. FSL_FEATURE_FLASH_FLEX_NVM_DFLASH_SIZE_FOR_DEPART_1100,
  206. FSL_FEATURE_FLASH_FLEX_NVM_DFLASH_SIZE_FOR_DEPART_1101,
  207. FSL_FEATURE_FLASH_FLEX_NVM_DFLASH_SIZE_FOR_DEPART_1110,
  208. FSL_FEATURE_FLASH_FLEX_NVM_DFLASH_SIZE_FOR_DEPART_1111
  209. };
  210. #endif /* FSL_FEATURE_FLASH_HAS_FLEX_NVM */
  211. /*******************************************************************************
  212. * Code
  213. ******************************************************************************/
  214. status_t FTFx_API_Init(ftfx_config_t *config)
  215. {
  216. if (config == NULL)
  217. {
  218. return kStatus_FTFx_InvalidArgument;
  219. }
  220. config->flexramBlockBase = FSL_FEATURE_FLASH_FLEX_RAM_START_ADDRESS;
  221. config->flexramTotalSize = FSL_FEATURE_FLASH_FLEX_RAM_SIZE;
  222. /* copy required flash command to RAM */
  223. #if FTFx_DRIVER_IS_FLASH_RESIDENT
  224. if (NULL == config->runCmdFuncAddr)
  225. {
  226. #if FTFx_DRIVER_IS_EXPORTED
  227. return kStatus_FTFx_ExecuteInRamFunctionNotReady;
  228. #else
  229. config->runCmdFuncAddr = s_ftfxRunCommand;
  230. #endif /* FTFx_DRIVER_IS_EXPORTED */
  231. }
  232. ftfx_copy_run_command_to_ram(config->runCmdFuncAddr);
  233. #endif /* FTFx_DRIVER_IS_FLASH_RESIDENT */
  234. ftfx_init_ifr(config);
  235. return kStatus_FTFx_Success;
  236. }
  237. #if FSL_FEATURE_FLASH_HAS_FLEX_NVM
  238. status_t FTFx_API_UpdateFlexnvmPartitionStatus(ftfx_config_t *config)
  239. {
  240. struct _dflash_ifr_field_config
  241. {
  242. uint32_t reserved0;
  243. uint8_t FlexNVMPartitionCode;
  244. uint8_t EEPROMDataSetSize;
  245. uint16_t reserved1;
  246. } dataIFRReadOut;
  247. uint32_t flexnvmInfoIfrAddr;
  248. status_t returnCode;
  249. if (config == NULL)
  250. {
  251. return kStatus_FTFx_InvalidArgument;
  252. }
  253. flexnvmInfoIfrAddr = config->ifrDesc.resRange.dflashIfrStart + config->ifrDesc.resRange.ifrMemSize - sizeof(dataIFRReadOut);
  254. #if defined(FSL_FEATURE_FLASH_HAS_READ_RESOURCE_CMD) && FSL_FEATURE_FLASH_HAS_READ_RESOURCE_CMD
  255. /* Get FlexNVM memory partition info from data flash IFR */
  256. returnCode = FTFx_CMD_ReadResource(config, flexnvmInfoIfrAddr, (uint8_t *)&dataIFRReadOut,
  257. sizeof(dataIFRReadOut), kFTFx_ResourceOptionFlashIfr);
  258. if (returnCode != kStatus_FTFx_Success)
  259. {
  260. return kStatus_FTFx_PartitionStatusUpdateFailure;
  261. }
  262. #else
  263. #error "Cannot get FlexNVM memory partition info"
  264. #endif
  265. /* Fill out partitioned EEPROM size */
  266. dataIFRReadOut.EEPROMDataSetSize &= 0x0FU;
  267. config->eepromTotalSize = kEepromDensities[dataIFRReadOut.EEPROMDataSetSize];
  268. /* Fill out partitioned DFlash size */
  269. dataIFRReadOut.FlexNVMPartitionCode &= 0x0FU;
  270. config->flashDesc.totalSize = kDflashDensities[dataIFRReadOut.FlexNVMPartitionCode];
  271. return kStatus_FTFx_Success;
  272. }
  273. #endif /* FSL_FEATURE_FLASH_HAS_FLEX_NVM */
  274. status_t FTFx_CMD_Erase(ftfx_config_t *config,
  275. uint32_t start,
  276. uint32_t lengthInBytes,
  277. uint32_t key)
  278. {
  279. uint32_t sectorSize;
  280. uint32_t endAddress; /* storing end address */
  281. uint32_t numberOfSectors; /* number of sectors calculated by endAddress */
  282. status_t returnCode;
  283. /* Check the supplied address range. */
  284. returnCode = ftfx_check_mem_range(config, start, lengthInBytes, config->opsConfig.addrAligment.sectorCmd);
  285. if (returnCode)
  286. {
  287. return returnCode;
  288. }
  289. /* Validate the user key */
  290. returnCode = ftfx_check_user_key(key);
  291. if (returnCode)
  292. {
  293. return returnCode;
  294. }
  295. start = config->opsConfig.convertedAddress;
  296. sectorSize = config->flashDesc.sectorSize;
  297. /* calculating Flash end address */
  298. endAddress = start + lengthInBytes - 1;
  299. /* re-calculate the endAddress and align it to the start of the next sector
  300. * which will be used in the comparison below */
  301. if (endAddress % sectorSize)
  302. {
  303. numberOfSectors = endAddress / sectorSize + 1;
  304. endAddress = numberOfSectors * sectorSize - 1;
  305. }
  306. /* the start address will increment to the next sector address
  307. * until it reaches the endAdddress */
  308. while (start <= endAddress)
  309. {
  310. /* preparing passing parameter to erase a flash block */
  311. kFCCOBx[0] = BYTE2WORD_1_3(FTFx_ERASE_SECTOR, start);
  312. /* calling flash command sequence function to execute the command */
  313. returnCode = ftfx_command_sequence(config);
  314. /* checking the success of command execution */
  315. if (kStatus_FTFx_Success != returnCode)
  316. {
  317. break;
  318. }
  319. else
  320. {
  321. /* Increment to the next sector */
  322. start += sectorSize;
  323. }
  324. }
  325. return (returnCode);
  326. }
  327. status_t FTFx_CMD_EraseAll(ftfx_config_t *config, uint32_t key)
  328. {
  329. status_t returnCode;
  330. if (config == NULL)
  331. {
  332. return kStatus_FTFx_InvalidArgument;
  333. }
  334. /* preparing passing parameter to erase all flash blocks */
  335. kFCCOBx[0] = BYTE2WORD_1_3(FTFx_ERASE_ALL_BLOCK, 0xFFFFFFU);
  336. /* Validate the user key */
  337. returnCode = ftfx_check_user_key(key);
  338. if (returnCode)
  339. {
  340. return returnCode;
  341. }
  342. /* calling flash command sequence function to execute the command */
  343. returnCode = ftfx_command_sequence(config);
  344. #if FSL_FEATURE_FLASH_HAS_FLEX_NVM
  345. /* Data flash IFR will be erased by erase all command, so we need to
  346. * update FlexNVM memory partition status synchronously */
  347. if (returnCode == kStatus_FTFx_Success)
  348. {
  349. returnCode = FTFx_API_UpdateFlexnvmPartitionStatus(config);
  350. }
  351. #endif
  352. return returnCode;
  353. }
  354. #if defined(FSL_FEATURE_FLASH_HAS_ERASE_ALL_BLOCKS_UNSECURE_CMD) && FSL_FEATURE_FLASH_HAS_ERASE_ALL_BLOCKS_UNSECURE_CMD
  355. status_t FTFx_CMD_EraseAllUnsecure(ftfx_config_t *config, uint32_t key)
  356. {
  357. status_t returnCode;
  358. if (config == NULL)
  359. {
  360. return kStatus_FTFx_InvalidArgument;
  361. }
  362. /* Prepare passing parameter to erase all flash blocks (unsecure). */
  363. kFCCOBx[0] = BYTE2WORD_1_3(FTFx_ERASE_ALL_BLOCK_UNSECURE, 0xFFFFFFU);
  364. /* Validate the user key */
  365. returnCode = ftfx_check_user_key(key);
  366. if (returnCode)
  367. {
  368. return returnCode;
  369. }
  370. /* calling flash command sequence function to execute the command */
  371. returnCode = ftfx_command_sequence(config);
  372. #if FSL_FEATURE_FLASH_HAS_FLEX_NVM
  373. /* Data flash IFR will be erased by erase all unsecure command, so we need to
  374. * update FlexNVM memory partition status synchronously */
  375. if (returnCode == kStatus_FTFx_Success)
  376. {
  377. returnCode = FTFx_API_UpdateFlexnvmPartitionStatus(config);
  378. }
  379. #endif
  380. return returnCode;
  381. }
  382. #endif /* FSL_FEATURE_FLASH_HAS_ERASE_ALL_BLOCKS_UNSECURE_CMD */
  383. status_t FTFx_CMD_EraseAllExecuteOnlySegments(ftfx_config_t *config, uint32_t key)
  384. {
  385. status_t returnCode;
  386. if (config == NULL)
  387. {
  388. return kStatus_FTFx_InvalidArgument;
  389. }
  390. /* preparing passing parameter to erase all execute-only segments
  391. * 1st element for the FCCOB register */
  392. kFCCOBx[0] = BYTE2WORD_1_3(FTFx_ERASE_ALL_EXECUTE_ONLY_SEGMENT, 0xFFFFFFU);
  393. /* Validate the user key */
  394. returnCode = ftfx_check_user_key(key);
  395. if (returnCode)
  396. {
  397. return returnCode;
  398. }
  399. /* calling flash command sequence function to execute the command */
  400. returnCode = ftfx_command_sequence(config);
  401. return returnCode;
  402. }
  403. status_t FTFx_CMD_Program(ftfx_config_t *config,
  404. uint32_t start,
  405. uint8_t *src,
  406. uint32_t lengthInBytes)
  407. {
  408. status_t returnCode;
  409. uint8_t blockWriteUnitSize = config->opsConfig.addrAligment.blockWriteUnitSize;
  410. if (src == NULL)
  411. {
  412. return kStatus_FTFx_InvalidArgument;
  413. }
  414. /* Check the supplied address range. */
  415. returnCode = ftfx_check_mem_range(config, start, lengthInBytes, blockWriteUnitSize);
  416. if (returnCode)
  417. {
  418. return returnCode;
  419. }
  420. start = config->opsConfig.convertedAddress;
  421. while (lengthInBytes > 0)
  422. {
  423. /* preparing passing parameter to program the flash block */
  424. kFCCOBx[1] = ftfx_read_word_from_byte_address((const uint8_t*)src);
  425. src += 4;
  426. if (4 == blockWriteUnitSize)
  427. {
  428. kFCCOBx[0] = BYTE2WORD_1_3(FTFx_PROGRAM_LONGWORD, start);
  429. }
  430. else if (8 == blockWriteUnitSize)
  431. {
  432. kFCCOBx[2] = ftfx_read_word_from_byte_address((const uint8_t*)src);
  433. src += 4;
  434. kFCCOBx[0] = BYTE2WORD_1_3(FTFx_PROGRAM_PHRASE, start);
  435. }
  436. else
  437. {
  438. }
  439. /* calling flash command sequence function to execute the command */
  440. returnCode = ftfx_command_sequence(config);
  441. /* checking for the success of command execution */
  442. if (kStatus_FTFx_Success != returnCode)
  443. {
  444. break;
  445. }
  446. else
  447. {
  448. /* update start address for next iteration */
  449. start += blockWriteUnitSize;
  450. /* update lengthInBytes for next iteration */
  451. lengthInBytes -= blockWriteUnitSize;
  452. }
  453. }
  454. return (returnCode);
  455. }
  456. status_t FTFx_CMD_ProgramOnce(ftfx_config_t *config, uint32_t index, uint8_t *src, uint32_t lengthInBytes)
  457. {
  458. status_t returnCode;
  459. if ((config == NULL) || (src == NULL))
  460. {
  461. return kStatus_FTFx_InvalidArgument;
  462. }
  463. /* pass paramters to FTFx */
  464. kFCCOBx[0] = BYTE2WORD_1_1_2(FTFx_PROGRAM_ONCE, index, 0xFFFFU);
  465. kFCCOBx[1] = ftfx_read_word_from_byte_address((const uint8_t*)src);
  466. /* Note: Have to seperate the first index from the rest if it equals 0
  467. * to avoid a pointless comparison of unsigned int to 0 compiler warning */
  468. if (config->ifrDesc.feature.has8ByteIdxSupport)
  469. {
  470. if (config->ifrDesc.feature.has4ByteIdxSupport)
  471. {
  472. if (((index == config->ifrDesc.idxInfo.mix8byteIdxStart) ||
  473. ((index >= config->ifrDesc.idxInfo.mix8byteIdxStart + 1) && (index <= config->ifrDesc.idxInfo.mix8byteIdxStart))) &&
  474. (lengthInBytes == 8))
  475. {
  476. kFCCOBx[2] = ftfx_read_word_from_byte_address((const uint8_t*)src + 4);
  477. }
  478. }
  479. else
  480. {
  481. kFCCOBx[2] = ftfx_read_word_from_byte_address((const uint8_t*)src + 4);
  482. }
  483. }
  484. /* calling flash command sequence function to execute the command */
  485. returnCode = ftfx_command_sequence(config);
  486. return returnCode;
  487. }
  488. #if defined(FSL_FEATURE_FLASH_HAS_PROGRAM_SECTION_CMD) && FSL_FEATURE_FLASH_HAS_PROGRAM_SECTION_CMD
  489. status_t FTFx_CMD_ProgramSection(ftfx_config_t *config,
  490. uint32_t start,
  491. uint8_t *src,
  492. uint32_t lengthInBytes)
  493. {
  494. status_t returnCode;
  495. uint32_t sectorSize;
  496. uint8_t aligmentInBytes = config->opsConfig.addrAligment.sectionCmd;
  497. #if defined(FSL_FEATURE_FLASH_HAS_SET_FLEXRAM_FUNCTION_CMD) && FSL_FEATURE_FLASH_HAS_SET_FLEXRAM_FUNCTION_CMD
  498. bool needSwitchFlexRamMode = false;
  499. #endif /* FSL_FEATURE_FLASH_HAS_SET_FLEXRAM_FUNCTION_CMD */
  500. if (src == NULL)
  501. {
  502. return kStatus_FTFx_InvalidArgument;
  503. }
  504. /* Check the supplied address range. */
  505. returnCode = ftfx_check_mem_range(config, start, lengthInBytes, aligmentInBytes);
  506. if (returnCode)
  507. {
  508. return returnCode;
  509. }
  510. start = config->opsConfig.convertedAddress;
  511. sectorSize = config->flashDesc.sectorSize;
  512. #if defined(FSL_FEATURE_FLASH_HAS_SET_FLEXRAM_FUNCTION_CMD) && FSL_FEATURE_FLASH_HAS_SET_FLEXRAM_FUNCTION_CMD
  513. /* Switch function of FlexRAM if needed */
  514. if (!(FTFx->FCNFG & FTFx_FCNFG_RAMRDY_MASK))
  515. {
  516. needSwitchFlexRamMode = true;
  517. returnCode = FTFx_CMD_SetFlexramFunction(config, kFTFx_FlexramFuncOptAvailableAsRam);
  518. if (returnCode != kStatus_FTFx_Success)
  519. {
  520. return kStatus_FTFx_SetFlexramAsRamError;
  521. }
  522. }
  523. #endif /* FSL_FEATURE_FLASH_HAS_SET_FLEXRAM_FUNCTION_CMD */
  524. while (lengthInBytes > 0)
  525. {
  526. /* Make sure the write operation doesn't span two sectors */
  527. uint32_t endAddressOfCurrentSector = ALIGN_UP(start, sectorSize);
  528. uint32_t lengthTobeProgrammedOfCurrentSector;
  529. uint32_t currentOffset = 0;
  530. if (endAddressOfCurrentSector == start)
  531. {
  532. endAddressOfCurrentSector += sectorSize;
  533. }
  534. if (lengthInBytes + start > endAddressOfCurrentSector)
  535. {
  536. lengthTobeProgrammedOfCurrentSector = endAddressOfCurrentSector - start;
  537. }
  538. else
  539. {
  540. lengthTobeProgrammedOfCurrentSector = lengthInBytes;
  541. }
  542. /* Program Current Sector */
  543. while (lengthTobeProgrammedOfCurrentSector > 0)
  544. {
  545. /* Make sure the program size doesn't exceeds Acceleration RAM size */
  546. uint32_t programSizeOfCurrentPass;
  547. uint32_t numberOfPhases;
  548. if (lengthTobeProgrammedOfCurrentSector > config->flexramTotalSize)
  549. {
  550. programSizeOfCurrentPass = config->flexramTotalSize;
  551. }
  552. else
  553. {
  554. programSizeOfCurrentPass = lengthTobeProgrammedOfCurrentSector;
  555. }
  556. /* Copy data to FlexRAM */
  557. memcpy((void *)config->flexramBlockBase, src + currentOffset, programSizeOfCurrentPass);
  558. /* Set start address of the data to be programmed */
  559. kFCCOBx[0] = BYTE2WORD_1_3(FTFx_PROGRAM_SECTION, start + currentOffset);
  560. /* Set program size in terms of FEATURE_FLASH_SECTION_CMD_ADDRESS_ALIGMENT */
  561. numberOfPhases = programSizeOfCurrentPass / aligmentInBytes;
  562. kFCCOBx[1] = BYTE2WORD_2_2(numberOfPhases, 0xFFFFU);
  563. /* Peform command sequence */
  564. returnCode = ftfx_command_sequence(config);
  565. if (returnCode != kStatus_FTFx_Success)
  566. {
  567. return returnCode;
  568. }
  569. lengthTobeProgrammedOfCurrentSector -= programSizeOfCurrentPass;
  570. currentOffset += programSizeOfCurrentPass;
  571. }
  572. src += currentOffset;
  573. start += currentOffset;
  574. lengthInBytes -= currentOffset;
  575. }
  576. #if defined(FSL_FEATURE_FLASH_HAS_SET_FLEXRAM_FUNCTION_CMD) && FSL_FEATURE_FLASH_HAS_SET_FLEXRAM_FUNCTION_CMD
  577. /* Restore function of FlexRAM if needed. */
  578. if (needSwitchFlexRamMode)
  579. {
  580. returnCode = FTFx_CMD_SetFlexramFunction(config, kFTFx_FlexramFuncOptAvailableForEeprom);
  581. if (returnCode != kStatus_FTFx_Success)
  582. {
  583. return kStatus_FTFx_RecoverFlexramAsEepromError;
  584. }
  585. }
  586. #endif /* FSL_FEATURE_FLASH_HAS_SET_FLEXRAM_FUNCTION_CMD */
  587. return returnCode;
  588. }
  589. #endif /* FSL_FEATURE_FLASH_HAS_PROGRAM_SECTION_CMD */
  590. #if defined(FSL_FEATURE_FLASH_HAS_PROGRAM_PARTITION_CMD) && FSL_FEATURE_FLASH_HAS_PROGRAM_PARTITION_CMD
  591. status_t FTFx_CMD_ProgramPartition(ftfx_config_t *config,
  592. ftfx_partition_flexram_load_opt_t option,
  593. uint32_t eepromDataSizeCode,
  594. uint32_t flexnvmPartitionCode)
  595. {
  596. status_t returnCode;
  597. if (config == NULL)
  598. {
  599. return kStatus_FTFx_InvalidArgument;
  600. }
  601. /* eepromDataSizeCode[7:6], flexnvmPartitionCode[7:4] should be all 1'b0
  602. * or it will cause access error. */
  603. /* eepromDataSizeCode &= 0x3FU; */
  604. /* flexnvmPartitionCode &= 0x0FU; */
  605. /* preparing passing parameter to program the flash block */
  606. kFCCOBx[0] = BYTE2WORD_1_2_1(FTFx_PROGRAM_PARTITION, 0xFFFFU, option);
  607. kFCCOBx[1] = BYTE2WORD_1_1_2(eepromDataSizeCode, flexnvmPartitionCode, 0xFFFFU);
  608. /* calling flash command sequence function to execute the command */
  609. returnCode = ftfx_command_sequence(config);
  610. #if FSL_FEATURE_FLASH_HAS_FLEX_NVM
  611. /* Data flash IFR will be updated by program partition command during reset sequence,
  612. * so we just set reserved values for partitioned FlexNVM size here */
  613. config->eepromTotalSize = 0xFFFFU;
  614. config->flashDesc.totalSize = 0xFFFFFFFFU;
  615. #endif
  616. return (returnCode);
  617. }
  618. #endif /* FSL_FEATURE_FLASH_HAS_PROGRAM_PARTITION_CMD */
  619. status_t FTFx_CMD_ReadOnce(ftfx_config_t *config, uint32_t index, uint8_t *dst, uint32_t lengthInBytes)
  620. {
  621. status_t returnCode;
  622. if ((config == NULL) || (dst == NULL))
  623. {
  624. return kStatus_FTFx_InvalidArgument;
  625. }
  626. /* pass paramters to FTFx */
  627. kFCCOBx[0] = BYTE2WORD_1_1_2(FTFx_READ_ONCE, index, 0xFFFFU);
  628. /* calling flash command sequence function to execute the command */
  629. returnCode = ftfx_command_sequence(config);
  630. if (kStatus_FTFx_Success == returnCode)
  631. {
  632. ftfx_write_word_to_byte_address(dst, kFCCOBx[1]);
  633. /* Note: Have to seperate the first index from the rest if it equals 0
  634. * to avoid a pointless comparison of unsigned int to 0 compiler warning */
  635. if (config->ifrDesc.feature.has8ByteIdxSupport)
  636. {
  637. if (config->ifrDesc.feature.has4ByteIdxSupport)
  638. {
  639. if (((index == config->ifrDesc.idxInfo.mix8byteIdxStart) ||
  640. ((index >= config->ifrDesc.idxInfo.mix8byteIdxStart + 1) && (index <= config->ifrDesc.idxInfo.mix8byteIdxStart))) &&
  641. (lengthInBytes == 8))
  642. {
  643. ftfx_write_word_to_byte_address(dst + 4, kFCCOBx[2]);
  644. }
  645. }
  646. else
  647. {
  648. ftfx_write_word_to_byte_address(dst + 4, kFCCOBx[2]);
  649. }
  650. }
  651. }
  652. return returnCode;
  653. }
  654. #if defined(FSL_FEATURE_FLASH_HAS_READ_RESOURCE_CMD) && FSL_FEATURE_FLASH_HAS_READ_RESOURCE_CMD
  655. status_t FTFx_CMD_ReadResource(ftfx_config_t *config,
  656. uint32_t start,
  657. uint8_t *dst,
  658. uint32_t lengthInBytes,
  659. ftfx_read_resource_opt_t option)
  660. {
  661. status_t returnCode;
  662. if ((config == NULL) || (dst == NULL))
  663. {
  664. return kStatus_FTFx_InvalidArgument;
  665. }
  666. uint8_t aligmentInBytes = config->opsConfig.addrAligment.resourceCmd;
  667. /* Check the supplied address range. */
  668. returnCode = ftfx_check_resource_range(config, start, lengthInBytes, aligmentInBytes, option);
  669. if (returnCode != kStatus_FTFx_Success)
  670. {
  671. return returnCode;
  672. }
  673. while (lengthInBytes > 0)
  674. {
  675. /* preparing passing parameter */
  676. kFCCOBx[0] = BYTE2WORD_1_3(FTFx_READ_RESOURCE, start);
  677. if (aligmentInBytes == 4)
  678. {
  679. kFCCOBx[2] = BYTE2WORD_1_3(option, 0xFFFFFFU);
  680. }
  681. else if (aligmentInBytes == 8)
  682. {
  683. kFCCOBx[1] = BYTE2WORD_1_3(option, 0xFFFFFFU);
  684. }
  685. else
  686. {
  687. }
  688. /* calling flash command sequence function to execute the command */
  689. returnCode = ftfx_command_sequence(config);
  690. if (kStatus_FTFx_Success != returnCode)
  691. {
  692. break;
  693. }
  694. /* fetch data */
  695. ftfx_write_word_to_byte_address(dst, kFCCOBx[1]);
  696. dst += 4;
  697. if (aligmentInBytes == 8)
  698. {
  699. ftfx_write_word_to_byte_address(dst, kFCCOBx[2]);
  700. dst += 4;
  701. }
  702. /* update start address for next iteration */
  703. start += aligmentInBytes;
  704. /* update lengthInBytes for next iteration */
  705. lengthInBytes -= aligmentInBytes;
  706. }
  707. return (returnCode);
  708. }
  709. #endif /* FSL_FEATURE_FLASH_HAS_READ_RESOURCE_CMD */
  710. status_t FTFx_CMD_VerifyErase(ftfx_config_t *config,
  711. uint32_t start,
  712. uint32_t lengthInBytes,
  713. ftfx_margin_value_t margin)
  714. {
  715. /* Check arguments. */
  716. uint32_t blockSize;
  717. uint32_t nextBlockStartAddress;
  718. uint32_t remainingBytes;
  719. uint8_t aligmentInBytes = config->opsConfig.addrAligment.sectionCmd;
  720. status_t returnCode;
  721. returnCode = ftfx_check_mem_range(config, start, lengthInBytes, aligmentInBytes);
  722. if (returnCode)
  723. {
  724. return returnCode;
  725. }
  726. start = config->opsConfig.convertedAddress;
  727. blockSize = config->flashDesc.totalSize / config->flashDesc.blockCount;
  728. nextBlockStartAddress = ALIGN_UP(start, blockSize);
  729. if (nextBlockStartAddress == start)
  730. {
  731. nextBlockStartAddress += blockSize;
  732. }
  733. remainingBytes = lengthInBytes;
  734. while (remainingBytes)
  735. {
  736. uint32_t numberOfPhrases;
  737. uint32_t verifyLength = nextBlockStartAddress - start;
  738. if (verifyLength > remainingBytes)
  739. {
  740. verifyLength = remainingBytes;
  741. }
  742. numberOfPhrases = verifyLength / aligmentInBytes;
  743. /* Fill in verify section command parameters. */
  744. kFCCOBx[0] = BYTE2WORD_1_3(FTFx_VERIFY_SECTION, start);
  745. kFCCOBx[1] = BYTE2WORD_2_1_1(numberOfPhrases, margin, 0xFFU);
  746. /* calling flash command sequence function to execute the command */
  747. returnCode = ftfx_command_sequence(config);
  748. if (returnCode)
  749. {
  750. return returnCode;
  751. }
  752. remainingBytes -= verifyLength;
  753. start += verifyLength;
  754. nextBlockStartAddress += blockSize;
  755. }
  756. return kStatus_FTFx_Success;
  757. }
  758. status_t FTFx_CMD_VerifyEraseAll(ftfx_config_t *config, ftfx_margin_value_t margin)
  759. {
  760. if (config == NULL)
  761. {
  762. return kStatus_FTFx_InvalidArgument;
  763. }
  764. /* preparing passing parameter to verify all block command */
  765. kFCCOBx[0] = BYTE2WORD_1_1_2(FTFx_VERIFY_ALL_BLOCK, margin, 0xFFFFU);
  766. /* calling flash command sequence function to execute the command */
  767. return ftfx_command_sequence(config);
  768. }
  769. status_t FTFx_CMD_VerifyEraseAllExecuteOnlySegments(ftfx_config_t *config, ftfx_margin_value_t margin)
  770. {
  771. if (config == NULL)
  772. {
  773. return kStatus_FTFx_InvalidArgument;
  774. }
  775. /* preparing passing parameter to verify erase all execute-only segments command */
  776. kFCCOBx[0] = BYTE2WORD_1_1_2(FTFx_VERIFY_ALL_EXECUTE_ONLY_SEGMENT, margin, 0xFFFFU);
  777. /* calling flash command sequence function to execute the command */
  778. return ftfx_command_sequence(config);
  779. }
  780. status_t FTFx_CMD_VerifyProgram(ftfx_config_t *config,
  781. uint32_t start,
  782. uint32_t lengthInBytes,
  783. const uint8_t *expectedData,
  784. ftfx_margin_value_t margin,
  785. uint32_t *failedAddress,
  786. uint32_t *failedData)
  787. {
  788. status_t returnCode;
  789. uint8_t aligmentInBytes = config->opsConfig.addrAligment.checkCmd;
  790. if (expectedData == NULL)
  791. {
  792. return kStatus_FTFx_InvalidArgument;
  793. }
  794. returnCode = ftfx_check_mem_range(config, start, lengthInBytes, aligmentInBytes);
  795. if (returnCode)
  796. {
  797. return returnCode;
  798. }
  799. start = config->opsConfig.convertedAddress;
  800. while (lengthInBytes)
  801. {
  802. /* preparing passing parameter to program check the flash block */
  803. kFCCOBx[0] = BYTE2WORD_1_3(FTFx_PROGRAM_CHECK, start);
  804. kFCCOBx[1] = BYTE2WORD_1_3(margin, 0xFFFFFFU);
  805. kFCCOBx[2] = ftfx_read_word_from_byte_address((const uint8_t*)expectedData);
  806. /* calling flash command sequence function to execute the command */
  807. returnCode = ftfx_command_sequence(config);
  808. /* checking for the success of command execution */
  809. if (kStatus_FTFx_Success != returnCode)
  810. {
  811. if (failedAddress)
  812. {
  813. *failedAddress = start;
  814. }
  815. if (failedData)
  816. {
  817. *failedData = 0;
  818. }
  819. break;
  820. }
  821. lengthInBytes -= aligmentInBytes;
  822. expectedData += aligmentInBytes;
  823. start += aligmentInBytes;
  824. }
  825. return (returnCode);
  826. }
  827. status_t FTFx_CMD_SecurityBypass(ftfx_config_t *config, const uint8_t *backdoorKey)
  828. {
  829. uint8_t registerValue; /* registerValue */
  830. status_t returnCode; /* return code variable */
  831. if ((config == NULL) || (backdoorKey == NULL))
  832. {
  833. return kStatus_FTFx_InvalidArgument;
  834. }
  835. /* set the default return code as kStatus_Success */
  836. returnCode = kStatus_FTFx_Success;
  837. /* Get flash security register value */
  838. registerValue = FTFx->FSEC;
  839. /* Check to see if flash is in secure state (any state other than 0x2)
  840. * If not, then skip this since flash is not secure */
  841. if (0x02 != (registerValue & 0x03))
  842. {
  843. /* preparing passing parameter to erase a flash block */
  844. kFCCOBx[0] = BYTE2WORD_1_3(FTFx_SECURITY_BY_PASS, 0xFFFFFFU);
  845. kFCCOBx[1] = BYTE2WORD_1_1_1_1(backdoorKey[0], backdoorKey[1], backdoorKey[2], backdoorKey[3]);
  846. kFCCOBx[2] = BYTE2WORD_1_1_1_1(backdoorKey[4], backdoorKey[5], backdoorKey[6], backdoorKey[7]);
  847. /* calling flash command sequence function to execute the command */
  848. returnCode = ftfx_command_sequence(config);
  849. }
  850. return (returnCode);
  851. }
  852. status_t FTFx_REG_GetSecurityState(ftfx_config_t *config, ftfx_security_state_t *state)
  853. {
  854. /* store data read from flash register */
  855. uint8_t registerValue;
  856. if ((config == NULL) || (state == NULL))
  857. {
  858. return kStatus_FTFx_InvalidArgument;
  859. }
  860. /* Get flash security register value */
  861. registerValue = FTFx->FSEC;
  862. /* check the status of the flash security bits in the security register */
  863. if (kFTFx_FsecRegCode_SEC_Unsecured == (registerValue & FTFx_FSEC_SEC_MASK))
  864. {
  865. /* Flash in unsecured state */
  866. *state = kFTFx_SecurityStateNotSecure;
  867. }
  868. else
  869. {
  870. /* Flash in secured state
  871. * check for backdoor key security enable bit */
  872. if (kFTFx_FsecRegCode_KEYEN_Enabled == (registerValue & FTFx_FSEC_KEYEN_MASK))
  873. {
  874. /* Backdoor key security enabled */
  875. *state = kFTFx_SecurityStateBackdoorEnabled;
  876. }
  877. else
  878. {
  879. /* Backdoor key security disabled */
  880. *state = kFTFx_SecurityStateBackdoorDisabled;
  881. }
  882. }
  883. return (kStatus_FTFx_Success);
  884. }
  885. #if defined(FSL_FEATURE_FLASH_HAS_SET_FLEXRAM_FUNCTION_CMD) && FSL_FEATURE_FLASH_HAS_SET_FLEXRAM_FUNCTION_CMD
  886. status_t FTFx_CMD_SetFlexramFunction(ftfx_config_t *config, ftfx_flexram_func_opt_t option)
  887. {
  888. status_t status;
  889. if (config == NULL)
  890. {
  891. return kStatus_FTFx_InvalidArgument;
  892. }
  893. status = ftfx_check_flexram_function_option(option);
  894. if (status != kStatus_FTFx_Success)
  895. {
  896. return status;
  897. }
  898. /* preparing passing parameter to verify all block command */
  899. kFCCOBx[0] = BYTE2WORD_1_1_2(FTFx_SET_FLEXRAM_FUNCTION, option, 0xFFFFU);
  900. /* calling flash command sequence function to execute the command */
  901. return ftfx_command_sequence(config);
  902. }
  903. #endif /* FSL_FEATURE_FLASH_HAS_SET_FLEXRAM_FUNCTION_CMD */
  904. #if defined(FSL_FEATURE_FLASH_HAS_SWAP_CONTROL_CMD) && FSL_FEATURE_FLASH_HAS_SWAP_CONTROL_CMD
  905. status_t FTFx_CMD_SwapControl(ftfx_config_t *config,
  906. uint32_t address,
  907. ftfx_swap_control_opt_t option,
  908. ftfx_swap_state_config_t *returnInfo)
  909. {
  910. status_t returnCode;
  911. if ((config == NULL) || (returnInfo == NULL))
  912. {
  913. return kStatus_FTFx_InvalidArgument;
  914. }
  915. if (address & (FSL_FEATURE_FLASH_PFLASH_SWAP_CONTROL_CMD_ADDRESS_ALIGMENT - 1))
  916. {
  917. return kStatus_FTFx_AlignmentError;
  918. }
  919. /* Make sure address provided is in the lower half of Program flash but not in the Flash Configuration Field */
  920. if ((address >= (config->flashDesc.totalSize / 2)) ||
  921. ((address >= kFTFx_PflashConfigAreaStart) && (address <= kFTFx_PflashConfigAreaEnd)))
  922. {
  923. return kStatus_FTFx_SwapIndicatorAddressError;
  924. }
  925. /* Check the option. */
  926. returnCode = ftfx_check_swap_control_option(option);
  927. if (returnCode)
  928. {
  929. return returnCode;
  930. }
  931. kFCCOBx[0] = BYTE2WORD_1_3(FTFx_SWAP_CONTROL, address);
  932. kFCCOBx[1] = BYTE2WORD_1_3(option, 0xFFFFFFU);
  933. returnCode = ftfx_command_sequence(config);
  934. returnInfo->flashSwapState = (ftfx_swap_state_t)FTFx_FCCOB5_REG;
  935. returnInfo->currentSwapBlockStatus = (ftfx_swap_block_status_t)FTFx_FCCOB6_REG;
  936. returnInfo->nextSwapBlockStatus = (ftfx_swap_block_status_t)FTFx_FCCOB7_REG;
  937. return returnCode;
  938. }
  939. #endif /* FSL_FEATURE_FLASH_HAS_SWAP_CONTROL_CMD */
  940. static status_t ftfx_init_ifr(ftfx_config_t *config)
  941. {
  942. if (config == NULL)
  943. {
  944. return kStatus_FTFx_InvalidArgument;
  945. }
  946. #if FSL_FEATURE_FLASH_IS_FTFA
  947. /* FTFA parts(eg. K80, KL80, L5K) support both 4-bytes and 8-bytes unit size */
  948. config->ifrDesc.feature.has4ByteIdxSupport = 1;
  949. config->ifrDesc.feature.has8ByteIdxSupport = 1;
  950. config->ifrDesc.idxInfo.mix8byteIdxStart = 0x10U;
  951. config->ifrDesc.idxInfo.mix8byteIdxEnd = 0x13U;
  952. #elif FSL_FEATURE_FLASH_IS_FTFE
  953. /* FTFE parts(eg. K65, KE18) only support 8-bytes unit size */
  954. config->ifrDesc.feature.has4ByteIdxSupport = 0;
  955. config->ifrDesc.feature.has8ByteIdxSupport = 1;
  956. #elif FSL_FEATURE_FLASH_IS_FTFL
  957. /* FTFL parts(eg. K20) only support 4-bytes unit size */
  958. config->ifrDesc.feature.has4ByteIdxSupport = 1;
  959. config->ifrDesc.feature.has8ByteIdxSupport = 0;
  960. #endif
  961. config->ifrDesc.resRange.pflashIfrStart = 0x0000U;
  962. config->ifrDesc.resRange.versionIdSize = 0x08U;
  963. #if FSL_FEATURE_FLASH_IS_FTFE
  964. config->ifrDesc.resRange.versionIdStart = 0x08U;
  965. config->ifrDesc.resRange.ifrMemSize = 0x0400U;
  966. #else /* FSL_FEATURE_FLASH_IS_FTFL == 1 or FSL_FEATURE_FLASH_IS_FTFA = =1 */
  967. config->ifrDesc.resRange.versionIdStart = 0x00U;
  968. config->ifrDesc.resRange.ifrMemSize = 0x0100U;
  969. #endif
  970. #if FSL_FEATURE_FLASH_HAS_FLEX_NVM
  971. config->ifrDesc.resRange.dflashIfrStart = 0x800000U;
  972. #endif
  973. #if FSL_FEATURE_FLASH_HAS_SWAP_CONTROL_CMD
  974. #if FSL_FEATURE_FLASH_IS_FTFE
  975. config->ifrDesc.resRange.pflashSwapIfrStart = 0x40000U;
  976. #else /* FSL_FEATURE_FLASH_IS_FTFL == 1 or FSL_FEATURE_FLASH_IS_FTFA == 1 */
  977. config->ifrDesc.resRange.pflashSwapIfrStart = config->flashDesc.totalSize / 4;
  978. #endif
  979. #endif /* FSL_FEATURE_FLASH_HAS_SWAP_CONTROL_CMD */
  980. return kStatus_FTFx_Success;
  981. }
  982. #if FTFx_DRIVER_IS_FLASH_RESIDENT
  983. /*!
  984. * @brief Copy PIC of flash_run_command() to RAM
  985. */
  986. static void ftfx_copy_run_command_to_ram(uint32_t *ftfxRunCommand)
  987. {
  988. assert(sizeof(s_ftfxRunCommandFunctionCode) <= (kFTFx_RamFuncMaxSizeInWords * 4));
  989. /* Since the value of ARM function pointer is always odd, but the real start address
  990. * of function memory should be even, that's why +1 operation exist. */
  991. memcpy((uint8_t *)ftfxRunCommand, (const uint8_t *)s_ftfxRunCommandFunctionCode, sizeof(s_ftfxRunCommandFunctionCode));
  992. }
  993. #endif /* FTFx_DRIVER_IS_FLASH_RESIDENT */
  994. /*!
  995. * @brief FTFx Command Sequence
  996. *
  997. * This function is used to perform the command write sequence to the flash.
  998. *
  999. * @param driver Pointer to storage for the driver runtime state.
  1000. * @return An error code or kStatus_FTFx_Success
  1001. */
  1002. static status_t ftfx_command_sequence(ftfx_config_t *config)
  1003. {
  1004. uint8_t registerValue;
  1005. #if FTFx_DRIVER_IS_FLASH_RESIDENT
  1006. /* clear RDCOLERR & ACCERR & FPVIOL flag in flash status register */
  1007. FTFx->FSTAT = FTFx_FSTAT_RDCOLERR_MASK | FTFx_FSTAT_ACCERR_MASK | FTFx_FSTAT_FPVIOL_MASK;
  1008. /* Since the value of ARM function pointer is always odd, but the real start address
  1009. * of function memory should be even, that's why +1 operation exist. */
  1010. callFtfxRunCommand_t callFtfxRunCommand = (callFtfxRunCommand_t)((uint32_t)config->runCmdFuncAddr + 1);
  1011. /* We pass the ftfx_fstat address as a parameter to flash_run_comamnd() instead of using
  1012. * pre-processed MICRO sentences or operating global variable in flash_run_comamnd()
  1013. * to make sure that flash_run_command() will be compiled into position-independent code (PIC). */
  1014. callFtfxRunCommand((FTFx_REG8_ACCESS_TYPE)(&FTFx->FSTAT));
  1015. #else
  1016. /* clear RDCOLERR & ACCERR & FPVIOL flag in flash status register */
  1017. FTFx->FSTAT = FTFx_FSTAT_RDCOLERR_MASK | FTFx_FSTAT_ACCERR_MASK | FTFx_FSTAT_FPVIOL_MASK;
  1018. /* clear CCIF bit */
  1019. FTFx->FSTAT = FTFx_FSTAT_CCIF_MASK;
  1020. /* Check CCIF bit of the flash status register, wait till it is set.
  1021. * IP team indicates that this loop will always complete. */
  1022. while (!(FTFx->FSTAT & FTFx_FSTAT_CCIF_MASK))
  1023. {
  1024. }
  1025. #endif /* FTFx_DRIVER_IS_FLASH_RESIDENT */
  1026. /* Check error bits */
  1027. /* Get flash status register value */
  1028. registerValue = FTFx->FSTAT;
  1029. /* checking access error */
  1030. if (registerValue & FTFx_FSTAT_ACCERR_MASK)
  1031. {
  1032. return kStatus_FTFx_AccessError;
  1033. }
  1034. /* checking protection error */
  1035. else if (registerValue & FTFx_FSTAT_FPVIOL_MASK)
  1036. {
  1037. return kStatus_FTFx_ProtectionViolation;
  1038. }
  1039. /* checking MGSTAT0 non-correctable error */
  1040. else if (registerValue & FTFx_FSTAT_MGSTAT0_MASK)
  1041. {
  1042. return kStatus_FTFx_CommandFailure;
  1043. }
  1044. else
  1045. {
  1046. return kStatus_FTFx_Success;
  1047. }
  1048. }
  1049. /*! @brief Validates the range and alignment of the given address range.*/
  1050. static status_t ftfx_check_mem_range(ftfx_config_t *config,
  1051. uint32_t startAddress,
  1052. uint32_t lengthInBytes,
  1053. uint8_t alignmentBaseline)
  1054. {
  1055. if (config == NULL)
  1056. {
  1057. return kStatus_FTFx_InvalidArgument;
  1058. }
  1059. /* Verify the start and length are alignmentBaseline aligned. */
  1060. if ((startAddress & (alignmentBaseline - 1)) || (lengthInBytes & (alignmentBaseline - 1)))
  1061. {
  1062. return kStatus_FTFx_AlignmentError;
  1063. }
  1064. /* check for valid range of the target addresses */
  1065. if ((startAddress >= config->flashDesc.blockBase) &&
  1066. ((startAddress + lengthInBytes) <= (config->flashDesc.blockBase + config->flashDesc.totalSize)))
  1067. {
  1068. return kStatus_FTFx_Success;
  1069. }
  1070. return kStatus_FTFx_AddressError;
  1071. }
  1072. /*! @brief Validates the given user key for flash erase APIs.*/
  1073. static status_t ftfx_check_user_key(uint32_t key)
  1074. {
  1075. /* Validate the user key */
  1076. if (key != kFTFx_ApiEraseKey)
  1077. {
  1078. return kStatus_FTFx_EraseKeyError;
  1079. }
  1080. return kStatus_FTFx_Success;
  1081. }
  1082. /*! @brief Reads word from byte address.*/
  1083. static uint32_t ftfx_read_word_from_byte_address(const uint8_t *src)
  1084. {
  1085. uint32_t word = 0;
  1086. if (!((uint32_t)src % 4))
  1087. {
  1088. word = *(const uint32_t *)src;
  1089. }
  1090. else
  1091. {
  1092. for (uint32_t i = 0; i < 4; i++)
  1093. {
  1094. word |= (uint32_t)(*src) << (i * 8);
  1095. src++;
  1096. }
  1097. }
  1098. return word;
  1099. }
  1100. /*! @brief Writes word to byte address.*/
  1101. static void ftfx_write_word_to_byte_address(uint8_t *dst, uint32_t word)
  1102. {
  1103. if (!((uint32_t)dst % 4))
  1104. {
  1105. *(uint32_t *)dst = word;
  1106. }
  1107. else
  1108. {
  1109. for (uint32_t i = 0; i < 4; i++)
  1110. {
  1111. *dst = (uint8_t)((word >> (i * 8)) & 0xFFU);
  1112. dst++;
  1113. }
  1114. }
  1115. }
  1116. #if defined(FSL_FEATURE_FLASH_HAS_READ_RESOURCE_CMD) && FSL_FEATURE_FLASH_HAS_READ_RESOURCE_CMD
  1117. /*! @brief Validates the range of the given resource address.*/
  1118. static status_t ftfx_check_resource_range(ftfx_config_t *config,
  1119. uint32_t start,
  1120. uint32_t lengthInBytes,
  1121. uint32_t alignmentBaseline,
  1122. ftfx_read_resource_opt_t option)
  1123. {
  1124. status_t status;
  1125. uint32_t maxReadbleAddress;
  1126. if ((start & (alignmentBaseline - 1)) || (lengthInBytes & (alignmentBaseline - 1)))
  1127. {
  1128. return kStatus_FTFx_AlignmentError;
  1129. }
  1130. status = kStatus_FTFx_Success;
  1131. maxReadbleAddress = start + lengthInBytes - 1;
  1132. if (option == kFTFx_ResourceOptionVersionId)
  1133. {
  1134. if ((start != config->ifrDesc.resRange.versionIdStart) ||
  1135. (lengthInBytes != config->ifrDesc.resRange.versionIdSize))
  1136. {
  1137. status = kStatus_FTFx_InvalidArgument;
  1138. }
  1139. }
  1140. else if (option == kFTFx_ResourceOptionFlashIfr)
  1141. {
  1142. if ((start >= config->ifrDesc.resRange.pflashIfrStart) &&
  1143. (maxReadbleAddress < (config->ifrDesc.resRange.pflashIfrStart + config->ifrDesc.resRange.ifrMemSize)))
  1144. {
  1145. }
  1146. #if FSL_FEATURE_FLASH_HAS_FLEX_NVM
  1147. else if ((start >= config->ifrDesc.resRange.dflashIfrStart) &&
  1148. (maxReadbleAddress < (config->ifrDesc.resRange.dflashIfrStart + config->ifrDesc.resRange.ifrMemSize)))
  1149. {
  1150. }
  1151. #endif
  1152. #if FSL_FEATURE_FLASH_HAS_SWAP_CONTROL_CMD
  1153. else if ((start >= config->ifrDesc.resRange.pflashSwapIfrStart) &&
  1154. (maxReadbleAddress < (config->ifrDesc.resRange.pflashSwapIfrStart + config->ifrDesc.resRange.ifrMemSize)))
  1155. {
  1156. }
  1157. #endif
  1158. else
  1159. {
  1160. status = kStatus_FTFx_InvalidArgument;
  1161. }
  1162. }
  1163. else
  1164. {
  1165. status = kStatus_FTFx_InvalidArgument;
  1166. }
  1167. return status;
  1168. }
  1169. #endif /* FSL_FEATURE_FLASH_HAS_READ_RESOURCE_CMD */
  1170. #if defined(FSL_FEATURE_FLASH_HAS_SET_FLEXRAM_FUNCTION_CMD) && FSL_FEATURE_FLASH_HAS_SET_FLEXRAM_FUNCTION_CMD
  1171. /*! @brief Validates the gived flexram function option.*/
  1172. static inline status_t ftfx_check_flexram_function_option(ftfx_flexram_func_opt_t option)
  1173. {
  1174. if ((option != kFTFx_FlexramFuncOptAvailableAsRam) &&
  1175. (option != kFTFx_FlexramFuncOptAvailableForEeprom))
  1176. {
  1177. return kStatus_FTFx_InvalidArgument;
  1178. }
  1179. return kStatus_FTFx_Success;
  1180. }
  1181. #endif /* FSL_FEATURE_FLASH_HAS_SET_FLEXRAM_FUNCTION_CMD */
  1182. #if defined(FSL_FEATURE_FLASH_HAS_SWAP_CONTROL_CMD) && FSL_FEATURE_FLASH_HAS_SWAP_CONTROL_CMD
  1183. /*! @brief Validates the gived swap control option.*/
  1184. static status_t ftfx_check_swap_control_option(ftfx_swap_control_opt_t option)
  1185. {
  1186. if ((option == kFTFx_SwapControlOptionIntializeSystem) || (option == kFTFx_SwapControlOptionSetInUpdateState) ||
  1187. (option == kFTFx_SwapControlOptionSetInCompleteState) || (option == kFTFx_SwapControlOptionReportStatus) ||
  1188. (option == kFTFx_SwapControlOptionDisableSystem))
  1189. {
  1190. return kStatus_FTFx_Success;
  1191. }
  1192. return kStatus_FTFx_InvalidArgument;
  1193. }
  1194. #endif /* FSL_FEATURE_FLASH_HAS_SWAP_CONTROL_CMD */