1 /**************************************************************************//**
2  * @file     RMC.c
3  * @version  V1.00
4  * @brief    M2L31 series RRAM Memory Controller driver source file
5  *
6  * SPDX-License-Identifier: Apache-2.0
7  * @copyright (C) 2016-2020 Nuvoton Technology Corp. All rights reserved.
8 *****************************************************************************/
9 
10 #include <stdio.h>
11 
12 #include "NuMicro.h"
13 
14 
15 /** @addtogroup Standard_Driver Standard Driver
16   @{
17 */
18 
19 /** @addtogroup RMC_Driver RMC Driver
20   @{
21 */
22 
23 
24 /** @addtogroup RMC_EXPORTED_FUNCTIONS RMC Exported Functions
25   @{
26 */
27 
28 int32_t  g_RMC_i32ErrCode;
29 
30 /**
31   * @brief    Disable ISP Functions
32   *
33   * @param    None
34   *
35   * @return   None
36   *
37   * @details  This function will clear ISPEN bit of ISPCON to disable ISP function
38   *
39   */
RMC_Close(void)40 void RMC_Close(void)
41 {
42     RMC->ISPCTL &= ~RMC_ISPCTL_ISPEN_Msk;
43 }
44 
45 /**
46   * @brief     Config XOM Region
47   * @param[in] u32XomNum    The XOM number(0~3)
48   * @param[in] u32XomBase   The XOM region base address.
49   * @param[in] u8XomPage   The XOM page number of region size.
50   *
51   * @retval   0   Success
52   * @retval   1   XOM is has already actived.
53   * @retval   -1  Program failed.
54   * @retval   -2  Invalid XOM number.
55   *
56   * @details  Program XOM base address and XOM size(page)
57   */
RMC_ConfigXOM(uint32_t u32XomNum,uint32_t u32XomBase,uint8_t u8XomPage)58 int32_t RMC_ConfigXOM(uint32_t u32XomNum, uint32_t u32XomBase, uint8_t u8XomPage)
59 {
60     int32_t  ret = 0;
61 
62     g_RMC_i32ErrCode = 0;
63 
64     if(u32XomNum >= 4UL)
65     {
66         ret = -2;
67     }
68 
69     if(ret == 0)
70     {
71         ret = RMC_GetXOMState(u32XomNum);
72     }
73 
74     if(ret == 0)
75     {
76         ret = g_RMC_i32ErrCode = RMC_Write(RMC_XOM_BASE + (u32XomNum * 0x10u),u32XomBase);
77         if(g_RMC_i32ErrCode == 0)
78             ret = g_RMC_i32ErrCode = RMC_Write(RMC_XOM_BASE + (u32XomNum * 0x10u + 0x04u),u8XomPage);
79 
80         if(g_RMC_i32ErrCode == 0)
81             ret = g_RMC_i32ErrCode = RMC_Write(RMC_XOM_BASE + (u32XomNum * 0x10u + 0x08u),0);
82 
83     }
84     return ret;
85 }
86 
87 /**
88   * @brief  Execute Erase XOM Region
89   *
90   * @param[in]  u32XomNum  The XOMRn(n=0~3)
91   *
92   * @return   XOM erase success or not.
93   * @retval    0  Success
94   * @retval   -1  Erase failed
95   * @retval   -2  Invalid XOM number.
96   *
97   * @details Execute RMC_ISPCMD_PAGE_ERASE command to erase XOM.
98   */
RMC_EraseXOM(uint32_t u32XomNum)99 int32_t RMC_EraseXOM(uint32_t u32XomNum)
100 {
101     uint32_t u32Addr = 0UL;
102     int32_t i32Active, err = 0;
103     uint32_t  tout;
104     g_RMC_i32ErrCode = 0;
105     if(u32XomNum >= 5UL)
106     {
107         err = -2;
108     }
109 
110     if(err == 0)
111     {
112         i32Active = RMC_GetXOMState(u32XomNum);
113 
114         RMC->ISPCTL = RMC->ISPCTL & ~BIT8;
115         if(i32Active)
116         {
117             switch(u32XomNum)
118             {
119             case 0u:
120                 u32Addr = (RMC->XOMR0STS & 0xFFFFFF00u) >> 8u;
121                 break;
122             case 1u:
123                 u32Addr = (RMC->XOMR1STS & 0xFFFFFF00u) >> 8u;
124                 break;
125             case 2u:
126                 u32Addr = (RMC->XOMR2STS & 0xFFFFFF00u) >> 8u;
127                 break;
128             case 3u:
129                 u32Addr = (RMC->XOMR3STS & 0xFFFFFF00u) >> 8u;
130                 break;
131             case 4u:
132                 u32Addr = (RMC->XOMR0STS & 0xFFFFFF00u) >> 8u;
133                 RMC->ISPCMD = RMC_ISPCMD_PAGE_ERASE;
134                 RMC->ISPADDR = u32Addr;
135                 RMC->ISPDAT = 0x0u;
136                 RMC->ISPTRG = 0x1u;
137                 goto test;
138                 break;
139             default:
140                 break;
141             }
142             RMC->ISPCMD = RMC_ISPCMD_PAGE_ERASE;
143             RMC->ISPADDR = u32Addr;
144             RMC->ISPDAT = 0x55aa03u;
145             RMC->ISPTRG = 0x1u;
146 test:
147 #if ISBEN
148             __ISB();
149 #endif
150             tout = RMC_TIMEOUT_ERASE;
151             while ((--tout > 0) && RMC->ISPTRG) {}
152             if (tout == 0)
153                 err = -1;
154 
155             /* Check ISPFF flag to know whether erase OK or fail. */
156             if(RMC->ISPCTL & RMC_ISPCTL_ISPFF_Msk)
157             {
158                 RMC->ISPCTL |= RMC_ISPCTL_ISPFF_Msk;
159                 printf(" * ISPFF is set\n");
160                 err = -1;
161             }
162         }
163         else
164         {
165             err = -1;
166         }
167     }
168     return err;
169 }
170 
171 /**
172   * @brief  Check the XOM is actived or not.
173   *
174   * @param[in] u32XomNum    The xom number(0~3).
175   *
176   * @retval   1   XOM is actived.
177   * @retval   0   XOM is not actived.
178   * @retval   -2  Invalid XOM number.
179   *
180   * @details To get specify XOMRn(n=0~3) active status
181   */
RMC_GetXOMState(uint32_t u32XomNum)182 int32_t RMC_GetXOMState(uint32_t u32XomNum)
183 {
184     uint32_t u32act;
185     int32_t  ret = 0;
186 
187     if(u32XomNum >= 4UL)
188     {
189         ret = -2;
190     }
191 
192     if(ret >= 0)
193     {
194         u32act = (((RMC->XOMSTS) & 0xful) & (1ul << u32XomNum)) >> u32XomNum;
195         ret = (int32_t)u32act;
196     }
197     return ret;
198 }
199 
200 /**
201   * @brief Enable RMC ISP function
202   * @return None
203   */
RMC_Open(void)204 void RMC_Open(void)
205 {
206     RMC->ISPCTL |=  RMC_ISPCTL_ISPEN_Msk;
207 }
208 
209 
210 /**
211   * @brief Execute RMC_ISPCMD_READ command to read a word from flash.
212   * @param[in]  u32Addr Address of the flash location to be read.
213   *             It must be a word aligned address.
214   * @return The word data read from specified flash address.
215   */
RMC_Read(uint32_t u32Addr)216 uint32_t RMC_Read(uint32_t u32Addr)
217 {
218     uint32_t  tout;
219 
220     g_RMC_i32ErrCode = 0;
221     RMC->ISPCTL = RMC->ISPCTL & ~BIT8;
222     RMC->ISPCMD = RMC_ISPCMD_READ;
223     RMC->ISPADDR = u32Addr;
224     RMC->ISPTRG = RMC_ISPTRG_ISPGO_Msk;
225     tout = RMC_TIMEOUT_READ;
226     while ((--tout > 0) && (RMC->ISPTRG & RMC_ISPTRG_ISPGO_Msk)) {}
227     if (tout == 0)
228     {
229         g_RMC_i32ErrCode = -1;
230         return 0xFFFFFFFF;
231     }
232     if(RMC->ISPCTL & RMC_ISPCTL_ISPFF_Msk)
233     {
234         RMC->ISPCTL |= RMC_ISPCTL_ISPFF_Msk;
235 //        printf(" * ISPFF is set\n");
236         g_RMC_i32ErrCode = -1;
237         return 0xFFFFFFFF;
238     }
239     return RMC->ISPDAT;
240 }
241 
242 /**
243   * @brief    Get the base address of Data Flash if enabled.
244   * @retval   The base address of Data Flash
245   */
RMC_ReadDataFlashBaseAddr(void)246 uint32_t RMC_ReadDataFlashBaseAddr(void)
247 {
248     return RMC->DFBA;
249 }
250 
251 /**
252   * @brief      Set boot source from LDROM or APROM after next software reset
253   * @param[in]  i32BootSrc
254   *                1: Boot from LDROM
255   *                0: Boot from APROM
256   * @return    None
257   * @details   This function is used to switch APROM boot or LDROM boot. User need to call
258   *            RMC_SetBootSource to select boot source first, then use CPU reset or
259   *            System Reset Request to reset system.
260   */
RMC_SetBootSource(int32_t i32BootSrc)261 void RMC_SetBootSource(int32_t i32BootSrc)
262 {
263     if(i32BootSrc)
264     {
265         RMC->ISPCTL |= RMC_ISPCTL_BS_Msk; /* Boot from LDROM */
266     }
267     else
268     {
269         RMC->ISPCTL &= ~RMC_ISPCTL_BS_Msk;/* Boot from APROM */
270     }
271 }
272 
273 /**
274   * @brief Get the current boot source.
275   * @return The current boot source.
276   * @retval   0  Is boot from APROM.
277   * @retval   1  Is boot from LDROM.
278   */
RMC_GetBootSource(void)279 int32_t RMC_GetBootSource (void)
280 {
281     int32_t  ret = 0;
282 
283     if (RMC->ISPCTL & RMC_ISPCTL_BS_Msk)
284     {
285         ret = 1;
286     }
287 
288     return ret;
289 }
290 
291 /**
292   * @brief Execute ISP RMC_ISPCMD_PROGRAM to program a word to flash.
293   * @param[in]  u32Addr Address of the flash location to be programmed.
294   *             It must be a word aligned address.
295   * @param[in]  u32Data The word data to be programmed.
296   * @return None
297   */
RMC_Write(uint32_t u32Addr,uint32_t u32Data)298 int32_t RMC_Write(uint32_t u32Addr, uint32_t u32Data)
299 {
300     uint32_t  tout;
301 
302     g_RMC_i32ErrCode = 0;
303     RMC->ISPCTL = RMC->ISPCTL & ~BIT8;
304     RMC->ISPCMD = RMC_ISPCMD_CLEAR_DATA_BUFFER;
305     RMC->ISPADDR = 0x00000000;
306     RMC->ISPTRG = RMC_ISPTRG_ISPGO_Msk;
307 
308     tout = RMC_TIMEOUT_WRITE;
309     while ((--tout > 0) && (RMC->ISPTRG & RMC_ISPTRG_ISPGO_Msk)) {}
310     if (tout == 0)
311     {
312         g_RMC_i32ErrCode = -1;
313         return -1;
314     }
315 
316     if (RMC->ISPSTS & RMC_ISPSTS_ISPFF_Msk)
317     {
318         RMC->ISPSTS |= RMC_ISPSTS_ISPFF_Msk;
319         g_RMC_i32ErrCode = -1;
320         return -1;
321     }
322     RMC->ISPCMD = RMC_ISPCMD_LOAD_DATA_BUFFER;
323     RMC->ISPADDR = u32Addr;
324     RMC->ISPDAT = u32Data;
325     RMC->ISPTRG = RMC_ISPTRG_ISPGO_Msk;
326 
327     tout = RMC_TIMEOUT_WRITE;
328     while ((--tout > 0) && (RMC->ISPTRG & RMC_ISPTRG_ISPGO_Msk)) {}
329     if (tout == 0)
330     {
331         g_RMC_i32ErrCode = -1;
332         return -1;
333     }
334 
335     if (RMC->ISPSTS & RMC_ISPSTS_ISPFF_Msk)
336     {
337         RMC->ISPSTS |= RMC_ISPSTS_ISPFF_Msk;
338         g_RMC_i32ErrCode = -1;
339         return -1;
340     }
341 
342     RMC->ISPCMD = RMC_ISPCMD_PROGRAM;
343     RMC->ISPADDR = u32Addr;
344     RMC->ISPDAT = u32Data;
345     RMC->ISPTRG = RMC_ISPTRG_ISPGO_Msk;
346 
347     tout = RMC_TIMEOUT_WRITE;
348     while ((--tout > 0) && (RMC->ISPTRG & RMC_ISPTRG_ISPGO_Msk)) {}
349     if (tout == 0)
350     {
351         g_RMC_i32ErrCode = -1;
352         return -1;
353     }
354 
355     if (RMC->ISPSTS & RMC_ISPSTS_ISPFF_Msk)
356     {
357         RMC->ISPSTS |= RMC_ISPSTS_ISPFF_Msk;
358         g_RMC_i32ErrCode = -1;
359         return -1;
360     }
361     return 0;
362 }
363 
364 /**
365   * @brief Execute RMC_ISPCMD_PAGE_ERASE command to erase a flash page. The page size is 4096 bytes.
366   * @param[in]  u32PageAddr Address of the flash page to be erased.
367   *             It must be a 4096 bytes aligned address.
368   * @return ISP page erase success or not.
369   * @retval   0  Success
370   * @retval   -1  Erase failed
371   */
RMC_Erase(uint32_t u32PageAddr)372 int32_t RMC_Erase(uint32_t u32PageAddr)
373 {
374     uint32_t  addr = 0;
375     int32_t  ret = 0;
376     for(addr =0; addr<RMC_FLASH_PAGE_SIZE; addr+=4)
377         ret = ret | RMC_Write(u32PageAddr + addr, 0xFFFFFFFF);
378 
379     return ret;
380 }
381 
382 
383 /**
384   * @brief Execute RMC_ISPCMD_PAGE_ERASE command to erase a flash page. The page size is 4096 bytes.
385   * @param[in]  u32PageAddr Address of the flash page to be erased.
386   *             It must be a 4096 bytes aligned address.
387   * @return ISP page erase success or not.
388   * @retval   0  Success
389   * @retval   -1  Erase failed
390   */
RMC_MassErase(void)391 int32_t RMC_MassErase(void)
392 {
393     int32_t  ret = 0;
394 
395     uint32_t  tout;
396 
397     g_RMC_i32ErrCode = 0;
398     RMC->ISPCMD = 0x26;
399     RMC->ISPADDR = 0;
400     RMC->ISPTRG = RMC_ISPTRG_ISPGO_Msk;
401 
402     tout = 0xFFFFFFFF;
403     while ((--tout > 0) && (RMC->ISPTRG & RMC_ISPTRG_ISPGO_Msk)) {}
404     if (tout == 0)
405     {
406         g_RMC_i32ErrCode = -1;
407         return -1;
408     }
409 
410     if (RMC->ISPSTS & RMC_ISPSTS_ISPFF_Msk)
411     {
412         RMC->ISPSTS |= RMC_ISPSTS_ISPFF_Msk;
413         g_RMC_i32ErrCode = -1;
414         return -1;
415     }
416 
417     return ret;
418 }
419 /**
420   * @brief Execute RMC_ISPCMD_READ command to read User Configuration.
421   * @param[out]  u32Config A two-word array.
422   *              u32Config[0] holds CONFIG0, while u32Config[1] holds CONFIG1.
423   * @param[in] u32Count Available word count in u32Config.
424   * @return Success or not.
425   * @retval   0  Success.
426   * @retval   -1  Invalid parameter.
427   */
RMC_ReadConfig(uint32_t u32Config[],uint32_t u32Count)428 int32_t RMC_ReadConfig(uint32_t u32Config[], uint32_t u32Count)
429 {
430     int32_t   ret = 0;
431 
432     u32Config[0] = RMC_Read(RMC_CONFIG_BASE);
433 
434     if (u32Count < 2UL)
435     {
436         ret = -1;
437     }
438     else
439     {
440         u32Config[1] = RMC_Read(RMC_CONFIG_BASE+4UL);
441     }
442     return ret;
443 }
444 
445 
446 /**
447   * @brief Execute ISP commands to erase then write User Configuration.
448   * @param[in] u32Config   A two-word array.
449   *            u32Config[0] holds CONFIG0, while u32Config[1] holds CONFIG1.
450   * @param[in] u32Count    The number of User Configuration words to be written.
451   * @return Success or not.
452   * @retval   0   Success
453   * @retval   -1  Failed
454   */
RMC_WriteConfig(uint32_t u32Config[],uint32_t u32Count)455 int32_t RMC_WriteConfig(uint32_t u32Config[], uint32_t u32Count)
456 {
457     int   i;
458 
459     RMC_ENABLE_CFG_UPDATE();
460 
461     RMC->ISPCTL = RMC->ISPCTL & ~BIT8;
462 
463     for (i = 0; i < u32Count; i++)
464     {
465         if (RMC_Write(RMC_CONFIG_BASE+i*4UL, u32Config[i]) != 0)
466         {
467             RMC_DISABLE_CFG_UPDATE();
468             return -1;
469         }
470         if (RMC_Read(RMC_CONFIG_BASE+i*4UL) != u32Config[i])
471         {
472             RMC_DISABLE_CFG_UPDATE();
473             return -1;
474         }
475         if (g_RMC_i32ErrCode != 0)
476         {
477             RMC_DISABLE_CFG_UPDATE();
478             return -1;
479         }
480     }
481 
482     RMC_DISABLE_CFG_UPDATE();
483     return 0;
484 }
485 
486 
487 /**
488   * @brief Run CRC32 checksum calculation and get result.
489   * @param[in] u32addr   Starting flash address. It must be a page aligned address.
490   * @param[in] u32count  Byte count of flash to be calculated. It must be multiple of 512 bytes.
491   * @return Success or not.
492   * @retval   0           Success.
493   * @retval   0xFFFFFFFF  Invalid parameter.
494   */
RMC_GetChkSum(uint32_t u32addr,uint32_t u32count)495 uint32_t  RMC_GetChkSum(uint32_t u32addr, uint32_t u32count)
496 {
497     uint32_t   ret, tout;
498 
499     g_RMC_i32ErrCode = 0;
500 
501     if ((u32addr % 512UL) || (u32count % 512UL))
502     {
503         ret = 0xFFFFFFFF;
504     }
505     else
506     {
507         RMC->ISPCTL = RMC->ISPCTL & ~BIT8;
508         RMC->ISPCMD  = RMC_ISPCMD_RUN_CKS;
509         RMC->ISPADDR = u32addr;
510         RMC->ISPDAT  = u32count;
511         RMC->ISPTRG  = RMC_ISPTRG_ISPGO_Msk;
512 
513         tout = RMC_TIMEOUT_CHKSUM;
514         while ((--tout > 0) && (RMC->ISPSTS & RMC_ISPSTS_ISPBUSY_Msk)) {}
515         if (tout == 0)
516         {
517             g_RMC_i32ErrCode = -1;
518             return 0xFFFFFFFF;
519         }
520 
521         if (RMC->ISPSTS & RMC_ISPSTS_ISPFF_Msk)
522         {
523             RMC->ISPSTS |= RMC_ISPSTS_ISPFF_Msk;
524             g_RMC_i32ErrCode = -1;
525             return -1;
526         }
527         RMC->ISPCMD = RMC_ISPCMD_READ_CKS;
528         RMC->ISPADDR    = u32addr;
529         RMC->ISPTRG = RMC_ISPTRG_ISPGO_Msk;
530 
531         tout = RMC_TIMEOUT_CHKSUM;
532         while ((--tout > 0) && (RMC->ISPSTS & RMC_ISPSTS_ISPBUSY_Msk)) {}
533         if (tout == 0)
534         {
535             g_RMC_i32ErrCode = -1;
536             return 0xFFFFFFFF;
537         }
538 
539         if (RMC->ISPSTS & RMC_ISPSTS_ISPFF_Msk)
540         {
541             RMC->ISPSTS |= RMC_ISPSTS_ISPFF_Msk;
542             g_RMC_i32ErrCode = -1;
543             return 0xFFFFFFFF;
544         }
545         ret = RMC->ISPDAT;
546     }
547 
548     return ret;
549 }
550 
551 
552 /**
553   * @brief Run flash all one verification and get result.
554   * @param[in] u32addr   Starting flash address. It must be a page aligned address.
555   * @param[in] u32count  Byte count of flash to be calculated. It must be multiple of 512 bytes.
556   * @retval   READ_ALLONE_YES      The contents of verified flash area are 0xFFFFFFFF.
557   * @retval   READ_ALLONE_NOT  Some contents of verified flash area are not 0xFFFFFFFF.
558   * @retval   READ_ALLONE_CMD_FAIL  Unexpected error occurred.
559   * @note     Global error code g_RMC_i32ErrCode
560   *           -1  RUN_ALL_ONE or CHECK_ALL_ONE commands time-out
561   */
RMC_CheckAllOne(uint32_t u32addr,uint32_t u32count)562 uint32_t  RMC_CheckAllOne(uint32_t u32addr, uint32_t u32count)
563 {
564     uint32_t  ret = READ_ALLONE_CMD_FAIL;
565     int32_t   i32TimeOutCnt0, i32TimeOutCnt1;
566 
567     g_RMC_i32ErrCode = 0;
568 
569     RMC->ISPSTS = 0x80UL;   /* clear check all one bit */
570 
571     RMC->ISPCMD   = RMC_ISPCMD_RUN_ALL1;
572     RMC->ISPADDR  = u32addr;
573     RMC->ISPDAT   = u32count;
574     RMC->ISPTRG   = RMC_ISPTRG_ISPGO_Msk;
575 
576     i32TimeOutCnt0 = RMC_TIMEOUT_CHKALLONE;
577     while(RMC->ISPSTS & RMC_ISPSTS_ISPBUSY_Msk)
578     {
579         if( i32TimeOutCnt0-- <= 0)
580         {
581             g_RMC_i32ErrCode = -1;
582             break;
583         }
584     }
585 
586     if(g_RMC_i32ErrCode == 0)
587     {
588         i32TimeOutCnt1 = RMC_TIMEOUT_CHKALLONE;
589         do
590         {
591             RMC->ISPCMD = RMC_ISPCMD_READ_ALL1;
592             RMC->ISPADDR = u32addr;
593             RMC->ISPTRG = RMC_ISPTRG_ISPGO_Msk;
594 
595             i32TimeOutCnt0 = RMC_TIMEOUT_CHKALLONE;
596             while(RMC->ISPSTS & RMC_ISPSTS_ISPBUSY_Msk)
597             {
598                 if( i32TimeOutCnt0-- <= 0)
599                 {
600                     g_RMC_i32ErrCode = -1;
601                     break;
602                 }
603             }
604 
605             if( i32TimeOutCnt1-- <= 0)
606             {
607                 g_RMC_i32ErrCode = -1;
608             }
609         }
610         while( (RMC->ISPDAT == 0UL) && (g_RMC_i32ErrCode == 0) );
611     }
612 
613     if( g_RMC_i32ErrCode == 0 )
614     {
615         if(RMC->ISPDAT == READ_ALLONE_YES)
616             ret = READ_ALLONE_YES;
617         else if(RMC->ISPDAT == READ_ALLONE_NOT)
618             ret = READ_ALLONE_NOT;
619         else
620             g_RMC_i32ErrCode = -1;
621     }
622 
623     return ret;
624 }
625 
626 /**
627   * @brief     Remap Bank0/Bank1
628   *
629   * @param[in] u32Bank    Bank Num which will remap to.
630   *
631   * @retval    0   Success
632   * @retval    -1  Program failed.
633   *
634   * @details  Remap Bank0/Bank1
635   *
636   * @note     Global error code g_FMC_i32ErrCode
637   *           -1  Program failed or time-out
638   */
RMC_RemapBank(uint32_t u32BankAddr)639 int32_t RMC_RemapBank(uint32_t u32BankAddr)
640 {
641     int32_t  ret = 0;
642     uint32_t  tout;
643 
644     g_RMC_i32ErrCode = 0;
645     RMC->ISPCMD = RMC_ISPCMD_BANK_REMAP;
646     RMC->ISPADDR = u32BankAddr;
647     RMC->ISPDAT = 0x5AA55AA5UL;
648     RMC->ISPTRG = RMC_ISPTRG_ISPGO_Msk;
649 
650     tout = RMC_TIMEOUT_WRITE;
651     while ((--tout > 0) && (RMC->ISPTRG & RMC_ISPTRG_ISPGO_Msk)) {}
652     if (tout == 0)
653     {
654         g_RMC_i32ErrCode = -1;
655         return -1;
656     }
657 
658     if (RMC->ISPSTS & RMC_ISPSTS_ISPFF_Msk)
659     {
660         RMC->ISPSTS |= RMC_ISPSTS_ISPFF_Msk;
661         g_RMC_i32ErrCode = -1;
662         printf("ispff is set!!\n");
663         return -1;
664     }
665 
666     return ret;
667 }
668 
669 /**
670   * @brief  Read the 64-bits data from the specified OTP.
671   * @param[in] otp_num    The OTP number.
672   * @param[in] low_word   Low word of the 64-bits data.
673   * @param[in] high_word   Low word of the 64-bits data.
674   * @retval   0   Success
675   * @retval   -1  Read failed.
676   * @retval   -2  Invalid OTP number.
677   */
RMC_ReadOTP(uint32_t otp_num,uint32_t * low_word,uint32_t * high_word)678 int32_t RMC_ReadOTP(uint32_t otp_num, uint32_t *low_word, uint32_t *high_word)
679 {
680     int32_t  ret = 0;
681 
682     if (otp_num > 255UL)
683     {
684         ret = -2;
685     }
686 
687     if (ret == 0)
688     {
689         *low_word  = RMC_Read(RMC_OTP_BASE + otp_num * 8UL);
690         if(g_RMC_i32ErrCode == 0)
691             *high_word = RMC_Read(RMC_OTP_BASE + otp_num * 8UL +4);
692     }
693     return ret;
694 }
695 
696 /**
697   * @brief  Lock the specified OTP.
698   * @param[in] otp_num    The OTP number.
699   * @retval   0   Success
700   * @retval   -1  Failed to write OTP lock bits.
701   * @retval   -2  Invalid OTP number.
702   */
RMC_LockOTP(uint32_t otp_num)703 int32_t RMC_LockOTP(uint32_t otp_num)
704 {
705     int32_t  ret = 0;
706 
707     if (otp_num > 255UL)
708     {
709         ret = -2;
710     }
711 
712     if (ret == 0)
713     {
714         RMC_Write(RMC_OTP_BASE + 0x800UL + otp_num * 4UL, 0);
715     }
716     return ret;
717 }
718 
719 /**
720   * @brief  Check the OTP is locked or not.
721   * @param[in] otp_num    The OTP number.
722   * @retval   1   OTP is locked.
723   * @retval   0   OTP is not locked.
724   * @retval   -1  Failed to read OTP lock bits.
725   * @retval   -2  Invalid OTP number.
726   */
RMC_IsOTPLocked(uint32_t otp_num)727 int32_t RMC_IsOTPLocked(uint32_t otp_num)
728 {
729     int32_t  ret = 0;
730     uint32_t  u32data = 0;
731 
732     if (otp_num > 255UL)
733     {
734         ret = -2;
735     }
736 
737     if (ret == 0)
738     {
739         u32data = RMC_Read(RMC_OTP_BASE + 0x800UL + otp_num * 4UL);
740         if (u32data != 0xFFFFFFFFUL)
741         {
742             ret = 1;   /* Lock work was progrmmed. OTP was locked. */
743         }
744     }
745     return ret;
746 }
747 
748 /**
749   * @brief Program a 64-bits data to the specified OTP.
750   * @param[in] otp_num    The OTP number.
751   * @param[in] low_word   Low word of the 64-bits data.
752   * @param[in] high_word   Low word of the 64-bits data.
753   * @retval   0   Success
754   * @retval   -1  Program failed.
755   * @retval   -2  Invalid OTP number.
756   */
RMC_WriteOTP(uint32_t otp_num,uint32_t low_word,uint32_t high_word)757 int32_t RMC_WriteOTP(uint32_t otp_num, uint32_t low_word, uint32_t high_word)
758 {
759     int32_t  ret = 0;
760 
761     if (otp_num > 255UL)
762     {
763         ret = -2;
764     }
765 
766     if (ret == 0)
767     {
768         RMC_Write(RMC_OTP_BASE + otp_num * 8UL, low_word);
769     }
770 
771     if (g_RMC_i32ErrCode == 0)
772     {
773         RMC_Write(RMC_OTP_BASE + otp_num * 8UL+ 4UL, high_word);
774     }
775 
776     return ret;
777 }
778 
779 
780 /*@}*/ /* end of group RMC_EXPORTED_FUNCTIONS */
781 
782 /*@}*/ /* end of group RMC_Driver */
783 
784 /*@}*/ /* end of group Standard_Driver */
785 
786 /*** (C) COPYRIGHT 2016 Nuvoton Technology Corp. ***/
787 
788 
789