1 /*
2  * Copyright 2018-2021, 2023 NXP
3  * All rights reserved.
4  *
5  * SPDX-License-Identifier: BSD-3-Clause
6  */
7 
8 #include "fsl_iap.h"
9 
10 /* Component ID definition, used by tools. */
11 #ifndef FSL_COMPONENT_ID
12 #define FSL_COMPONENT_ID "platform.drivers.iap"
13 #endif
14 
15 #define HZ_TO_KHZ_DIV 1000U
16 
17 /*******************************************************************************
18  * Definitions
19  ******************************************************************************/
20 #define IAP_ISP_TYPE_I2C  1U
21 #define IAP_ISP_TYPE_SPI  4U
22 #define IAP_ISP_TYPE_SPI1 5U
23 #define IAP_ISP_TYPE_USB0 8U
24 #define IAP_ISP_TYPE_USB1 9U
25 
26 /*! @brief IAP_ENTRY API function type */
27 typedef void (*IAP_ENTRY_T)(uint32_t cmd[], uint32_t stat[]);
28 
29 /*******************************************************************************
30  * Prototypes
31  ******************************************************************************/
32 /*!
33  * @brief Translate the IAP return status.
34  *
35  * @param status IAP status return from the IAP function.
36  *
37  * @return sdk status code.
38  */
39 static inline status_t translate_iap_status(uint32_t status);
40 
41 /*!
42  * @brief IAP_ENTRY API function type.
43  *
44  * Wrapper for rom iap call.
45  *
46  * @param cmd_param IAP command and relevant parameter array.
47  * @param status_result IAP status result array.
48  */
49 static inline void iap_entry(uint32_t *cmd_param, uint32_t *status_result);
50 
51 /*!
52  * @brief IAP_ENTRY API function type.
53  *
54  * Wrapper for rom iap call, but doesn't disable global interrupt.
55  *
56  * @param cmd_param IAP command and relevant parameter array.
57  * @param status_result IAP status result array.
58  */
59 static inline void iap_entry_no_disable_irq(uint32_t *cmd_param, uint32_t *status_result);
60 
61 /*******************************************************************************
62  * Variables
63  ******************************************************************************/
64 
65 /*******************************************************************************
66  * Code
67  ******************************************************************************/
translate_iap_status(uint32_t status)68 static inline status_t translate_iap_status(uint32_t status)
69 {
70     status_t ret = (status_t)status;
71 
72     /* Translate IAP return code to sdk status code */
73     if (status != (uint32_t)kStatus_Success)
74     {
75         ret = MAKE_STATUS((int32_t)kStatusGroup_IAP, (int32_t)status);
76     }
77 
78     return ret;
79 }
80 
iap_entry(uint32_t * cmd_param,uint32_t * status_result)81 static inline void iap_entry(uint32_t *cmd_param, uint32_t *status_result)
82 {
83     __disable_irq();
84     ((IAP_ENTRY_T)FSL_FEATURE_SYSCON_IAP_ENTRY_LOCATION)(cmd_param, status_result);
85     __enable_irq();
86 }
87 
iap_entry_no_disable_irq(uint32_t * cmd_param,uint32_t * status_result)88 static inline void iap_entry_no_disable_irq(uint32_t *cmd_param, uint32_t *status_result)
89 {
90     ((IAP_ENTRY_T)FSL_FEATURE_SYSCON_IAP_ENTRY_LOCATION)(cmd_param, status_result);
91 }
92 
93 /*!
94  * @brief Read part identification number.
95  *
96  * This function is used to read the part identification number.
97  *
98  * @param partID Address to store the part identification number.
99  *
100  * @retval kStatus_IAP_Success Api has been executed successfully.
101  */
IAP_ReadPartID(uint32_t * partID)102 status_t IAP_ReadPartID(uint32_t *partID)
103 {
104     uint32_t command[5] = {0x00U};
105     uint32_t result[5]  = {0x00U};
106 
107     command[0] = (uint32_t)kIapCmd_IAP_ReadPartId;
108     iap_entry(command, result);
109     *partID = result[1];
110 
111     return translate_iap_status(result[0]);
112 }
113 
114 /*!
115  * @brief Read boot code version number.
116  *
117  * This function is used to read the boot code version number.
118  *
119  * @param bootCodeVersion Address to store the boot code version.
120  *
121  * @retval kStatus_IAP_Success Api has been executed successfully.
122  *
123  * note Boot code version is two 32-bit words. Word 0 is the major version, word 1 is the minor version.
124  */
IAP_ReadBootCodeVersion(uint32_t * bootCodeVersion)125 status_t IAP_ReadBootCodeVersion(uint32_t *bootCodeVersion)
126 {
127     uint32_t command[5] = {0x00U};
128     uint32_t result[5]  = {0x00U};
129 
130     command[0] = (uint32_t)kIapCmd_IAP_Read_BootromVersion;
131     iap_entry(command, result);
132     bootCodeVersion[0] = result[1];
133     bootCodeVersion[1] = result[2];
134 
135     return translate_iap_status(result[0]);
136 }
137 
138 /*!
139  * @brief Reinvoke ISP.
140  *
141  * This function is used to invoke the boot loader in ISP mode. It maps boot vectors and configures the peripherals for
142  * ISP.
143  *
144  * @param ispType ISP type selection.
145  * @param status store the possible status.
146  *
147  * @retval kStatus_IAP_ReinvokeISPConfig reinvoke configuration error.
148  *
149  * note The error response will be returned when IAP is disabled or an invalid ISP type selection appears. The call
150  * won't return unless an error occurs, so there can be no status code.
151  */
IAP_ReinvokeISP(uint8_t ispType,uint32_t * status)152 void IAP_ReinvokeISP(uint8_t ispType, uint32_t *status)
153 {
154 #if (defined(FSL_FEATURE_SYSCON_IAP_REINVOKE_ISP_PARAM_POINTER) && FSL_FEATURE_SYSCON_IAP_REINVOKE_ISP_PARAM_POINTER)
155     uint32_t command[5] = {0x00U};
156     uint32_t result[5]  = {0x00U};
157     uint8_t ispParameterArray[8];
158 
159     command[0] = (uint32_t)kIapCmd_IAP_ReinvokeISP;
160     (void)memset(ispParameterArray, 0, sizeof(uint8_t) * 8U);
161     if ((IAP_ISP_TYPE_I2C == ispType) || (IAP_ISP_TYPE_SPI == ispType) || (IAP_ISP_TYPE_SPI1 == ispType))
162     {
163         ispParameterArray[0] = 0x55U;
164     }
165     else if ((IAP_ISP_TYPE_USB0 == ispType) || (IAP_ISP_TYPE_USB1 == ispType))
166     {
167         ispParameterArray[0] = 0xAAU;
168     }
169     else
170     {
171         ispParameterArray[0] = 0x00U;
172     }
173     ispParameterArray[1] = ispType;
174     ispParameterArray[7] = ispParameterArray[0] ^ ispParameterArray[1] ^ ispParameterArray[2] ^ ispParameterArray[3] ^
175                            ispParameterArray[4] ^ ispParameterArray[5] ^ ispParameterArray[6];
176     command[1] = (uint32_t)ispParameterArray;
177     iap_entry_no_disable_irq(command, result);
178     *status = (uint32_t)translate_iap_status(result[0]);
179 #else
180     uint32_t command[5] = {0x00U};
181     uint32_t result[5]  = {0x00U};
182 
183     command[0] = (uint32_t)kIapCmd_IAP_ReinvokeISP;
184     command[1] = (uint32_t)ispType;
185     iap_entry_no_disable_irq(command, result);
186     *status             = (uint32_t)translate_iap_status(result[0]);
187 #endif
188 }
189 
190 /*!
191  * @brief Read unique identification.
192  *
193  * This function is used to read the unique id.
194  *
195  * @param uniqueID store the uniqueID.
196  *
197  * @retval kStatus_IAP_Success Api has been executed successfully.
198  */
IAP_ReadUniqueID(uint32_t * uniqueID)199 status_t IAP_ReadUniqueID(uint32_t *uniqueID)
200 {
201 #if defined(FSL_FEATURE_IAP_READ_UNIQUE_ID_NOWORK) && FSL_FEATURE_IAP_READ_UNIQUE_ID_NOWORK
202     uint32_t *result = (uint32_t *)0x01000100;
203     uint8_t i        = 0;
204 
205     for (i = 0; i < 4; i++)
206         uniqueID[i] = result[i];
207     return kStatus_IAP_Success;
208 #else
209     uint32_t command[5] = {0x00U};
210     uint32_t result[5]  = {0x00U};
211 
212     command[0] = (uint32_t)kIapCmd_IAP_ReadUid;
213     iap_entry(command, result);
214     uniqueID[0] = result[1];
215     uniqueID[1] = result[2];
216     uniqueID[2] = result[3];
217     uniqueID[3] = result[4];
218 
219     return translate_iap_status(result[0]);
220 #endif
221 }
222 
223 #if defined(FLASH_CTRL_FLASHCFG_FLASHTIM_MASK)
224 /*!
225  * @brief Flash memory access time.
226  *
227  * This function is used to configure the access time to the flash memory.
228  *
229  * @param accessTime Flash memory access time FLASHTIM +1 is equal to the
230  *                   number of system clocks used for flash access.
231  */
IAP_ConfigAccessFlashTime(uint32_t accessTime)232 void IAP_ConfigAccessFlashTime(uint32_t accessTime)
233 {
234     uint32_t temp;
235     temp = FLASH_CTRL->FLASHCFG;
236     temp &= ~FLASH_CTRL_FLASHCFG_FLASHTIM_MASK;
237     FLASH_CTRL->FLASHCFG = temp | FLASH_CTRL_FLASHCFG_FLASHTIM(accessTime);
238 }
239 #endif
240 
241 #if defined(FSL_FEATURE_IAP_HAS_READ_FACTORY_SETTINGS_FUNCTION) && FSL_FEATURE_IAP_HAS_READ_FACTORY_SETTINGS_FUNCTION
242 /*!
243  * @brief Read factory settings.
244  *
245  * This function reads the factory settings for calibration registers.
246  *
247  * @param dstRegAddr Address of the targeted calibration register.
248  * @param factoryValue Store the factory value
249  *
250  * @retval kStatus_IAP_Success Api has been executed successfully.
251  * @retval kStatus_IAP_ParamError Param0 is not one of the supported calibration registers.
252  */
IAP_ReadFactorySettings(uint32_t dstRegAddr,uint32_t * factoryValue)253 status_t IAP_ReadFactorySettings(uint32_t dstRegAddr, uint32_t *factoryValue)
254 {
255     uint32_t command[5] = {0x00U};
256     uint32_t result[5]  = {0x00U};
257 
258     command[0] = (uint32_t)kIapCmd_IAP_ReadFactorySettings;
259     command[1] = dstRegAddr;
260     iap_entry(command, result);
261     *factoryValue = result[1];
262 
263     return translate_iap_status(result[0]);
264 }
265 #endif /* FSL_FEATURE_IAP_HAS_READ_FACTORY_SETTINGS_FUNCTION */
266 
267 #if defined(FSL_FEATURE_IAP_HAS_FLASH_FUNCTION) && FSL_FEATURE_IAP_HAS_FLASH_FUNCTION
268 /*!
269  * @brief Prepare sector for write operation.
270  *
271  * This function prepares sector(s) for write/erase operation. This function must be called before calling the
272  * IAP_CopyRamToFlash() or IAP_EraseSector() or IAP_ErasePage() function. The end sector number must be greater than or
273  * equal to the start sector number.
274  *
275  * @param startSector Start sector number.
276  * @param endSector End sector number.
277  *
278  * @retval kStatus_IAP_Success Api has been executed successfully.
279  * @retval kStatus_IAP_NoPower Flash memory block is powered down.
280  * @retval kStatus_IAP_NoClock Flash memory block or controller is not clocked.
281  * @retval kStatus_IAP_InvalidSector Sector number is invalid or end sector number is greater than start sector number.
282  * @retval kStatus_IAP_Busy Flash programming hardware interface is busy.
283  */
IAP_PrepareSectorForWrite(uint32_t startSector,uint32_t endSector)284 status_t IAP_PrepareSectorForWrite(uint32_t startSector, uint32_t endSector)
285 {
286     uint32_t command[5] = {0x00U};
287     uint32_t result[5]  = {0x00U};
288 
289     command[0] = (uint32_t)kIapCmd_IAP_PrepareSectorforWrite;
290     command[1] = startSector;
291     command[2] = endSector;
292     iap_entry(command, result);
293 
294     return translate_iap_status(result[0]);
295 }
296 
297 /*!
298  * @brief Copy RAM to flash.
299  *
300  * This function programs the flash memory. Corresponding sectors must be prepared via IAP_PrepareSectorForWrite before
301  * calling this function.
302  *
303  * @param dstAddr Destination flash address where data bytes are to be written, the address should be multiples
304  *      of FSL_FEATURE_SYSCON_FLASH_PAGE_SIZE_BYTES boundary.
305  * @param srcAddr Source ram address from where data bytes are to be read.
306  * @param numOfBytes Number of bytes to be written, it should be multiples of FSL_FEATURE_SYSCON_FLASH_PAGE_SIZE_BYTES,
307  *      and ranges from FSL_FEATURE_SYSCON_FLASH_PAGE_SIZE_BYTES to FSL_FEATURE_SYSCON_FLASH_SECTOR_SIZE_BYTES.
308  * @param systemCoreClock SystemCoreClock in Hz. It is converted to KHz before calling the rom IAP function. When the
309  *      flash controller has a fixed reference clock, this parameter is bypassed.
310  *
311  * @retval kStatus_IAP_Success Api has been executed successfully.
312  * @retval kStatus_IAP_NoPower Flash memory block is powered down.
313  * @retval kStatus_IAP_NoClock Flash memory block or controller is not clocked.
314  * @retval kStatus_IAP_SrcAddrError Source address is not on word boundary.
315  * @retval kStatus_IAP_DstAddrError Destination address is not on a correct boundary.
316  * @retval kStatus_IAP_SrcAddrNotMapped Source address is not mapped in the memory map.
317  * @retval kStatus_IAP_DstAddrNotMapped Destination address is not mapped in the memory map.
318  * @retval kStatus_IAP_CountError Byte count is not multiple of 4 or is not a permitted value.
319  * @retval kStatus_IAP_NotPrepared Command to prepare sector for write operation has not been executed.
320  * @retval kStatus_IAP_Busy Flash programming hardware interface is busy.
321  */
IAP_CopyRamToFlash(uint32_t dstAddr,uint32_t * srcAddr,uint32_t numOfBytes,uint32_t systemCoreClock)322 status_t IAP_CopyRamToFlash(uint32_t dstAddr, uint32_t *srcAddr, uint32_t numOfBytes, uint32_t systemCoreClock)
323 {
324     uint32_t command[5] = {0x00U};
325     uint32_t result[5]  = {0x00U};
326 
327     command[0] = (uint32_t)kIapCmd_IAP_CopyRamToFlash;
328     command[1] = dstAddr;
329     command[2] = (uint32_t)srcAddr;
330     command[3] = numOfBytes;
331 #if !(defined(FSL_FEATURE_SYSCON_HAS_FLASH_REFERENCE_CLOCK) && FSL_FEATURE_SYSCON_HAS_FLASH_REFERENCE_CLOCK)
332     command[4] = systemCoreClock / HZ_TO_KHZ_DIV;
333 #endif /* FSL_FEATURE_SYSCON_HAS_FLASH_REFERENCE_CLOCK */
334     iap_entry(command, result);
335 
336     return translate_iap_status(result[0]);
337 }
338 
339 /*!
340  * @brief Erase sector.
341  *
342  * This function erases sector(s). The end sector number must be greater than or equal to the start sector number.
343  *
344  * @param startSector Start sector number.
345  * @param endSector End sector number.
346  * @param systemCoreClock SystemCoreClock in Hz. It is converted to KHz before calling the rom IAP function. When the
347  * flash controller has a fixed reference clock, this parameter is bypassed.
348  *
349  * @retval kStatus_IAP_Success Api has been executed successfully.
350  * @retval kStatus_IAP_NoPower Flash memory block is powered down.
351  * @retval kStatus_IAP_NoClock Flash memory block or controller is not clocked.
352  * @retval kStatus_IAP_InvalidSector Sector number is invalid or end sector number is greater than start sector number.
353  * @retval kStatus_IAP_NotPrepared Command to prepare sector for write operation has not been executed.
354  * @retval kStatus_IAP_Busy Flash programming hardware interface is busy.
355  */
IAP_EraseSector(uint32_t startSector,uint32_t endSector,uint32_t systemCoreClock)356 status_t IAP_EraseSector(uint32_t startSector, uint32_t endSector, uint32_t systemCoreClock)
357 {
358     uint32_t command[5] = {0x00U};
359     uint32_t result[5]  = {0x00U};
360 
361     command[0] = (uint32_t)kIapCmd_IAP_EraseSector;
362     command[1] = startSector;
363     command[2] = endSector;
364 #if !(defined(FSL_FEATURE_SYSCON_HAS_FLASH_REFERENCE_CLOCK) && FSL_FEATURE_SYSCON_HAS_FLASH_REFERENCE_CLOCK)
365     command[3] = systemCoreClock / HZ_TO_KHZ_DIV;
366 #endif /* FSL_FEATURE_SYSCON_HAS_FLASH_REFERENCE_CLOCK */
367     iap_entry(command, result);
368 
369     return translate_iap_status(result[0]);
370 }
371 
372 /*!
373  * @brief Erase page.
374  *
375  * This function erases page(s). The end page number must be greater than or equal to the start page number.
376  *
377  * @param startPage Start page number.
378  * @param endPage End page number.
379  * @param systemCoreClock SystemCoreClock in Hz. It is converted to KHz before calling the rom IAP function. When the
380  * flash controller has a fixed reference clock, this parameter is bypassed.
381  *
382  * @retval kStatus_IAP_Success Api has been executed successfully.
383  * @retval kStatus_IAP_NoPower Flash memory block is powered down.
384  * @retval kStatus_IAP_NoClock Flash memory block or controller is not clocked.
385  * @retval kStatus_IAP_InvalidSector Page number is invalid or end page number is greater than start page number.
386  * @retval kStatus_IAP_NotPrepared Command to prepare sector for write operation has not been executed.
387  * @retval kStatus_IAP_Busy Flash programming hardware interface is busy.
388  */
IAP_ErasePage(uint32_t startPage,uint32_t endPage,uint32_t systemCoreClock)389 status_t IAP_ErasePage(uint32_t startPage, uint32_t endPage, uint32_t systemCoreClock)
390 {
391     uint32_t command[5] = {0x00U};
392     uint32_t result[5]  = {0x00U};
393 
394     command[0] = (uint32_t)kIapCmd_IAP_ErasePage;
395     command[1] = startPage;
396     command[2] = endPage;
397 #if !(defined(FSL_FEATURE_SYSCON_HAS_FLASH_REFERENCE_CLOCK) && FSL_FEATURE_SYSCON_HAS_FLASH_REFERENCE_CLOCK)
398     command[3] = systemCoreClock / HZ_TO_KHZ_DIV;
399 #endif /* FSL_FEATURE_SYSCON_HAS_FLASH_REFERENCE_CLOCK */
400     iap_entry(command, result);
401 
402     return translate_iap_status(result[0]);
403 }
404 
405 /*!
406  * @brief Blank check sector(s)
407  *
408  * Blank check single or multiples sectors of flash memory. The end sector number must be greater than or equal to the
409  * start sector number. It can be used to verify the sector erasure after IAP_EraseSector call.
410  *
411  * @param startSector Start sector number.
412  * @param endSector End sector number.
413  * @retval kStatus_IAP_Success One or more sectors are in erased state.
414  * @retval kStatus_IAP_NoPower Flash memory block is powered down.
415  * @retval kStatus_IAP_NoClock Flash memory block or controller is not clocked.
416  * @retval kStatus_IAP_SectorNotblank One or more sectors are not blank.
417  */
IAP_BlankCheckSector(uint32_t startSector,uint32_t endSector)418 status_t IAP_BlankCheckSector(uint32_t startSector, uint32_t endSector)
419 {
420     uint32_t command[5] = {0x00U};
421     uint32_t result[5]  = {0x00U};
422 
423     command[0] = (uint32_t)kIapCmd_IAP_BlankCheckSector;
424     command[1] = startSector;
425     command[2] = endSector;
426     iap_entry(command, result);
427 
428     return translate_iap_status(result[0]);
429 }
430 
431 /*!
432  * @brief Compare memory contents of flash with ram.
433  *
434  * This function compares the contents of flash and ram. It can be used to verify the flash memory contents after
435  * IAP_CopyRamToFlash call.
436  *
437  * @param dstAddr Destination flash address.
438  * @param srcAddr Source ram address.
439  * @param numOfBytes Number of bytes to be compared.
440  *
441  * @retval kStatus_IAP_Success Contents of flash and ram match.
442  * @retval kStatus_IAP_NoPower Flash memory block is powered down.
443  * @retval kStatus_IAP_NoClock Flash memory block or controller is not clocked.
444  * @retval kStatus_IAP_AddrError Address is not on word boundary.
445  * @retval kStatus_IAP_AddrNotMapped Address is not mapped in the memory map.
446  * @retval kStatus_IAP_CountError Byte count is not multiple of 4 or is not a permitted value.
447  * @retval kStatus_IAP_CompareError Destination and source memory contents do not match.
448  */
IAP_Compare(uint32_t dstAddr,uint32_t * srcAddr,uint32_t numOfBytes)449 status_t IAP_Compare(uint32_t dstAddr, uint32_t *srcAddr, uint32_t numOfBytes)
450 {
451     uint32_t command[5] = {0x00U};
452     uint32_t result[5]  = {0x00U};
453 
454     command[0] = (uint32_t)kIapCmd_IAP_Compare;
455     command[1] = dstAddr;
456     command[2] = (uint32_t)srcAddr;
457     command[3] = numOfBytes;
458     iap_entry(command, result);
459 
460     return translate_iap_status(result[0]);
461 }
462 
463 #if defined(FSL_FEATURE_IAP_HAS_FLASH_EXTENDED_SIGNATURE_READ) && FSL_FEATURE_IAP_HAS_FLASH_EXTENDED_SIGNATURE_READ
464 /*!
465  * @brief Extended Read signature.
466  *
467  * This function calculates the signature value for one or more pages of on-chip flash memory.
468  *
469  * @param startPage Start page number.
470  * @param endPage End page number.
471  * @param numOfStates Number of wait states.
472  * @param signature Address to store the signature value.
473  *
474  * @retval kStatus_IAP_Success Api has been executed successfully.
475  */
IAP_ExtendedFlashSignatureRead(uint32_t startPage,uint32_t endPage,uint32_t numOfStates,uint32_t * signature)476 status_t IAP_ExtendedFlashSignatureRead(uint32_t startPage, uint32_t endPage, uint32_t numOfStates, uint32_t *signature)
477 {
478     uint32_t command[5] = {0x00U};
479     uint32_t result[5]  = {0x00U};
480 
481     command[0] = (uint32_t)kIapCmd_IAP_ExtendedReadSignature;
482     command[1] = startPage;
483     command[2] = endPage;
484     command[3] = numOfStates;
485     command[4] = 0;
486     iap_entry(command, result);
487     signature[0] = result[4];
488     signature[1] = result[3];
489     signature[2] = result[2];
490     signature[3] = result[1];
491 
492     return translate_iap_status(result[0]);
493 }
494 #endif /* FSL_FEATURE_IAP_HAS_FLASH_EXTENDED_SIGNATURE_READ */
495 
496 #if defined(FSL_FEATURE_IAP_HAS_FLASH_SIGNATURE_READ) && FSL_FEATURE_IAP_HAS_FLASH_SIGNATURE_READ
497 /*!
498  * @brief Read flash signature.
499  *
500  * This funtion is used to obtain a 32-bit signature value of the entire flash memory.
501  *
502  * @param signature Address to store the 32-bit generated signature value.
503  *
504  * @retval kStatus_IAP_Success Api has been executed successfully.
505  */
IAP_ReadFlashSignature(uint32_t * signature)506 status_t IAP_ReadFlashSignature(uint32_t *signature)
507 {
508     uint32_t command[5] = {0x00U};
509     uint32_t result[5]  = {0x00U};
510 
511     command[0] = (uint32_t)kIapCmd_IAP_ReadSignature;
512     iap_entry(command, result);
513     *signature = result[1];
514 
515     return translate_iap_status(result[0]);
516 }
517 #endif /* FSL_FEATURE_IAP_HAS_FLASH_SIGNATURE_READ */
518 #endif /* FSL_FEATURE_IAP_HAS_FLASH_FUNCTION */
519 
520 #if (defined(FSL_FEATURE_IAP_HAS_EEPROM_FUNCTION) && (FSL_FEATURE_IAP_HAS_EEPROM_FUNCTION == 1))
521 /*!
522  * @brief Read EEPROM page.
523  *
524  * This function is used to read given page of EEPROM into the memory provided.
525  *
526  * @param pageNumber EEPROM page number.
527  * @param dstAddr Memory address to store the value read from EEPROM.
528  * @param systemCoreClock Current core clock frequency in kHz.
529  *
530  * @retval kStatus_IAP_Success Api has been executed successfully.
531  * @retval kStatus_IAP_InvalidSector Sector number is invalid.
532  * @retval kStatus_IAP_DstAddrNotMapped Destination address is not mapped in the memory map.
533  *
534  * note Value 0xFFFFFFFF of systemCoreClock will retain the timing and clock settings for EEPROM.
535  */
IAP_ReadEEPROMPage(uint32_t pageNumber,uint32_t * dstAddr,uint32_t systemCoreClock)536 status_t IAP_ReadEEPROMPage(uint32_t pageNumber, uint32_t *dstAddr, uint32_t systemCoreClock)
537 {
538     uint32_t command[5] = {0x00U};
539     uint32_t result[5]  = {0x00U};
540 
541     command[0] = (uint32_t)kIapCmd_IAP_ReadEEPROMPage;
542     command[1] = pageNumber;
543     command[2] = (uint32_t)dstAddr;
544     command[3] = systemCoreClock / HZ_TO_KHZ_DIV;
545     iap_entry(command, result);
546 
547     return translate_iap_status(result[0]);
548 }
549 
550 /*!
551  * @brief Write EEPROM page.
552  *
553  * This function is used to write given data in the provided memory to a page of EEPROM.
554  *
555  * @param pageNumber EEPROM page number.
556  * @param srcAddr Memory address holding data to be stored on to EEPROM page.
557  * @param systemCoreClock Current core clock frequency in kHz.
558  *
559  * @retval kStatus_IAP_Success Api has been executed successfully.
560  * @retval kStatus_IAP_InvalidSector Sector number is invalid.
561  * @retval kStatus_IAP_SrcAddrNotMapped Source address is not mapped in the memory map.
562  *
563  * note Value 0xFFFFFFFF of systemCoreClock will retain the timing and clock settings for EEPROM
564  */
IAP_WriteEEPROMPage(uint32_t pageNumber,uint32_t * srcAddr,uint32_t systemCoreClock)565 status_t IAP_WriteEEPROMPage(uint32_t pageNumber, uint32_t *srcAddr, uint32_t systemCoreClock)
566 {
567     uint32_t command[5] = {0x00U};
568     uint32_t result[5]  = {0x00U};
569 
570     command[0] = (uint32_t)kIapCmd_IAP_WriteEEPROMPage;
571     command[1] = pageNumber;
572     command[2] = (uint32_t)srcAddr;
573     command[3] = systemCoreClock / HZ_TO_KHZ_DIV;
574     iap_entry(command, result);
575 
576     return translate_iap_status(result[0]);
577 }
578 #endif /* FSL_FEATURE_IAP_HAS_EEPROM_FUNCTION */
579 
580 #if defined(FSL_FEATURE_IAP_HAS_FAIM_FUNCTION) && FSL_FEATURE_IAP_HAS_FAIM_FUNCTION
581 /*!
582  * @brief Read FAIM page.
583  *
584  * This function is used to read given page of FAIM into the memory provided.
585  *
586  * @param pageNumber FAIM page number.
587  * @param dstAddr Memory address to store the value read from FAIM.
588  *
589  * @retval kStatus_IAP_Success Api has been executed successfully.
590  * @retval kStatus_IAP_DstAddrNotMapped Destination address is not mapped in the memory map.
591  */
IAP_ReadFAIMPage(uint32_t pageNumber,uint32_t * dstAddr)592 status_t IAP_ReadFAIMPage(uint32_t pageNumber, uint32_t *dstAddr)
593 {
594     uint32_t command[5] = {0x00U};
595     uint32_t result[5]  = {0x00U};
596 
597     command[0] = (uint32_t)kIapCmd_IAP_ReadFAIMPage;
598     command[1] = pageNumber;
599     command[2] = (uint32_t)dstAddr;
600     iap_entry(command, result);
601 
602     return translate_iap_status(result[0]);
603 }
604 
605 /*!
606  * @brief Write FAIM page.
607  *
608  * This function is used to write given data in the provided memory to a page of G.
609  *
610  * @param pageNumber FAIM page number.
611  * @param srcAddr Memory address holding data to be stored on to FAIM page.
612  *
613  * @retval kStatus_IAP_Success Api has been executed successfully.
614  * @retval kStatus_IAP_SrcAddrNotMapped Source address is not mapped in the memory map.
615  */
IAP_WriteFAIMPage(uint32_t pageNumber,uint32_t * srcAddr)616 status_t IAP_WriteFAIMPage(uint32_t pageNumber, uint32_t *srcAddr)
617 {
618     uint32_t command[5] = {0x00U};
619     uint32_t result[5]  = {0x00U};
620 
621     command[0] = (uint32_t)kIapCmd_IAP_WriteFAIMPage;
622     command[1] = pageNumber;
623     command[2] = (uint32_t)srcAddr;
624     iap_entry(command, result);
625 
626     return translate_iap_status(result[0]);
627 }
628 #endif /* FSL_FEATURE_IAP_HAS_FAIM_FUNCTION */
629