Non puoi selezionare più di 25 argomenti Gli argomenti devono iniziare con una lettera o un numero, possono includere trattini ('-') e possono essere lunghi fino a 35 caratteri.
 
 
 

1476 righe
58 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_flash.h"
  10. /*******************************************************************************
  11. * Definitions
  12. ******************************************************************************/
  13. /*!
  14. * @brief Enumeration for special memory property.
  15. */
  16. enum _ftfx_special_mem_property
  17. {
  18. kFTFx_AccessSegmentUnitSize = 256UL,
  19. kFTFx_MinProtectBlockSize = 1024UL,
  20. };
  21. #if defined(FSL_FEATURE_FLASH_HAS_SWAP_CONTROL_CMD) && FSL_FEATURE_FLASH_HAS_SWAP_CONTROL_CMD
  22. /*!
  23. * @brief Enumeration for the index of read/program once record
  24. */
  25. enum _k3_flash_read_once_index
  26. {
  27. kFLASH_RecordIndexSwapAddr = 0xA1U, /*!< Index of Swap indicator address.*/
  28. kFLASH_RecordIndexSwapEnable = 0xA2U, /*!< Index of Swap system enable.*/
  29. kFLASH_RecordIndexSwapDisable = 0xA3U, /*!< Index of Swap system disable.*/
  30. };
  31. #endif /* FSL_FEATURE_FLASH_HAS_SWAP_CONTROL_CMD */
  32. /*******************************************************************************
  33. * Prototypes
  34. ******************************************************************************/
  35. /*! @brief init flash features */
  36. static void flash_init_features(ftfx_config_t *config);
  37. /*! @brief init protection feature */
  38. static void flash_protection_init(flash_config_t *config, uint8_t flashIndex);
  39. /*! @brief init access segment feature */
  40. #if defined(FSL_FEATURE_FLASH_HAS_ACCESS_CONTROL) && FSL_FEATURE_FLASH_HAS_ACCESS_CONTROL
  41. static void flash_access_init(flash_config_t *config, uint8_t flashIndex);
  42. #endif
  43. /*! @brief init flash operation config */
  44. static void flash_opsonfig_Init(flash_config_t *config, uint8_t flashIndex);
  45. /*! @brief Calculate flash memory size based on given parameter */
  46. static uint32_t flash_calculate_mem_size(uint32_t pflashBlockCount,
  47. uint32_t pflashBlockSize,
  48. uint32_t pfsizeMask,
  49. uint32_t pfsizeShift);
  50. static uint32_t flash_calculate_prot_segment_size(uint32_t flashSize, uint32_t segmentCount);
  51. /*! @brief Validates the given address to get current flash index */
  52. static status_t flash_check_range_to_get_index(flash_config_t *config,
  53. uint32_t start,
  54. uint32_t lengthInBytes,
  55. uint8_t *flashIndex);
  56. /*! @brief Decide whether to convert the start address from primary flash to secondary flash based on the current start
  57. * address*/
  58. static void flash_convert_start_address(ftfx_config_t *config, uint32_t start);
  59. #if defined(FSL_FEATURE_FLASH_HAS_PFLASH_BLOCK_SWAP) && FSL_FEATURE_FLASH_HAS_PFLASH_BLOCK_SWAP
  60. /*! @brief Validates the given address to see if it is equal to swap indicator address in pflash swap IFR.*/
  61. static status_t flash_validate_swap_indicator_address(ftfx_config_t *config, uint32_t address);
  62. #endif /* FSL_FEATURE_FLASH_HAS_PFLASH_BLOCK_SWAP */
  63. /*******************************************************************************
  64. * Variables
  65. ******************************************************************************/
  66. static volatile uint32_t *const kFPROTL = (volatile uint32_t *)(uint32_t)&FTFx_FPROT_LOW_REG;
  67. #if defined(FTFx_FLASH0_HAS_HIGH_PROT_REG) && FTFx_FLASH0_HAS_HIGH_PROT_REG
  68. static volatile uint32_t *const kFPROTH = (volatile uint32_t *)&FTFx_FPROT_HIGH_REG;
  69. #endif /* FTFx_FLASH0_HAS_HIGH_PROT_REG */
  70. #if defined(FTFx_FLASH1_HAS_INT_PROT_REG) && FTFx_FLASH1_HAS_INT_PROT_REG
  71. volatile uint8_t *const kFPROTSL = (volatile uint8_t *)&FTFx_FPROTSL_REG;
  72. volatile uint8_t *const kFPROTSH = (volatile uint8_t *)&FTFx_FPROTSH_REG;
  73. #endif /* FTFx_FLASH1_HAS_INT_PROT_REG */
  74. /*!
  75. * @brief Table of pflash sizes.
  76. *
  77. * The index into this table is the value of the SIM_FCFG1.PFSIZE bitfield.
  78. *
  79. * The values in this table have been right shifted 10 bits so that they will all fit within
  80. * an 16-bit integer. To get the actual flash density, you must left shift the looked up value
  81. * by 10 bits.
  82. *
  83. * Elements of this table have a value of 0 in cases where the PFSIZE bitfield value is
  84. * reserved.
  85. *
  86. * Code to use the table:
  87. * @code
  88. * uint8_t pfsize = (SIM->FCFG1 & SIM_FCFG1_PFSIZE_MASK) >> SIM_FCFG1_PFSIZE_SHIFT;
  89. * flashDensity = ((uint32_t)kPFlashDensities[pfsize]) << 10;
  90. * @endcode
  91. */
  92. #if defined(FSL_FEATURE_FLASH_SIZE_ENCODING_RULE_VERSION) && (FSL_FEATURE_FLASH_SIZE_ENCODING_RULE_VERSION == 1)
  93. static const uint16_t kPFlashDensities[] = {
  94. 0u, /* 0x0 - undefined */
  95. 0u, /* 0x1 - undefined */
  96. 0u, /* 0x2 - undefined */
  97. 0u, /* 0x3 - undefined */
  98. 0u, /* 0x4 - undefined */
  99. 0u, /* 0x5 - undefined */
  100. 0u, /* 0x6 - undefined */
  101. 0u, /* 0x7 - undefined */
  102. 0u, /* 0x8 - undefined */
  103. 0u, /* 0x9 - undefined */
  104. 256u, /* 0xa - 262144, 256KB */
  105. 0u, /* 0xb - undefined */
  106. 1024u, /* 0xc - 1048576, 1MB */
  107. 0u, /* 0xd - undefined */
  108. 0u, /* 0xe - undefined */
  109. 0u, /* 0xf - undefined */
  110. };
  111. #else
  112. static const uint16_t kPFlashDensities[] = {
  113. 8u, /* 0x0 - 8192, 8KB */
  114. 16u, /* 0x1 - 16384, 16KB */
  115. 24u, /* 0x2 - 24576, 24KB */
  116. 32u, /* 0x3 - 32768, 32KB */
  117. 48u, /* 0x4 - 49152, 48KB */
  118. 64u, /* 0x5 - 65536, 64KB */
  119. 96u, /* 0x6 - 98304, 96KB */
  120. 128u, /* 0x7 - 131072, 128KB */
  121. 192u, /* 0x8 - 196608, 192KB */
  122. 256u, /* 0x9 - 262144, 256KB */
  123. 384u, /* 0xa - 393216, 384KB */
  124. 512u, /* 0xb - 524288, 512KB */
  125. 768u, /* 0xc - 786432, 768KB */
  126. 1024u, /* 0xd - 1048576, 1MB */
  127. 1536u, /* 0xe - 1572864, 1.5MB */
  128. /* 2048u, 0xf - 2097152, 2MB */
  129. };
  130. #endif
  131. /*******************************************************************************
  132. * Code
  133. ******************************************************************************/
  134. /*!
  135. * @brief Initializes the global flash properties structure members.
  136. *
  137. * This function checks and initializes the Flash module for the other Flash APIs.
  138. *
  139. * @param config Pointer to the storage for the driver runtime state.
  140. *
  141. * @retval #kStatus_FTFx_Success API was executed successfully.
  142. * @retval #kStatus_FTFx_InvalidArgument An invalid argument is provided.
  143. * @retval #kStatus_FTFx_ExecuteInRamFunctionNotReady Execute-in-RAM function is not available.
  144. * @retval #kStatus_FTFx_PartitionStatusUpdateFailure Failed to update the partition status.
  145. */
  146. status_t FLASH_Init(flash_config_t *config)
  147. {
  148. if (config == NULL)
  149. {
  150. return kStatus_FTFx_InvalidArgument;
  151. }
  152. for (uint8_t flashIndex = 0U; flashIndex < FTFx_FLASH_COUNT; flashIndex++)
  153. {
  154. /* init flash type, kinetis has Pflash and flxnvm, pflash is often used to store executable code
  155. * and flexnvm can be used as date flash to store user data, and can also be configured as eeprom backup space
  156. * with flexram.
  157. */
  158. config->ftfxConfig[flashIndex].flashDesc.type = (uint8_t)kFTFx_MemTypePflash;
  159. /* init the current flash index */
  160. config->ftfxConfig[flashIndex].flashDesc.index = flashIndex;
  161. /* init flash features */
  162. flash_init_features(&config->ftfxConfig[flashIndex]);
  163. /* init flash Operation Config */
  164. flash_opsonfig_Init(config, flashIndex);
  165. #if defined(FSL_FEATURE_FLASH_HAS_ACCESS_CONTROL) && FSL_FEATURE_FLASH_HAS_ACCESS_CONTROL
  166. if (0U != (config->ftfxConfig[flashIndex].flashDesc.feature.hasXaccControl))
  167. {
  168. /* init access segment feature */
  169. flash_access_init(config, flashIndex);
  170. }
  171. #endif /* FSL_FEATURE_FLASH_HAS_ACCESS_CONTROL */
  172. #if (FTFx_FLASH_COUNT > 1U)
  173. if (0U != (config->ftfxConfig[flashIndex].flashDesc.feature.hasProtControl))
  174. #endif
  175. {
  176. /* init protection feature */
  177. flash_protection_init(config, flashIndex);
  178. }
  179. /* Init FTFx Kernel */
  180. FTFx_API_Init(&config->ftfxConfig[flashIndex]);
  181. }
  182. return kStatus_FTFx_Success;
  183. }
  184. /*!
  185. * @brief Erases the Dflash sectors encompassed by parameters passed into function.
  186. *
  187. * This function erases the appropriate number of flash sectors based on the
  188. * desired start address and length.
  189. *
  190. * @param config The pointer to the storage for the driver runtime state.
  191. * @param start The start address of the desired flash memory to be erased.
  192. * The start address does not need to be sector-aligned but must be word-aligned.
  193. * @param lengthInBytes The length, given in bytes (not words or long-words)
  194. * to be erased. Must be word-aligned.
  195. * @param key The value used to validate all flash erase APIs.
  196. *
  197. * @retval #kStatus_FTFx_Success API was executed successfully; the appropriate number of flash sectors based on the
  198. * desired start address and length was erased successfully.
  199. *
  200. * @retval #kStatus_FTFx_InvalidArgument An invalid argument is provided.
  201. * @retval #kStatus_FTFx_AlignmentError The parameter is not aligned with the specified baseline.
  202. * @retval #kStatus_FTFx_AddressError The address is out of range.
  203. * @retval #kStatus_FTFx_EraseKeyError The API erase key is invalid.
  204. * @retval #kStatus_FTFx_ExecuteInRamFunctionNotReady Execute-in-RAM function is not available.
  205. * @retval #kStatus_FTFx_AccessError Invalid instruction codes and out-of bounds addresses.
  206. * @retval #kStatus_FTFx_ProtectionViolation The program/erase operation is requested to execute on protected areas.
  207. * @retval #kStatus_FTFx_CommandFailure Run-time error during the command execution.
  208. */
  209. status_t FLASH_Erase(flash_config_t *config, uint32_t start, uint32_t lengthInBytes, uint32_t key)
  210. {
  211. status_t returnCode;
  212. uint8_t flashIndex;
  213. /* check the supplied address range to get flash index */
  214. returnCode = flash_check_range_to_get_index(config, start, lengthInBytes, &flashIndex);
  215. if (returnCode != kStatus_FTFx_Success)
  216. {
  217. return returnCode;
  218. }
  219. /* Decide whether to convert the start address from primary flash to secondary flash based on the current address */
  220. flash_convert_start_address(&config->ftfxConfig[flashIndex], start);
  221. return FTFx_CMD_Erase(&config->ftfxConfig[flashIndex], start, lengthInBytes, key);
  222. }
  223. /*!
  224. * @brief Erases entire flexnvm
  225. */
  226. status_t FLASH_EraseAll(flash_config_t *config, uint32_t key)
  227. {
  228. return FTFx_CMD_EraseAll(&config->ftfxConfig[0], key);
  229. }
  230. #if defined(FSL_FEATURE_FLASH_HAS_ERASE_ALL_BLOCKS_UNSECURE_CMD) && FSL_FEATURE_FLASH_HAS_ERASE_ALL_BLOCKS_UNSECURE_CMD
  231. /*!
  232. * @brief Erases the entire flexnvm, including protected sectors.
  233. */
  234. status_t FLASH_EraseAllUnsecure(flash_config_t *config, uint32_t key)
  235. {
  236. return FTFx_CMD_EraseAllUnsecure(&config->ftfxConfig[0], key);
  237. }
  238. #endif
  239. /*!
  240. * @brief Programs flash with data at locations passed in through parameters.
  241. *
  242. * This function programs the flash memory with the desired data for a given
  243. * flash area as determined by the start address and the length.
  244. */
  245. status_t FLASH_Program(flash_config_t *config, uint32_t start, uint8_t *src, uint32_t lengthInBytes)
  246. {
  247. status_t returnCode;
  248. uint8_t flashIndex;
  249. /* check range to get flash index */
  250. returnCode = flash_check_range_to_get_index(config, start, lengthInBytes, &flashIndex);
  251. if (returnCode != kStatus_FTFx_Success)
  252. {
  253. return returnCode;
  254. }
  255. /* convert the start address from primary flash to secondary flash based on the current address */
  256. flash_convert_start_address(&config->ftfxConfig[flashIndex], start);
  257. /* Programs flash */
  258. return FTFx_CMD_Program(&config->ftfxConfig[flashIndex], start, src, lengthInBytes);
  259. }
  260. /*!
  261. * @brief Reads the Program Once Field through parameters.
  262. */
  263. status_t FLASH_ProgramOnce(flash_config_t *config, uint32_t index, uint8_t *src, uint32_t lengthInBytes)
  264. {
  265. return FTFx_CMD_ProgramOnce(&config->ftfxConfig[0], index, src, lengthInBytes);
  266. }
  267. #if defined(FSL_FEATURE_FLASH_HAS_PROGRAM_SECTION_CMD) && FSL_FEATURE_FLASH_HAS_PROGRAM_SECTION_CMD
  268. /*!
  269. * @brief Programs flash with data at locations passed in through parameters via the Program Section command.
  270. *
  271. * This function programs the flash memory with the desired data for a given
  272. * flash area as determined by the start address and length.
  273. *
  274. */
  275. status_t FLASH_ProgramSection(flash_config_t *config, uint32_t start, uint8_t *src, uint32_t lengthInBytes)
  276. {
  277. status_t returnCode;
  278. uint8_t flashIndex;
  279. /* Validates the range of the given address range and get flash index */
  280. returnCode = flash_check_range_to_get_index(config, start, lengthInBytes, &flashIndex);
  281. if (returnCode != kStatus_FTFx_Success)
  282. {
  283. return returnCode;
  284. }
  285. /* convert the start address from primary flash to secondary flash based on the current address */
  286. flash_convert_start_address(&config->ftfxConfig[flashIndex], start);
  287. return FTFx_CMD_ProgramSection(&config->ftfxConfig[flashIndex], start, src, lengthInBytes);
  288. }
  289. #endif
  290. #if defined(FSL_FEATURE_FLASH_HAS_READ_RESOURCE_CMD) && FSL_FEATURE_FLASH_HAS_READ_RESOURCE_CMD
  291. /*!
  292. * @brief Reads the resource with data at locations passed in through parameters.
  293. */
  294. status_t FLASH_ReadResource(
  295. flash_config_t *config, uint32_t start, uint8_t *dst, uint32_t lengthInBytes, ftfx_read_resource_opt_t option)
  296. {
  297. return FTFx_CMD_ReadResource(&config->ftfxConfig[0], start, dst, lengthInBytes, option);
  298. }
  299. #endif
  300. /*!
  301. * @brief Reads the Program Once Field through parameters.
  302. */
  303. status_t FLASH_ReadOnce(flash_config_t *config, uint32_t index, uint8_t *dst, uint32_t lengthInBytes)
  304. {
  305. return FTFx_CMD_ReadOnce(&config->ftfxConfig[0], index, dst, lengthInBytes);
  306. }
  307. /*!
  308. * @brief Verifies an erasure of the desired flash area at a specified margin level.
  309. *
  310. * This function checks the appropriate number of flash sectors based on
  311. * the desired start address and length to check whether the flash is erased
  312. * to the specified read margin level.
  313. */
  314. status_t FLASH_VerifyErase(flash_config_t *config, uint32_t start, uint32_t lengthInBytes, ftfx_margin_value_t margin)
  315. {
  316. status_t returnCode;
  317. uint8_t flashIndex;
  318. /* check range to get flash index */
  319. returnCode = flash_check_range_to_get_index(config, start, lengthInBytes, &flashIndex);
  320. if (returnCode != kStatus_FTFx_Success)
  321. {
  322. return returnCode;
  323. }
  324. /* convert the start address from primary flash to secondary flash based on the current start address*/
  325. flash_convert_start_address(&config->ftfxConfig[flashIndex], start);
  326. return FTFx_CMD_VerifyErase(&config->ftfxConfig[flashIndex], start, lengthInBytes, margin);
  327. }
  328. /*!
  329. * @brief Verifies erasure of the entire flash at a specified margin level.
  330. */
  331. status_t FLASH_VerifyEraseAll(flash_config_t *config, ftfx_margin_value_t margin)
  332. {
  333. return FTFx_CMD_VerifyEraseAll(&config->ftfxConfig[0], margin);
  334. }
  335. /*!
  336. * @brief Verifies programming of the desired flash area at a specified margin level.
  337. *
  338. * This function verifies the data programmed in the flash memory using the
  339. * Flash Program Check Command and compares it to the expected data for a given
  340. * flash area as determined by the start address and length.
  341. */
  342. status_t FLASH_VerifyProgram(flash_config_t *config,
  343. uint32_t start,
  344. uint32_t lengthInBytes,
  345. const uint8_t *expectedData,
  346. ftfx_margin_value_t margin,
  347. uint32_t *failedAddress,
  348. uint32_t *failedData)
  349. {
  350. status_t returnCode;
  351. uint8_t flashIndex;
  352. /* Validates the given address to get current flash index */
  353. returnCode = flash_check_range_to_get_index(config, start, lengthInBytes, &flashIndex);
  354. if (returnCode != kStatus_FTFx_Success)
  355. {
  356. return returnCode;
  357. }
  358. /* convert the start address from primary flash to secondary flash based on the current start address */
  359. flash_convert_start_address(&config->ftfxConfig[flashIndex], start);
  360. return FTFx_CMD_VerifyProgram(&config->ftfxConfig[flashIndex], start, lengthInBytes, expectedData, margin,
  361. failedAddress, failedData);
  362. }
  363. /*!
  364. * @brief Returns the security state via the pointer passed into the function.
  365. */
  366. status_t FLASH_GetSecurityState(flash_config_t *config, ftfx_security_state_t *state)
  367. {
  368. return FTFx_REG_GetSecurityState(&config->ftfxConfig[0], state);
  369. }
  370. /*!
  371. * @brief Allows users to bypass security with a backdoor key.
  372. */
  373. status_t FLASH_SecurityBypass(flash_config_t *config, const uint8_t *backdoorKey)
  374. {
  375. return FTFx_CMD_SecurityBypass(&config->ftfxConfig[0], backdoorKey);
  376. }
  377. #if defined(FSL_FEATURE_FLASH_HAS_SET_FLEXRAM_FUNCTION_CMD) && FSL_FEATURE_FLASH_HAS_SET_FLEXRAM_FUNCTION_CMD
  378. /*!
  379. * @brief Sets the FlexRAM function command.
  380. */
  381. status_t FLASH_SetFlexramFunction(flash_config_t *config, ftfx_flexram_func_opt_t option)
  382. {
  383. return FTFx_CMD_SetFlexramFunction(&config->ftfxConfig[0], option);
  384. }
  385. #endif
  386. #if defined(FSL_FEATURE_FLASH_HAS_PFLASH_BLOCK_SWAP) && FSL_FEATURE_FLASH_HAS_PFLASH_BLOCK_SWAP
  387. /*!
  388. * @brief Swaps the lower half flash with the higher half flash.
  389. */
  390. status_t FLASH_Swap(flash_config_t *config, uint32_t address, bool isSetEnable)
  391. {
  392. status_t returnCode;
  393. ftfx_swap_state_config_t returnInfo;
  394. ftfx_config_t *ftfxConfig;
  395. uint8_t flashIndex;
  396. returnCode = flash_check_range_to_get_index(config, address, 1U, &flashIndex);
  397. if (returnCode != kStatus_FTFx_Success)
  398. {
  399. return returnCode;
  400. }
  401. ftfxConfig = &config->ftfxConfig[flashIndex];
  402. (void)memset(&returnInfo, 0xFFU, sizeof(returnInfo));
  403. do
  404. {
  405. returnCode = FTFx_CMD_SwapControl(ftfxConfig, address, kFTFx_SwapControlOptionReportStatus, &returnInfo);
  406. if (returnCode != kStatus_FTFx_Success)
  407. {
  408. return returnCode;
  409. }
  410. if (!isSetEnable)
  411. {
  412. if (returnInfo.flashSwapState == kFTFx_SwapStateDisabled)
  413. {
  414. return kStatus_FTFx_Success;
  415. }
  416. else if (returnInfo.flashSwapState == kFTFx_SwapStateUninitialized)
  417. {
  418. /* The swap system changed to the DISABLED state with Program flash block 0
  419. * located at relative flash address 0x0_0000 */
  420. returnCode =
  421. FTFx_CMD_SwapControl(ftfxConfig, address, kFTFx_SwapControlOptionDisableSystem, &returnInfo);
  422. }
  423. else
  424. {
  425. /* Swap disable should be requested only when swap system is in the uninitialized state */
  426. return kStatus_FTFx_SwapSystemNotInUninitialized;
  427. }
  428. }
  429. else
  430. {
  431. /* When first swap: the initial swap state is Uninitialized, flash swap indicator address is unset,
  432. * the swap procedure should be Uninitialized -> Update-Erased -> Complete.
  433. * After the first swap has been completed, the flash swap inidicator address cannot be modified
  434. * unless EraseAllBlocks command is issued, the swap procedure is changed to Update -> Update-Erased ->
  435. * Complete. */
  436. switch (returnInfo.flashSwapState)
  437. {
  438. case kFTFx_SwapStateUninitialized:
  439. /* If current swap mode is Uninitialized, Initialize Swap to Initialized/READY state. */
  440. returnCode =
  441. FTFx_CMD_SwapControl(ftfxConfig, address, kFTFx_SwapControlOptionIntializeSystem, &returnInfo);
  442. break;
  443. case kFTFx_SwapStateReady:
  444. /* Validate whether the address provided to the swap system is matched to
  445. * swap indicator address in the IFR */
  446. returnCode = flash_validate_swap_indicator_address(ftfxConfig, address);
  447. if (returnCode == kStatus_FTFx_Success)
  448. {
  449. /* If current swap mode is Initialized/Ready, Initialize Swap to UPDATE state. */
  450. returnCode = FTFx_CMD_SwapControl(ftfxConfig, address, kFTFx_SwapControlOptionSetInUpdateState,
  451. &returnInfo);
  452. }
  453. break;
  454. case kFTFx_SwapStateUpdate:
  455. /* If current swap mode is Update, Erase indicator sector in non active block
  456. * to proceed swap system to update-erased state */
  457. returnCode = FLASH_Erase(config, address + (ftfxConfig->flashDesc.totalSize >> 1u),
  458. ftfxConfig->opsConfig.addrAligment.sectorCmd, (uint32_t)kFTFx_ApiEraseKey);
  459. break;
  460. case kFTFx_SwapStateUpdateErased:
  461. /* If current swap mode is Update or Update-Erased, progress Swap to COMPLETE State */
  462. returnCode = FTFx_CMD_SwapControl(ftfxConfig, address, kFTFx_SwapControlOptionSetInCompleteState,
  463. &returnInfo);
  464. break;
  465. case kFTFx_SwapStateComplete:
  466. break;
  467. case kFTFx_SwapStateDisabled:
  468. /* When swap system is in disabled state, We need to clear swap system back to uninitialized
  469. * by issuing EraseAllBlocks command */
  470. returnCode = kStatus_FTFx_SwapSystemNotInUninitialized;
  471. break;
  472. default:
  473. returnCode = kStatus_FTFx_InvalidArgument;
  474. break;
  475. }
  476. }
  477. if (returnCode != kStatus_FTFx_Success)
  478. {
  479. break;
  480. }
  481. } while (!((kFTFx_SwapStateComplete == returnInfo.flashSwapState) && isSetEnable));
  482. return returnCode;
  483. }
  484. #endif /* FSL_FEATURE_FLASH_HAS_PFLASH_BLOCK_SWAP */
  485. /*!
  486. * @brief Returns the protection state of the desired flash area via the pointer passed into the function.
  487. */
  488. status_t FLASH_IsProtected(flash_config_t *config,
  489. uint32_t start,
  490. uint32_t lengthInBytes,
  491. flash_prot_state_t *protection_state)
  492. {
  493. status_t returnCode;
  494. ftfx_config_t *ftfxConfig;
  495. uint8_t flashIndex;
  496. if (protection_state == NULL)
  497. {
  498. return kStatus_FTFx_InvalidArgument;
  499. }
  500. returnCode = flash_check_range_to_get_index(config, start, lengthInBytes, &flashIndex);
  501. if (returnCode != kStatus_FTFx_Success)
  502. {
  503. return returnCode;
  504. }
  505. ftfxConfig = &config->ftfxConfig[flashIndex];
  506. #if (FTFx_FLASH_COUNT > 1U)
  507. if (0U != (ftfxConfig->flashDesc.feature.hasProtControl))
  508. #endif
  509. {
  510. uint32_t endAddress; /* end address for protection check */
  511. uint32_t regionCheckedCounter; /* increments each time the flash address was checked for
  512. * protection status */
  513. uint32_t regionCounter; /* incrementing variable used to increment through the flash
  514. * protection regions */
  515. uint32_t protectStatusCounter; /* increments each time a flash region was detected as protected */
  516. uint8_t flashRegionProtectStatus[MAX_FLASH_PROT_REGION_COUNT]; /* array of the protection
  517. * status for each
  518. * protection region */
  519. for (uint32_t i = 0U; i < (uint32_t)MAX_FLASH_PROT_REGION_COUNT;
  520. i++) /* The protection register is initialized to the */
  521. { /* unprotected state by default. */
  522. flashRegionProtectStatus[i] = (uint8_t)0xFF; /* The array is initialized to all 1 */
  523. }
  524. uint32_t
  525. flashRegionAddress[MAX_FLASH_PROT_REGION_COUNT + 1U]; /* array of the start addresses for each flash
  526. * protection region. Note this is REGION_COUNT+1
  527. * due to requiring the next start address after
  528. * the end of flash for loop-check purposes below */
  529. bool isBreakNeeded = false;
  530. /* Calculate Flash end address */
  531. endAddress = start + lengthInBytes;
  532. /* populate the flashRegionAddress array with the start address of each flash region */
  533. regionCounter = 0U; /* make sure regionCounter is initialized to 0 first */
  534. /* populate up to 33rd element of array, this is the next address after end of flash array */
  535. while (regionCounter <= ftfxConfig->flashDesc.protectRegionMem.count)
  536. {
  537. flashRegionAddress[regionCounter] = ftfxConfig->flashDesc.protectRegionMem.base +
  538. ftfxConfig->flashDesc.protectRegionMem.size * regionCounter;
  539. regionCounter++;
  540. }
  541. /* populate flashRegionProtectStatus array with status information
  542. * Protection status for each region is stored in the FPROT[3:0] registers
  543. * Each bit represents one region of flash
  544. * 4 registers * 8-bits-per-register = 32-bits (32-regions)
  545. * The convention is:
  546. * FPROT3[bit 0] is the first protection region (start of flash memory)
  547. * FPROT0[bit 7] is the last protection region (end of flash memory)
  548. * regionCounter is used to determine which FPROT[3:0] register to check for protection status
  549. * Note: FPROT=1 means NOT protected, FPROT=0 means protected */
  550. regionCounter = 0U; /* make sure regionCounter is initialized to 0 first */
  551. static volatile uint32_t *const kFPROTLx = (volatile uint32_t *)(uint32_t)&FTFx_FPROTL3_REG;
  552. #if defined(FTFx_FLASH0_HAS_HIGH_PROT_REG) && FTFx_FLASH0_HAS_HIGH_PROT_REG
  553. static volatile uint32_t *const kFPROTHx = (volatile uint32_t *)(uint32_t)&FTFx_FPROTH3_REG;
  554. #endif
  555. #if defined(FTFx_FLASH1_HAS_INT_PROT_REG) && FTFx_FLASH1_HAS_INT_PROT_REG
  556. static volatile uint16_t *const kFPROTSx = (volatile uint16_t *)(uint32_t)&FTFx_FPROTSL_REG;
  557. #endif
  558. while (regionCounter < ftfxConfig->flashDesc.protectRegionMem.count)
  559. {
  560. #if (FTFx_FLASH_COUNT > 1U)
  561. if ((0U == ftfxConfig->flashDesc.index) || (0U != ftfxConfig->flashDesc.feature.hasIndProtReg))
  562. #endif
  563. {
  564. #if defined(MAX_FLASH_PROT_REGION_COUNT) && (MAX_FLASH_PROT_REGION_COUNT <= 32U)
  565. if (regionCounter < (uint32_t)MAX_FLASH_PROT_REGION_COUNT)
  566. {
  567. flashRegionProtectStatus[regionCounter] = (uint8_t)(((kFPROTLx[0]) >> regionCounter) & 0x1U);
  568. }
  569. #else
  570. if (regionCounter < 32u)
  571. {
  572. flashRegionProtectStatus[regionCounter] = (uint8_t)(((kFPROTLx[0]) >> regionCounter) & 0x1U);
  573. }
  574. #endif
  575. #if defined(MAX_FLASH_PROT_REGION_COUNT) && (MAX_FLASH_PROT_REGION_COUNT == 64u)
  576. else if (regionCounter < 64U)
  577. {
  578. flashRegionProtectStatus[regionCounter] =
  579. (uint8_t)(((kFPROTHx[0]) >> (regionCounter - 32U)) & 0x1U);
  580. }
  581. #endif
  582. else
  583. {
  584. isBreakNeeded = true;
  585. }
  586. regionCounter++;
  587. }
  588. #if defined(FTFx_FLASH1_HAS_INT_PROT_REG) && FTFx_FLASH1_HAS_INT_PROT_REG
  589. else if ((1U == ftfxConfig->flashDesc.index) && (0U != ftfxConfig->flashDesc.feature.hasIndProtReg))
  590. {
  591. /* Note: So far protection region count may be 8/16 */
  592. if (regionCounter < 16U)
  593. {
  594. flashRegionProtectStatus[regionCounter] = (uint8_t)((kFPROTSx[0] >> regionCounter) & (0x01u));
  595. }
  596. else
  597. {
  598. isBreakNeeded = true;
  599. }
  600. regionCounter++;
  601. }
  602. #endif /* FTFx_FLASH1_HAS_INT_PROT_REG */
  603. #if (FTFx_FLASH_COUNT > 1U)
  604. else
  605. {
  606. return kStatus_FTFx_InvalidArgument;
  607. }
  608. #endif
  609. if (isBreakNeeded)
  610. {
  611. break;
  612. }
  613. }
  614. /* loop through the flash regions and check
  615. * desired flash address range for protection status
  616. * loop stops when it is detected that start has exceeded the endAddress */
  617. regionCounter = 0U; /* make sure regionCounter is initialized to 0 first */
  618. regionCheckedCounter = 0U;
  619. protectStatusCounter = 0U; /* make sure protectStatusCounter is initialized to 0 first */
  620. while (start < endAddress)
  621. {
  622. /* check to see if the address falls within this protection region
  623. * Note that if the entire flash is to be checked, the last protection
  624. * region checked would consist of the last protection start address and
  625. * the start address following the end of flash */
  626. if ((start >= flashRegionAddress[regionCounter]) && (start < flashRegionAddress[regionCounter + 1U]))
  627. {
  628. /* increment regionCheckedCounter to indicate this region was checked */
  629. regionCheckedCounter++;
  630. /* check the protection status of this region
  631. * Note: FPROT=1 means NOT protected, FPROT=0 means protected */
  632. if (0U == flashRegionProtectStatus[regionCounter])
  633. {
  634. /* increment protectStatusCounter to indicate this region is protected */
  635. protectStatusCounter++;
  636. }
  637. start +=
  638. ftfxConfig->flashDesc.protectRegionMem.size; /* increment to an address within the next region */
  639. }
  640. regionCounter++; /* increment regionCounter to check for the next flash protection region */
  641. }
  642. /* if protectStatusCounter == 0, then no region of the desired flash region is protected */
  643. if (protectStatusCounter == 0U)
  644. {
  645. *protection_state = kFLASH_ProtectionStateUnprotected;
  646. }
  647. /* if protectStatusCounter == regionCheckedCounter, then each region checked was protected */
  648. else if (protectStatusCounter == regionCheckedCounter)
  649. {
  650. *protection_state = kFLASH_ProtectionStateProtected;
  651. }
  652. /* if protectStatusCounter != regionCheckedCounter, then protection status is mixed
  653. * In other words, some regions are protected while others are unprotected */
  654. else
  655. {
  656. *protection_state = kFLASH_ProtectionStateMixed;
  657. }
  658. }
  659. #if (FTFx_FLASH_COUNT > 1U)
  660. else
  661. {
  662. *protection_state = kFLASH_ProtectionStateUnprotected;
  663. }
  664. #endif
  665. return kStatus_FTFx_Success;
  666. }
  667. #if defined(FSL_FEATURE_FLASH_HAS_ACCESS_CONTROL) && FSL_FEATURE_FLASH_HAS_ACCESS_CONTROL
  668. /*!
  669. * @brief Returns the access state of the desired flash area via the pointer passed into the function.
  670. *
  671. * This function retrieves the current flash access status for a given
  672. * flash area as determined by the start address and length.
  673. */
  674. status_t FLASH_IsExecuteOnly(flash_config_t *config,
  675. uint32_t start,
  676. uint32_t lengthInBytes,
  677. flash_xacc_state_t *access_state)
  678. {
  679. status_t returnCode;
  680. ftfx_config_t *ftfxConfig;
  681. uint8_t flashIndex;
  682. if (access_state == NULL)
  683. {
  684. return kStatus_FTFx_InvalidArgument;
  685. }
  686. returnCode = flash_check_range_to_get_index(config, start, lengthInBytes, &flashIndex);
  687. if (returnCode != kStatus_FTFx_Success)
  688. {
  689. return returnCode;
  690. }
  691. ftfxConfig = &config->ftfxConfig[flashIndex];
  692. /* store the execute only segment count */
  693. uint32_t executeOnlySegmentCounter = 0U;
  694. /* Calculate end address */
  695. uint32_t endAddress = start + lengthInBytes;
  696. /* Aligning start address and end address */
  697. uint32_t alignedStartAddress = ALIGN_DOWN(start, ftfxConfig->flashDesc.accessSegmentMem.size);
  698. uint32_t alignedEndAddress = ALIGN_UP(endAddress, ftfxConfig->flashDesc.accessSegmentMem.size);
  699. uint32_t u32flag = 1U;
  700. uint32_t segmentIndex = 0U;
  701. /* Calculate the execute only segment Count */
  702. uint32_t maxSupportedExecuteOnlySegmentCount =
  703. (alignedEndAddress - alignedStartAddress) / ftfxConfig->flashDesc.accessSegmentMem.size;
  704. while (start < endAddress)
  705. {
  706. uint32_t xacc = 0U;
  707. bool isInvalidSegmentIndex = false;
  708. /* Calculate which segmentIndex the address is in */
  709. segmentIndex =
  710. (start - ftfxConfig->flashDesc.accessSegmentMem.base) / ftfxConfig->flashDesc.accessSegmentMem.size;
  711. if ((0U == ftfxConfig->flashDesc.index) || (0U != ftfxConfig->flashDesc.feature.hasIndXaccReg))
  712. {
  713. /* For primary flash, The eight XACC registers allow up to 64 restricted segments of equal memory size.
  714. */
  715. if (segmentIndex < 32U)
  716. {
  717. xacc = *(const volatile uint32_t *)(uint32_t)&FTFx_XACCL3_REG;
  718. }
  719. else if (segmentIndex < ftfxConfig->flashDesc.accessSegmentMem.count)
  720. {
  721. xacc = *(const volatile uint32_t *)(uint32_t)&FTFx_XACCH3_REG;
  722. segmentIndex -= 32U;
  723. }
  724. else
  725. {
  726. isInvalidSegmentIndex = true;
  727. }
  728. }
  729. #if defined(FTFx_FLASH1_HAS_INT_XACC_REG) && FTFx_FLASH1_HAS_INT_XACC_REG
  730. else if ((ftfxConfig->flashDesc.index == 1U) && (0u != ftfxConfig->flashDesc.feature.hasIndXaccReg))
  731. {
  732. /* For secondary flash, The two XACCS registers allow up to 16 restricted segments of equal memory size.
  733. */
  734. if (segmentIndex < 8U)
  735. {
  736. xacc = *(const volatile uint8_t *)&FTFx_XACCSL_REG;
  737. }
  738. else if (segmentIndex < ftfxConfig->flashDesc.accessSegmentMem.count)
  739. {
  740. xacc = *(const volatile uint8_t *)&FTFx_XACCSH_REG;
  741. segmentIndex -= 8U;
  742. }
  743. else
  744. {
  745. isInvalidSegmentIndex = true;
  746. }
  747. }
  748. #endif
  749. else
  750. {
  751. return kStatus_FTFx_InvalidArgument;
  752. }
  753. if (isInvalidSegmentIndex)
  754. {
  755. break;
  756. }
  757. /* Determine if this address range is in a execute-only protection flash segment. */
  758. if (0U != ((~xacc) & (u32flag << segmentIndex)))
  759. {
  760. executeOnlySegmentCounter++;
  761. }
  762. /* Calculate tne next start address */
  763. start += ftfxConfig->flashDesc.accessSegmentMem.size;
  764. }
  765. if (executeOnlySegmentCounter < 1u)
  766. {
  767. *access_state = kFLASH_AccessStateUnLimited;
  768. }
  769. else if (executeOnlySegmentCounter < maxSupportedExecuteOnlySegmentCount)
  770. {
  771. *access_state = kFLASH_AccessStateMixed;
  772. }
  773. else
  774. {
  775. *access_state = kFLASH_AccessStateExecuteOnly;
  776. }
  777. return kStatus_FTFx_Success;
  778. }
  779. #endif /* FSL_FEATURE_FLASH_HAS_ACCESS_CONTROL */
  780. /*!
  781. * @brief Sets the PFlash Protection to the intended protection status.
  782. *
  783. * @param config A pointer to storage for the driver runtime state.
  784. * @param protectStatus The expected protect status to set to the PFlash protection register. Each bit is
  785. * corresponding to protection of 1/32(64) of the total PFlash. The least significant bit is corresponding to the lowest
  786. * address area of PFlash. The most significant bit is corresponding to the highest address area of PFlash. There are
  787. * two possible cases as shown below:
  788. * 0: this area is protected.
  789. * 1: this area is unprotected.
  790. *
  791. * @retval #kStatus_FTFx_Success API was executed successfully.
  792. * @retval #kStatus_FTFx_InvalidArgument An invalid argument is provided.
  793. * @retval #kStatus_FTFx_CommandFailure Run-time error during command execution.
  794. */
  795. status_t FLASH_PflashSetProtection(flash_config_t *config, pflash_prot_status_t *protectStatus)
  796. {
  797. if ((config == NULL) || (protectStatus == NULL))
  798. {
  799. return kStatus_FTFx_InvalidArgument;
  800. }
  801. /* Most boards support program flash protect feature, The FPROT registers
  802. * define which program flash regions are protected from program and erase operations.
  803. * Protected flash regions cannot have their content changed;
  804. * that is, these regions cannot be programmed and cannot be erased by any flash command
  805. */
  806. #if (FTFx_FLASH_COUNT > 1U)
  807. if (0U != (config->ftfxConfig[0].flashDesc.feature.hasProtControl))
  808. #endif
  809. {
  810. if (config->ftfxConfig[0].flashDesc.feature.ProtRegBits >= 32U)
  811. {
  812. /* set PFlash protection register, unprotected regions are marked with a 1 and
  813. * setting PFlash protection register, unprotected regions are marked with a 1 and
  814. * protected regions use a 0; each bit of FPROT register can only be changed from 1s to 0s
  815. * while all bits with 0s to 1s transitions are ignored.
  816. */
  817. *kFPROTL = protectStatus->protl;
  818. if (protectStatus->protl != *kFPROTL)
  819. {
  820. return kStatus_FTFx_CommandFailure;
  821. }
  822. }
  823. #if defined(FTFx_FLASH0_HAS_HIGH_PROT_REG) && FTFx_FLASH0_HAS_HIGH_PROT_REG
  824. /* For primary flash with eight PROT registers allow up to 64 protected segments of equal memory size. */
  825. if (config->ftfxConfig[0].flashDesc.feature.ProtRegBits == 64U)
  826. {
  827. *kFPROTH = protectStatus->proth;
  828. if (protectStatus->proth != *kFPROTH)
  829. {
  830. return kStatus_FTFx_CommandFailure;
  831. }
  832. }
  833. #endif
  834. }
  835. #if defined(FTFx_FLASH1_HAS_INT_PROT_REG) && FTFx_FLASH1_HAS_INT_PROT_REG
  836. else if ((0U != config->ftfxConfig[1].flashDesc.feature.hasProtControl) &&
  837. (0U != config->ftfxConfig[1].flashDesc.feature.hasIndProtReg))
  838. {
  839. /* For secondary flash with two FPROT registers allow up to 16 protected segments of equal memory size. */
  840. if (config->ftfxConfig[1].flashDesc.feature.ProtRegBits == 16U)
  841. {
  842. *kFPROTSL = protectStatus->protsl;
  843. if (protectStatus->protsl != *kFPROTSL)
  844. {
  845. return kStatus_FTFx_CommandFailure;
  846. }
  847. *kFPROTSH = protectStatus->protsh;
  848. if (protectStatus->protsh != *kFPROTSH)
  849. {
  850. return kStatus_FTFx_CommandFailure;
  851. }
  852. }
  853. }
  854. #endif
  855. #if (FTFx_FLASH_COUNT > 1U)
  856. else
  857. {
  858. /*do nothing*/
  859. }
  860. #endif
  861. return kStatus_FTFx_Success;
  862. }
  863. /*!
  864. * @brief Gets the PFlash protection status.
  865. *
  866. * @param config A pointer to the storage for the driver runtime state.
  867. * @param protectStatus Protect status returned by the PFlash IP. Each bit is corresponding to the protection of
  868. * 1/32(64)
  869. * of the total PFlash. The least significant bit corresponds to the lowest address area of the PFlash.
  870. * The most significant bit corresponds to the highest address area of PFlash. There are two possible cases as shown
  871. * below: 0: this area is protected. 1: this area is unprotected.
  872. *
  873. * @retval #kStatus_FTFx_Success API was executed successfully.
  874. * @retval #kStatus_FTFx_InvalidArgument An invalid argument is provided.
  875. */
  876. status_t FLASH_PflashGetProtection(flash_config_t *config, pflash_prot_status_t *protectStatus)
  877. {
  878. if ((config == NULL) || (protectStatus == NULL))
  879. {
  880. return kStatus_FTFx_InvalidArgument;
  881. }
  882. #if (FTFx_FLASH_COUNT > 1U)
  883. if (0U != (config->ftfxConfig[0].flashDesc.feature.hasProtControl))
  884. #endif
  885. {
  886. /* get the flash protect status */
  887. if (config->ftfxConfig[0].flashDesc.feature.ProtRegBits >= 32U)
  888. {
  889. protectStatus->protl = *kFPROTL;
  890. }
  891. #if defined(FTFx_FLASH0_HAS_HIGH_PROT_REG) && FTFx_FLASH0_HAS_HIGH_PROT_REG
  892. /* For primary flash with eight PROT registers allow up to 64 protected segments of equal memory size. */
  893. if (config->ftfxConfig[0].flashDesc.feature.ProtRegBits == 64U)
  894. {
  895. protectStatus->proth = *kFPROTH;
  896. }
  897. #endif
  898. }
  899. #if defined(FTFx_FLASH1_HAS_INT_PROT_REG) && FTFx_FLASH1_HAS_INT_PROT_REG
  900. /* For secondary flash with two FPROT registers allow up to 16 protected segments of equal memory size. */
  901. else if ((0U != config->ftfxConfig[1].flashDesc.feature.hasProtControl) &&
  902. (0U != config->ftfxConfig[1].flashDesc.feature.hasIndProtReg))
  903. {
  904. if (config->ftfxConfig[0].flashDesc.feature.ProtRegBits == 16U)
  905. {
  906. protectStatus->protsl = *kFPROTSL;
  907. protectStatus->protsh = *kFPROTSH;
  908. }
  909. }
  910. #endif
  911. #if (FTFx_FLASH_COUNT > 1U)
  912. else
  913. {
  914. /*do nothing*/
  915. }
  916. #endif
  917. return kStatus_FTFx_Success;
  918. }
  919. /*!
  920. * @brief Returns the desired flash property.
  921. *
  922. * @param config A pointer to the storage for the driver runtime state.
  923. * @param whichProperty The desired property from the list of properties in
  924. * enum flash_property_tag_t
  925. * @param value A pointer to the value returned for the desired flash property.
  926. *
  927. * @retval #kStatus_FTFx_Success API was executed successfully.
  928. * @retval #kStatus_FTFx_InvalidArgument An invalid argument is provided.
  929. * @retval #kStatus_FTFx_UnknownProperty An unknown property tag.
  930. */
  931. status_t FLASH_GetProperty(flash_config_t *config, flash_property_tag_t whichProperty, uint32_t *value)
  932. {
  933. if ((config == NULL) || (value == NULL))
  934. {
  935. return kStatus_FTFx_InvalidArgument;
  936. }
  937. status_t status = kStatus_FTFx_Success;
  938. switch (whichProperty)
  939. {
  940. /* gat Pflash0 sector size */
  941. case kFLASH_PropertyPflash0SectorSize:
  942. *value = config->ftfxConfig[0].flashDesc.sectorSize;
  943. break;
  944. /* gat Pflash0 total size */
  945. case kFLASH_PropertyPflash0TotalSize:
  946. *value = config->ftfxConfig[0].flashDesc.totalSize;
  947. break;
  948. /* gat Pflash0 block size */
  949. case kFLASH_PropertyPflash0BlockSize:
  950. *value = config->ftfxConfig[0].flashDesc.totalSize / config->ftfxConfig[0].flashDesc.blockCount;
  951. break;
  952. /* gat Pflash0 block cont */
  953. case kFLASH_PropertyPflash0BlockCount:
  954. *value = config->ftfxConfig[0].flashDesc.blockCount;
  955. break;
  956. /* gat Pflash0 block base address */
  957. case kFLASH_PropertyPflash0BlockBaseAddr:
  958. *value = config->ftfxConfig[0].flashDesc.blockBase;
  959. break;
  960. /* gat Pflash0 fac support feature */
  961. case kFLASH_PropertyPflash0FacSupport:
  962. *value = (uint32_t)config->ftfxConfig[0].flashDesc.feature.hasXaccControl;
  963. break;
  964. /* gat Pflash0 access segment size feature */
  965. case kFLASH_PropertyPflash0AccessSegmentSize:
  966. *value = config->ftfxConfig[0].flashDesc.accessSegmentMem.size;
  967. break;
  968. /* gat Pflash0 access segment count feature */
  969. case kFLASH_PropertyPflash0AccessSegmentCount:
  970. *value = config->ftfxConfig[0].flashDesc.accessSegmentMem.count;
  971. break;
  972. #if defined(FTFx_DRIVER_HAS_FLASH1_SUPPORT) && FTFx_DRIVER_HAS_FLASH1_SUPPORT
  973. case kFLASH_PropertyPflash1SectorSize:
  974. *value = config->ftfxConfig[1].flashDesc.sectorSize;
  975. break;
  976. case kFLASH_PropertyPflash1TotalSize:
  977. *value = config->ftfxConfig[1].flashDesc.totalSize;
  978. break;
  979. case kFLASH_PropertyPflash1BlockSize:
  980. *value = config->ftfxConfig[1].flashDesc.totalSize / config->ftfxConfig[1].flashDesc.blockCount;
  981. break;
  982. case kFLASH_PropertyPflash1BlockCount:
  983. *value = config->ftfxConfig[1].flashDesc.blockCount;
  984. break;
  985. case kFLASH_PropertyPflash1BlockBaseAddr:
  986. *value = config->ftfxConfig[1].flashDesc.blockBase;
  987. break;
  988. case kFLASH_PropertyPflash1FacSupport:
  989. *value = (uint32_t)config->ftfxConfig[1].flashDesc.feature.hasXaccControl;
  990. break;
  991. case kFLASH_PropertyPflash1AccessSegmentSize:
  992. *value = config->ftfxConfig[1].flashDesc.accessSegmentMem.size;
  993. break;
  994. case kFLASH_PropertyPflash1AccessSegmentCount:
  995. *value = config->ftfxConfig[1].flashDesc.accessSegmentMem.count;
  996. break;
  997. #endif
  998. /* gat FlexRam block base addrese */
  999. case kFLASH_PropertyFlexRamBlockBaseAddr:
  1000. *value = config->ftfxConfig[0].flexramBlockBase;
  1001. break;
  1002. /* gat FlexRam total size */
  1003. case kFLASH_PropertyFlexRamTotalSize:
  1004. *value = config->ftfxConfig[0].flexramTotalSize;
  1005. break;
  1006. default: /* catch inputs that are not recognized */
  1007. status = kStatus_FTFx_UnknownProperty;
  1008. break;
  1009. }
  1010. return status;
  1011. }
  1012. /*!
  1013. * @brief init flash FPROT, XACC registers and Independent flash block
  1014. */
  1015. static void flash_init_features(ftfx_config_t *config)
  1016. {
  1017. /* Initialize whether flash0 has independent block, protection registers and
  1018. * execute only access registers */
  1019. #if (FTFx_FLASH_COUNT > 1U)
  1020. if (config->flashDesc.index == 0U)
  1021. #endif
  1022. {
  1023. config->flashDesc.feature.isIndBlock = 1U;
  1024. config->flashDesc.feature.hasIndPfsizeReg = 1U;
  1025. config->flashDesc.feature.hasIndProtReg = 1U;
  1026. config->flashDesc.feature.hasIndXaccReg = 1U;
  1027. }
  1028. /* if another flash exists */
  1029. #if defined(FTFx_DRIVER_HAS_FLASH1_SUPPORT) && FTFx_DRIVER_HAS_FLASH1_SUPPORT
  1030. else if (config->flashDesc.index == 1U)
  1031. {
  1032. config->flashDesc.feature.isIndBlock = FTFx_FLASH1_IS_INDEPENDENT_BLOCK;
  1033. config->flashDesc.feature.hasIndPfsizeReg = config->flashDesc.feature.isIndBlock;
  1034. config->flashDesc.feature.hasIndProtReg = FTFx_FLASH1_HAS_INT_PROT_REG;
  1035. config->flashDesc.feature.hasIndXaccReg = FTFx_FLASH1_HAS_INT_XACC_REG;
  1036. }
  1037. #endif
  1038. #if (FTFx_FLASH_COUNT > 1U)
  1039. else
  1040. {
  1041. /*do nothing*/
  1042. }
  1043. #endif
  1044. /* init protection Registers feature*/
  1045. config->flashDesc.feature.hasProtControl = 1U;
  1046. /* init Execute-only Access Registers feature*/
  1047. config->flashDesc.feature.hasXaccControl = FSL_FEATURE_FLASH_HAS_ACCESS_CONTROL;
  1048. }
  1049. /*!
  1050. * @brief Initializes the flash operation config.
  1051. */
  1052. static void flash_opsonfig_Init(flash_config_t *config, uint8_t flashIndex)
  1053. {
  1054. uint32_t pflashStartAddress;
  1055. uint32_t pflashBlockSize;
  1056. uint32_t pflashBlockCount;
  1057. uint32_t pflashBlockSectorSize;
  1058. uint32_t pfsizeMask;
  1059. uint32_t pfsizeShift;
  1060. uint32_t pflashBlockWriteUnitSize; /* store P-Flash write unit size */
  1061. uint32_t pflashSectorCmdAlignment; /* store P-Flash Erase sector command address alignment */
  1062. uint32_t pflashSectionCmdAlignment; /* store Rrogram/Verify section command address alignment */
  1063. #if (FTFx_FLASH_COUNT > 1U)
  1064. if (flashIndex == 1U)
  1065. {
  1066. pflashStartAddress = FLASH1_FEATURE_PFLASH_START_ADDRESS;
  1067. pflashBlockSize = FLASH1_FEATURE_PFLASH_BLOCK_SIZE;
  1068. pflashBlockCount = FLASH1_FEATURE_PFLASH_BLOCK_COUNT;
  1069. pflashBlockSectorSize = FLASH1_FEATURE_PFLASH_BLOCK_SECTOR_SIZE;
  1070. pflashBlockWriteUnitSize = FLASH1_FEATURE_PFLASH_BLOCK_WRITE_UNIT_SIZE;
  1071. pflashSectorCmdAlignment = FLASH1_FEATURE_PFLASH_SECTOR_CMD_ADDRESS_ALIGMENT;
  1072. pflashSectionCmdAlignment = FLASH1_FEATURE_PFLASH_SECTION_CMD_ADDRESS_ALIGMENT;
  1073. pfsizeMask = SIM_FLASH1_PFSIZE_MASK;
  1074. pfsizeShift = SIM_FLASH1_PFSIZE_SHIFT;
  1075. }
  1076. else
  1077. #endif
  1078. {
  1079. pflashStartAddress = FLASH0_FEATURE_PFLASH_START_ADDRESS; /* get P-Flash start address */
  1080. pflashBlockSize = FLASH0_FEATURE_PFLASH_BLOCK_SIZE;
  1081. pflashBlockCount = FLASH0_FEATURE_PFLASH_BLOCK_COUNT;
  1082. pflashBlockSectorSize = FLASH0_FEATURE_PFLASH_BLOCK_SECTOR_SIZE;
  1083. pflashBlockWriteUnitSize = FLASH0_FEATURE_PFLASH_BLOCK_WRITE_UNIT_SIZE;
  1084. pflashSectorCmdAlignment = FLASH0_FEATURE_PFLASH_SECTOR_CMD_ADDRESS_ALIGMENT;
  1085. pflashSectionCmdAlignment = FLASH0_FEATURE_PFLASH_SECTION_CMD_ADDRESS_ALIGMENT;
  1086. pfsizeMask = SIM_FLASH0_PFSIZE_MASK;
  1087. pfsizeShift = SIM_FLASH0_PFSIZE_SHIFT;
  1088. }
  1089. /* init current flash start address */
  1090. config->ftfxConfig[flashIndex].flashDesc.blockBase = pflashStartAddress;
  1091. /* init current flash block count */
  1092. config->ftfxConfig[flashIndex].flashDesc.blockCount = pflashBlockCount;
  1093. /* init current flash block sector size */
  1094. config->ftfxConfig[flashIndex].flashDesc.sectorSize = pflashBlockSectorSize;
  1095. #if (FTFx_FLASH_COUNT > 1U)
  1096. if ((0U != config->ftfxConfig[flashIndex].flashDesc.feature.isIndBlock) &&
  1097. (0U != config->ftfxConfig[flashIndex].flashDesc.feature.hasIndPfsizeReg))
  1098. #endif
  1099. {
  1100. /* Calculate flash memory size based on given parameter */
  1101. config->ftfxConfig[flashIndex].flashDesc.totalSize =
  1102. flash_calculate_mem_size(pflashBlockCount, pflashBlockSize, pfsizeMask, pfsizeShift);
  1103. }
  1104. #if (FTFx_FLASH_COUNT > 1U)
  1105. else
  1106. {
  1107. config->ftfxConfig[flashIndex].flashDesc.totalSize = pflashBlockCount * pflashBlockSize;
  1108. }
  1109. #endif
  1110. /* init P-Flash write unit size */
  1111. config->ftfxConfig[flashIndex].opsConfig.addrAligment.blockWriteUnitSize = (uint8_t)pflashBlockWriteUnitSize;
  1112. /* init P-Flash Erase sector command address alignment */
  1113. config->ftfxConfig[flashIndex].opsConfig.addrAligment.sectorCmd = (uint8_t)pflashSectorCmdAlignment;
  1114. /* init P-Flash Rrogram/Verify section command address alignment */
  1115. config->ftfxConfig[flashIndex].opsConfig.addrAligment.sectionCmd = (uint8_t)pflashSectionCmdAlignment;
  1116. /* init P-Flash Read resource command address alignment. */
  1117. config->ftfxConfig[flashIndex].opsConfig.addrAligment.resourceCmd =
  1118. (uint8_t)FSL_FEATURE_FLASH_PFLASH_RESOURCE_CMD_ADDRESS_ALIGMENT;
  1119. /* init P-Flash Program check command address alignment. */
  1120. config->ftfxConfig[flashIndex].opsConfig.addrAligment.checkCmd =
  1121. (uint8_t)FSL_FEATURE_FLASH_PFLASH_CHECK_CMD_ADDRESS_ALIGMENT;
  1122. /* init P-Flash swap command address alignment */
  1123. config->ftfxConfig[flashIndex].opsConfig.addrAligment.swapCtrlCmd =
  1124. (uint8_t)FSL_FEATURE_FLASH_PFLASH_SWAP_CONTROL_CMD_ADDRESS_ALIGMENT;
  1125. }
  1126. #if defined(FSL_FEATURE_FLASH_HAS_ACCESS_CONTROL) && FSL_FEATURE_FLASH_HAS_ACCESS_CONTROL
  1127. /*! @brief init access segment feature */
  1128. static void flash_access_init(flash_config_t *config, uint8_t flashIndex)
  1129. {
  1130. ftfx_spec_mem_t *specMem;
  1131. /* start to initialize the structure of access segment */
  1132. #if defined(FTFx_FLASH1_HAS_INT_XACC_REG) && FTFx_FLASH1_HAS_INT_XACC_REG
  1133. specMem = &config->ftfxConfig[flashIndex].flashDesc.accessSegmentMem;
  1134. if (flashIndex == 1U)
  1135. {
  1136. specMem->base = config->ftfxConfig[flashIndex].flashDesc.blockBase;
  1137. specMem->size = (uint32_t)kFTFx_AccessSegmentUnitSize << FTFx_FACSSS_REG;
  1138. specMem->count = FTFx_FACSNS_REG;
  1139. }
  1140. else
  1141. #else
  1142. specMem = &config->ftfxConfig[0].flashDesc.accessSegmentMem;
  1143. #endif /* FTFx_FLASH1_HAS_INT_XACC_REG */
  1144. {
  1145. specMem->base = config->ftfxConfig[0].flashDesc.blockBase;
  1146. specMem->size = (uint32_t)kFTFx_AccessSegmentUnitSize << FTFx_FACSS_REG;
  1147. specMem->count = FTFx_FACSN_REG;
  1148. }
  1149. }
  1150. #endif /* FSL_FEATURE_FLASH_HAS_ACCESS_CONTROL */
  1151. /*! @brief init protection feature */
  1152. static void flash_protection_init(flash_config_t *config, uint8_t flashIndex)
  1153. {
  1154. uint32_t pflashProtectionRegionCount;
  1155. #if (FTFx_FLASH_COUNT > 1U)
  1156. uint8_t i;
  1157. if (flashIndex == 1U)
  1158. {
  1159. /* store flash0 Protection region count */
  1160. pflashProtectionRegionCount = FLASH1_FEATURE_PFLASH_PROTECTION_REGION_COUNT;
  1161. }
  1162. else
  1163. #endif // #if (FTFx_FLASH_COUNT > 1U)
  1164. {
  1165. /* store flash0 Protection region count */
  1166. pflashProtectionRegionCount = FLASH0_FEATURE_PFLASH_PROTECTION_REGION_COUNT;
  1167. }
  1168. /* Start to initialize the structure of protection features */
  1169. ftfx_spec_mem_t *specMem;
  1170. specMem = &config->ftfxConfig[flashIndex].flashDesc.protectRegionMem;
  1171. #if (FTFx_FLASH_COUNT > 1U)
  1172. if (0U != (config->ftfxConfig[flashIndex].flashDesc.feature.hasIndProtReg))
  1173. #endif // #if (FTFx_FLASH_COUNT > 1U)
  1174. {
  1175. specMem->base = config->ftfxConfig[flashIndex].flashDesc.blockBase;
  1176. specMem->count = pflashProtectionRegionCount;
  1177. /* Calculate flash prot segment size */
  1178. specMem->size =
  1179. flash_calculate_prot_segment_size(config->ftfxConfig[flashIndex].flashDesc.totalSize, specMem->count);
  1180. }
  1181. #if (FTFx_FLASH_COUNT > 1U)
  1182. else
  1183. {
  1184. uint32_t pflashTotalSize = 0U;
  1185. specMem->base = config->ftfxConfig[0].flashDesc.blockBase;
  1186. specMem->count = FLASH0_FEATURE_PFLASH_PROTECTION_REGION_COUNT;
  1187. if (flashIndex == FTFx_FLASH_COUNT - 1U)
  1188. {
  1189. uint32_t segmentSize; /* store the flash protection region count */
  1190. for (i = 0U; i < FTFx_FLASH_COUNT; i++)
  1191. {
  1192. /* get pflash total size*/
  1193. pflashTotalSize += config->ftfxConfig[flashIndex].flashDesc.totalSize;
  1194. }
  1195. /* get pflash port segment size based on parameters */
  1196. segmentSize = flash_calculate_prot_segment_size(pflashTotalSize, specMem->count);
  1197. for (i = 0U; i < FTFx_FLASH_COUNT; i++)
  1198. {
  1199. /* init flash0 and flash1 port segment size */
  1200. config->ftfxConfig[i].flashDesc.protectRegionMem.size = segmentSize;
  1201. }
  1202. }
  1203. }
  1204. #endif // #if (FTFx_FLASH_COUNT > 1U)
  1205. }
  1206. /*!
  1207. * @brief Calculate flash memory size based on given parameter
  1208. */
  1209. static uint32_t flash_calculate_mem_size(uint32_t pflashBlockCount,
  1210. uint32_t pflashBlockSize,
  1211. uint32_t pfsizeMask,
  1212. uint32_t pfsizeShift)
  1213. {
  1214. uint8_t pfsize;
  1215. uint32_t flashDensity;
  1216. /* PFSIZE=0xf means that on customer parts the IFR was not correctly programmed.
  1217. * We just use the pre-defined flash size in feature file here to support pre-production parts */
  1218. pfsize = (uint8_t)((SIM_FCFG1_REG & pfsizeMask) >> pfsizeShift);
  1219. if (pfsize == 0xfU)
  1220. {
  1221. flashDensity = pflashBlockCount * pflashBlockSize;
  1222. }
  1223. else
  1224. {
  1225. flashDensity = ((uint32_t)kPFlashDensities[pfsize]) << 10U;
  1226. }
  1227. return flashDensity;
  1228. }
  1229. /*!
  1230. * @brief Calculate flash prot segment size
  1231. */
  1232. static uint32_t flash_calculate_prot_segment_size(uint32_t flashSize, uint32_t segmentCount)
  1233. {
  1234. uint32_t segmentSize;
  1235. /* Calculate the size of the flash protection region
  1236. * If the flash density is > 32KB, then protection region is 1/32 of total flash density
  1237. * Else if flash density is < 32KB, then flash protection region is set to 1KB */
  1238. if (flashSize > segmentCount * (uint32_t)kFTFx_MinProtectBlockSize)
  1239. {
  1240. segmentSize = flashSize / segmentCount;
  1241. }
  1242. else
  1243. {
  1244. segmentSize = (uint32_t)kFTFx_MinProtectBlockSize;
  1245. }
  1246. return segmentSize;
  1247. }
  1248. /*!
  1249. * @brief Validates the given start address and length to get flash index
  1250. */
  1251. static status_t flash_check_range_to_get_index(flash_config_t *config,
  1252. uint32_t start,
  1253. uint32_t lengthInBytes,
  1254. uint8_t *flashIndex)
  1255. {
  1256. if (config == NULL)
  1257. {
  1258. return kStatus_FTFx_InvalidArgument;
  1259. }
  1260. /* Validates the range of the given address */
  1261. for (uint8_t index = 0U; index < FTFx_FLASH_COUNT; index++)
  1262. {
  1263. if ((start >= config->ftfxConfig[index].flashDesc.blockBase) &&
  1264. ((start + lengthInBytes) <=
  1265. (config->ftfxConfig[index].flashDesc.blockBase + config->ftfxConfig[index].flashDesc.totalSize)))
  1266. {
  1267. *flashIndex = config->ftfxConfig[index].flashDesc.index;
  1268. return kStatus_FTFx_Success;
  1269. }
  1270. }
  1271. return kStatus_FTFx_AddressError;
  1272. }
  1273. /*!
  1274. * @brief Decide whether to convert the start address from primary flash to secondary flash based on the current start
  1275. * address
  1276. */
  1277. static void flash_convert_start_address(ftfx_config_t *config, uint32_t start)
  1278. {
  1279. // The caller will guarantee that the config is valid
  1280. #if (FTFx_FLASH_COUNT > 1U)
  1281. if ((0U != config->flashDesc.index) && (0U != config->flashDesc.feature.isIndBlock))
  1282. {
  1283. /* When required by the command, address bit 23 selects between main flash memory
  1284. * (=0) and secondary flash memory (=1).*/
  1285. config->opsConfig.convertedAddress = start - config->flashDesc.blockBase + 0x800000U;
  1286. }
  1287. else
  1288. #endif
  1289. {
  1290. config->opsConfig.convertedAddress = start;
  1291. }
  1292. }
  1293. #if defined(FSL_FEATURE_FLASH_HAS_PFLASH_BLOCK_SWAP) && FSL_FEATURE_FLASH_HAS_PFLASH_BLOCK_SWAP
  1294. /*!
  1295. * @brief Validates the given address to see if it is equal to swap indicator address in pflash swap IFR.
  1296. */
  1297. static status_t flash_validate_swap_indicator_address(ftfx_config_t *config, uint32_t address)
  1298. {
  1299. status_t returnCode;
  1300. struct _flash_swap_ifr_field_config
  1301. {
  1302. uint16_t swapIndicatorAddress; /*!< A Swap indicator address field.*/
  1303. uint16_t swapEnableWord; /*!< A Swap enable word field.*/
  1304. uint8_t reserved0[4]; /*!< A reserved field.*/
  1305. uint8_t reserved1[2]; /*!< A reserved field.*/
  1306. uint16_t swapDisableWord; /*!< A Swap disable word field.*/
  1307. uint8_t reserved2[4]; /*!< A reserved field.*/
  1308. } flashSwapIfrFieldData;
  1309. uint32_t swapIndicatorAddress;
  1310. #if defined(FSL_FEATURE_FLASH_HAS_READ_RESOURCE_CMD) && FSL_FEATURE_FLASH_HAS_READ_RESOURCE_CMD
  1311. returnCode =
  1312. FTFx_CMD_ReadResource(config, config->ifrDesc.resRange.pflashSwapIfrStart, (uint8_t *)&flashSwapIfrFieldData,
  1313. sizeof(flashSwapIfrFieldData), kFTFx_ResourceOptionFlashIfr);
  1314. if (returnCode != kStatus_FTFx_Success)
  1315. {
  1316. return returnCode;
  1317. }
  1318. #else
  1319. {
  1320. /* From RM, the actual info are stored in FCCOB6,7 */
  1321. uint32_t returnValue[2];
  1322. returnCode = FTFx_CMD_ReadOnce(config, (uint32_t)kFLASH_RecordIndexSwapAddr, (uint8_t *)returnValue, 4U);
  1323. if (returnCode != kStatus_FTFx_Success)
  1324. {
  1325. return returnCode;
  1326. }
  1327. flashSwapIfrFieldData.swapIndicatorAddress = (uint16_t)returnValue[0];
  1328. returnCode = FTFx_CMD_ReadOnce(config, (uint32_t)kFLASH_RecordIndexSwapEnable, (uint8_t *)returnValue, 4U);
  1329. if (returnCode != kStatus_FTFx_Success)
  1330. {
  1331. return returnCode;
  1332. }
  1333. returnCode = FTFx_CMD_ReadOnce(config, (uint32_t)kFLASH_RecordIndexSwapDisable, (uint8_t *)returnValue, 4U);
  1334. if (returnCode != kStatus_FTFx_Success)
  1335. {
  1336. return returnCode;
  1337. }
  1338. }
  1339. #endif
  1340. /* The high bits value of Swap Indicator Address is stored in Program Flash Swap IFR Field,
  1341. * the low several bit value of Swap Indicator Address is always 1'b0 */
  1342. swapIndicatorAddress =
  1343. (uint32_t)flashSwapIfrFieldData.swapIndicatorAddress * config->opsConfig.addrAligment.swapCtrlCmd;
  1344. if (address != swapIndicatorAddress)
  1345. {
  1346. return kStatus_FTFx_SwapIndicatorAddressError;
  1347. }
  1348. return returnCode;
  1349. }
  1350. #endif /* FSL_FEATURE_FLASH_HAS_PFLASH_BLOCK_SWAP */