You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 

1445 line
50 KiB

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