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