1 /*
2 * Copyright 2017 - 2021 NXP
3 * All rights reserved.
4 *
5 *
6 * SPDX-License-Identifier: BSD-3-Clause
7 */
8
9 #include "fsl_flash.h"
10
11 /*******************************************************************************
12 * Definitions
13 ******************************************************************************/
14
15 /* Component ID definition, used by tools. */
16 #ifndef FSL_COMPONENT_ID
17 #define FSL_COMPONENT_ID "platform.drivers.flash"
18 #endif
19
20 /*!
21 * @name Misc utility defines
22 * @{
23 */
24 /*! @brief Alignment utility. */
25 #ifndef ALIGN_DOWN
26 #define ALIGN_DOWN(x, a) (((uint32_t)(x)) & ~((uint32_t)(a)-1u))
27 #endif
28 #ifndef ALIGN_UP
29 #define ALIGN_UP(x, a) ALIGN_DOWN((uint32_t)(x) + (uint32_t)(a)-1u, a)
30 #endif
31
32 /*! @brief Join bytes to word utility. */
33 #define B1P2(b) (((uint32_t)(b)&0xFFU) << 8U)
34 #define B1P1(b) ((uint32_t)(b)&0xFFU)
35 #define B2P1(b) ((uint32_t)(b)&0xFFFFU)
36 #define BYTES_JOIN_TO_WORD_1_1(x, y) (B1P1(x) | B1P2(y))
37 #define BYTES_JOIN_TO_WORD_1_2(x, y) (B1P2(x) | B2P1(y))
38 /*@}*/
39
40 /*!
41 * @name Secondary flash configuration
42 * @{
43 */
44 /*! @brief Indicates whether the secondary flash has its own protection register
45 * in flash module. */
46 #define FLASH_SSD_SECONDARY_FLASH_HAS_ITS_OWN_PROTECTION_REGISTER (0)
47 /*@}*/
48
49 /*!
50 * @name Flash cache ands speculation control defines
51 * @{
52 */
53 #if defined(MCM_PLACR_CFCC_MASK) || defined(MCM_CPCR2_CCBC_MASK)
54 #define FLASH_CACHE_IS_CONTROLLED_BY_MCM (1U)
55 #else
56 #define FLASH_CACHE_IS_CONTROLLED_BY_MCM (0U)
57 #endif
58 #if defined(FMC_PFB0CR_CINV_WAY_MASK) || defined(FMC_PFB01CR_CINV_WAY_MASK)
59 #define FLASH_CACHE_IS_CONTROLLED_BY_FMC (1U)
60 #else
61 #define FLASH_CACHE_IS_CONTROLLED_BY_FMC (0U)
62 #endif
63 #if defined(MCM_PLACR_DFCS_MASK)
64 #define FLASH_PREFETCH_SPECULATION_IS_CONTROLLED_BY_MCM (1U)
65 #else
66 #define FLASH_PREFETCH_SPECULATION_IS_CONTROLLED_BY_MCM (0U)
67 #endif
68 #if defined(FMC_PFB0CR_S_INV_MASK) || defined(FMC_PFB0CR_S_B_INV_MASK) || defined(FMC_PFB01CR_S_INV_MASK) || \
69 defined(FMC_PFB01CR_S_B_INV_MASK)
70 #define FLASH_PREFETCH_SPECULATION_IS_CONTROLLED_BY_FMC (1U)
71 #else
72 #define FLASH_PREFETCH_SPECULATION_IS_CONTROLLED_BY_FMC (0U)
73 #endif
74 /*@}*/
75
76 /*!
77 * @name Reserved EEPROM size (For a variety of purposes) defines
78 * @{
79 */
80 #define NVM_EEPROM_SIZE_FOR_EEESIZE_RESERVED 0x100UL
81 /*@}*/
82
83 /*!
84 * @name Flash Program Once Field defines
85 * @{
86 */
87 #if defined(FSL_FEATURE_FLASH_IS_FTMRE) || defined(FSL_FEATURE_FLASH_IS_FTMRH)
88 /* FTMRE and FTMRH only support 8-bytes unit size */
89 #define FLASH_PROGRAM_ONCE_IS_4BYTES_UNIT_SUPPORT 0U
90 #define FLASH_PROGRAM_ONCE_IS_8BYTES_UNIT_SUPPORT 1U
91 #endif
92 /*@}*/
93
94 /*!
95 * @name Flash security status defines
96 * @{
97 */
98 #define FLASH_SECURITY_STATE_KEYEN 0x80U
99 #define FLASH_SECURITY_STATE_UNSECURED 0x02U
100 #define FLASH_NOT_SECURE 0x01U
101 #define FLASH_SECURE_BACKDOOR_ENABLED 0x02U
102 #define FLASH_SECURE_BACKDOOR_DISABLED 0x04U
103 /*@}*/
104
105 /*!
106 * @name Flash controller command numbers
107 * @{
108 */
109 #define FTMRx_ERASE_VERIFY_ALL_BLOCK 0x01U /*!< ERSVERALL*/
110 #define FTMRx_ERASE_VERIFY_BLOCK 0x02U /*!< ERSVERBLK*/
111 #define FTMRx_ERASE_VERIFY_SECTION 0x03U /*!< ERSVERSECT*/
112 #define FTMRx_READ_ONCE 0x04U /*!< RDONCE or RDINDEX*/
113 #define FTMRx_PROGRAM 0x06U /*!< PGM*/
114 #define FTMRx_PROGRAM_ONCE 0x07U /*!< PGMONCE or PGMINDEX*/
115 #define FTMRx_ERASE_ALL_BLOCK 0x08U /*!< ERSALL*/
116 #define FTMRx_ERASE_BLOCK 0x09U /*!< ERSBLK*/
117 #define FTMRx_ERASE_SECTOR 0x0AU /*!< ERSSCR*/
118 #define FTMRx_ERASE_ALL_BLOCK_UNSECURE 0x0BU /*!< ERSALLU*/
119 #define FTMRx_SECURITY_BY_PASS 0x0CU /*!< VFYKEY*/
120 #define FTMRx_SET_USER_MARGIN_LEVEL 0x0DU /*!< SETUSERLVL*/
121 #define FTMRx_SET_FACTORY_MARGIN_LEVEL 0x0EU /*!< SETFTYLVL*/
122 #define FTMRx_CONFIGURE_NVM 0x0FU /*!< CONNVM*/
123 #define FTMRx_ERASE_VERIFY_EEPROM_SECTION 0x10U /*!< ERSVES*/
124 #define FTMRx_PROGRAM_EEPROM 0x11U /*!< PGME*/
125 #define FTMRx_ERASE_EEPROM_SECTOR 0x12U /*!< ERSESCR*/
126 /*@}*/
127
128 /*!
129 * @name Common flash register info defines
130 * @{
131 */
132 #if defined(FTMRE)
133 #define FTMRx FTMRE
134 #define FTMRx_BASE FTMRE_BASE
135 #define FTMRx_FCCOBIX_CCOBIX(x) FTMRE_FCCOBIX_CCOBIX(x)
136 #define FTMRx_FCCOBLO_CCOB(x) FTMRE_FCCOBLO_CCOB(x)
137 #define FTMRx_FCCOBHI_CCOB(x) FTMRE_FCCOBHI_CCOB(x)
138 #define FTMRx_FCLKDIV_FDIVLCK_MASK FTMRE_FCLKDIV_FDIVLCK_MASK
139 #define FTMRx_FCLKDIV_FDIVLD_MASK FTMRE_FCLKDIV_FDIVLD_MASK
140 #define FTMRx_FCLKDIV_FDIV_MASK FTMRE_FCLKDIV_FDIV_MASK
141 #define FTMRx_FSTAT_CCIF_MASK FTMRE_FSTAT_CCIF_MASK
142 #define FTMRx_FCLKDIV_FDIV(x) FTMRE_FCLKDIV_FDIV(x)
143 #define FTMRx_FSTAT_ACCERR_MASK FTMRE_FSTAT_ACCERR_MASK
144 #define FTMRx_FSTAT_FPVIOL_MASK FTMRE_FSTAT_FPVIOL_MASK
145 #define FTMRx_FSTAT_MGBUSY_MASK FTMRE_FSTAT_MGBUSY_MASK
146 #define FTMRx_FSTAT_MGSTAT_MASK FTMRE_FSTAT_MGSTAT_MASK
147 #define FTMRx_FSTAT_MGSTAT0_MASK FTMRE_FSTAT_MGSTAT(1)
148 #define FTMRx_FSTAT_MGSTAT1_MASK FTMRE_FSTAT_MGSTAT(2)
149 #define FTMRx_FSEC_SEC_MASK FTMRE_FSEC_SEC_MASK
150 #define FTMRx_FSEC_KEYEN_MASK FTMRE_FSEC_KEYEN_MASK
151 #if defined(FTMRE_FPROT_FPHDIS_MASK)
152 #define FTMRx_FPROT_FPHDIS_MASK FTMRE_FPROT_FPHDIS_MASK
153 #endif
154 #if defined(FTMRE_FERSTAT_SFDIF_MASK)
155 #define FTMRx_FERSTAT_SFDIF_MASK FTMRE_FERSTAT_SFDIF_MASK
156 #define FTMRx_FERSTAT_DFDIF_MASK FTMRE_FERSTAT_DFDIF_MASK
157 #endif
158 #elif defined(FTMRH)
159 #define FTMRx FTMRH
160 #define FTMRx_BASE FTMRH_BASE
161 #define FTMRx_FCCOBIX_CCOBIX(x) FTMRH_FCCOBIX_CCOBIX(x)
162 #define FTMRx_FCCOBLO_CCOB(x) FTMRH_FCCOBLO_CCOB(x)
163 #define FTMRx_FCCOBHI_CCOB(x) FTMRH_FCCOBHI_CCOB(x)
164 #define FTMRx_FCLKDIV_FDIVLCK_MASK FTMRH_FCLKDIV_FDIVLCK_MASK
165 #define FTMRx_FCLKDIV_FDIVLD_MASK FTMRH_FCLKDIV_FDIVLD_MASK
166 #define FTMRx_FCLKDIV_FDIV_MASK FTMRH_FCLKDIV_FDIV_MASK
167 #define FTMRx_FCLKDIV_FDIV(x) FTMRH_FCLKDIV_FDIV(x)
168 #define FTMRx_FSTAT_CCIF_MASK FTMRH_FSTAT_CCIF_MASK
169 #define FTMRx_FSTAT_ACCERR_MASK FTMRH_FSTAT_ACCERR_MASK
170 #define FTMRx_FSTAT_FPVIOL_MASK FTMRH_FSTAT_FPVIOL_MASK
171 #define FTMRx_FSTAT_MGBUSY_MASK FTMRH_FSTAT_MGBUSY_MASK
172 #define FTMRx_FSTAT_MGSTAT_MASK FTMRH_FSTAT_MGSTAT_MASK
173 #define FTMRx_FSTAT_MGSTAT0_MASK FTMRH_FSTAT_MGSTAT(1U)
174 #define FTMRx_FSTAT_MGSTAT1_MASK FTMRH_FSTAT_MGSTAT(2U)
175 #define FTMRx_FSEC_SEC_MASK FTMRH_FSEC_SEC_MASK
176 #define FTMRx_FSEC_KEYEN_MASK FTMRH_FSEC_KEYEN_MASK
177 #if defined(FTMRH_FPROT_FPHDIS_MASK)
178 #define FTMRx_FPROT_FPHDIS_MASK FTMRH_FPROT_FPHDIS_MASK
179 #endif
180 #if defined(FTMRH_FERSTAT_SFDIF_MASK)
181 #define FTMRx_FERSTAT_SFDIF_MASK FTMRH_FERSTAT_SFDIF_MASK
182 #define FTMRx_FERSTAT_DFDIF_MASK FTMRH_FERSTAT_DFDIF_MASK
183 #endif
184 #else
185 #error "Unknown flash controller"
186 #endif
187 /*@}*/
188
189 /*!
190 * @brief Enumeration for flash config area.
191 */
192 enum _flash_config_area_range
193 {
194 kFLASH_ConfigAreaStart = 0x400UL,
195 kFLASH_ConfigAreaEnd = 0x40FUL
196 };
197
198 /*!
199 * @name Flash register access type defines
200 * @{
201 */
202 #define FTMRx_REG8_ACCESS_TYPE volatile uint8_t *
203 #define FTMRx_REG32_ACCESS_TYPE volatile uint32_t *
204 /*@}*/
205
206 /*!
207 * @brief MCM cache register access info defines.
208 */
209 #if defined(MCM_PLACR_CFCC_MASK)
210 #define MCM_CACHE_CLEAR_MASK MCM_PLACR_CFCC_MASK
211 #define MCM_CACHE_CLEAR_SHIFT MCM_PLACR_CFCC_SHIFT
212 #if defined(MCM)
213 #define MCM0_CACHE_REG MCM->PLACR
214 #elif defined(MCM0)
215 #define MCM0_CACHE_REG MCM0->PLACR
216 #endif
217 #if defined(MCM1)
218 #define MCM1_CACHE_REG MCM1->PLACR
219 #endif
220 #elif defined(MCM_CPCR2_CCBC_MASK)
221 #define MCM_CACHE_CLEAR_MASK MCM_CPCR2_CCBC_MASK
222 #define MCM_CACHE_CLEAR_SHIFT MCM_CPCR2_CCBC_SHIFT
223 #if defined(MCM)
224 #define MCM0_CACHE_REG MCM->CPCR2
225 #elif defined(MCM0)
226 #define MCM0_CACHE_REG MCM0->CPCR2
227 #endif
228 #if defined(MCM1)
229 #define MCM1_CACHE_REG MCM1->CPCR2
230 #endif
231 #endif
232
233 /*******************************************************************************
234 * Prototypes
235 ******************************************************************************/
236
237 #if FLASH_DRIVER_IS_FLASH_RESIDENT
238 /*! @brief Copy flash_run_command() to RAM*/
239 static void copy_flash_run_command(flash_config_t *config);
240 /*! @brief Copy flash_cache_clear_command() to RAM*/
241 static void copy_flash_common_bit_operation(flash_config_t *config);
242 /*! @brief Check whether flash execute-in-ram functions are ready*/
243 static status_t flash_check_execute_in_ram_function_info(flash_config_t *config);
244 #endif /* FLASH_DRIVER_IS_FLASH_RESIDENT */
245
246 /*! @brief Internal function Flash command sequence. Called by driver APIs
247 * only
248 */
249 static status_t flash_command_sequence(flash_config_t *config);
250
251 /*! @brief Internal function Flash common bit operation command sequence. Called by driver APIs
252 * only
253 */
254 #if FLASH_DRIVER_IS_FLASH_RESIDENT
255 static void flash_common_bit_operation_command_sequence(
256 flash_config_t *config, FTMRx_REG32_ACCESS_TYPE base, uint32_t bitMask, uint32_t bitShift, uint32_t bitValue);
257 #endif /* FLASH_DRIVER_IS_FLASH_RESIDENT */
258
259 /*! @brief Internal function Flash set command. Called by driver APIs only*/
260 void flash_set_command(uint32_t index, uint32_t fValue, uint32_t sValue);
261
262 /*! @brief Perform the cache clear to the flash*/
263 void flash_cache_clear(flash_config_t *config);
264
265 /*! @brief Process the cache to the flash*/
266 static void flash_cache_clear_process(flash_config_t *config, flash_cache_clear_process_t process);
267
268 /*! @brief Validates the range and alignment of the given address range.*/
269 static status_t flash_check_range(flash_config_t *config,
270 uint32_t startAddress,
271 uint32_t lengthInBytes,
272 uint32_t alignmentBaseline);
273
274 /*! @brief Validates the range and alignment of the given address range.*/
275 #if FLASH_SSD_IS_EEPROM_ENABLED
276 static status_t EEPROM_check_range(flash_config_t *config,
277 uint32_t startAddress,
278 uint32_t lengthInBytes,
279 uint32_t alignmentBaseline);
280 #endif /* FLASH_SSD_IS_EEPROM_ENABLED */
281
282 /*! @brief Gets the right address, sector and block size of current flash type
283 * which is indicated by address.*/
284 static status_t flash_get_matched_operation_info(flash_config_t *config,
285 uint32_t address,
286 flash_operation_config_t *info);
287 /*! @brief Validates the given user key for flash erase APIs.*/
288 static status_t flash_check_user_key(uint32_t key);
289
290 /*! @brief Gets the flash protection information.*/
291 static status_t flash_get_protection_info(flash_config_t *config, flash_protection_config_t *info);
292
293 #if FLASH_CACHE_IS_CONTROLLED_BY_MCM
294 /*! @brief Performs the cache clear to the flash by MCM.*/
295 void mcm_flash_cache_clear(flash_config_t *config);
296 #endif /* FLASH_CACHE_IS_CONTROLLED_BY_MCM */
297
298 #if FLASH_CACHE_IS_CONTROLLED_BY_FMC
299 /*! @brief Performs the cache clear to the flash by FMC.*/
300 void fmc_flash_cache_clear(void);
301 #endif /* FLASH_CACHE_IS_CONTROLLED_BY_FMC */
302
303 #if FLASH_PREFETCH_SPECULATION_IS_CONTROLLED_BY_FMC
304 /*! @brief Performs the prefetch speculation buffer clear to the flash by FMC.*/
305 void fmc_flash_prefetch_speculation_clear(void);
306 #endif /* FLASH_PREFETCH_SPECULATION_IS_CONTROLLED_BY_FMC */
307
308 /*! @brief Set the flash and eeprom to the specified user margin level.*/
309 status_t flash_setusermarginlevel(flash_config_t *config,
310 uint32_t start,
311 uint8_t iseeprom,
312 flash_user_margin_value_t margin);
313
314 /*! @brief Set the flash and eeprom to the specified factory margin level.*/
315 status_t flash_setfactorymarginlevel(flash_config_t *config,
316 uint32_t start,
317 uint8_t iseeprom,
318 flash_factory_margin_value_t margin);
319
320 /*******************************************************************************
321 * Variables
322 ******************************************************************************/
323
324 #if FLASH_DRIVER_IS_FLASH_RESIDENT
325 /*! @brief A function pointer used to point to relocated flash_run_command() */
326 static void (*callFlashRunCommand)(FTMRx_REG8_ACCESS_TYPE FTMRx_fstat);
327 /*! @brief A function pointer used to point to relocated
328 * flash_common_bit_operation() */
329 static void (*callFlashCommonBitOperation)(FTMRx_REG32_ACCESS_TYPE base,
330 uint32_t bitMask,
331 uint32_t bitShift,
332 uint32_t bitValue);
333
334 /*!
335 * @brief Position independent code of flash_run_command()
336 *
337 * Note1: The prototype of C function is shown as below:
338 * @code
339 * void flash_run_command(FTMRx_REG8_ACCESS_TYPE FTMRx_fstat)
340 * {
341 * PRINT("\r\nClear CCIF bit.\r\n);
342 * *FTMRx_fstat = FTMRx_FSTAT_CCIF_MASK;
343 *
344 * PRINT("\r\nCheck CCIF bit of the flash status register, wait till it is set.\r\n");
345 * PRINT("\r\nIP team indicates that this loop will always complete.\r\n");
346 * while (!((*FTMRx_fstat) & FTMRx_FSTAT_CCIF_MASK))
347 * {
348 * }
349 * }
350 * @endcode
351 * Note2: The binary code is generated by IAR 7.70.1
352 */
353 const static uint16_t s_flashRunCommandFunctionCode[] = {0x2180, 0x7001, 0x7802, 0x420a, 0xd0fc, 0x4770};
354
355 /*!
356 * @brief Position independent code of flash_common_bit_operation()
357 *
358 * Note1: The prototype of C function is shown as below:
359 * @code
360 * void flash_common_bit_operation(FTMRx_REG32_ACCESS_TYPE base, uint32_t
361 * bitMask, uint32_t bitShift, uint32_t
362 * bitValue)
363 * {
364 * if (bitMask)
365 * {
366 * uint32_t value = (((uint32_t)(((uint32_t)(bitValue)) << bitShift))
367 * & bitMask);
368 * *base = (*base & (~bitMask)) | value;
369 * }
370 *
371 * __ISB();
372 * __DSB();
373 * }
374 * @endcode
375 * Note2: The binary code is generated by IAR 7.70.1
376 */
377 const static uint16_t s_flashCommonBitOperationFunctionCode[] = {
378 0xb510, 0x2900, 0xd005, 0x6804, 0x438c, 0x4093, 0x4019, 0x4321, 0x6001, 0xf3bf, 0x8f6f, 0xf3bf, 0x8f4f, 0xbd10};
379 #endif /* FLASH_DRIVER_IS_FLASH_RESIDENT */
380
381 #if (FLASH_DRIVER_IS_FLASH_RESIDENT && !FLASH_DRIVER_IS_EXPORTED)
382 /*! @brief A static buffer used to hold flash_run_command() */
383 static uint32_t s_flashRunCommand[kFLASH_ExecuteInRamFunctionMaxSizeInWords];
384 /*! @brief A static buffer used to hold flash_common_bit_operation() */
385 static uint32_t s_flashCommonBitOperation[kFLASH_ExecuteInRamFunctionMaxSizeInWords];
386 #endif
387
388 /*******************************************************************************
389 * Code
390 ******************************************************************************/
391
392 /*!
393 * brief Initializes the global flash properties structure members.
394 *
395 * This function checks and initializes the Flash module for the other Flash
396 * APIs.
397 *
398 * param config Pointer to the storage for the driver runtime state.
399 *
400 * retval #kStatus_FLASH_Success API was executed successfully.
401 * retval #kStatus_FLASH_InvalidArgument An invalid argument is provided.
402 * retval #kStatus_FLASH_ClockDivider Flash clock prescaler is wrong.
403 * retval #kStatus_FLASH_ExecuteInRamFunctionNotReady Execute-in-RAM function is
404 * not available.
405 */
FLASH_Init(flash_config_t * config)406 status_t FLASH_Init(flash_config_t *config)
407 {
408 status_t returnCode;
409 uint8_t clkDiver;
410
411 if (config == NULL)
412 {
413 return kStatus_FLASH_InvalidArgument;
414 }
415 clkDiver = (uint8_t)(config->PFlashClockFreq / 1000000UL - 1UL);
416
417 /* Initialize the flash clock to be within spec 1MHz. */
418 if ((0U == (FTMRx->FCLKDIV & FTMRx_FCLKDIV_FDIVLCK_MASK)) && (0U != (FTMRx->FSTAT & FTMRx_FSTAT_CCIF_MASK)))
419 {
420 /* FCLKDIV register is not locked.*/
421 FTMRx->FCLKDIV = (uint8_t)(FTMRx->FCLKDIV & (~FTMRx_FCLKDIV_FDIV_MASK)) | FTMRx_FCLKDIV_FDIV(clkDiver);
422 if ((FTMRx->FCLKDIV & FTMRx_FCLKDIV_FDIV_MASK) != FTMRx_FCLKDIV_FDIV(clkDiver))
423 {
424 return kStatus_FLASH_ClockDivider;
425 }
426 }
427 else
428 {
429 /* FCLKDIV register is locked. */
430 if ((FTMRx->FCLKDIV & FTMRx_FCLKDIV_FDIV_MASK) != FTMRx_FCLKDIV_FDIV(clkDiver))
431 {
432 return kStatus_FLASH_ClockDivider;
433 }
434 }
435 #if FLASH_SSD_IS_SECONDARY_FLASH_ENABLED
436 if (config->FlashMemoryIndex == (uint8_t)kFLASH_MemoryIndexSecondaryFlash)
437 {
438 config->PFlashBlockBase = SECONDARY_FLASH_FEATURE_PFLASH_START_ADDRESS;
439 config->PFlashTotalSize =
440 SECONDARY_FLASH_FEATURE_PFLASH_BLOCK_COUNT * SECONDARY_FLASH_FEATURE_PFLASH_BLOCK_SIZE;
441 config->PFlashBlockCount = SECONDARY_FLASH_FEATURE_PFLASH_BLOCK_COUNT;
442 config->PFlashSectorSize = SECONDARY_FLASH_FEATURE_PFLASH_BLOCK_SECTOR_SIZE;
443 }
444 else
445 #endif
446 {
447 /* fill out a few of the structure members */
448 config->PFlashBlockBase = FSL_FEATURE_FLASH_PFLASH_START_ADDRESS;
449 config->PFlashTotalSize = FSL_FEATURE_FLASH_PFLASH_BLOCK_COUNT * FSL_FEATURE_FLASH_PFLASH_BLOCK_SIZE;
450 config->PFlashBlockCount = FSL_FEATURE_FLASH_PFLASH_BLOCK_COUNT;
451 config->PFlashSectorSize = FSL_FEATURE_FLASH_PFLASH_BLOCK_SECTOR_SIZE;
452 }
453 config->PFlashCallback = NULL;
454
455 /* copy required flash commands to RAM */
456 #if (FLASH_DRIVER_IS_FLASH_RESIDENT && !FLASH_DRIVER_IS_EXPORTED)
457 if (kStatus_FLASH_Success != flash_check_execute_in_ram_function_info(config))
458 {
459 config->executeInRamFunction.activeFunctionCount = 0UL;
460 config->executeInRamFunction.runCmdFuncAddr.commadAddr = (uint32_t)s_flashRunCommand;
461 config->executeInRamFunction.CommonBitOperationAddr.bitOperationAddr = (uint32_t)s_flashCommonBitOperation;
462 config->flashExecuteInRamFunctionInfo = &config->executeInRamFunction.activeFunctionCount;
463 returnCode = FLASH_PrepareExecuteInRamFunctions(config);
464 if (returnCode != kStatus_FLASH_Success)
465 {
466 return returnCode;
467 }
468 }
469 #endif
470 #if FLASH_SSD_IS_EEPROM_ENABLED
471 config->EEpromBlockBase = FSL_FEATURE_FLASH_EEPROM_START_ADDRESS;
472 config->EEpromBlockCount = FSL_FEATURE_FLASH_EEPROM_BLOCK_COUNT;
473 config->EEpromTotalSize = FSL_FEATURE_FLASH_EEPROM_BLOCK_SIZE * FSL_FEATURE_FLASH_EEPROM_BLOCK_COUNT;
474 config->EEpromSectorSize = FSL_FEATURE_FLASH_EEPROM_BLOCK_SECTOR_SIZE;
475 #endif
476 config->PFlashMarginLevel = (uint32_t)kFLASH_MarginValueNormal;
477
478 return kStatus_FLASH_Success;
479 }
480
481 /*!
482 * brief Sets the desired flash callback function.
483 *
484 * param config Pointer to the storage for the driver runtime state.
485 * param callback A callback function to be stored in the driver.
486 *
487 * retval #kStatus_FLASH_Success API was executed successfully.
488 * retval #kStatus_FLASH_InvalidArgument An invalid argument is provided.
489 */
FLASH_SetCallback(flash_config_t * config,flash_callback_t callback)490 status_t FLASH_SetCallback(flash_config_t *config, flash_callback_t callback)
491 {
492 if (config == NULL)
493 {
494 return kStatus_FLASH_InvalidArgument;
495 }
496
497 config->PFlashCallback = callback;
498
499 return kStatus_FLASH_Success;
500 }
501
502 #if defined(FLASH_DRIVER_IS_FLASH_RESIDENT) && FLASH_DRIVER_IS_FLASH_RESIDENT
FLASH_PrepareExecuteInRamFunctions(flash_config_t * config)503 status_t FLASH_PrepareExecuteInRamFunctions(flash_config_t *config)
504 {
505 flash_execute_in_ram_function_config_t *flashExecuteInRamFunctionInfo = &config->executeInRamFunction;
506
507 if ((config == NULL) || (config->flashExecuteInRamFunctionInfo == NULL))
508 {
509 return kStatus_FLASH_InvalidArgument;
510 }
511 /* copy flash run command to ram*/
512 copy_flash_run_command(config);
513
514 /* copy flash common bit operation command to ram*/
515 copy_flash_common_bit_operation(config);
516 flashExecuteInRamFunctionInfo->activeFunctionCount = kFLASH_ExecuteInRamFunctionTotalNum;
517
518 return kStatus_FLASH_Success;
519 }
520 #endif /* FLASH_DRIVER_IS_FLASH_RESIDENT */
521
522 /*!
523 * brief Erases entire flash
524 *
525 * param config Pointer to the storage for the driver runtime state.
526 * param key A value used to validate all flash erase APIs.
527 *
528 * retval #kStatus_FLASH_Success API was executed successfully.
529 * retval #kStatus_FLASH_InvalidArgument An invalid argument is provided.
530 * retval #kStatus_FLASH_EraseKeyError API erase key is invalid.
531 * retval #kStatus_FLASH_ExecuteInRamFunctionNotReady Execute-in-RAM function is
532 * not available.
533 * retval #kStatus_FLASH_AccessError Invalid instruction codes and out-of bounds
534 * addresses.
535 * retval #kStatus_FLASH_ProtectionViolation The program/erase operation is
536 * requested to execute on protected areas.
537 * retval #kStatus_FLASH_CommandFailure Run-time error during command execution.
538 * retval #kStatus_FLASH_EepromSingleBitFault EEPROM single bit fault error
539 * code.
540 * retval #kStatus_FLASH_EepromDoubleBitFault EEPROM double bit fault error
541 * code.
542 */
FLASH_EraseAll(flash_config_t * config,uint32_t key)543 status_t FLASH_EraseAll(flash_config_t *config, uint32_t key)
544 {
545 status_t returnCode;
546
547 if (config == NULL)
548 {
549 return kStatus_FLASH_InvalidArgument;
550 }
551
552 /* preparing passing parameter to erase all flash & EEPROM blocks */
553 FTMRx->FSTAT = FTMRx_FSTAT_ACCERR_MASK | FTMRx_FSTAT_FPVIOL_MASK;
554
555 /* Write index to specify the command code to be loaded */
556 flash_set_command(0UL, 0UL, FTMRx_ERASE_ALL_BLOCK);
557
558 /* Validate the user key */
559 returnCode = flash_check_user_key(key);
560 if (returnCode != kStatus_FLASH_Success)
561 {
562 return returnCode;
563 }
564
565 flash_cache_clear_process(config, kFLASH_CacheClearProcessPre);
566
567 /* calling flash command sequence function to execute the command */
568 returnCode = flash_command_sequence(config);
569
570 flash_cache_clear(config);
571
572 return returnCode;
573 }
574
575 /*!
576 * brief Erases the flash sectors encompassed by parameters passed into
577 * function.
578 *
579 * This function erases the appropriate number of flash sectors based on the
580 * desired start address and length.
581 *
582 * param config The pointer to the storage for the driver runtime state.
583 * param start The start address of the desired flash memory to be erased.
584 * The start address does not need to be sector-aligned but must be
585 * word-aligned.
586 * param lengthInBytes The length, given in bytes (not words or long-words)
587 * to be erased. Must be word-aligned.
588 * param key The value used to validate all flash erase APIs.
589 *
590 * retval #kStatus_FLASH_Success API was executed successfully.
591 * retval #kStatus_FLASH_InvalidArgument An invalid argument is provided.
592 * retval #kStatus_FLASH_AlignmentError The parameter is not aligned with the
593 * specified baseline.
594 * retval #kStatus_FLASH_AddressError The address is out of range.
595 * retval #kStatus_FLASH_EraseKeyError The API erase key is invalid.
596 * retval #kStatus_FLASH_ExecuteInRamFunctionNotReady Execute-in-RAM function is
597 * not available.
598 * retval #kStatus_FLASH_AccessError Invalid instruction codes and out-of bounds
599 * addresses.
600 * retval #kStatus_FLASH_ProtectionViolation The program/erase operation is
601 * requested to execute on protected areas.
602 * retval #kStatus_FLASH_CommandFailure Run-time error during the command
603 * execution.
604 */
FLASH_Erase(flash_config_t * config,uint32_t start,uint32_t lengthInBytes,uint32_t key)605 status_t FLASH_Erase(flash_config_t *config, uint32_t start, uint32_t lengthInBytes, uint32_t key)
606 {
607 uint32_t sectorSize;
608 flash_operation_config_t flashOperationInfo;
609 uint32_t endAddress; /* storing end address */
610 uint32_t numberOfSectors; /* number of sectors calculated by endAddress */
611 status_t returnCode;
612
613 returnCode = flash_get_matched_operation_info(config, start, &flashOperationInfo);
614 if (returnCode != kStatus_FLASH_Success)
615 {
616 return returnCode;
617 }
618
619 /* Check the supplied address range. */
620 returnCode = flash_check_range(config, start, lengthInBytes, flashOperationInfo.sectorCmdAddressAligment);
621 if (returnCode != kStatus_FLASH_Success)
622 {
623 return returnCode;
624 }
625 /* Validate the user key */
626 returnCode = flash_check_user_key(key);
627 if (returnCode != kStatus_FLASH_Success)
628 {
629 return returnCode;
630 }
631
632 start = flashOperationInfo.convertedAddress;
633 sectorSize = flashOperationInfo.activeSectorSize;
634
635 /* calculating Flash end address */
636 endAddress = start + lengthInBytes - 1U;
637
638 /* re-calculate the endAddress and align it to the start of the next sector
639 * which will be used in the comparison below */
640 if (0U != (endAddress % sectorSize))
641 {
642 numberOfSectors = (endAddress / sectorSize) + 1UL;
643 endAddress = (numberOfSectors * sectorSize) - 1UL;
644 }
645
646 flash_cache_clear_process(config, kFLASH_CacheClearProcessPre);
647
648 /* the start address will increment to the next sector address
649 * until it reaches the endAdddress */
650 while (start <= endAddress)
651 {
652 /* clear error flags */
653 FTMRx->FSTAT = FTMRx_FSTAT_ACCERR_MASK | FTMRx_FSTAT_FPVIOL_MASK;
654 /* preparing passing parameter to erase a flash block */
655 /* Write index to specify the command code to be loaded */
656 flash_set_command(0UL, start >> 16UL, FTMRx_ERASE_SECTOR);
657
658 /* Write index to specify the lower byte memory address bits[15:0] to be
659 * loaded */
660 flash_set_command(1UL, start, start >> 8UL);
661
662 /* calling flash command sequence function to execute the command */
663 returnCode = flash_command_sequence(config);
664
665 /* calling flash callback function if it is available */
666 if ((config->PFlashCallback) != NULL)
667 {
668 config->PFlashCallback();
669 }
670
671 /* checking the success of command execution */
672 if (kStatus_FLASH_Success != returnCode)
673 {
674 break;
675 }
676 /* Increment to the next sector */
677 start += sectorSize;
678 }
679
680 flash_cache_clear(config);
681
682 return (returnCode);
683 }
684
685 /*!
686 * brief Erases the eeprom sectors encompassed by parameters passed into
687 * function.
688 *
689 * This function erases the appropriate number of eeprom sectors based on the
690 * desired start address and length.
691 *
692 * param config The pointer to the storage for the driver runtime state.
693 * param start The start address of the desired eeprom memory to be erased.
694 * The start address does not need to be sector-aligned but must be
695 * word-aligned.
696 * param lengthInBytes The length, given in bytes (not words or long-words)
697 * to be erased. Must be word-aligned.
698 * param key The value used to validate all eeprom erase APIs.
699 *
700 * retval #kStatus_FLASH_Success API was executed successfully.
701 * retval #kStatus_FLASH_InvalidArgument An invalid argument is provided.
702 * retval #kStatus_FLASH_AlignmentError The parameter is not aligned with the
703 * specified baseline.
704 * retval #kStatus_FLASH_AddressError The address is out of range.
705 * retval #kStatus_FLASH_EraseKeyError The API erase key is invalid.
706 * retval #kStatus_FLASH_ExecuteInRamFunctionNotReady Execute-in-RAM function is
707 * not available.
708 * retval #kStatus_FLASH_AccessError Invalid instruction codes and out-of bounds
709 * addresses.
710 * retval #kStatus_FLASH_ProtectionViolation The program/erase operation is
711 * requested to execute on protected areas.
712 * retval #kStatus_FLASH_CommandFailure Run-time error during the command
713 * execution.
714 */
715 #if defined(FLASH_SSD_IS_EEPROM_ENABLED) && FLASH_SSD_IS_EEPROM_ENABLED
FLASH_EraseEEprom(flash_config_t * config,uint32_t start,uint32_t lengthInBytes,uint32_t key)716 status_t FLASH_EraseEEprom(flash_config_t *config, uint32_t start, uint32_t lengthInBytes, uint32_t key)
717 {
718 uint32_t sectorSize;
719 flash_operation_config_t flashOperationInfo;
720 uint32_t endAddress; /* storing end address */
721 uint32_t numberOfSectors; /* number of sectors calculated by endAddress */
722 status_t returnCode;
723
724 returnCode = flash_get_matched_operation_info(config, start, &flashOperationInfo);
725 if (returnCode != kStatus_FLASH_Success)
726 {
727 return returnCode;
728 }
729 /* Check the supplied address range. */
730 returnCode = EEPROM_check_range(config, start, lengthInBytes, config->EEpromSectorSize);
731 if (returnCode != kStatus_FLASH_Success)
732 {
733 return returnCode;
734 }
735 /* Validate the user key */
736 returnCode = flash_check_user_key(key);
737 if (returnCode != kStatus_FLASH_Success)
738 {
739 return returnCode;
740 }
741
742 sectorSize = config->EEpromSectorSize;
743
744 /* calculating Flash end address */
745 endAddress = start + lengthInBytes - 1UL;
746
747 /* re-calculate the endAddress and align it to the start of the next sector
748 * which will be used in the comparison below */
749 if (0UL != (endAddress % sectorSize))
750 {
751 numberOfSectors = (endAddress / sectorSize) + 1UL;
752 endAddress = (numberOfSectors * sectorSize) - 1UL;
753 }
754
755 flash_cache_clear_process(config, kFLASH_CacheClearProcessPre);
756
757 /* the start address will increment to the next sector address
758 * until it reaches the endAdddress */
759 while (start <= endAddress)
760 {
761 /* clear error flags */
762 FTMRx->FSTAT = FTMRx_FSTAT_ACCERR_MASK | FTMRx_FSTAT_FPVIOL_MASK;
763 /* preparing passing parameter to erase a flash block */
764 /* Write index to specify the command code to be loaded */
765 flash_set_command(0UL, start >> 16UL, FTMRx_ERASE_EEPROM_SECTOR);
766
767 /* Write index to specify the lower byte memory address bits[15:0] to be
768 * loaded */
769 flash_set_command(1UL, start, start >> 8UL);
770
771 /* calling flash command sequence function to execute the command */
772 returnCode = flash_command_sequence(config);
773
774 /* calling flash callback function if it is available */
775 if (config->PFlashCallback != NULL)
776 {
777 config->PFlashCallback();
778 }
779
780 /* checking the success of command execution */
781 if (kStatus_FLASH_Success != returnCode)
782 {
783 break;
784 }
785 /* Increment to the next sector */
786 start += sectorSize;
787 }
788
789 flash_cache_clear(config);
790
791 return (returnCode);
792 }
793 #endif /* FLASH_SSD_IS_EEPROM_ENABLED */
794
795 #if defined(FSL_FEATURE_FLASH_HAS_UNSECURE_FLASH_CMD) && FSL_FEATURE_FLASH_HAS_UNSECURE_FLASH_CMD
FLASH_EraseAllUnsecure(flash_config_t * config,uint32_t key)796 status_t FLASH_EraseAllUnsecure(flash_config_t *config, uint32_t key)
797 {
798 status_t returnCode;
799
800 if (config == NULL)
801 {
802 return kStatus_FLASH_InvalidArgument;
803 }
804
805 /* Prepare passing parameter to erase all flash blocks (unsecure). */
806 /* clear error flags */
807 FTMRx->FSTAT = FTMRx_FSTAT_ACCERR_MASK | FTMRx_FSTAT_FPVIOL_MASK;
808
809 /* Write index to specify the command code to be loaded */
810 flash_set_command(0UL, 0UL, FTMRx_ERASE_ALL_BLOCK_UNSECURE);
811
812 /* Validate the user key */
813 returnCode = flash_check_user_key(key);
814 if (returnCode != kStatus_FLASH_Success)
815 {
816 return returnCode;
817 }
818
819 flash_cache_clear_process(config, kFLASH_CacheClearProcessPre);
820
821 /* calling flash command sequence function to execute the command */
822 returnCode = flash_command_sequence(config);
823
824 flash_cache_clear(config);
825
826 return returnCode;
827 }
828 #endif /* FSL_FEATURE_FLASH_HAS_UNSECURE_FLASH_CMD */
829
830 /*!
831 * brief Programs flash with data at locations passed in through parameters.
832 *
833 * This function programs the flash memory with the desired data for a given
834 * flash area as determined by the start address and the length.
835 *
836 * param config A pointer to the storage for the driver runtime state.
837 * param start The start address of the desired flash memory to be programmed.
838 * Must be
839 * word-aligned.
840 * param src A pointer to the source buffer of data that is to be programmed
841 * into the flash.
842 * param lengthInBytes The length, given in bytes (not words or long-words),
843 * to be programmed. Must be word-aligned.
844 *
845 * retval #kStatus_FLASH_Success API was executed successfully.
846 * retval #kStatus_FLASH_InvalidArgument An invalid argument is provided.
847 * retval #kStatus_FLASH_AlignmentError Parameter is not aligned with the
848 * specified baseline.
849 * retval #kStatus_FLASH_AddressError Address is out of range.
850 * retval #kStatus_FLASH_ExecuteInRamFunctionNotReady Execute-in-RAM function is
851 * not available.
852 * retval #kStatus_FLASH_AccessError Invalid instruction codes and out-of bounds
853 * addresses.
854 * retval #kStatus_FLASH_ProtectionViolation The program/erase operation is
855 * requested to execute on protected areas.
856 * retval #kStatus_FLASH_CommandFailure Run-time error during the command
857 * execution.
858 */
FLASH_Program(flash_config_t * config,uint32_t start,uint32_t * src,uint32_t lengthInBytes)859 status_t FLASH_Program(flash_config_t *config, uint32_t start, uint32_t *src, uint32_t lengthInBytes)
860 {
861 status_t returnCode;
862 flash_operation_config_t flashOperationInfo;
863
864 if (src == NULL)
865 {
866 return kStatus_FLASH_InvalidArgument;
867 }
868
869 returnCode = flash_get_matched_operation_info(config, start, &flashOperationInfo);
870 if (returnCode != kStatus_FLASH_Success)
871 {
872 return returnCode;
873 }
874
875 /* Check the supplied address range. */
876 returnCode = flash_check_range(config, start, lengthInBytes, flashOperationInfo.blockWriteUnitSize);
877 if (returnCode != kStatus_FLASH_Success)
878 {
879 return returnCode;
880 }
881
882 flash_cache_clear_process(config, kFLASH_CacheClearProcessPre);
883
884 while (lengthInBytes > 0UL)
885 {
886 /* pass paramters to FTMRx */
887 FTMRx->FSTAT = FTMRx_FSTAT_ACCERR_MASK | FTMRx_FSTAT_FPVIOL_MASK;
888
889 /* Write index to specify the command code to be loaded */
890 flash_set_command(0UL, start >> 16UL, FTMRx_PROGRAM);
891 flash_set_command(1UL, start, start >> 8UL);
892 /*Small endian by default.*/
893 /* Write index to specify the word0 (MSB word) to be programmed */
894 flash_set_command(2UL, *src, *src >> 8UL);
895
896 /* Write index to specify the word1 (LSB word) to be programmed */
897 flash_set_command(3UL, *src >> 16UL, *src >> 24UL);
898 /* preparing passing parameter to program the flash block */
899
900 if (4UL == flashOperationInfo.blockWriteUnitSize)
901 {
902 /* calling flash command sequence function to execute the command */
903 returnCode = flash_command_sequence(config);
904 }
905 else if (8UL == flashOperationInfo.blockWriteUnitSize)
906 {
907 src++;
908 /* Write index to specify the word (MSB word) to be programmed */
909 flash_set_command(4UL, *src, *src >> 8UL);
910 /* Write index to specify the word (LSB word) to be programmed */
911 flash_set_command(5UL, *src >> 16UL, *src >> 24UL);
912
913 /* calling flash command sequence function to execute the command */
914 returnCode = flash_command_sequence(config);
915 }
916 else
917 {
918 /*"There's nothing to do here."*/
919 }
920 src++;
921 /* calling flash callback function if it is available */
922 if (config->PFlashCallback != NULL)
923 {
924 config->PFlashCallback();
925 }
926
927 /* checking for the success of command execution */
928 if (kStatus_FLASH_Success != returnCode)
929 {
930 break;
931 }
932 else
933 {
934 /* update start address for next iteration */
935 start += flashOperationInfo.blockWriteUnitSize;
936
937 /* update lengthInBytes for next iteration */
938 lengthInBytes -= flashOperationInfo.blockWriteUnitSize;
939 }
940 }
941
942 flash_cache_clear(config);
943
944 return (returnCode);
945 }
946
947 /*!
948 * brief Programs Program Once Field through parameters.
949 *
950 * This function programs the Program Once Field with the desired data for a
951 * given
952 * flash area as determined by the index and length.
953 *
954 * param config A pointer to the storage for the driver runtime state.
955 * param index The index indicating which area of the Program Once Field to be
956 * programmed.
957 * param src A pointer to the source buffer of data that is to be programmed
958 * into the Program Once Field.
959 * param lengthInBytes The length, given in bytes (not words or long-words),
960 * to be programmed. Must be word-aligned.
961 *
962 * retval #kStatus_FLASH_Success API was executed successfully.
963 * retval #kStatus_FLASH_InvalidArgument An invalid argument is provided.
964 * retval #kStatus_FLASH_ExecuteInRamFunctionNotReady Execute-in-RAM function is
965 * not available.
966 * retval #kStatus_FLASH_AccessError Invalid instruction codes and out-of bounds
967 * addresses.
968 * retval #kStatus_FLASH_ProtectionViolation The program/erase operation is
969 * requested to execute on protected areas.
970 * retval #kStatus_FLASH_CommandFailure Run-time error during the command
971 * execution.
972 */
FLASH_ProgramOnce(flash_config_t * config,uint32_t index,uint32_t * src,uint32_t lengthInBytes)973 status_t FLASH_ProgramOnce(flash_config_t *config, uint32_t index, uint32_t *src, uint32_t lengthInBytes)
974 {
975 status_t returnCode;
976
977 if ((config == NULL) || (src == NULL))
978 {
979 return kStatus_FLASH_InvalidArgument;
980 }
981
982 /* pass paramters to FTMRx */
983 FTMRx->FSTAT = FTMRx_FSTAT_ACCERR_MASK | FTMRx_FSTAT_FPVIOL_MASK;
984
985 /* Write index to specify the command code to be loaded. */
986 flash_set_command(0UL, 0UL, FTMRx_PROGRAM_ONCE);
987 flash_set_command(1UL, index, index >> 8UL);
988
989 /* Write index to specify the word0 (MSB word) to be programmed. */
990 flash_set_command(2UL, *src, *src >> 8UL);
991
992 /* Write index to specify the word1 (LSB word) to be programmed. */
993 flash_set_command(3UL, *src >> 16UL, *src >> 24UL);
994
995 #if FLASH_PROGRAM_ONCE_IS_8BYTES_UNIT_SUPPORT
996
997 /* Write index to specify the word2 (MSB word) to be programmed. */
998 flash_set_command(4UL, *(src + 1UL), *(src + 1UL) >> 8UL);
999
1000 /* Write index to specify the word3 (LSB word) to be programmed. */
1001 flash_set_command(5UL, *(src + 1UL) >> 16UL, *(src + 1UL) >> 24UL);
1002 #endif
1003 flash_cache_clear_process(config, kFLASH_CacheClearProcessPre);
1004
1005 /* calling flash command sequence function to execute the command */
1006 returnCode = flash_command_sequence(config);
1007
1008 flash_cache_clear(config);
1009
1010 return returnCode;
1011 }
1012
1013 #if defined(FLASH_SSD_IS_EEPROM_ENABLED) && FLASH_SSD_IS_EEPROM_ENABLED
FLASH_EepromWrite(flash_config_t * config,uint32_t start,uint8_t * src,uint32_t lengthInBytes)1014 status_t FLASH_EepromWrite(flash_config_t *config, uint32_t start, uint8_t *src, uint32_t lengthInBytes)
1015 {
1016 status_t returnCode;
1017 uint32_t i;
1018 if ((config == NULL) || (src == NULL))
1019 {
1020 return kStatus_FLASH_InvalidArgument;
1021 }
1022
1023 /* Check the supplied address range. */
1024 /* Validates the range of the given address */
1025 if ((start < config->EEpromBlockBase) ||
1026 ((start + lengthInBytes) > (config->EEpromBlockBase + config->EEpromTotalSize)))
1027 {
1028 return kStatus_FLASH_AddressError;
1029 }
1030
1031 returnCode = kStatus_FLASH_Success;
1032
1033 flash_cache_clear_process(config, kFLASH_CacheClearProcessPre);
1034
1035 while (lengthInBytes > 0UL)
1036 {
1037 /* pass paramters to FTMRx */
1038 FTMRx->FSTAT = FTMRx_FSTAT_ACCERR_MASK | FTMRx_FSTAT_FPVIOL_MASK;
1039
1040 if (lengthInBytes >= 4UL)
1041 {
1042 /* Write index to specify the command code to be loaded */
1043 flash_set_command(0UL, start >> 16UL, FTMRx_PROGRAM_EEPROM);
1044 flash_set_command(1UL, (start & 0x000000FFUL), start >> 8UL);
1045
1046 for (i = 0UL; i < 4UL; i++)
1047 {
1048 flash_set_command(0x02UL + i, *src++, 0UL);
1049 }
1050
1051 /* calling flash command sequence function to execute the command */
1052 returnCode = flash_command_sequence(config);
1053
1054 /* calling flash callback function if it is available */
1055 if (config->PFlashCallback != NULL)
1056 {
1057 config->PFlashCallback();
1058 }
1059
1060 /* checking for the success of command execution */
1061 if (returnCode != kStatus_FLASH_Success)
1062 {
1063 break;
1064 }
1065 else
1066 {
1067 /* update start address for next iteration */
1068 start += 4UL;
1069 /* update lengthInBytes for next iteration */
1070 lengthInBytes -= 4UL;
1071 }
1072 }
1073 else if (lengthInBytes > 0UL)
1074 {
1075 /* Write index to specify the command code to be loaded */
1076 flash_set_command(0UL, start >> 16UL, FTMRx_PROGRAM_EEPROM);
1077 flash_set_command(1UL, (start & 0x000000FFUL), start >> 8UL);
1078
1079 /* Write index to specify the byte (MSB word) to be programmed */
1080 for (i = 0UL; i < lengthInBytes; i++)
1081 {
1082 flash_set_command(0x02UL + i, *src++, 0UL);
1083 }
1084 /* calling flash command sequence function to execute the command */
1085 returnCode = flash_command_sequence(config);
1086 lengthInBytes = 0UL;
1087 }
1088 else
1089 {
1090 /*"There's nothing to do here."*/
1091 }
1092 }
1093 flash_cache_clear(config);
1094 return (returnCode);
1095 }
1096 #endif /* FLASH_SSD_IS_EEPROM_ENABLED */
1097
1098 /*!
1099 * brief Reads the Program Once Field through parameters.
1100 *
1101 * This function reads the read once feild with given index and length.
1102 *
1103 * param config A pointer to the storage for the driver runtime state.
1104 * param index The index indicating the area of program once field to be read.
1105 * param dst A pointer to the destination buffer of data that is used to store
1106 * data to be read.
1107 * param lengthInBytes The length, given in bytes (not words or long-words),
1108 * to be programmed. Must be word-aligned.
1109 *
1110 * retval #kStatus_FLASH_Success API was executed successfully.
1111 * retval #kStatus_FLASH_InvalidArgument An invalid argument is provided.
1112 * retval #kStatus_FLASH_ExecuteInRamFunctionNotReady Execute-in-RAM function is
1113 * not available.
1114 * retval #kStatus_FLASH_AccessError Invalid instruction codes and out-of bounds
1115 * addresses.
1116 * retval #kStatus_FLASH_ProtectionViolation The program/erase operation is
1117 * requested to execute on protected areas.
1118 * retval #kStatus_FLASH_CommandFailure Run-time error during the command
1119 * execution.
1120 */
FLASH_ReadOnce(flash_config_t * config,uint32_t index,uint32_t * dst,uint32_t lengthInBytes)1121 status_t FLASH_ReadOnce(flash_config_t *config, uint32_t index, uint32_t *dst, uint32_t lengthInBytes)
1122 {
1123 uint32_t fccobloValue, fccobhiValue;
1124 status_t returnCode;
1125
1126 if ((config == NULL) || (dst == NULL))
1127 {
1128 return kStatus_FLASH_InvalidArgument;
1129 }
1130
1131 flash_cache_clear_process(config, kFLASH_CacheClearProcessPre);
1132 /* clear error flags */
1133 FTMRx->FSTAT = FTMRx_FSTAT_ACCERR_MASK | FTMRx_FSTAT_FPVIOL_MASK;
1134
1135 /* Write index to specify the command code to be loaded */
1136 flash_set_command(0UL, 0UL, FTMRx_READ_ONCE);
1137 flash_set_command(1UL, index, index >> 8UL);
1138
1139 /* calling flash command sequence function to execute the command */
1140 returnCode = flash_command_sequence(config);
1141
1142 if (kStatus_FLASH_Success == returnCode)
1143 {
1144 fccobloValue = FTMRx->FCCOBLO;
1145 fccobhiValue = FTMRx->FCCOBHI;
1146 /* Read lengthInBytes words. */
1147 FTMRx->FCCOBIX = FTMRx_FCCOBIX_CCOBIX(2UL);
1148 *dst = (uint32_t)BYTES_JOIN_TO_WORD_1_1(fccobloValue, fccobhiValue);
1149 FTMRx->FCCOBIX = FTMRx_FCCOBIX_CCOBIX(3UL);
1150 *dst |= ((uint32_t)BYTES_JOIN_TO_WORD_1_1(fccobloValue, fccobhiValue)) << 16UL;
1151 #if FLASH_PROGRAM_ONCE_IS_8BYTES_UNIT_SUPPORT
1152 FTMRx->FCCOBIX = FTMRx_FCCOBIX_CCOBIX(4UL);
1153 *(dst + 1UL) = (uint32_t)BYTES_JOIN_TO_WORD_1_1(fccobloValue, fccobhiValue);
1154 FTMRx->FCCOBIX = FTMRx_FCCOBIX_CCOBIX(5UL);
1155 *(dst + 1UL) |= ((uint32_t)BYTES_JOIN_TO_WORD_1_1(fccobloValue, fccobhiValue)) << 16UL;
1156 #endif
1157 }
1158 flash_cache_clear(config);
1159
1160 return returnCode;
1161 }
1162
1163 /*!
1164 * brief Returns the security state via the pointer passed into the function.
1165 *
1166 * This function retrieves the current flash security status, including the
1167 * security enabling state and the backdoor key enabling state.
1168 *
1169 * param config A pointer to storage for the driver runtime state.
1170 * param state A pointer to the value returned for the current security status
1171 * code:
1172 *
1173 * retval #kStatus_FLASH_Success API was executed successfully.
1174 * retval #kStatus_FLASH_InvalidArgument An invalid argument is provided.
1175 */
FLASH_GetSecurityState(flash_config_t * config,flash_security_state_t * state)1176 status_t FLASH_GetSecurityState(flash_config_t *config, flash_security_state_t *state)
1177 {
1178 /* store data read from flash register */
1179 uint8_t registerValue;
1180
1181 if ((config == NULL) || (state == NULL))
1182 {
1183 return kStatus_FLASH_InvalidArgument;
1184 }
1185
1186 /* Get flash security register value */
1187 registerValue = FTMRx->FSEC;
1188
1189 /* check the status of the flash security bits in the security register */
1190 if (FLASH_SECURITY_STATE_UNSECURED == (registerValue & FTMRx_FSEC_SEC_MASK))
1191 {
1192 /* Flash in unsecured state */
1193 *state = kFLASH_SecurityStateNotSecure;
1194 }
1195 else
1196 {
1197 /* Flash in secured state
1198 * check for backdoor key security enable bit */
1199 if (FLASH_SECURITY_STATE_KEYEN == (registerValue & FTMRx_FSEC_KEYEN_MASK))
1200 {
1201 /* Backdoor key security enabled */
1202 *state = kFLASH_SecurityStateBackdoorEnabled;
1203 }
1204 else
1205 {
1206 /* Backdoor key security disabled */
1207 *state = kFLASH_SecurityStateBackdoorDisabled;
1208 }
1209 }
1210
1211 return (kStatus_FLASH_Success);
1212 }
1213
1214 /*!
1215 * brief Allows users to bypass security with a backdoor key.
1216 *
1217 * If the MCU is in secured state, this function unsecures the MCU by
1218 * comparing the provided backdoor key with ones in the flash configuration
1219 * field.
1220 *
1221 * param config A pointer to the storage for the driver runtime state.
1222 * param backdoorKey A pointer to the user buffer containing the backdoor key.
1223 *
1224 * retval #kStatus_FLASH_Success API was executed successfully.
1225 * retval #kStatus_FLASH_InvalidArgument An invalid argument is provided.
1226 * retval #kStatus_FLASH_ExecuteInRamFunctionNotReady Execute-in-RAM function is
1227 * not available.
1228 * retval #kStatus_FLASH_AccessError Invalid instruction codes and out-of bounds
1229 * addresses.
1230 * retval #kStatus_FLASH_ProtectionViolation The program/erase operation is
1231 * requested to execute on protected areas.
1232 * retval #kStatus_FLASH_CommandFailure Run-time error during the command
1233 * execution.
1234 */
FLASH_SecurityBypass(flash_config_t * config,const uint8_t * backdoorKey)1235 status_t FLASH_SecurityBypass(flash_config_t *config, const uint8_t *backdoorKey)
1236 {
1237 uint8_t registerValue; /* registerValue */
1238 status_t returnCode; /* return code variable */
1239 uint8_t tmpKey;
1240 uint32_t i;
1241
1242 if ((config == NULL) || (backdoorKey == NULL))
1243 {
1244 return kStatus_FLASH_InvalidArgument;
1245 }
1246
1247 /* set the default return code as kStatus_Success */
1248 returnCode = kStatus_FLASH_Success;
1249
1250 /* Get flash security register value */
1251 registerValue = FTMRx->FSEC;
1252
1253 /* Check to see if flash is in secure state (any state other than 0x2)
1254 * If not, then skip this since flash is not secure */
1255 if (0x02UL != (registerValue & 0x03UL))
1256 {
1257 /* clear error flags */
1258 FTMRx->FSTAT = FTMRx_FSTAT_ACCERR_MASK | FTMRx_FSTAT_FPVIOL_MASK;
1259 /* preparing passing parameter to erase a flash block */
1260 /* Write index to specify the command code to be loaded */
1261 flash_set_command(0UL, 0UL, FTMRx_SECURITY_BY_PASS);
1262
1263 for (i = 0UL; i < 4UL; i++)
1264 {
1265 tmpKey = *backdoorKey++;
1266 flash_set_command(i + 1UL, tmpKey, *backdoorKey++);
1267 }
1268
1269 /* calling flash command sequence function to execute the command */
1270 returnCode = flash_command_sequence(config);
1271 }
1272
1273 return (returnCode);
1274 }
1275
1276 /*!
1277 * brief Verifies erasure of the entire flash at a specified margin level.
1278 *
1279 * This function checks whether the flash is erased to the
1280 * specified read margin level.
1281 *
1282 * param config A pointer to the storage for the driver runtime state.
1283 * param margin Read margin choice.
1284 *
1285 * retval #kStatus_FLASH_Success API was executed successfully.
1286 * retval #kStatus_FLASH_InvalidArgument An invalid argument is provided.
1287 * retval #kStatus_FLASH_ExecuteInRamFunctionNotReady Execute-in-RAM function is
1288 * not available.
1289 * retval #kStatus_FLASH_AccessError Invalid instruction codes and out-of bounds
1290 * addresses.
1291 * retval #kStatus_FLASH_ProtectionViolation The program/erase operation is
1292 * requested to execute on protected areas.
1293 * retval #kStatus_FLASH_CommandFailure Run-time error during the command
1294 * execution.
1295 * retval #kStatus_FLASH_EepromSingleBitFault EEPROM single bit fault error
1296 * code.
1297 * retval #kStatus_FLASH_EepromDoubleBitFault EEPROM double bit fault error
1298 * code.
1299 */
FLASH_VerifyEraseAll(flash_config_t * config,flash_margin_value_t margin)1300 status_t FLASH_VerifyEraseAll(flash_config_t *config, flash_margin_value_t margin)
1301 {
1302 status_t returnCode;
1303 if (config == NULL)
1304 {
1305 return kStatus_FLASH_InvalidArgument;
1306 }
1307 /* set the default return code as kStatus_Success */
1308 returnCode = kStatus_FLASH_Success;
1309
1310 if ((uint32_t)margin != config->PFlashMarginLevel)
1311 {
1312 switch (margin)
1313 {
1314 case kFLASH_MarginValueUser:
1315 returnCode = flash_setusermarginlevel(config, config->PFlashBlockBase, 0U, kFLASH_UserMarginValue1);
1316 break;
1317 case kFLASH_MarginValueFactory:
1318 returnCode =
1319 flash_setfactorymarginlevel(config, config->PFlashBlockBase, 0U, kFLASH_FactoryMarginValue1);
1320 break;
1321 case kFLASH_MarginValueNormal:
1322 returnCode =
1323 flash_setusermarginlevel(config, config->PFlashBlockBase, 0U, kFLASH_ReadMarginValueNormal);
1324 break;
1325 default:
1326 returnCode = kStatus_FLASH_InvalidArgument;
1327 break;
1328 }
1329 config->PFlashMarginLevel = (uint32_t)margin;
1330 }
1331 if (returnCode != kStatus_FLASH_Success)
1332 {
1333 return returnCode;
1334 }
1335 #if FLASH_SSD_IS_EEPROM_ENABLED
1336 if ((uint32_t)margin != config->PFlashMarginLevel)
1337 {
1338 switch (margin)
1339 {
1340 case kFLASH_MarginValueUser:
1341 returnCode = flash_setusermarginlevel(config, config->EEpromBlockBase, 1U, kFLASH_UserMarginValue1);
1342 break;
1343 case kFLASH_MarginValueFactory:
1344 returnCode =
1345 flash_setfactorymarginlevel(config, config->EEpromBlockBase, 1U, kFLASH_FactoryMarginValue1);
1346 break;
1347 case kFLASH_MarginValueNormal:
1348 returnCode =
1349 flash_setusermarginlevel(config, config->EEpromBlockBase, 1U, kFLASH_ReadMarginValueNormal);
1350 break;
1351 default:
1352 returnCode = kStatus_FLASH_InvalidArgument;
1353 break;
1354 }
1355 config->PFlashMarginLevel = (uint32_t)margin;
1356 }
1357 if (returnCode != kStatus_FLASH_Success)
1358 {
1359 return returnCode;
1360 }
1361 #endif
1362
1363 /* clear error flags */
1364 FTMRx->FSTAT = FTMRx_FSTAT_ACCERR_MASK | FTMRx_FSTAT_FPVIOL_MASK;
1365
1366 /* Erase verify all flash & EEPROM blocks */
1367 flash_set_command(0UL, 0UL, FTMRx_ERASE_VERIFY_ALL_BLOCK);
1368
1369 returnCode = flash_command_sequence(config);
1370
1371 return returnCode;
1372 }
1373
1374 /*!
1375 * brief Verifies an erasure of the desired flash area at a specified margin
1376 * level.
1377 *
1378 * This function checks the appropriate number of flash sectors based on
1379 * the desired start address and length to check whether the flash is erased
1380 * to the specified read margin level.
1381 *
1382 * param config A pointer to the storage for the driver runtime state.
1383 * param margin Read margin choice.
1384 * param start The start address of the desired flash memory to be verified.
1385 * The start address does not need to be sector-aligned but must be
1386 * word-aligned.
1387 * param lengthInBytes The length, given in bytes (not words or long-words),
1388 * to be verified. Must be word-aligned.
1389 *
1390 * retval #kStatus_FLASH_Success API was executed successfully.
1391 * retval #kStatus_FLASH_InvalidArgument An invalid argument is provided.
1392 * retval #kStatus_FLASH_AlignmentError Parameter is not aligned with specified
1393 * baseline.
1394 * retval #kStatus_FLASH_AddressError Address is out of range.
1395 * retval #kStatus_FLASH_ExecuteInRamFunctionNotReady Execute-in-RAM function is
1396 * not available.
1397 * retval #kStatus_FLASH_AccessError Invalid instruction codes and out-of bounds
1398 * addresses.
1399 * retval #kStatus_FLASH_ProtectionViolation The program/erase operation is
1400 * requested to execute on protected areas.
1401 * retval #kStatus_FLASH_CommandFailure Run-time error during the command
1402 * execution.
1403 */
FLASH_VerifyErase(flash_config_t * config,uint32_t start,uint32_t lengthInBytes,flash_margin_value_t margin)1404 status_t FLASH_VerifyErase(flash_config_t *config, uint32_t start, uint32_t lengthInBytes, flash_margin_value_t margin)
1405 {
1406 uint32_t blockSize;
1407 flash_operation_config_t flashOperationInfo;
1408 uint32_t nextBlockStartAddress;
1409 uint32_t remainingBytes;
1410 status_t returnCode;
1411
1412 returnCode = flash_get_matched_operation_info(config, start, &flashOperationInfo);
1413 if (kStatus_FLASH_Success != returnCode)
1414 {
1415 return returnCode;
1416 }
1417
1418 returnCode = flash_check_range(config, start, lengthInBytes, flashOperationInfo.sectionCmdAddressAligment);
1419 if (kStatus_FLASH_Success != returnCode)
1420 {
1421 return returnCode;
1422 }
1423
1424 returnCode = flash_get_matched_operation_info(config, start, &flashOperationInfo);
1425 if (kStatus_FLASH_Success != returnCode)
1426 {
1427 return returnCode;
1428 }
1429 start = flashOperationInfo.convertedAddress;
1430 blockSize = flashOperationInfo.activeBlockSize;
1431
1432 nextBlockStartAddress = ALIGN_UP(start, blockSize);
1433 if (nextBlockStartAddress == start)
1434 {
1435 nextBlockStartAddress += blockSize;
1436 }
1437
1438 remainingBytes = lengthInBytes;
1439
1440 while (remainingBytes != 0UL)
1441 {
1442 uint32_t numberOfPhrases;
1443 uint32_t verifyLength = nextBlockStartAddress - start;
1444 if (verifyLength > remainingBytes)
1445 {
1446 verifyLength = remainingBytes;
1447 }
1448 numberOfPhrases = verifyLength >> flashOperationInfo.sectionCmdAddressAligment;
1449 if ((uint32_t)margin != config->PFlashMarginLevel)
1450 {
1451 switch (margin)
1452 {
1453 case kFLASH_MarginValueUser:
1454 returnCode = flash_setusermarginlevel(config, start, 0U, kFLASH_UserMarginValue1);
1455 break;
1456 case kFLASH_MarginValueFactory:
1457 returnCode = flash_setfactorymarginlevel(config, start, 0U, kFLASH_FactoryMarginValue1);
1458 break;
1459 case kFLASH_MarginValueNormal:
1460 returnCode = flash_setusermarginlevel(config, start, 0U, kFLASH_ReadMarginValueNormal);
1461 break;
1462 default:
1463 returnCode = kStatus_FLASH_InvalidArgument;
1464 break;
1465 }
1466 config->PFlashMarginLevel = (uint32_t)margin;
1467 }
1468 if (kStatus_FLASH_Success != returnCode)
1469 {
1470 return returnCode;
1471 }
1472 flash_cache_clear_process(config, kFLASH_CacheClearProcessPre);
1473 /* clear error flags */
1474 FTMRx->FSTAT = FTMRx_FSTAT_ACCERR_MASK | FTMRx_FSTAT_FPVIOL_MASK;
1475
1476 /* Fill in verify FLASH section command parameters. */
1477 flash_set_command(0UL, start >> 16UL, FTMRx_ERASE_VERIFY_SECTION);
1478 flash_set_command(1UL, start, start >> 8UL);
1479 /* Write index to specify the # of longwords to be verified */
1480 flash_set_command(2UL, numberOfPhrases, numberOfPhrases >> 8UL);
1481
1482 /* calling flash command sequence function to execute the command */
1483 returnCode = flash_command_sequence(config);
1484 if (kStatus_FLASH_Success != returnCode)
1485 {
1486 return returnCode;
1487 }
1488
1489 remainingBytes -= verifyLength;
1490 start += verifyLength;
1491 nextBlockStartAddress += blockSize;
1492 }
1493
1494 return kStatus_FLASH_Success;
1495 }
1496
1497 /*!
1498 * brief Returns the protection state of the desired flash area via the pointer
1499 * passed into the function.
1500 *
1501 * This function retrieves the current flash protect status for a given
1502 * flash area as determined by the start address and length.
1503 *
1504 * param config A pointer to the storage for the driver runtime state.
1505 * param start The start address of the desired flash memory to be checked. Must
1506 * be word-aligned.
1507 * param lengthInBytes The length, given in bytes (not words or long-words)
1508 * to be checked. Must be word-aligned.
1509 * param protection_state A pointer to the value returned for the current
1510 * protection status code for the desired flash area.
1511 *
1512 * retval #kStatus_FLASH_Success API was executed successfully.
1513 * retval #kStatus_FLASH_InvalidArgument An invalid argument is provided.
1514 * retval #kStatus_FLASH_AlignmentError Parameter is not aligned with specified
1515 * baseline.
1516 * retval #kStatus_FLASH_AddressError The address is out of range.
1517 */
FLASH_IsProtected(flash_config_t * config,uint32_t start,uint32_t lengthInBytes,flash_protection_state_t * protection_state)1518 status_t FLASH_IsProtected(flash_config_t *config,
1519 uint32_t start,
1520 uint32_t lengthInBytes,
1521 flash_protection_state_t *protection_state)
1522 {
1523 flash_protection_config_t flashProtectionInfo; /* flash protection information */
1524 uint32_t endAddress; /* end address for protection check */
1525 status_t returnCode;
1526
1527 if ((protection_state == NULL) || (lengthInBytes == 0UL))
1528 {
1529 return kStatus_FLASH_InvalidArgument;
1530 }
1531
1532 /* Check the supplied address range. */
1533 returnCode = flash_check_range(config, start, lengthInBytes, FSL_FEATURE_FLASH_PFLASH_BLOCK_WRITE_UNIT_SIZE);
1534 if (returnCode != kStatus_FLASH_Success)
1535 {
1536 return returnCode;
1537 }
1538
1539 /* Get necessary flash protection information. */
1540 returnCode = flash_get_protection_info(config, &flashProtectionInfo);
1541 if (returnCode != kStatus_FLASH_Success)
1542 {
1543 return returnCode;
1544 }
1545
1546 /* calculating Flash end address */
1547 endAddress = start + lengthInBytes;
1548
1549 if (((start >= flashProtectionInfo.lowRegionStart) && (endAddress <= flashProtectionInfo.lowRegionEnd)) ||
1550 ((start >= flashProtectionInfo.highRegionStart) && (endAddress <= flashProtectionInfo.highRegionEnd)))
1551 {
1552 *protection_state = kFLASH_ProtectionStateProtected;
1553 }
1554 else if (((start >= flashProtectionInfo.lowRegionEnd) && (endAddress <= flashProtectionInfo.highRegionStart)) ||
1555 (start >= flashProtectionInfo.highRegionEnd) || (endAddress <= flashProtectionInfo.lowRegionStart))
1556 {
1557 *protection_state = kFLASH_ProtectionStateUnprotected;
1558 }
1559 else
1560 {
1561 *protection_state = kFLASH_ProtectionStateMixed;
1562 }
1563
1564 return kStatus_FLASH_Success;
1565 }
1566
1567 /*!
1568 * brief Returns the desired flash property.
1569 *
1570 * param config A pointer to the storage for the driver runtime state.
1571 * param whichProperty The desired property from the list of properties in
1572 * enum flash_property_tag_t
1573 * param value A pointer to the value returned for the desired flash property.
1574 *
1575 * retval #kStatus_FLASH_Success API was executed successfully.
1576 * retval #kStatus_FLASH_InvalidArgument An invalid argument is provided.
1577 * retval #kStatus_FLASH_UnknownProperty An unknown property tag.
1578 */
FLASH_GetProperty(flash_config_t * config,flash_property_tag_t whichProperty,uint32_t * value)1579 status_t FLASH_GetProperty(flash_config_t *config, flash_property_tag_t whichProperty, uint32_t *value)
1580 {
1581 status_t status = kStatus_FLASH_UnknownProperty;
1582 if ((config == NULL) || (value == NULL))
1583 {
1584 return kStatus_FLASH_InvalidArgument;
1585 }
1586
1587 switch (whichProperty)
1588 {
1589 case kFLASH_PropertyPflashSectorSize:
1590 *value = config->PFlashSectorSize;
1591 status = kStatus_FLASH_Success;
1592 break;
1593
1594 case kFLASH_PropertyPflashTotalSize:
1595 *value = config->PFlashTotalSize;
1596 status = kStatus_FLASH_Success;
1597 break;
1598
1599 case kFLASH_PropertyPflashBlockSize:
1600 *value = config->PFlashTotalSize / (uint32_t)config->PFlashBlockCount;
1601 status = kStatus_FLASH_Success;
1602 break;
1603
1604 case kFLASH_PropertyPflashBlockCount:
1605 *value = (uint32_t)config->PFlashBlockCount;
1606 status = kStatus_FLASH_Success;
1607 break;
1608
1609 case kFLASH_PropertyPflashBlockBaseAddr:
1610 *value = config->PFlashBlockBase;
1611 status = kStatus_FLASH_Success;
1612 break;
1613
1614 case kFLASH_PropertyPflashFacSupport:
1615 #if defined(FSL_FEATURE_FLASH_HAS_ACCESS_CONTROL)
1616 *value = FSL_FEATURE_FLASH_HAS_ACCESS_CONTROL;
1617 #else
1618 *value = 0UL;
1619 #endif /* FSL_FEATURE_FLASH_HAS_ACCESS_CONTROL */
1620 status = kStatus_FLASH_Success;
1621 break;
1622
1623 case kFLASH_PropertyFlashClockFrequency:
1624 *value = config->PFlashClockFreq;
1625 status = kStatus_FLASH_Success;
1626 break;
1627
1628 #if FLASH_SSD_IS_EEPROM_ENABLED
1629 case kFLASH_PropertyEepromBlockBaseAddr:
1630 *value = config->EEpromBlockBase;
1631 status = kStatus_FLASH_Success;
1632 break;
1633
1634 case kFLASH_PropertyEepromTotalSize:
1635 *value = config->EEpromTotalSize;
1636 status = kStatus_FLASH_Success;
1637 break;
1638
1639 case kFLASH_PropertyEepromSectorSize:
1640 *value = (uint32_t)config->EEpromSectorSize;
1641 status = kStatus_FLASH_Success;
1642 break;
1643
1644 case kFLASH_PropertyEepromBlockSize:
1645 *value = config->EEpromTotalSize / (uint32_t)config->EEpromBlockCount;
1646 status = kStatus_FLASH_Success;
1647 break;
1648
1649 case kFLASH_PropertyEepromBlockCount:
1650 *value = (uint32_t)config->EEpromBlockCount;
1651 status = kStatus_FLASH_Success;
1652 break;
1653 #endif /* FLASH_SSD_IS_EEPROM_ENABLED */
1654
1655 default: /* catch inputs that are not recognized */
1656 status = kStatus_FLASH_UnknownProperty;
1657 break;
1658 }
1659
1660 return status;
1661 }
1662
1663 /*!
1664 * brief Sets the desired flash property.
1665 *
1666 * param config A pointer to the storage for the driver runtime state.
1667 * param whichProperty The desired property from the list of properties in
1668 * enum flash_property_tag_t
1669 * param value A to set for the desired flash property.
1670 *
1671 * retval #kStatus_FLASH_Success API was executed successfully.
1672 * retval #kStatus_FLASH_InvalidArgument An invalid argument is provided.
1673 * retval #kStatus_FLASH_UnknownProperty An unknown property tag.
1674 * retval #kStatus_FLASH_InvalidPropertyValue An invalid property value.
1675 * retval #kStatus_FLASH_ReadOnlyProperty An read-only property tag.
1676 */
FLASH_SetProperty(flash_config_t * config,flash_property_tag_t whichProperty,uint32_t value)1677 status_t FLASH_SetProperty(flash_config_t *config, flash_property_tag_t whichProperty, uint32_t value)
1678 {
1679 status_t status = kStatus_FLASH_Success;
1680
1681 if (config == NULL)
1682 {
1683 return kStatus_FLASH_InvalidArgument;
1684 }
1685
1686 switch (whichProperty)
1687 {
1688 #if FLASH_SSD_IS_SECONDARY_FLASH_ENABLED
1689 case kFLASH_PropertyFlashMemoryIndex:
1690 if ((value != (uint32_t)kFLASH_MemoryIndexPrimaryFlash) &&
1691 (value != (uint32_t)kFLASH_MemoryIndexSecondaryFlash))
1692 {
1693 return kStatus_FLASH_InvalidPropertyValue;
1694 }
1695 config->FlashMemoryIndex = (uint8_t)value;
1696 break;
1697 #endif /* FLASH_SSD_IS_SECONDARY_FLASH_ENABLED */
1698
1699 case kFLASH_PropertyFlashCacheControllerIndex:
1700 if ((value != (uint32_t)kFLASH_CacheControllerIndexForCore0) &&
1701 (value != (uint32_t)kFLASH_CacheControllerIndexForCore1))
1702 {
1703 return kStatus_FLASH_InvalidPropertyValue;
1704 }
1705 config->FlashCacheControllerIndex = (uint8_t)value;
1706 break;
1707 case kFLASH_PropertyFlashClockFrequency:
1708 config->PFlashClockFreq = value;
1709 break;
1710 case kFLASH_PropertyPflashSectorSize:
1711 case kFLASH_PropertyPflashTotalSize:
1712 case kFLASH_PropertyPflashBlockSize:
1713 case kFLASH_PropertyPflashBlockCount:
1714 case kFLASH_PropertyPflashBlockBaseAddr:
1715 case kFLASH_PropertyPflashFacSupport:
1716 #if FLASH_SSD_IS_EEPROM_ENABLED
1717 case kFLASH_PropertyEepromBlockBaseAddr:
1718 case kFLASH_PropertyEepromTotalSize:
1719 case kFLASH_PropertyEepromSectorSize:
1720 case kFLASH_PropertyEepromBlockSize:
1721 case kFLASH_PropertyEepromBlockCount:
1722 #endif /* FLASH_SSD_IS_EEPROM_ENABLED */
1723 status = kStatus_FLASH_ReadOnlyProperty;
1724 break;
1725 default: /* catch inputs that are not recognized */
1726 status = kStatus_FLASH_UnknownProperty;
1727 break;
1728 }
1729
1730 return status;
1731 }
1732
1733 /*!
1734 * brief Sets the PFlash Protection to the intended protection status.
1735 *
1736 * param config A pointer to storage for the driver runtime state.
1737 * param protectStatus The expected protect status to set to the PFlash
1738 * protection register.
1739 *
1740 * retval #kStatus_FLASH_Success API was executed successfully.
1741 * retval #kStatus_FLASH_InvalidArgument An invalid argument is provided.
1742 * retval #kStatus_FLASH_CommandFailure Run-time error during command execution.
1743 */
FLASH_PflashSetProtection(flash_config_t * config,pflash_protection_status_t * protectStatus)1744 status_t FLASH_PflashSetProtection(flash_config_t *config, pflash_protection_status_t *protectStatus)
1745 {
1746 if (config == NULL)
1747 {
1748 return kStatus_FLASH_InvalidArgument;
1749 }
1750 /* The reserved bit6 value of FPROT is reset value, which cannot change.
1751 * If flash memory is only 8KB, the bit3 to bit5 of FPROT are also reserved.*/
1752 FTMRx->FPROT = protectStatus->fprotvalue;
1753 if (protectStatus->fprotvalue != FTMRx->FPROT)
1754 {
1755 return kStatus_FLASH_CommandFailure;
1756 }
1757
1758 return kStatus_FLASH_Success;
1759 }
1760
1761 /*!
1762 * brief Gets the PFlash protection status.
1763 *
1764 * param config A pointer to the storage for the driver runtime state.
1765 * param protectStatus Protect status returned by the PFlash IP.
1766 *
1767 * retval #kStatus_FLASH_Success API was executed successfully.
1768 * retval #kStatus_FLASH_InvalidArgument An invalid argument is provided.
1769 */
FLASH_PflashGetProtection(flash_config_t * config,pflash_protection_status_t * protectStatus)1770 status_t FLASH_PflashGetProtection(flash_config_t *config, pflash_protection_status_t *protectStatus)
1771 {
1772 if ((config == NULL) || (protectStatus == NULL))
1773 {
1774 return kStatus_FLASH_InvalidArgument;
1775 }
1776
1777 protectStatus->fprotvalue = FTMRx->FPROT;
1778
1779 return kStatus_FLASH_Success;
1780 }
1781
1782 #if defined(FLASH_SSD_IS_EEPROM_ENABLED) && FLASH_SSD_IS_EEPROM_ENABLED
FLASH_EepromSetProtection(flash_config_t * config,uint8_t protectStatus)1783 status_t FLASH_EepromSetProtection(flash_config_t *config, uint8_t protectStatus)
1784 {
1785 if (config == NULL)
1786 {
1787 return kStatus_FLASH_InvalidArgument;
1788 }
1789
1790 if ((config->EEpromTotalSize == 0UL) || (config->EEpromTotalSize == NVM_EEPROM_SIZE_FOR_EEESIZE_RESERVED))
1791 {
1792 return kStatus_FLASH_CommandNotSupported;
1793 }
1794
1795 FTMRx->EEPROT = protectStatus;
1796
1797 if (FTMRx->EEPROT != protectStatus)
1798 {
1799 return kStatus_FLASH_CommandFailure;
1800 }
1801
1802 return kStatus_FLASH_Success;
1803 }
1804 #endif /* FLASH_SSD_IS_EEPROM_ENABLED */
1805
1806 #if defined(FLASH_SSD_IS_EEPROM_ENABLED) && FLASH_SSD_IS_EEPROM_ENABLED
FLASH_EepromGetProtection(flash_config_t * config,uint8_t * protectStatus)1807 status_t FLASH_EepromGetProtection(flash_config_t *config, uint8_t *protectStatus)
1808 {
1809 if ((config == NULL) || (protectStatus == NULL))
1810 {
1811 return kStatus_FLASH_InvalidArgument;
1812 }
1813
1814 if ((config->EEpromTotalSize == 0UL) || (config->EEpromTotalSize == NVM_EEPROM_SIZE_FOR_EEESIZE_RESERVED))
1815 {
1816 return kStatus_FLASH_CommandNotSupported;
1817 }
1818
1819 *protectStatus = FTMRx->EEPROT;
1820
1821 return kStatus_FLASH_Success;
1822 }
1823 #endif /* FLASH_SSD_IS_EEPROM_ENABLED */
1824
1825 /*!
1826 * brief Sets the PFlash prefetch speculation to the intended speculation
1827 * status.
1828 *
1829 * param speculationStatus The expected protect status to set to the PFlash
1830 * protection register. Each bit is
1831 * retval #kStatus_FLASH_Success API was executed successfully.
1832 * retval #kStatus_FLASH_InvalidSpeculationOption An invalid speculation option
1833 * argument is provided.
1834 */
FLASH_PflashSetPrefetchSpeculation(flash_prefetch_speculation_status_t * speculationStatus)1835 status_t FLASH_PflashSetPrefetchSpeculation(flash_prefetch_speculation_status_t *speculationStatus)
1836 {
1837 #if FLASH_PREFETCH_SPECULATION_IS_CONTROLLED_BY_MCM
1838 {
1839 FTMRx_REG32_ACCESS_TYPE regBase;
1840 #if defined(MCM)
1841 regBase = (FTMRx_REG32_ACCESS_TYPE)&MCM->PLACR;
1842 #elif defined(MCM0)
1843 regBase = (FTMRx_REG32_ACCESS_TYPE)&MCM0->PLACR;
1844 #endif
1845 if (speculationStatus->instructionOption == kFLASH_prefetchSpeculationOptionDisable)
1846 {
1847 if (speculationStatus->dataOption == kFLASH_prefetchSpeculationOptionEnable)
1848 {
1849 return kStatus_FLASH_InvalidSpeculationOption;
1850 }
1851 else
1852 {
1853 *regBase |= MCM_PLACR_DFCS_MASK;
1854 }
1855 }
1856 else
1857 {
1858 *regBase &= ~MCM_PLACR_DFCS_MASK;
1859 if (speculationStatus->dataOption == kFLASH_prefetchSpeculationOptionEnable)
1860 {
1861 *regBase |= MCM_PLACR_EFDS_MASK;
1862 }
1863 else
1864 {
1865 *regBase &= ~MCM_PLACR_EFDS_MASK;
1866 }
1867 }
1868 }
1869 #elif FLASH_PREFETCH_SPECULATION_IS_CONTROLLED_BY_FMC
1870 {
1871 FTMRx_REG32_ACCESS_TYPE regBase;
1872 uint32_t b0dpeMask, b0ipeMask;
1873 #if defined(FMC_PFB01CR_B0DPE_MASK)
1874 regBase = (FTMRx_REG32_ACCESS_TYPE)&FMC->PFB01CR;
1875 b0dpeMask = FMC_PFB01CR_B0DPE_MASK;
1876 b0ipeMask = FMC_PFB01CR_B0IPE_MASK;
1877 #elif defined(FMC_PFB0CR_B0DPE_MASK)
1878 regBase = (FTMRx_REG32_ACCESS_TYPE)&FMC->PFB0CR;
1879 b0dpeMask = FMC_PFB0CR_B0DPE_MASK;
1880 b0ipeMask = FMC_PFB0CR_B0IPE_MASK;
1881 #endif
1882 if (speculationStatus->instructionOption == kFLASH_prefetchSpeculationOptionEnable)
1883 {
1884 *regBase |= b0ipeMask;
1885 }
1886 else
1887 {
1888 *regBase &= ~b0ipeMask;
1889 }
1890 if (speculationStatus->dataOption == kFLASH_prefetchSpeculationOptionEnable)
1891 {
1892 *regBase |= b0dpeMask;
1893 }
1894 else
1895 {
1896 *regBase &= ~b0dpeMask;
1897 }
1898
1899 /* Invalidate Prefetch Speculation Buffer */
1900 #if defined(FMC_PFB01CR_S_INV_MASK)
1901 FMC->PFB01CR |= FMC_PFB01CR_S_INV_MASK;
1902 #elif defined(FMC_PFB01CR_S_B_INV_MASK)
1903 FMC->PFB01CR |= FMC_PFB01CR_S_B_INV_MASK;
1904 #elif defined(FMC_PFB0CR_S_INV_MASK)
1905 FMC->PFB0CR |= FMC_PFB0CR_S_INV_MASK;
1906 #elif defined(FMC_PFB0CR_S_B_INV_MASK)
1907 FMC->PFB0CR |= FMC_PFB0CR_S_B_INV_MASK;
1908 #endif
1909 }
1910 #endif /* FSL_FEATURE_FTMRx_MCM_FLASH_CACHE_CONTROLS */
1911
1912 return kStatus_FLASH_Success;
1913 }
1914
1915 /*!
1916 * brief Gets the PFlash prefetch speculation status.
1917 *
1918 * param speculationStatus Speculation status returned by the PFlash IP.
1919 * retval #kStatus_FLASH_Success API was executed successfully.
1920 */
FLASH_PflashGetPrefetchSpeculation(flash_prefetch_speculation_status_t * speculationStatus)1921 status_t FLASH_PflashGetPrefetchSpeculation(flash_prefetch_speculation_status_t *speculationStatus)
1922 {
1923 (void)memset(speculationStatus, 0, sizeof(flash_prefetch_speculation_status_t));
1924
1925 /* Assuming that all speculation options are enabled. */
1926 speculationStatus->instructionOption = kFLASH_prefetchSpeculationOptionEnable;
1927 speculationStatus->dataOption = kFLASH_prefetchSpeculationOptionEnable;
1928
1929 #if FLASH_PREFETCH_SPECULATION_IS_CONTROLLED_BY_MCM
1930 {
1931 uint32_t value;
1932 #if defined(MCM)
1933 value = MCM->PLACR;
1934 #elif defined(MCM0)
1935 value = MCM0->PLACR;
1936 #endif
1937 if (0UL != (value & MCM_PLACR_DFCS_MASK))
1938 {
1939 /* Speculation buffer is off. */
1940 speculationStatus->instructionOption = kFLASH_prefetchSpeculationOptionDisable;
1941 speculationStatus->dataOption = kFLASH_prefetchSpeculationOptionDisable;
1942 }
1943 else
1944 {
1945 /* Speculation buffer is on for instruction. */
1946 if (0UL == (value & MCM_PLACR_EFDS_MASK))
1947 {
1948 /* Speculation buffer is off for data. */
1949 speculationStatus->dataOption = kFLASH_prefetchSpeculationOptionDisable;
1950 }
1951 }
1952 }
1953 #elif FLASH_PREFETCH_SPECULATION_IS_CONTROLLED_BY_FMC
1954 {
1955 uint32_t value;
1956 uint32_t b0dpeMask, b0ipeMask;
1957 #if defined(FMC_PFB01CR_B0DPE_MASK)
1958 value = FMC->PFB01CR;
1959 b0dpeMask = FMC_PFB01CR_B0DPE_MASK;
1960 b0ipeMask = FMC_PFB01CR_B0IPE_MASK;
1961 #elif defined(FMC_PFB0CR_B0DPE_MASK)
1962 value = FMC->PFB0CR;
1963 b0dpeMask = FMC_PFB0CR_B0DPE_MASK;
1964 b0ipeMask = FMC_PFB0CR_B0IPE_MASK;
1965 #endif
1966 if (0UL == (value & b0dpeMask))
1967 {
1968 /* Do not prefetch in response to data references. */
1969 speculationStatus->dataOption = kFLASH_prefetchSpeculationOptionDisable;
1970 }
1971 if (0UL == (value & b0ipeMask))
1972 {
1973 /* Do not prefetch in response to instruction fetches. */
1974 speculationStatus->instructionOption = kFLASH_prefetchSpeculationOptionDisable;
1975 }
1976 }
1977 #endif
1978
1979 return kStatus_FLASH_Success;
1980 }
1981
1982 #if FLASH_DRIVER_IS_FLASH_RESIDENT
1983 /*!
1984 * @brief Copy PIC of flash_run_command() to RAM
1985 */
copy_flash_run_command(flash_config_t * config)1986 static void copy_flash_run_command(flash_config_t *config)
1987 {
1988 assert(sizeof(s_flashRunCommandFunctionCode) <= ((uint32_t)kFLASH_ExecuteInRamFunctionMaxSizeInWords * 4U));
1989
1990 uint32_t flashRunCommand = config->executeInRamFunction.runCmdFuncAddr.commadAddr;
1991
1992 /* copy required flash command to RAM */
1993 (void)memcpy((uint8_t *)flashRunCommand, (const uint8_t *)s_flashRunCommandFunctionCode,
1994 sizeof(s_flashRunCommandFunctionCode));
1995 }
1996 #endif /* FLASH_DRIVER_IS_FLASH_RESIDENT */
1997
1998 /*!
1999 * @brief Flash Set Command
2000 *
2001 * This function is used to write the command sequence to the flash reg.
2002 */
flash_set_command(uint32_t index,uint32_t fValue,uint32_t sValue)2003 void flash_set_command(uint32_t index, uint32_t fValue, uint32_t sValue)
2004 {
2005 FTMRx->FCCOBIX = FTMRx_FCCOBIX_CCOBIX(index);
2006 FTMRx->FCCOBLO = FTMRx_FCCOBLO_CCOB(fValue);
2007 FTMRx->FCCOBHI = FTMRx_FCCOBHI_CCOB(sValue);
2008 }
2009
2010 /*!
2011 * @brief Flash Command Sequence
2012 *
2013 * This function is used to perform the command write sequence to the flash.
2014 *
2015 * @param driver Pointer to storage for the driver runtime state.
2016 * @return An error code or kStatus_FLASH_Success
2017 */
flash_command_sequence(flash_config_t * config)2018 static status_t flash_command_sequence(flash_config_t *config)
2019 {
2020 uint8_t registerValue;
2021
2022 #if FLASH_DRIVER_IS_FLASH_RESIDENT
2023 /* clear ACCERR & FPVIOL flag in flash status register */
2024 FTMRx->FSTAT = FTMRx_FSTAT_ACCERR_MASK | FTMRx_FSTAT_FPVIOL_MASK;
2025
2026 status_t returnCode = flash_check_execute_in_ram_function_info(config);
2027 if (kStatus_FLASH_Success != returnCode)
2028 {
2029 return returnCode;
2030 }
2031
2032 /* Since the value of ARM function pointer is always odd, but the real start address
2033 * of function memory should be even, that's why +1 operation exist. */
2034 config->executeInRamFunction.runCmdFuncAddr.commadAddr += 1UL;
2035 callFlashRunCommand = config->executeInRamFunction.runCmdFuncAddr.callFlashCommand;
2036
2037 /* We pass the FTMRx_fstat address as a parameter to flash_run_comamnd()
2038 * instead of using
2039 * pre-processed MICRO sentences or operating global variable in
2040 * flash_run_comamnd()
2041 * to make sure that flash_run_command() will be compiled into
2042 * position-independent code (PIC). */
2043 callFlashRunCommand((FTMRx_REG8_ACCESS_TYPE)(&FTMRx->FSTAT));
2044 config->executeInRamFunction.runCmdFuncAddr.commadAddr -= 1UL;
2045 #else
2046 #if FLASH_ENABLE_STALLING_FLASH_CONTROLLER
2047 MCM->PLACR |= MCM_PLACR_ESFC_MASK; /* enable stalling flash controller when
2048 flash is busy */
2049 #endif
2050 /* clear ACCERR & FPVIOL flag in flash status register */
2051 FTMRx->FSTAT = FTMRx_FSTAT_ACCERR_MASK | FTMRx_FSTAT_FPVIOL_MASK;
2052 /* clear CCIF bit */
2053 FTMRx->FSTAT = FTMRx_FSTAT_CCIF_MASK;
2054 /* Check CCIF bit of the flash status register, wait till it is set.
2055 * IP team indicates that this loop will always complete. */
2056 while (!(FTMRx->FSTAT & FTMRx_FSTAT_CCIF_MASK))
2057 ;
2058 {
2059 }
2060 #endif /* FLASH_DRIVER_IS_FLASH_RESIDENT */
2061 /* Check error bits */
2062 /* Get flash status register value */
2063 registerValue = FTMRx->FSTAT;
2064 /* checking access error */
2065 if (0U != (registerValue & FTMRx_FSTAT_ACCERR_MASK))
2066 {
2067 return kStatus_FLASH_AccessError;
2068 }
2069 /* checking protection error */
2070 if (0U != (registerValue & FTMRx_FSTAT_FPVIOL_MASK))
2071 {
2072 return kStatus_FLASH_ProtectionViolation;
2073 }
2074 /* checking MGSTAT non-correctable error */
2075 if (0U != (registerValue & FTMRx_FSTAT_MGSTAT_MASK))
2076 {
2077 return kStatus_FLASH_CommandFailure;
2078 }
2079
2080 #if FLASH_SSD_IS_EEPROM_ENABLED
2081 registerValue = FTMRx->FERSTAT;
2082
2083 if (0U != (registerValue & (FTMRx_FERSTAT_SFDIF_MASK)))
2084 {
2085 return kStatus_FLASH_EepromDoubleBitFault;
2086 }
2087 if (0U != (registerValue & (FTMRx_FERSTAT_DFDIF_MASK)))
2088 {
2089 return kStatus_FLASH_EepromSingleBitFault;
2090 }
2091 #endif
2092 return kStatus_FLASH_Success;
2093 }
2094
2095 /*!
2096 * @brief Flash common bit operation sequence Command Sequence
2097 */
2098 #if FLASH_DRIVER_IS_FLASH_RESIDENT
flash_common_bit_operation_command_sequence(flash_config_t * config,FTMRx_REG32_ACCESS_TYPE base,uint32_t bitMask,uint32_t bitShift,uint32_t bitValue)2099 static void flash_common_bit_operation_command_sequence(
2100 flash_config_t *config, FTMRx_REG32_ACCESS_TYPE base, uint32_t bitMask, uint32_t bitShift, uint32_t bitValue)
2101 {
2102 uint32_t *flashCommonBitOperationAddr;
2103 flashCommonBitOperationAddr = &config->executeInRamFunction.CommonBitOperationAddr.bitOperationAddr;
2104 /* Since the value of ARM function pointer is always odd, but the real start
2105 * address
2106 * of function memory should be even, that's why +1 operation exist. */
2107 *flashCommonBitOperationAddr += 1UL;
2108 callFlashCommonBitOperation = config->executeInRamFunction.CommonBitOperationAddr.callCommonBitOperationCommand;
2109 /* Workround for some devices which doesn't need this function */
2110 callFlashCommonBitOperation((FTMRx_REG32_ACCESS_TYPE)base, bitMask, bitShift, bitValue);
2111 *flashCommonBitOperationAddr -= 1UL;
2112 }
2113 #endif /*FLASH_DRIVER_IS_FLASH_RESIDENT*/
2114
2115 #if FLASH_DRIVER_IS_FLASH_RESIDENT
2116 /*!
2117 * @brief Copy PIC of flash_common_bit_operation() to RAM
2118 *
2119 */
copy_flash_common_bit_operation(flash_config_t * config)2120 static void copy_flash_common_bit_operation(flash_config_t *config)
2121 {
2122 assert(sizeof(s_flashCommonBitOperationFunctionCode) <=
2123 ((uint32_t)kFLASH_ExecuteInRamFunctionMaxSizeInWords * 4UL));
2124
2125 uint32_t *flashCommonBitOperationAddr;
2126 flashCommonBitOperationAddr = &config->executeInRamFunction.CommonBitOperationAddr.bitOperationAddr;
2127 /* Since the value of ARM function pointer is always odd, but the real start
2128 * address
2129 * of function memory should be even, that's why +1 operation exist. */
2130 (void)memcpy((uint8_t *)(*flashCommonBitOperationAddr), (const uint8_t *)s_flashCommonBitOperationFunctionCode,
2131 sizeof(s_flashCommonBitOperationFunctionCode));
2132 }
2133 #endif /* FLASH_DRIVER_IS_FLASH_RESIDENT */
2134
2135 #if FLASH_CACHE_IS_CONTROLLED_BY_MCM
2136 /*! @brief Performs the cache clear to the flash by MCM.*/
mcm_flash_cache_clear(flash_config_t * config)2137 void mcm_flash_cache_clear(flash_config_t *config)
2138 {
2139 FTMRx_REG32_ACCESS_TYPE regBase = (FTMRx_REG32_ACCESS_TYPE)&MCM0_CACHE_REG;
2140
2141 #if defined(MCM0) && defined(MCM1)
2142 if (config->FlashCacheControllerIndex == (uint8_t)kFLASH_CacheControllerIndexForCore1)
2143 {
2144 regBase = (FTMRx_REG32_ACCESS_TYPE)&MCM1_CACHE_REG;
2145 }
2146 #endif
2147
2148 #if FLASH_DRIVER_IS_FLASH_RESIDENT
2149 flash_common_bit_operation_command_sequence(config, regBase, MCM_CACHE_CLEAR_MASK, MCM_CACHE_CLEAR_SHIFT, 1U);
2150 #else /* !FLASH_DRIVER_IS_FLASH_RESIDENT */
2151 *regBase |= MCM_CACHE_CLEAR_MASK;
2152
2153 /* Memory barriers for good measure.
2154 * All Cache, Branch predictor and TLB maintenance operations before this
2155 * instruction complete */
2156 __ISB();
2157 __DSB();
2158 #endif /* FLASH_DRIVER_IS_FLASH_RESIDENT */
2159 }
2160 #endif /* FLASH_CACHE_IS_CONTROLLED_BY_MCM */
2161
2162 #if FLASH_CACHE_IS_CONTROLLED_BY_FMC
2163 /*! @brief Performs the cache clear to the flash by FMC.*/
fmc_flash_cache_clear(void)2164 void fmc_flash_cache_clear(void)
2165 {
2166 #if FLASH_DRIVER_IS_FLASH_RESIDENT
2167 FTMRx_REG32_ACCESS_TYPE regBase = (FTMRx_REG32_ACCESS_TYPE)0;
2168 #if defined(FMC_PFB01CR_CINV_WAY_MASK)
2169 regBase = (FTMRx_REG32_ACCESS_TYPE)&FMC->PFB01CR;
2170 flash_common_bit_operation_command_sequence(config, regBase, FMC_PFB01CR_CINV_WAY_MASK, FMC_PFB01CR_CINV_WAY_SHIFT,
2171 0xFUL);
2172 #else
2173 regBase = (FTMRx_REG32_ACCESS_TYPE)&FMC->PFB0CR;
2174 flash_common_bit_operation_command_sequence(config, regBase, FMC_PFB0CR_CINV_WAY_MASK, FMC_PFB0CR_CINV_WAY_SHIFT,
2175 0xFUL);
2176 #endif
2177 #else /* !FLASH_DRIVER_IS_FLASH_RESIDENT */
2178 #if defined(FMC_PFB01CR_CINV_WAY_MASK)
2179 FMC->PFB01CR = (FMC->PFB01CR & ~FMC_PFB01CR_CINV_WAY_MASK) | FMC_PFB01CR_CINV_WAY(~0);
2180 #else
2181 FMC->PFB0CR = (FMC->PFB0CR & ~FMC_PFB0CR_CINV_WAY_MASK) | FMC_PFB0CR_CINV_WAY(~0);
2182 #endif
2183 /* Memory barriers for good measure.
2184 * All Cache, Branch predictor and TLB maintenance operations before this
2185 * instruction complete */
2186 __ISB();
2187 __DSB();
2188 #endif /* FLASH_DRIVER_IS_FLASH_RESIDENT */
2189 }
2190 #endif /* FLASH_CACHE_IS_CONTROLLED_BY_FMC */
2191
2192 #if FLASH_PREFETCH_SPECULATION_IS_CONTROLLED_BY_FMC
2193 /*! @brief Performs the prefetch speculation buffer clear to the flash by FMC.*/
fmc_flash_prefetch_speculation_clear(void)2194 void fmc_flash_prefetch_speculation_clear(void)
2195 {
2196 #if FLASH_DRIVER_IS_FLASH_RESIDENT
2197 FTMRx_REG32_ACCESS_TYPE regBase = (FTMRx_REG32_ACCESS_TYPE)0UL;
2198 #if defined(FMC_PFB01CR_S_INV_MASK)
2199 regBase = (FTMRx_REG32_ACCESS_TYPE)&FMC->PFB01CR;
2200 flash_common_bit_operation_command_sequence(config, regBase, FMC_PFB01CR_S_INV_MASK, FMC_PFB01CR_S_INV_SHIFT, 1UL);
2201 #elif defined(FMC_PFB01CR_S_B_INV_MASK)
2202 regBase = (FTMRx_REG32_ACCESS_TYPE)&FMC->PFB01CR;
2203 flash_common_bit_operation_command_sequence(config, regBase, FMC_PFB01CR_S_B_INV_MASK, FMC_PFB01CR_S_B_INV_SHIFT,
2204 1UL);
2205 #elif defined(FMC_PFB0CR_S_INV_MASK)
2206 regBase = (FTMRx_REG32_ACCESS_TYPE)&FMC->PFB0CR;
2207 flash_common_bit_operation_command_sequence(config, regBase, FMC_PFB0CR_S_INV_MASK, FMC_PFB0CR_S_INV_SHIFT, 1UL);
2208 #elif defined(FMC_PFB0CR_S_B_INV_MASK)
2209 regBase = (FTMRx_REG32_ACCESS_TYPE)&FMC->PFB0CR;
2210 flash_common_bit_operation_command_sequence(config, regBase, FMC_PFB0CR_S_B_INV_MASK, FMC_PFB0CR_S_B_INV_SHIFT,
2211 1UL);
2212 #endif
2213 #else /* !FLASH_DRIVER_IS_FLASH_RESIDENT */
2214 #if defined(FMC_PFB01CR_S_INV_MASK)
2215 FMC->PFB01CR |= FMC_PFB01CR_S_INV_MASK;
2216 #elif defined(FMC_PFB01CR_S_B_INV_MASK)
2217 FMC->PFB01CR |= FMC_PFB01CR_S_B_INV_MASK;
2218 #elif defined(FMC_PFB0CR_S_INV_MASK)
2219 FMC->PFB0CR |= FMC_PFB0CR_S_INV_MASK;
2220 #elif defined(FMC_PFB0CR_S_B_INV_MASK)
2221 FMC->PFB0CR |= FMC_PFB0CR_S_B_INV_MASK;
2222 #endif
2223 /* Memory barriers for good measure.
2224 * All Cache, Branch predictor and TLB maintenance operations before this
2225 * instruction complete */
2226 __ISB();
2227 __DSB();
2228 #endif /* FLASH_DRIVER_IS_FLASH_RESIDENT */
2229 }
2230 #endif /* FLASH_PREFETCH_SPECULATION_IS_CONTROLLED_BY_FMC */
2231
2232 /*!
2233 * @brief Flash Cache Clear
2234 *
2235 * This function is used to perform the cache and prefetch speculation clear to
2236 * the flash.
2237 */
flash_cache_clear(flash_config_t * config)2238 void flash_cache_clear(flash_config_t *config)
2239 {
2240 flash_cache_clear_process(config, kFLASH_CacheClearProcessPost);
2241 }
2242
2243 /*!
2244 * @brief Flash Cache Clear Process
2245 *
2246 * This function is used to perform the cache and prefetch speculation clear
2247 * process to the flash.
2248 */
flash_cache_clear_process(flash_config_t * config,flash_cache_clear_process_t process)2249 static void flash_cache_clear_process(flash_config_t *config, flash_cache_clear_process_t process)
2250 {
2251 #if FLASH_DRIVER_IS_FLASH_RESIDENT
2252 status_t returnCode = flash_check_execute_in_ram_function_info(config);
2253 if (kStatus_FLASH_Success != returnCode)
2254 {
2255 return;
2256 }
2257 #endif /* FLASH_DRIVER_IS_FLASH_RESIDENT */
2258
2259 /* We pass the FTMRx register address as a parameter to
2260 * flash_common_bit_operation() instead of using
2261 * pre-processed MACROs or a global variable in flash_common_bit_operation()
2262 * to make sure that flash_common_bit_operation() will be compiled into
2263 * position-independent code (PIC). */
2264 if (process == kFLASH_CacheClearProcessPost)
2265 {
2266 #if FLASH_CACHE_IS_CONTROLLED_BY_MCM
2267 mcm_flash_cache_clear(config);
2268 #endif
2269 #if FLASH_CACHE_IS_CONTROLLED_BY_FMC
2270 fmc_flash_cache_clear();
2271 #endif
2272
2273 #if FLASH_PREFETCH_SPECULATION_IS_CONTROLLED_BY_FMC
2274 fmc_flash_prefetch_speculation_clear();
2275 #endif
2276 }
2277 if (process == kFLASH_CacheClearProcessPre)
2278 {
2279 }
2280 }
2281
2282 #if FLASH_DRIVER_IS_FLASH_RESIDENT
2283 /*! @brief Check whether flash execute-in-ram functions are ready */
flash_check_execute_in_ram_function_info(flash_config_t * config)2284 static status_t flash_check_execute_in_ram_function_info(flash_config_t *config)
2285 {
2286 flash_execute_in_ram_function_config_t *flashExecuteInRamFunctionInfo;
2287
2288 if (config == NULL)
2289 {
2290 return kStatus_FLASH_InvalidArgument;
2291 }
2292
2293 flashExecuteInRamFunctionInfo =
2294 (flash_execute_in_ram_function_config_t *)((void *)(config->flashExecuteInRamFunctionInfo));
2295
2296 if ((config->flashExecuteInRamFunctionInfo != NULL) &&
2297 ((uint32_t)kFLASH_ExecuteInRamFunctionTotalNum == flashExecuteInRamFunctionInfo->activeFunctionCount))
2298 {
2299 return kStatus_FLASH_Success;
2300 }
2301
2302 return kStatus_FLASH_ExecuteInRamFunctionNotReady;
2303 }
2304 #endif /* FLASH_DRIVER_IS_FLASH_RESIDENT */
2305
2306 /*! @brief Validates the range and alignment of the given address range.*/
flash_check_range(flash_config_t * config,uint32_t startAddress,uint32_t lengthInBytes,uint32_t alignmentBaseline)2307 static status_t flash_check_range(flash_config_t *config,
2308 uint32_t startAddress,
2309 uint32_t lengthInBytes,
2310 uint32_t alignmentBaseline)
2311 {
2312 if (config == NULL)
2313 {
2314 return kStatus_FLASH_InvalidArgument;
2315 }
2316
2317 /* Verify the start and length are alignmentBaseline aligned, Global address
2318 * [1:0] must be 00.*/
2319 if ((0UL != (startAddress & (alignmentBaseline - 1UL))) || (0UL != (lengthInBytes & (alignmentBaseline - 1UL))))
2320 {
2321 return kStatus_FLASH_AlignmentError;
2322 }
2323
2324 /* check for valid range of the target addresses */
2325 if ((startAddress >= config->PFlashBlockBase) &&
2326 ((startAddress + lengthInBytes) <= (config->PFlashBlockBase + config->PFlashTotalSize)))
2327 {
2328 return kStatus_FLASH_Success;
2329 }
2330
2331 return kStatus_FLASH_AddressError;
2332 }
2333
2334 /*! @brief Validates the range and alignment of the given address range.*/
2335 #if FLASH_SSD_IS_EEPROM_ENABLED
EEPROM_check_range(flash_config_t * config,uint32_t startAddress,uint32_t lengthInBytes,uint32_t alignmentBaseline)2336 static status_t EEPROM_check_range(flash_config_t *config,
2337 uint32_t startAddress,
2338 uint32_t lengthInBytes,
2339 uint32_t alignmentBaseline)
2340 {
2341 if (config == NULL)
2342 {
2343 return kStatus_FLASH_InvalidArgument;
2344 }
2345
2346 /* Verify the start and length are alignmentBaseline aligned, Global address
2347 * [1:0] must be 00.*/
2348 if ((0UL != (startAddress & (alignmentBaseline - 1UL))) || (0UL != (lengthInBytes & (alignmentBaseline - 1UL))))
2349 {
2350 return kStatus_FLASH_AlignmentError;
2351 }
2352
2353 /* check for valid range of the target addresses */
2354 if ((startAddress >= config->EEpromBlockBase) &&
2355 ((startAddress + lengthInBytes) <= (config->EEpromBlockBase + config->EEpromTotalSize)))
2356 {
2357 return kStatus_FLASH_Success;
2358 }
2359
2360 return kStatus_FLASH_AddressError;
2361 }
2362 #endif /* FLASH_SSD_IS_EEPROM_ENABLED */
2363
2364 /*! @brief Gets the right address, sector and block size of current flash type
2365 * which is indicated by address.*/
flash_get_matched_operation_info(flash_config_t * config,uint32_t address,flash_operation_config_t * info)2366 static status_t flash_get_matched_operation_info(flash_config_t *config,
2367 uint32_t address,
2368 flash_operation_config_t *info)
2369 {
2370 if ((config == NULL) || (info == NULL))
2371 {
2372 return kStatus_FLASH_InvalidArgument;
2373 }
2374
2375 /* Clean up info Structure*/
2376 (void)memset(info, 0, sizeof(flash_operation_config_t));
2377
2378 info->convertedAddress = address - config->PFlashBlockBase;
2379 info->activeSectorSize = config->PFlashSectorSize;
2380 info->activeBlockSize = config->PFlashTotalSize / config->PFlashBlockCount;
2381 #if FLASH_SSD_IS_SECONDARY_FLASH_ENABLED
2382 if (config->FlashMemoryIndex == (uint8_t)kFLASH_MemoryIndexSecondaryFlash)
2383 {
2384 #if FLASH_SSD_SECONDARY_FLASH_HAS_ITS_OWN_PROTECTION_REGISTER || FLASH_SSD_SECONDARY_FLASH_HAS_ITS_OWN_ACCESS_REGISTER
2385 /* When required by the command, address bit 23 selects between main flash
2386 * memory
2387 * (=0) and secondary flash memory (=1).*/
2388 info->convertedAddress += 0x800000UL;
2389 #endif
2390 info->blockWriteUnitSize = SECONDARY_FLASH_FEATURE_PFLASH_BLOCK_WRITE_UNIT_SIZE;
2391 }
2392 else
2393 #endif /* FLASH_SSD_IS_SECONDARY_FLASH_ENABLED */
2394 {
2395 info->blockWriteUnitSize = FSL_FEATURE_FLASH_PFLASH_BLOCK_WRITE_UNIT_SIZE;
2396 }
2397
2398 info->sectorCmdAddressAligment = FSL_FEATURE_FLASH_PFLASH_SECTOR_CMD_ADDRESS_ALIGMENT;
2399 info->sectionCmdAddressAligment = FSL_FEATURE_FLASH_PFLASH_SECTION_CMD_ADDRESS_ALIGMENT;
2400 info->programCmdAddressAligment = FSL_FEATURE_FLASH_PFLASH_PROGRAM_CMD_ADDRESS_ALIGMENT;
2401
2402 return kStatus_FLASH_Success;
2403 }
2404
2405 /*! @brief Validates the given user key for flash erase APIs.*/
flash_check_user_key(uint32_t key)2406 static status_t flash_check_user_key(uint32_t key)
2407 {
2408 /* Validate the user key */
2409 if (key != (uint32_t)kFLASH_ApiEraseKey)
2410 {
2411 return kStatus_FLASH_EraseKeyError;
2412 }
2413
2414 return kStatus_FLASH_Success;
2415 }
2416
2417 /*! @brief Gets the flash protection information.*/
flash_get_protection_info(flash_config_t * config,flash_protection_config_t * info)2418 static status_t flash_get_protection_info(flash_config_t *config, flash_protection_config_t *info)
2419 {
2420 uint32_t pflashTotalSize, regionBase;
2421 uint32_t pflashProtectionValue, pflashFPLS;
2422 #if defined(FTMRx_FPROT_FPHDIS_MASK)
2423 uint32_t pflashFPHS;
2424 #endif
2425
2426 if ((config == NULL) || (info == NULL))
2427 {
2428 return kStatus_FLASH_InvalidArgument;
2429 }
2430
2431 /* Clean up info Structure*/
2432 (void)memset(info, 0, sizeof(flash_protection_config_t));
2433
2434 /* Note: KW40 has a secondary flash, but it doesn't have independent protection
2435 * register*/
2436 #if FLASH_SSD_IS_SECONDARY_FLASH_ENABLED && (!FLASH_SSD_SECONDARY_FLASH_HAS_ITS_OWN_PROTECTION_REGISTER)
2437 pflashTotalSize = FSL_FEATURE_FLASH_PFLASH_BLOCK_COUNT * FSL_FEATURE_FLASH_PFLASH_BLOCK_SIZE +
2438 FSL_FEATURE_FLASH_PFLASH_1_BLOCK_COUNT * FSL_FEATURE_FLASH_PFLASH_1_BLOCK_SIZE;
2439 regionBase = FSL_FEATURE_FLASH_PFLASH_START_ADDRESS;
2440 #else
2441 pflashTotalSize = config->PFlashTotalSize;
2442 regionBase = config->PFlashBlockBase;
2443 #endif
2444
2445 /* Calculate the flash protection region */
2446 pflashProtectionValue = FTMRx->FPROT & 0xA4UL;
2447 pflashFPLS = (FTMRx->FPROT & 0x03UL);
2448 #if defined(FTMRx_FPROT_FPHDIS_MASK)
2449 pflashFPHS = (FTMRx->FPROT & 0x18UL) >> 3UL;
2450 #endif
2451
2452 switch (pflashProtectionValue)
2453 {
2454 #if defined(FTMRx_FPROT_FPHDIS_MASK)
2455 case 0xA4UL:
2456 /*!< All flash region is not protected.*/
2457 info->lowRegionStart = regionBase;
2458 info->lowRegionEnd = regionBase;
2459 info->highRegionStart = regionBase + pflashTotalSize;
2460 info->highRegionEnd = regionBase + pflashTotalSize;
2461 break;
2462 #endif
2463 case 0x84UL:
2464 info->lowRegionStart = regionBase;
2465 info->lowRegionEnd = regionBase;
2466 #if defined(FTMRx_FPROT_FPHDIS_MASK)
2467 /*!< Only flash high region is protected.*/
2468 info->highRegionStart =
2469 (uint32_t)FSL_FEATURE_FLASH_PFLASH_HIGH_START_ADDRESS - ((1UL << pflashFPLS) << 10UL);
2470 info->highRegionEnd = FSL_FEATURE_FLASH_PFLASH_HIGH_START_ADDRESS;
2471 #else
2472 /*!< All flash region is not protected.*/
2473 info->highRegionStart = regionBase + pflashTotalSize;
2474 info->highRegionEnd = regionBase + pflashTotalSize;
2475 #endif
2476 break;
2477 #if defined(FTMRx_FPROT_FPHDIS_MASK)
2478 case 0xA0UL:
2479 /*!< Only flash low region is protected.*/
2480 info->lowRegionStart = regionBase;
2481 info->lowRegionEnd = regionBase + ((2UL << pflashFPLS) << 10UL);
2482 info->highRegionStart = regionBase + pflashTotalSize;
2483 info->highRegionEnd = regionBase + pflashTotalSize;
2484 break;
2485 #endif
2486 case 0x80UL:
2487 info->lowRegionStart = regionBase;
2488 #if defined(FTMRx_FPROT_FPHDIS_MASK)
2489 /*!< Flash high and low region are protected.*/
2490 info->lowRegionEnd = regionBase + ((2UL << pflashFPLS) << 10UL);
2491 info->highRegionStart =
2492 (uint32_t)FSL_FEATURE_FLASH_PFLASH_HIGH_START_ADDRESS - ((1UL << pflashFPLS) << 10UL);
2493 info->highRegionEnd = FSL_FEATURE_FLASH_PFLASH_HIGH_START_ADDRESS;
2494 #else
2495 /*!< Only flash low region is protected.*/
2496 info->lowRegionEnd = regionBase + ((1UL << pflashFPLS) << 10UL);
2497 info->highRegionStart = regionBase + pflashTotalSize;
2498 info->highRegionEnd = regionBase + pflashTotalSize;
2499 #endif
2500 break;
2501 #if defined(FTMRx_FPROT_FPHDIS_MASK)
2502 case 0x24UL:
2503 /*!< All Flash region is protected.*/
2504 info->lowRegionStart = regionBase;
2505 info->lowRegionEnd = regionBase + pflashTotalSize;
2506 info->highRegionStart = regionBase;
2507 info->highRegionEnd = regionBase + pflashTotalSize;
2508 break;
2509 #endif
2510 case 0x04UL:
2511 info->lowRegionStart = regionBase;
2512 #if defined(FTMRx_FPROT_FPHDIS_MASK)
2513 /*!< Flash high region is not protected.*/
2514 info->lowRegionEnd = (uint32_t)FSL_FEATURE_FLASH_PFLASH_HIGH_START_ADDRESS - ((1UL << pflashFPHS) << 10UL);
2515 info->highRegionStart = FSL_FEATURE_FLASH_PFLASH_HIGH_START_ADDRESS;
2516
2517 #else
2518 /*!< All Flash region is protected.*/
2519 info->lowRegionEnd = regionBase + pflashTotalSize;
2520 info->highRegionStart = regionBase;
2521 #endif
2522 info->highRegionEnd = regionBase + pflashTotalSize;
2523 break;
2524 #if defined(FTMRx_FPROT_FPHDIS_MASK)
2525 case 0x20UL:
2526 /*!< Flash low region is not protected.*/
2527 info->lowRegionStart = regionBase + ((2UL << pflashFPLS) << 10UL);
2528 info->lowRegionEnd = regionBase + pflashTotalSize;
2529 info->highRegionStart = regionBase + ((2UL << pflashFPLS) << 10UL);
2530 info->highRegionEnd = regionBase + pflashTotalSize;
2531 break;
2532 #endif
2533 case 0x00UL:
2534 #if defined(FTMRx_FPROT_FPHDIS_MASK)
2535 /*!< Flash high and low region are not protected.*/
2536 info->lowRegionStart = regionBase + ((2UL << pflashFPLS) << 10UL);
2537 info->lowRegionEnd = (uint32_t)FSL_FEATURE_FLASH_PFLASH_HIGH_START_ADDRESS - ((1UL << pflashFPHS) << 10UL);
2538 info->highRegionStart = FSL_FEATURE_FLASH_PFLASH_HIGH_START_ADDRESS;
2539 #else
2540 /*!< Flash low region is not protected.*/
2541 info->lowRegionStart = regionBase;
2542 info->lowRegionEnd = regionBase;
2543 info->highRegionStart = regionBase + ((1UL << pflashFPLS) << 10UL);
2544 #endif
2545 info->highRegionEnd = regionBase + pflashTotalSize;
2546 break;
2547 default:
2548 /* Do Nothing*/
2549 break;
2550 }
2551
2552 return kStatus_FLASH_Success;
2553 }
2554
2555 /*! @brief Set the flash and eeprom to the specified user margin level.*/
flash_setusermarginlevel(flash_config_t * config,uint32_t start,uint8_t iseeprom,flash_user_margin_value_t margin)2556 status_t flash_setusermarginlevel(flash_config_t *config,
2557 uint32_t start,
2558 uint8_t iseeprom,
2559 flash_user_margin_value_t margin)
2560 {
2561 uint32_t marginValue;
2562 status_t returnCode;
2563 if (config == NULL)
2564 {
2565 return kStatus_FLASH_InvalidArgument;
2566 }
2567 marginValue = (uint32_t)margin;
2568 flash_cache_clear_process(config, kFLASH_CacheClearProcessPre);
2569
2570 /* clear error flags */
2571 FTMRx->FSTAT = FTMRx_FSTAT_ACCERR_MASK | FTMRx_FSTAT_FPVIOL_MASK;
2572
2573 /* Write index to specify the command code to be loaded */
2574 flash_set_command(0UL, start >> 16UL, FTMRx_SET_USER_MARGIN_LEVEL);
2575
2576 /* memory address bits[23:16] with bit23 = 0 for Flash block, 1 for EEPROM
2577 * block */
2578 if (0UL != iseeprom)
2579 {
2580 FTMRx->FCCOBLO |= FTMRx_FCCOBLO_CCOB(128UL);
2581 }
2582 flash_set_command(1UL, start, start >> 8UL);
2583
2584 flash_set_command(2UL, marginValue, marginValue >> 8UL);
2585
2586 /* calling flash command sequence function to execute the command */
2587 returnCode = flash_command_sequence(config);
2588
2589 flash_cache_clear(config);
2590 return returnCode;
2591 }
2592
2593 /*! @brief Set the flash and eeprom to the specified factory margin level.*/
flash_setfactorymarginlevel(flash_config_t * config,uint32_t start,uint8_t iseeprom,flash_factory_margin_value_t margin)2594 status_t flash_setfactorymarginlevel(flash_config_t *config,
2595 uint32_t start,
2596 uint8_t iseeprom,
2597 flash_factory_margin_value_t margin)
2598 {
2599 uint32_t marginValue;
2600 status_t returnCode;
2601 if (config == NULL)
2602 {
2603 return kStatus_FLASH_InvalidArgument;
2604 }
2605
2606 marginValue = (uint32_t)margin;
2607 flash_cache_clear_process(config, kFLASH_CacheClearProcessPre);
2608 /* clear error flags */
2609 FTMRx->FSTAT = FTMRx_FSTAT_ACCERR_MASK | FTMRx_FSTAT_FPVIOL_MASK;
2610
2611 /* Write index to specify the command code to be loaded */
2612 flash_set_command(0UL, start >> 16UL, FTMRx_SET_FACTORY_MARGIN_LEVEL);
2613 /* memory address bits[23:16] with bit23 = 0 for Flash block, 1 for EEPROM
2614 * block */
2615 if (0UL != iseeprom)
2616 {
2617 FTMRx->FCCOBLO |= FTMRx_FCCOBLO_CCOB(128UL);
2618 }
2619 flash_set_command(1UL, start, start >> 8UL);
2620
2621 flash_set_command(2UL, marginValue, marginValue >> 8UL);
2622
2623 /* calling flash command sequence function to execute the command */
2624 returnCode = flash_command_sequence(config);
2625
2626 flash_cache_clear(config);
2627 return returnCode;
2628 }
2629