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