1 /*
2 * Copyright 2018-2021 NXP
3 * All rights reserved.
4 *
5 * SPDX-License-Identifier: BSD-3-Clause
6 *
7 */
8
9 #include "fsl_k4_controller.h"
10
11 /*******************************************************************************
12 * Definitions
13 ******************************************************************************/
14
15 /*!
16 * @name Flash controller command numbers
17 * @{
18 */
19 #define FLASH_VERIFY_ERASE_ALL 0x00U /*!< RD1ALL*/
20 #define FLASH_VERIFY_ERASE_BLOCK 0x01U /*!< RD1BLK*/
21 #define FLASH_VERIFY_ERASE_SECTOR 0x02U /*!< RD1SCR*/
22 #define FLASH_VERIFY_ERASE_PAGE 0x03U /*!< RD1PG*/
23 #define FLASH_VERIFY_ERASE_PHRASE 0x04U /*!< RD1PHR*/
24 #define FLASH_READ_INTO_MISR 0x05U /*!< RDMISR*/
25 #define FLASH_VERIFY_ERASE_IFR_SECTOR 0x12U /*!< RD1ISCR*/
26 #define FLASH_VERIFY_ERASE_IFR_PAGE 0x13U /*!< RD1IPG*/
27 #define FLASH_VERIFY_ERASE_IFR_PHRASE 0x14U /*!< RD1IPHR*/
28 #define FLASH_READ_IFR_INTO_MISR 0x15U /*!< RDIMISR*/
29 #define FLASH_PROGRAM_PAGE 0x23U /*!< PGMPG*/
30 #define FLASH_PROGRAM_PHRASE 0x24U /*!< PGMPHR*/
31 #define FLASH_ERASE_ALL 0x40U /*!< ERSALL*/
32 #define FLASH_ERASE_SECTOR 0x42U /*!< ERSSCR*/
33 /*@}*/
34
35 /*******************************************************************************
36 * Prototypes
37 ******************************************************************************/
38
39 static void flash_command_pre_sequence(FMU_Type *base);
40
41 static void flash_command_sequence(FMU_Type *base);
42
43 static void flash_erase_sequence(FMU_Type *base, uint32_t start);
44
45 static void flash_pgm_sequence(FMU_Type *base, uint32_t start, uint32_t *src, uint8_t isPage);
46
47 /*! @brief Internal function Flash command*/
48 static status_t flash_command_complete(FMU_Type *base);
49
50 /*******************************************************************************
51 * Variables
52 ******************************************************************************/
53
54 /*******************************************************************************
55 * Code
56 ******************************************************************************/
57
FLASH_CMD_EraseSector(FMU_Type * base,uint32_t start)58 status_t FLASH_CMD_EraseSector(FMU_Type *base, uint32_t start)
59 {
60 status_t returnCode = kStatus_Fail;
61
62 flash_command_pre_sequence(base);
63 /* preparing passing parameter to erase a sector flash */
64 base->FCCOB[0] = FLASH_ERASE_SECTOR;
65 /* Erase Command sequence */
66 flash_erase_sequence(base, start);
67 /* check command completion and error handling */
68 returnCode = flash_command_complete(base);
69
70 return returnCode;
71 }
72
FLASH_CMD_EraseAll(FMU_Type * base)73 status_t FLASH_CMD_EraseAll(FMU_Type *base)
74 {
75 status_t returnCode = kStatus_Fail;
76
77 flash_command_pre_sequence(base);
78 /* preparing passing parameter to erase all flash blocks */
79 base->FCCOB[0] = FLASH_ERASE_ALL;
80 flash_command_sequence(base);
81 /* calling flash command sequence function to execute the command */
82 returnCode = flash_command_complete(base);
83
84 return returnCode;
85 }
86
FLASH_CMD_ProgramPhrase(FMU_Type * base,uint32_t start,uint32_t * src)87 status_t FLASH_CMD_ProgramPhrase(FMU_Type *base, uint32_t start, uint32_t *src)
88 {
89 status_t returnCode = kStatus_Fail;
90 uint8_t isPage = 0;
91
92 flash_command_pre_sequence(base);
93 /* preparing passing parameter to program the flash block */
94 base->FCCOB[0] = FLASH_PROGRAM_PHRASE;
95 /* Program Command sequence */
96 flash_pgm_sequence(base, start, src, isPage);
97 returnCode = flash_command_complete(base);
98
99 return returnCode;
100 }
101
FLASH_CMD_ProgramPage(FMU_Type * base,uint32_t start,uint32_t * src)102 status_t FLASH_CMD_ProgramPage(FMU_Type *base, uint32_t start, uint32_t *src)
103 {
104 status_t returnCode = kStatus_Fail;
105 uint8_t isPage = 1;
106
107 flash_command_pre_sequence(base);
108 /* preparing passing parameter to program the flash block */
109 base->FCCOB[0] = FLASH_PROGRAM_PAGE;
110 /* Program Command sequence */
111 flash_pgm_sequence(base, start, src, isPage);
112 returnCode = flash_command_complete(base);
113
114 return returnCode;
115 }
116
FLASH_CMD_VerifyErasePhrase(FMU_Type * base,uint32_t start)117 status_t FLASH_CMD_VerifyErasePhrase(FMU_Type *base, uint32_t start)
118 {
119 status_t returnCode = kStatus_Fail;
120
121 flash_command_pre_sequence(base);
122 /* Fill in verify erase phrase command parameters. */
123 base->FCCOB[0] = FLASH_VERIFY_ERASE_PHRASE;
124 base->FCCOB[2] = start;
125 flash_command_sequence(base);
126 /* calling flash command sequence function to execute the command */
127 returnCode = flash_command_complete(base);
128
129 return returnCode;
130 }
131
FLASH_CMD_VerifyErasePage(FMU_Type * base,uint32_t start)132 status_t FLASH_CMD_VerifyErasePage(FMU_Type *base, uint32_t start)
133 {
134 status_t returnCode = kStatus_Fail;
135
136 flash_command_pre_sequence(base);
137 /* Fill in verify erase page command parameters. */
138 base->FCCOB[0] = FLASH_VERIFY_ERASE_PAGE;
139 base->FCCOB[2] = start;
140 flash_command_sequence(base);
141 /* calling flash command sequence function to execute the command */
142 returnCode = flash_command_complete(base);
143
144 return returnCode;
145 }
146
FLASH_CMD_VerifyEraseSector(FMU_Type * base,uint32_t start)147 status_t FLASH_CMD_VerifyEraseSector(FMU_Type *base, uint32_t start)
148 {
149 status_t returnCode = kStatus_Fail;
150
151 flash_command_pre_sequence(base);
152 /* Fill in verify erase sector command parameters. */
153 base->FCCOB[0] = FLASH_VERIFY_ERASE_SECTOR;
154 base->FCCOB[2] = start;
155 flash_command_sequence(base);
156 /* calling flash command sequence function to execute the command */
157 returnCode = flash_command_complete(base);
158
159 return returnCode;
160 }
161
FLASH_CMD_VerifyEraseIFRPhrase(FMU_Type * base,uint32_t start)162 status_t FLASH_CMD_VerifyEraseIFRPhrase(FMU_Type *base, uint32_t start)
163 {
164 status_t returnCode = kStatus_Fail;
165
166 flash_command_pre_sequence(base);
167 /* Fill in verify erase ifr phrase command parameters. */
168 base->FCCOB[0] = FLASH_VERIFY_ERASE_IFR_PHRASE;
169 base->FCCOB[2] = start;
170 flash_command_sequence(base);
171 /* calling flash command function to execute the command */
172 returnCode = flash_command_complete(base);
173
174 return returnCode;
175 }
176
FLASH_CMD_VerifyEraseIFRPage(FMU_Type * base,uint32_t start)177 status_t FLASH_CMD_VerifyEraseIFRPage(FMU_Type *base, uint32_t start)
178 {
179 status_t returnCode = kStatus_Fail;
180
181 flash_command_pre_sequence(base);
182 /* Fill in verify erase ifr page command parameters. */
183 base->FCCOB[0] = FLASH_VERIFY_ERASE_IFR_PAGE;
184 base->FCCOB[2] = start;
185 flash_command_sequence(base);
186 /* calling flash command function to execute the command */
187 returnCode = flash_command_complete(base);
188
189 return returnCode;
190 }
191
FLASH_CMD_VerifyEraseIFRSector(FMU_Type * base,uint32_t start)192 status_t FLASH_CMD_VerifyEraseIFRSector(FMU_Type *base, uint32_t start)
193 {
194 status_t returnCode = kStatus_Fail;
195
196 flash_command_pre_sequence(base);
197 /* Fill in verify erase ifr sector command parameters. */
198 base->FCCOB[0] = FLASH_VERIFY_ERASE_IFR_SECTOR;
199 base->FCCOB[2] = start;
200 flash_command_sequence(base);
201 /* calling flash command function to execute the command */
202 returnCode = flash_command_complete(base);
203
204 return returnCode;
205 }
206
FLASH_CMD_VerifyEraseBlock(FMU_Type * base,uint32_t blockaddr)207 status_t FLASH_CMD_VerifyEraseBlock(FMU_Type *base, uint32_t blockaddr)
208 {
209 status_t returnCode = kStatus_Fail;
210
211 flash_command_pre_sequence(base);
212 /* preparing passing parameter to verify erase block command */
213 base->FCCOB[0] = FLASH_VERIFY_ERASE_BLOCK;
214 base->FCCOB[2] = blockaddr;
215 flash_command_sequence(base);
216 /* calling flash command sequence function to execute the command */
217 returnCode = flash_command_complete(base);
218
219 return returnCode;
220 }
221
FLASH_CMD_VerifyEraseAll(FMU_Type * base)222 status_t FLASH_CMD_VerifyEraseAll(FMU_Type *base)
223 {
224 status_t returnCode = kStatus_Fail;
225
226 flash_command_pre_sequence(base);
227 /* preparing passing parameter to verify erase all command */
228 base->FCCOB[0] = FLASH_VERIFY_ERASE_ALL;
229 flash_command_sequence(base);
230 /* calling flash command sequence function to execute the command */
231 returnCode = flash_command_complete(base);
232 return returnCode;
233 }
234
FLASH_CMD_ReadIntoMISR(FMU_Type * base,uint32_t start,uint32_t ending,uint32_t * seed,uint32_t * signature)235 status_t FLASH_CMD_ReadIntoMISR(FMU_Type *base, uint32_t start, uint32_t ending, uint32_t *seed, uint32_t *signature)
236 {
237 status_t returnCode = kStatus_Fail;
238
239 flash_command_pre_sequence(base);
240 /* preparing passing parameter to read into misr command */
241 base->FCCOB[0] = FLASH_READ_INTO_MISR;
242 base->FCCOB[2] = start;
243 base->FCCOB[3] = ending;
244 base->FCCOB[4] = seed[0];
245 base->FCCOB[5] = seed[1];
246 base->FCCOB[6] = seed[2];
247 base->FCCOB[7] = seed[3];
248 flash_command_sequence(base);
249 /* calling flash command sequence function to execute the command */
250 returnCode = flash_command_complete(base);
251
252 if ((kStatus_FLASH_Success == returnCode) && (signature != NULL))
253 {
254 signature[0] = base->FCCOB[4];
255 signature[1] = base->FCCOB[5];
256 signature[2] = base->FCCOB[6];
257 signature[3] = base->FCCOB[7];
258 }
259
260 return returnCode;
261 }
262
FLASH_CMD_ReadIFRIntoMISR(FMU_Type * base,uint32_t start,uint32_t ending,uint32_t * seed,uint32_t * signature)263 status_t FLASH_CMD_ReadIFRIntoMISR(FMU_Type *base, uint32_t start, uint32_t ending, uint32_t *seed, uint32_t *signature)
264 {
265 status_t returnCode = kStatus_Fail;
266
267 flash_command_pre_sequence(base);
268 /* preparing passing parameter to read into misr command */
269 base->FCCOB[0] = FLASH_READ_IFR_INTO_MISR;
270 base->FCCOB[2] = start;
271 base->FCCOB[3] = ending;
272 base->FCCOB[4] = seed[0];
273 base->FCCOB[5] = seed[1];
274 base->FCCOB[6] = seed[2];
275 base->FCCOB[7] = seed[3];
276 flash_command_sequence(base);
277 /* calling flash command sequence function to execute the command */
278 returnCode = flash_command_complete(base);
279
280 if ((kStatus_FLASH_Success == returnCode) && (signature != NULL))
281 {
282 signature[0] = base->FCCOB[4];
283 signature[1] = base->FCCOB[5];
284 signature[2] = base->FCCOB[6];
285 signature[3] = base->FCCOB[7];
286 }
287
288 return returnCode;
289 }
290
291 /*!
292 * @brief FLASH Command Pre Sequence
293 *
294 * This function is used to perform the check before loading FCCOB registers
295 *
296 * @param
297 * @return
298 */
299 #if defined(FLASH_DRIVER_IS_FLASH_RESIDENT) && (FLASH_DRIVER_IS_FLASH_RESIDENT == 1)
300 #if defined(__IAR_SYSTEMS_ICC__)
301 __ramfunc
302 #elif defined(__GNUC__)
303 __attribute__((section(".ramfunc"))) __attribute__((__noinline__))
304 #endif
305 #endif
flash_command_pre_sequence(FMU_Type * base)306 static void flash_command_pre_sequence(FMU_Type *base)
307 {
308 if ((base->FSTAT & FLASH_FSTAT_DFDIF_MASK) != 0U)
309 {
310 /* Acknowledge previous ECC fault. The fault occured during a previous read or verify erase but too late to */
311 base->FSTAT = FLASH_FSTAT_DFDIF_MASK;
312 }
313 // Check if previous command complete, CCIF==1, wait for CCIF set
314 while (((base->FSTAT) & FLASH_FSTAT_CCIF_MASK) == 0U)
315 {
316 }
317
318 /* clear CMDABT & ACCERR & PVIOL flag in flash status register */
319 base->FSTAT = (FLASH_FSTAT_CMDABT_MASK | FLASH_FSTAT_ACCERR_MASK | FLASH_FSTAT_PVIOL_MASK);
320 }
321
322 /*!
323 * @brief FLASH Command Pre Sequence
324 *
325 * This function is used to perform launching command and wait for completion
326 *
327 * @param
328 * @return
329 */
330 #if defined(FLASH_DRIVER_IS_FLASH_RESIDENT) && (FLASH_DRIVER_IS_FLASH_RESIDENT == 1)
331 #if defined(__IAR_SYSTEMS_ICC__)
332 __ramfunc
333 #elif defined(__GNUC__)
334 __attribute__((section(".ramfunc"))) __attribute__((__noinline__))
335 #endif
336 #endif
flash_command_sequence(FMU_Type * base)337 static void flash_command_sequence(FMU_Type *base)
338 {
339 /* clear CCIF bit to launch the command */
340 base->FSTAT = FLASH_FSTAT_CCIF_MASK;
341
342 /* Check CCIF bit of the flash status register, wait till it is set */
343 while ((base->FSTAT & FLASH_FSTAT_CCIF_MASK) == 0U)
344 {
345 }
346 }
347
348 /*!
349 * @brief Flash Erase Sector(ERSSCR) Command
350 *
351 * This function is used to perform the erase sector command sequence to the flash.
352 *
353 * @param driver Pointer to storage for the driver runtime state.
354 * @return
355 */
356 #if defined(FLASH_DRIVER_IS_FLASH_RESIDENT) && (FLASH_DRIVER_IS_FLASH_RESIDENT == 1)
357 #if defined(__IAR_SYSTEMS_ICC__)
358 __ramfunc
359 #elif defined(__GNUC__)
360 __attribute__((section(".ramfunc"))) __attribute__((__noinline__))
361 #endif
362 #endif
flash_erase_sequence(FMU_Type * base,uint32_t start)363 static void flash_erase_sequence(FMU_Type *base, uint32_t start)
364 {
365 /* clear CCIF bit to launch the command */
366 base->FSTAT = FLASH_FSTAT_CCIF_MASK;
367
368 while ((base->FSTAT & FLASH_FSTAT_PEWEN_MASK) == 0U)
369 {
370 }
371
372 for (uint32_t i = 0u; i < 4u; i++)
373 {
374 *((uint32_t *)(start + i * 4U)) = 0x0U;
375 }
376
377 while ((base->FSTAT & FLASH_FSTAT_PERDY_MASK) == 0U)
378 {
379 }
380
381 base->FSTAT = FLASH_FSTAT_PERDY_MASK;
382
383 /* Check CCIF bit of the flash status register, wait till it is set */
384 while ((base->FSTAT & FLASH_FSTAT_CCIF_MASK) == 0U)
385 {
386 }
387 }
388
389 /*!
390 * @brief Flash Program Command
391 *
392 * This function is used to perform the program command sequence to the flash.
393 *
394 * @param driver Pointer to storage for the driver runtime state.
395 * @return
396 */
397 #if defined(FLASH_DRIVER_IS_FLASH_RESIDENT) && (FLASH_DRIVER_IS_FLASH_RESIDENT == 1)
398 #if defined(__IAR_SYSTEMS_ICC__)
399 __ramfunc
400 #elif defined(__GNUC__)
401 __attribute__((section(".ramfunc"))) __attribute__((__noinline__))
402 #endif
403 #endif
flash_pgm_sequence(FMU_Type * base,uint32_t start,uint32_t * src,uint8_t isPage)404 static void flash_pgm_sequence(FMU_Type *base, uint32_t start, uint32_t *src, uint8_t isPage)
405 {
406 /* clear CCIF bit to launch the command */
407 base->FSTAT = FLASH_FSTAT_CCIF_MASK;
408
409 while ((base->FSTAT & FLASH_FSTAT_PEWEN_MASK) == 0U)
410 {
411 }
412
413 uint8_t lengthInWord;
414
415 if (isPage == 1U)
416 {
417 lengthInWord = FLASH_FEATURE_PAGE_SIZE_IN_WORD;
418 }
419 else
420 {
421 lengthInWord = FLASH_FEATURE_PHRASE_SIZE_IN_WORD;
422 }
423
424 for (uint32_t i = 0; i < lengthInWord; i++)
425 {
426 *((uint32_t *)(start + i * 4U)) = src[i];
427 }
428
429 while ((base->FSTAT & FLASH_FSTAT_PERDY_MASK) == 0U)
430 {
431 }
432
433 base->FSTAT = FLASH_FSTAT_PERDY_MASK;
434
435 /* Check CCIF bit of the flash status register, wait till it is set */
436 while ((base->FSTAT & FLASH_FSTAT_CCIF_MASK) == 0U)
437 {
438 }
439 }
440
441 /*!
442 * @brief FLASH Command
443 *
444 * This function is used to perform the program/erase command sequence to the flash.
445 *
446 * @param driver Pointer to storage for the driver runtime state.
447 * @return An error code or kStatus_FLASH_Success
448 */
flash_command_complete(FMU_Type * base)449 static status_t flash_command_complete(FMU_Type *base)
450 {
451 uint32_t registerValue;
452
453 /* Check error bits */
454 /* Get flash status register value */
455 registerValue = base->FSTAT;
456 status_t status = kStatus_Fail;
457
458 /* checking access error */
459 if ((registerValue & FLASH_FSTAT_ACCERR_MASK) != 0U)
460 {
461 status = kStatus_FLASH_AccessError;
462 }
463 /* checking protection error */
464 else if ((registerValue & FLASH_FSTAT_PVIOL_MASK) != 0U)
465 {
466 status = kStatus_FLASH_ProtectionViolation;
467 }
468 /* check protection level */
469 else if ((registerValue & FLASH_FSTAT_CMDABT_MASK) != 0U)
470 {
471 status = kStatus_FLASH_CommandAborOption;
472 }
473 else if ((registerValue & FLASH_FSTAT_FAIL_MASK) != 0U)
474 {
475 status = kStatus_FLASH_CommandFailure;
476 }
477 else if ((registerValue & FLASH_FSTAT_DFDIF_MASK) != 0U)
478 {
479 status = kStatus_FLASH_EccFaultDetected;
480 base->FSTAT = FLASH_FSTAT_DFDIF_MASK;
481 }
482 else
483 {
484 status = kStatus_FLASH_Success;
485 }
486 return status;
487 }
488