M480 BSP V3.05.006
The Board Support Package for M480 Series
fmc.c
Go to the documentation of this file.
1/**************************************************************************/
10#include <stdio.h>
11
12#include "NuMicro.h"
13
14
29
30
35void FMC_Close(void)
36{
37 FMC->ISPCTL &= ~FMC_ISPCTL_ISPEN_Msk;
38}
39
56int32_t FMC_ConfigXOM(uint32_t u32XomNum, uint32_t u32XomBase, uint8_t u8XomPage)
57{
58 int32_t tout;
59 int32_t ret;
60
62
63 if (u32XomNum >= 4UL)
64 {
66 return -2;
67 }
68
69 ret = FMC_GetXOMState(u32XomNum);
70 if (ret != 0)
71 return ret;
72
73 FMC->ISPCMD = FMC_ISPCMD_PROGRAM;
74 FMC->ISPADDR = FMC_XOM_BASE + (u32XomNum * 0x10u);
75 FMC->ISPDAT = u32XomBase;
76 FMC->ISPTRG = FMC_ISPTRG_ISPGO_Msk;
77 tout = FMC_TIMEOUT_WRITE;
78 while ((tout-- > 0) && (FMC->MPSTS & FMC_MPSTS_MPBUSY_Msk)) {}
79 if (tout <= 0)
80 {
82 return -1;
83 }
84
85 if (FMC->ISPSTS & FMC_ISPSTS_ISPFF_Msk)
86 {
87 FMC->ISPSTS |= FMC_ISPSTS_ISPFF_Msk;
89 return -1;
90 }
91
92 FMC->ISPCMD = FMC_ISPCMD_PROGRAM;
93 FMC->ISPADDR = FMC_XOM_BASE + (u32XomNum * 0x10u + 0x04u);
94 FMC->ISPDAT = u8XomPage;
95 FMC->ISPTRG = FMC_ISPTRG_ISPGO_Msk;
96 tout = FMC_TIMEOUT_WRITE;
97 while ((tout-- > 0) && (FMC->MPSTS & FMC_MPSTS_MPBUSY_Msk)) {}
98 if (tout <= 0)
99 {
100 g_FMC_i32ErrCode = -1;
101 return -1;
102 }
103
104 if(FMC->ISPSTS & FMC_ISPSTS_ISPFF_Msk)
105 {
106 FMC->ISPSTS |= FMC_ISPSTS_ISPFF_Msk;
107 g_FMC_i32ErrCode = -1;
108 return -1;
109 }
110
111 FMC->ISPCMD = FMC_ISPCMD_PROGRAM;
112 FMC->ISPADDR = FMC_XOM_BASE + (u32XomNum * 0x10u + 0x08u);
113 FMC->ISPDAT = 0u;
114 FMC->ISPTRG = FMC_ISPTRG_ISPGO_Msk;
115 tout = FMC_TIMEOUT_WRITE;
116 while ((tout-- > 0) && (FMC->MPSTS & FMC_MPSTS_MPBUSY_Msk)) {}
117 if (tout <= 0)
118 {
119 g_FMC_i32ErrCode = -1;
120 return -1;
121 }
122
123 if(FMC->ISPSTS & FMC_ISPSTS_ISPFF_Msk)
124 {
125 FMC->ISPSTS |= FMC_ISPSTS_ISPFF_Msk;
126 g_FMC_i32ErrCode = -1;
127 return -1;
128 }
129 return 0;
130}
131
143int32_t FMC_Erase(uint32_t u32PageAddr)
144{
145 int32_t tout;
146
148
149 if (u32PageAddr == FMC_SPROM_BASE)
150 {
151 return FMC_Erase_SPROM();
152 }
153
154 FMC->ISPCMD = FMC_ISPCMD_PAGE_ERASE;
155 FMC->ISPADDR = u32PageAddr;
156 FMC->ISPTRG = FMC_ISPTRG_ISPGO_Msk;
157
158 tout = FMC_TIMEOUT_ERASE;
159 while ((tout-- > 0) && (FMC->MPSTS & FMC_MPSTS_MPBUSY_Msk)) {}
160 if (tout <= 0)
161 {
162 g_FMC_i32ErrCode = -1;
163 return -1;
164 }
165
166 if (FMC->ISPCTL & FMC_ISPCTL_ISPFF_Msk)
167 {
168 FMC->ISPCTL |= FMC_ISPCTL_ISPFF_Msk;
169 g_FMC_i32ErrCode = -1;
170 return -1;
171 }
172 return 0;
173}
174
175
185int32_t FMC_Erase_SPROM(void)
186{
187 int32_t tout;
188
190 FMC->ISPCMD = FMC_ISPCMD_PAGE_ERASE;
191 FMC->ISPADDR = FMC_SPROM_BASE;
192 FMC->ISPDAT = 0x0055AA03UL;
193 FMC->ISPTRG = FMC_ISPTRG_ISPGO_Msk;
194
195 tout = FMC_TIMEOUT_ERASE;
196 while ((tout-- > 0) && (FMC->MPSTS & FMC_MPSTS_MPBUSY_Msk)) {}
197 if (tout <= 0)
198 {
199 g_FMC_i32ErrCode = -1;
200 return -1;
201 }
202
203 if (FMC->ISPCTL & FMC_ISPCTL_ISPFF_Msk)
204 {
205 FMC->ISPCTL |= FMC_ISPCTL_ISPFF_Msk;
206 g_FMC_i32ErrCode = -1;
207 return -1;
208 }
209 return 0;
210}
211
223int32_t FMC_Erase_Block(uint32_t u32BlockAddr)
224{
225 int32_t tout;
226
228 FMC->ISPCMD = FMC_ISPCMD_BLOCK_ERASE;
229 FMC->ISPADDR = u32BlockAddr;
230 FMC->ISPTRG = FMC_ISPTRG_ISPGO_Msk;
231
232 tout = FMC_TIMEOUT_ERASE;
233 while ((tout-- > 0) && (FMC->MPSTS & FMC_MPSTS_MPBUSY_Msk)) {}
234 if (tout <= 0)
235 {
236 g_FMC_i32ErrCode = -1;
237 return -1;
238 }
239
240 if (FMC->ISPCTL & FMC_ISPCTL_ISPFF_Msk)
241 {
242 FMC->ISPCTL |= FMC_ISPCTL_ISPFF_Msk;
243 g_FMC_i32ErrCode = -1;
244 return -1;
245 }
246 return 0;
247}
248
259int32_t FMC_Erase_Bank(uint32_t u32BankAddr)
260{
261 int32_t tout;
262
264 FMC->ISPCMD = FMC_ISPCMD_BANK_ERASE;
265 FMC->ISPADDR = u32BankAddr;
266 FMC->ISPTRG = FMC_ISPTRG_ISPGO_Msk;
267
268 tout = FMC_TIMEOUT_ERASE;
269 while ((tout-- > 0) && (FMC->MPSTS & FMC_MPSTS_MPBUSY_Msk)) {}
270 if (tout <= 0)
271 {
272 g_FMC_i32ErrCode = -1;
273 return -1;
274 }
275
276 if (FMC->ISPCTL & FMC_ISPCTL_ISPFF_Msk)
277 {
278 FMC->ISPCTL |= FMC_ISPCTL_ISPFF_Msk;
279 g_FMC_i32ErrCode = -1;
280 return -1;
281 }
282 return 0;
283}
284
301int32_t FMC_EraseXOM(uint32_t u32XomNum)
302{
303 uint32_t u32Addr;
304 int32_t i32Active, err = 0;
305 int32_t tout;
306
307 if(u32XomNum >= 4UL)
308 {
309 err = -2;
310 }
311
312 if (err == 0)
313 {
314 i32Active = FMC_GetXOMState(u32XomNum);
315
316 if(i32Active)
317 {
318 switch(u32XomNum)
319 {
320 case 0u:
321 u32Addr = (FMC->XOMR0STS & 0xFFFFFF00u) >> 8u;
322 break;
323 case 1u:
324 u32Addr = (FMC->XOMR1STS & 0xFFFFFF00u) >> 8u;
325 break;
326 case 2u:
327 u32Addr = (FMC->XOMR2STS & 0xFFFFFF00u) >> 8u;
328 break;
329 case 3u:
330 u32Addr = (FMC->XOMR3STS & 0xFFFFFF00u) >> 8u;
331 break;
332 default:
333 break;
334 }
335 FMC->ISPCMD = FMC_ISPCMD_PAGE_ERASE;
336 FMC->ISPADDR = u32Addr;
337 FMC->ISPDAT = 0x55aa03u;
338 FMC->ISPTRG = 0x1u;
339#if ISBEN
340 __ISB();
341#endif
342 tout = FMC_TIMEOUT_ERASE;
343 while ((tout-- > 0) && FMC->ISPTRG) {}
344 if (tout <= 0)
345 err = -1;
346
347 /* Check ISPFF flag to know whether erase OK or fail. */
348 if(FMC->ISPCTL & FMC_ISPCTL_ISPFF_Msk)
349 {
350 FMC->ISPCTL |= FMC_ISPCTL_ISPFF_Msk;
351 err = -1;
352 }
353 }
354 else
355 {
356 err = -1;
357 }
358 }
359 g_FMC_i32ErrCode = err;
360 return err;
361}
362
374int32_t FMC_GetXOMState(uint32_t u32XomNum)
375{
376 uint32_t u32act;
377 int32_t ret = 0;
378
379 if (u32XomNum >= 4UL)
380 ret = -2;
381
382 if (ret >= 0)
383 {
384 u32act = (((FMC->XOMSTS) & 0xful) & (1ul << u32XomNum)) >> u32XomNum;
385 ret = (int32_t)u32act;
386 }
387 return ret;
388}
389
397int32_t FMC_GetBootSource (void)
398{
399 if (FMC->ISPCTL & FMC_ISPCTL_BL_Msk)
400 {
401 return 2;
402 }
403 if (FMC->ISPCTL & FMC_ISPCTL_BS_Msk)
404 {
405 return 1;
406 }
407 return 0;
408}
409
410
415void FMC_Open(void)
416{
417 FMC->ISPCTL |= FMC_ISPCTL_ISPEN_Msk;
418}
419
420
431uint32_t FMC_Read(uint32_t u32Addr)
432{
433 int32_t tout;
434
436 FMC->ISPCMD = FMC_ISPCMD_READ;
437 FMC->ISPADDR = u32Addr;
438 FMC->ISPTRG = FMC_ISPTRG_ISPGO_Msk;
439
440 tout = FMC_TIMEOUT_READ;
441 while ((tout-- > 0) && (FMC->MPSTS & FMC_MPSTS_MPBUSY_Msk)) {}
442 if (tout <= 0)
443 {
444 g_FMC_i32ErrCode = -1;
445 return 0xFFFFFFFF;
446 }
447 return FMC->ISPDAT;
448}
449
450
463int32_t FMC_Read_64(uint32_t u32addr, uint32_t * u32data0, uint32_t * u32data1)
464{
465 int32_t tout;
466
468 FMC->ISPCMD = FMC_ISPCMD_READ_64;
469 FMC->ISPADDR = u32addr;
470 FMC->ISPDAT = 0x0UL;
471 FMC->ISPTRG = FMC_ISPTRG_ISPGO_Msk;
472
473 tout = FMC_TIMEOUT_READ;
474 while ((tout-- > 0) && (FMC->MPSTS & FMC_MPSTS_MPBUSY_Msk)) {}
475 if (tout <= 0)
476 {
477 g_FMC_i32ErrCode = -1;
478 return -1;
479 }
480
481 if (FMC->ISPSTS & FMC_ISPSTS_ISPFF_Msk)
482 {
483 FMC->ISPSTS |= FMC_ISPSTS_ISPFF_Msk;
484 g_FMC_i32ErrCode = -1;
485 return -1;
486 }
487 else
488 {
489 *u32data0 = FMC->MPDAT0;
490 *u32data1 = FMC->MPDAT1;
491 }
492 return 0;
493}
494
495
501{
502 return FMC->DFBA;
503}
504
515void FMC_SetBootSource(int32_t i32BootSrc)
516{
517 if(i32BootSrc)
518 {
519 FMC->ISPCTL |= FMC_ISPCTL_BS_Msk; /* Boot from LDROM */
520 }
521 else
522 {
523 FMC->ISPCTL &= ~FMC_ISPCTL_BS_Msk;/* Boot from APROM */
524 }
525}
526
538int32_t FMC_Write(uint32_t u32Addr, uint32_t u32Data)
539{
540 int32_t tout;
541
543 FMC->ISPCMD = FMC_ISPCMD_PROGRAM;
544 FMC->ISPADDR = u32Addr;
545 FMC->ISPDAT = u32Data;
546 FMC->ISPTRG = FMC_ISPTRG_ISPGO_Msk;
547
548 tout = FMC_TIMEOUT_WRITE;
549 while ((tout-- > 0) && (FMC->MPSTS & FMC_MPSTS_MPBUSY_Msk)) {}
550 if (tout <= 0)
551 {
552 g_FMC_i32ErrCode = -1;
553 return -1;
554 }
555
556 if (FMC->ISPSTS & FMC_ISPSTS_ISPFF_Msk)
557 {
558 FMC->ISPSTS |= FMC_ISPSTS_ISPFF_Msk;
559 g_FMC_i32ErrCode = -1;
560 return -1;
561 }
562 return 0;
563}
564
577int32_t FMC_Write8Bytes(uint32_t u32addr, uint32_t u32data0, uint32_t u32data1)
578{
579 int32_t tout;
580
582 FMC->ISPCMD = FMC_ISPCMD_PROGRAM_64;
583 FMC->ISPADDR = u32addr;
584 FMC->MPDAT0 = u32data0;
585 FMC->MPDAT1 = u32data1;
586 FMC->ISPTRG = FMC_ISPTRG_ISPGO_Msk;
587
588 tout = FMC_TIMEOUT_WRITE;
589 while ((tout-- > 0) && (FMC->MPSTS & FMC_MPSTS_MPBUSY_Msk)) {}
590 if (tout <= 0)
591 {
592 g_FMC_i32ErrCode = -1;
593 return -1;
594 }
595
596 if (FMC->ISPSTS & FMC_ISPSTS_ISPFF_Msk)
597 {
598 FMC->ISPSTS |= FMC_ISPSTS_ISPFF_Msk;
599 g_FMC_i32ErrCode = -1;
600 return -1;
601 }
602 return 0;
603}
604
605
620int32_t FMC_WriteMultiple(uint32_t u32Addr, uint32_t pu32Buf[], uint32_t u32Len)
621{
622 int i, idx, retval = 0;
623 int32_t tout;
624
626
627 if ((u32Addr >= FMC_APROM_END) || ((u32Addr % 8) != 0))
628 {
629 g_FMC_i32ErrCode = -2;
630 return -2;
631 }
632
633 u32Len = u32Len - (u32Len % 8); /* u32Len must be multiple of 8. */
634
635 idx = 0;
636
637 while (u32Len >= 8)
638 {
639 FMC->ISPADDR = u32Addr;
640 FMC->MPDAT0 = pu32Buf[idx++];
641 FMC->MPDAT1 = pu32Buf[idx++];
642 FMC->MPDAT2 = pu32Buf[idx++];
643 FMC->MPDAT3 = pu32Buf[idx++];
644 FMC->ISPCMD = FMC_ISPCMD_PROGRAM_MUL;
645 FMC->ISPTRG = FMC_ISPTRG_ISPGO_Msk;
646 u32Len -= 16;
647 retval += 16;
648
649 for (i = 16; i < FMC_MULTI_WORD_PROG_LEN; i += 16)
650 {
651 tout = FMC_TIMEOUT_WRITE;
652 while ((tout-- > 0) && (FMC->MPSTS & (FMC_MPSTS_D0_Msk | FMC_MPSTS_D1_Msk))) {}
653 if (tout <= 0)
654 {
655 g_FMC_i32ErrCode = -1;
656 return -1;
657 }
658 if (!(FMC->MPSTS & FMC_MPSTS_MPBUSY_Msk))
659 {
660 /* printf(" [WARNING] busy cleared after D0D1 cleared!\n"); */
661 break;
662 }
663
664 if (u32Len < 8)
665 break;
666
667 FMC->MPDAT0 = pu32Buf[idx++];
668 FMC->MPDAT1 = pu32Buf[idx++];
669 retval += 8;
670 u32Len -= 8;
671
672 tout = FMC_TIMEOUT_WRITE;
673 while ((tout-- > 0) && (FMC->MPSTS & (FMC_MPSTS_D2_Msk | FMC_MPSTS_D3_Msk))) {}
674 if (tout <= 0)
675 {
676 g_FMC_i32ErrCode = -1;
677 return -1;
678 }
679 if (!(FMC->MPSTS & FMC_MPSTS_MPBUSY_Msk))
680 {
681 /* printf(" [WARNING] busy cleared after D2D3 cleared!\n"); */
682 i += 8;
683 break;
684 }
685
686 if (u32Len < 8)
687 break;
688
689 FMC->MPDAT2 = pu32Buf[idx++];
690 FMC->MPDAT3 = pu32Buf[idx++];
691 retval += 8;
692 u32Len -= 8;
693 }
694
696 {
697 /* printf(" [WARNING] Multi-word program interrupted at 0x%x !!\n", i); */
698 return retval;
699 }
700
701 tout = FMC_TIMEOUT_WRITE;
702 while ((tout-- > 0) && (FMC->MPSTS & FMC_MPSTS_MPBUSY_Msk)) {}
703 if (tout <= 0)
704 {
705 g_FMC_i32ErrCode = -1;
706 return -1;
707 }
708
709 u32Addr += FMC_MULTI_WORD_PROG_LEN;
710 }
711 return retval;
712}
713
714
728int32_t FMC_Write_OTP(uint32_t otp_num, uint32_t low_word, uint32_t high_word)
729{
730 int32_t tout;
731
733
734 if (otp_num > 255UL)
735 {
736 g_FMC_i32ErrCode = -2;
737 return -2;
738 }
739
740 FMC->ISPCMD = FMC_ISPCMD_PROGRAM;
741 FMC->ISPADDR = FMC_OTP_BASE + otp_num * 8UL;
742 FMC->ISPDAT = low_word;
743 FMC->ISPTRG = FMC_ISPTRG_ISPGO_Msk;
744
745 tout = FMC_TIMEOUT_WRITE;
746 while ((tout-- > 0) && (FMC->MPSTS & FMC_MPSTS_MPBUSY_Msk)) {}
747 if (tout <= 0)
748 {
749 g_FMC_i32ErrCode = -1;
750 return -1;
751 }
752
753 if (FMC->ISPSTS & FMC_ISPSTS_ISPFF_Msk)
754 {
755 FMC->ISPSTS |= FMC_ISPSTS_ISPFF_Msk;
756 g_FMC_i32ErrCode = -1;
757 return -1;
758 }
759
760 FMC->ISPCMD = FMC_ISPCMD_PROGRAM;
761 FMC->ISPADDR = FMC_OTP_BASE + otp_num * 8UL + 4UL;
762 FMC->ISPDAT = high_word;
763 FMC->ISPTRG = FMC_ISPTRG_ISPGO_Msk;
764
765 tout = FMC_TIMEOUT_WRITE;
766 while ((tout-- > 0) && (FMC->MPSTS & FMC_MPSTS_MPBUSY_Msk)) {}
767 if (tout <= 0)
768 {
769 g_FMC_i32ErrCode = -1;
770 return -1;
771 }
772
773 if (FMC->ISPSTS & FMC_ISPSTS_ISPFF_Msk)
774 {
775 FMC->ISPSTS |= FMC_ISPSTS_ISPFF_Msk;
776 g_FMC_i32ErrCode = -1;
777 return -1;
778 }
779 return 0;
780}
781
795int32_t FMC_Read_OTP(uint32_t otp_num, uint32_t *low_word, uint32_t *high_word)
796{
797 int32_t tout;
798
800
801 if (otp_num > 255UL)
802 {
803 g_FMC_i32ErrCode = -2;
804 return -2;
805 }
806
807 FMC->ISPCMD = FMC_ISPCMD_READ_64;
808 FMC->ISPADDR = FMC_OTP_BASE + otp_num * 8UL ;
809 FMC->ISPDAT = 0x0UL;
810 FMC->ISPTRG = FMC_ISPTRG_ISPGO_Msk;
811
812 tout = FMC_TIMEOUT_WRITE;
813 while ((tout-- > 0) && (FMC->MPSTS & FMC_MPSTS_MPBUSY_Msk)) {}
814 if (tout <= 0)
815 {
816 g_FMC_i32ErrCode = -1;
817 return -1;
818 }
819
820 if (FMC->ISPSTS & FMC_ISPSTS_ISPFF_Msk)
821 {
822 FMC->ISPSTS |= FMC_ISPSTS_ISPFF_Msk;
823 g_FMC_i32ErrCode = -1;
824 return -1;
825 }
826 else
827 {
828 *low_word = FMC->MPDAT0;
829 *high_word = FMC->MPDAT1;
830 }
831 return 0;
832}
833
845int32_t FMC_Lock_OTP(uint32_t otp_num)
846{
847 int32_t tout;
848
850
851 if (otp_num > 255UL)
852 {
853 g_FMC_i32ErrCode = -2;
854 return -2;
855 }
856
857 FMC->ISPCMD = FMC_ISPCMD_PROGRAM;
858 FMC->ISPADDR = FMC_OTP_BASE + 0x800UL + otp_num * 4UL;
859 FMC->ISPDAT = 0UL;
860 FMC->ISPTRG = FMC_ISPTRG_ISPGO_Msk;
861
862 tout = FMC_TIMEOUT_WRITE;
863 while ((tout-- > 0) && (FMC->MPSTS & FMC_MPSTS_MPBUSY_Msk)) {}
864 if (tout <= 0)
865 {
866 g_FMC_i32ErrCode = -1;
867 return -1;
868 }
869
870 if (FMC->ISPSTS & FMC_ISPSTS_ISPFF_Msk)
871 {
872 FMC->ISPSTS |= FMC_ISPSTS_ISPFF_Msk;
873 g_FMC_i32ErrCode = -1;
874 return -1;
875 }
876 return 0;
877}
878
891int32_t FMC_Is_OTP_Locked(uint32_t otp_num)
892{
893 int32_t tout;
894
896
897 if (otp_num > 255UL)
898 {
899 g_FMC_i32ErrCode = -2;
900 return -2;
901 }
902
903 FMC->ISPCMD = FMC_ISPCMD_READ;
904 FMC->ISPADDR = FMC_OTP_BASE + 0x800UL + otp_num * 4UL;
905 FMC->ISPTRG = FMC_ISPTRG_ISPGO_Msk;
906
907 tout = FMC_TIMEOUT_READ;
908 while ((tout-- > 0) && (FMC->MPSTS & FMC_MPSTS_MPBUSY_Msk)) {}
909 if (tout <= 0)
910 {
911 g_FMC_i32ErrCode = -1;
912 return -1;
913 }
914
915 if (FMC->ISPSTS & FMC_ISPSTS_ISPFF_Msk)
916 {
917 FMC->ISPSTS |= FMC_ISPSTS_ISPFF_Msk;
918 g_FMC_i32ErrCode = -1;
919 return -1;
920 }
921 else
922 {
923 if (FMC->ISPDAT != 0xFFFFFFFFUL)
924 {
925 g_FMC_i32ErrCode = -1;
926 return 1; /* Lock work was progrmmed. OTP was locked. */
927 }
928 }
929 return 0;
930}
931
946int32_t FMC_ReadConfig(uint32_t u32Config[], uint32_t u32Count)
947{
948 int32_t ret = 0;
949
950 u32Config[0] = FMC_Read(FMC_CONFIG_BASE);
951
952 if (g_FMC_i32ErrCode != 0)
953 return g_FMC_i32ErrCode;
954
955 if (u32Count < 2UL)
956 {
957 ret = -2;
958 }
959 else
960 {
961 u32Config[1] = FMC_Read(FMC_CONFIG_BASE+4UL);
962 }
963 return ret;
964}
965
966
979int32_t FMC_WriteConfig(uint32_t u32Config[], uint32_t u32Count)
980{
981 int i;
982
984
985 if (FMC_Erase(FMC_CONFIG_BASE) != 0)
986 return -1;
987
988 if ((FMC_Read(FMC_CONFIG_BASE) != 0xFFFFFFFF) || (FMC_Read(FMC_CONFIG_BASE+4) != 0xFFFFFFFF) ||
989 (FMC_Read(FMC_CONFIG_BASE+8) != 0xFFFF5A5A))
990 {
992 return -1;
993 }
994
995 if (g_FMC_i32ErrCode != 0)
996 {
998 return -1;
999 }
1000
1001 for (i = 0; i < u32Count; i++)
1002 {
1003 if (FMC_Write(FMC_CONFIG_BASE+i*4UL, u32Config[i]) != 0)
1004 {
1006 return -1;
1007 }
1008
1009 if (FMC_Read(FMC_CONFIG_BASE+i*4UL) != u32Config[i])
1010 {
1012 return -1;
1013 }
1014
1015 if (g_FMC_i32ErrCode != 0)
1016 {
1018 return -1;
1019 }
1020 }
1021
1023 return 0;
1024}
1025
1026
1039uint32_t FMC_GetChkSum(uint32_t u32addr, uint32_t u32count)
1040{
1041 int32_t tout;
1042
1043 g_FMC_i32ErrCode = 0;
1044
1045 if ((u32addr % 4096UL) || (u32count % 4096UL))
1046 {
1047 g_FMC_i32ErrCode = -2;
1048 return 0xFFFFFFFF;
1049 }
1050
1051 FMC->ISPCMD = FMC_ISPCMD_RUN_CKS;
1052 FMC->ISPADDR = u32addr;
1053 FMC->ISPDAT = u32count;
1054 FMC->ISPTRG = FMC_ISPTRG_ISPGO_Msk;
1055
1056 tout = FMC_TIMEOUT_CHKSUM;
1057 while ((tout-- > 0) && (FMC->MPSTS & FMC_MPSTS_MPBUSY_Msk)) {}
1058 if (tout <= 0)
1059 {
1060 g_FMC_i32ErrCode = -1;
1061 return 0xFFFFFFFF;
1062 }
1063
1064 FMC->ISPCMD = FMC_ISPCMD_READ_CKS;
1065 FMC->ISPADDR = u32addr;
1066 FMC->ISPTRG = FMC_ISPTRG_ISPGO_Msk;
1067
1068 tout = FMC_TIMEOUT_CHKSUM;
1069 while ((tout-- > 0) && (FMC->MPSTS & FMC_MPSTS_MPBUSY_Msk)) {}
1070 if (tout <= 0)
1071 {
1072 g_FMC_i32ErrCode = -1;
1073 return 0xFFFFFFFF;
1074 }
1075
1076 return FMC->ISPDAT;
1077}
1078
1079
1091uint32_t FMC_CheckAllOne(uint32_t u32addr, uint32_t u32count)
1092{
1093 int32_t tout;
1094
1095 g_FMC_i32ErrCode = 0;
1096
1097 FMC->ISPSTS = 0x80UL; /* clear check all one bit */
1098
1099 FMC->ISPCMD = FMC_ISPCMD_RUN_ALL1;
1100 FMC->ISPADDR = u32addr;
1101 FMC->ISPDAT = u32count;
1102 FMC->ISPTRG = FMC_ISPTRG_ISPGO_Msk;
1103
1104 tout = FMC_TIMEOUT_CHKALLONE;
1105 while ((tout-- > 0) && (FMC->MPSTS & FMC_MPSTS_MPBUSY_Msk)) {}
1106 if (tout <= 0)
1107 {
1108 g_FMC_i32ErrCode = -1;
1109 return READ_ALLONE_CMD_FAIL;
1110 }
1111
1112 tout = FMC_TIMEOUT_CHKALLONE;
1113 do
1114 {
1115 FMC->ISPCMD = FMC_ISPCMD_READ_ALL1;
1116 FMC->ISPADDR = u32addr;
1117 FMC->ISPTRG = FMC_ISPTRG_ISPGO_Msk;
1118 while ((tout-- > 0) && (FMC->MPSTS & FMC_MPSTS_MPBUSY_Msk)) {}
1119 if (tout <= 0)
1120 {
1121 g_FMC_i32ErrCode = -1;
1122 return READ_ALLONE_CMD_FAIL;
1123 }
1124 }
1125 while (FMC->ISPDAT == 0UL);
1126
1127 if ((FMC->ISPDAT == READ_ALLONE_YES) || (FMC->ISPDAT == READ_ALLONE_NOT))
1128 return FMC->ISPDAT;
1129 else
1130 {
1131 g_FMC_i32ErrCode = -1;
1132 return READ_ALLONE_CMD_FAIL;
1133 }
1134}
1135
1136
1157int32_t FMC_SetSPKey(uint32_t key[3], uint32_t kpmax, uint32_t kemax,
1158 const int32_t lock_CONFIG, const int32_t lock_SPROM)
1159{
1160 uint32_t lock_ctrl = 0UL;
1161 uint32_t u32KeySts;
1162 int32_t tout;
1163 int32_t ret = 0;
1164
1165 g_FMC_i32ErrCode = 0;
1166
1167 if (FMC->KPKEYSTS != 0x200UL)
1168 {
1169 ret = -1;
1170 }
1171
1173 {
1174 ret = -2;
1175 }
1176
1177 if (FMC_Erase(FMC_KPROM_BASE+0x200UL))
1178 {
1179 ret = -3;
1180 }
1181
1182 if (!lock_CONFIG)
1183 {
1184 lock_ctrl |= 0x1UL;
1185 }
1186
1187 if (!lock_SPROM)
1188 {
1189 lock_ctrl |= 0x2UL;
1190 }
1191
1192 if (ret == 0)
1193 {
1194 FMC_Write(FMC_KPROM_BASE, key[0]);
1195 FMC_Write(FMC_KPROM_BASE+0x4UL, key[1]);
1196 FMC_Write(FMC_KPROM_BASE+0x8UL, key[2]);
1197 FMC_Write(FMC_KPROM_BASE+0xCUL, kpmax);
1198 FMC_Write(FMC_KPROM_BASE+0x10UL, kemax);
1199 FMC_Write(FMC_KPROM_BASE+0x14UL, lock_ctrl);
1200
1201 tout = FMC_TIMEOUT_WRITE;
1202 while ((tout-- > 0) && (FMC->KPKEYSTS & FMC_KPKEYSTS_KEYBUSY_Msk)) {}
1203 if (tout <= 0)
1204 {
1205 g_FMC_i32ErrCode = -3;
1206 return -3;
1207 }
1208
1209 u32KeySts = FMC->KPKEYSTS;
1210
1211 if (!(u32KeySts & FMC_KPKEYSTS_KEYLOCK_Msk))
1212 {
1213 /* Security key lock failed! */
1214 ret = -4;
1215 }
1216 else if ((lock_CONFIG && (!(u32KeySts & FMC_KPKEYSTS_CFGFLAG_Msk))) ||
1217 ((!lock_CONFIG) && (u32KeySts & FMC_KPKEYSTS_CFGFLAG_Msk)))
1218 {
1219 /* CONFIG lock failed! */
1220 ret = -5;
1221 }
1222 else if ((lock_SPROM && (!(u32KeySts & FMC_KPKEYSTS_SPFLAG_Msk))) ||
1223 ((!lock_SPROM) && (u32KeySts & FMC_KPKEYSTS_SPFLAG_Msk)))
1224 {
1225 /* CONFIG lock failed! */
1226 ret = -6;
1227 }
1228 else if (((FMC->KPCNT & FMC_KPCNT_KPMAX_Msk) >> FMC_KPCNT_KPMAX_Pos) != kpmax)
1229 {
1230 /* KPMAX failed! */
1231 ret = -7;
1232 }
1233 else if (((FMC->KPKEYCNT & FMC_KPKEYCNT_KPKEMAX_Msk) >> FMC_KPKEYCNT_KPKEMAX_Pos) != kemax)
1234 {
1235 /* KEMAX failed! */
1236 ret = -8;
1237 }
1238 }
1239 g_FMC_i32ErrCode = ret;
1240 return ret;
1241}
1242
1243
1257int32_t FMC_CompareSPKey(uint32_t key[3])
1258{
1259 uint32_t u32KeySts;
1260 int32_t tout;
1261
1262 g_FMC_i32ErrCode = 0;
1263
1264 if (FMC->KPKEYSTS & FMC_KPKEYSTS_FORBID_Msk)
1265 {
1266 /* FMC_CompareSPKey - FORBID! */
1267 g_FMC_i32ErrCode = -2;
1268 return -2;
1269 }
1270
1271 if (!(FMC->KPKEYSTS & FMC_KPKEYSTS_KEYLOCK_Msk))
1272 {
1273 /* FMC_CompareSPKey - key is not locked! */
1274 g_FMC_i32ErrCode = -4;
1275 return -4;
1276 }
1277
1278 FMC->KPKEY0 = key[0];
1279 FMC->KPKEY1 = key[1];
1280 FMC->KPKEY2 = key[2];
1282
1283 tout = FMC_TIMEOUT_READ;
1284 while ((tout-- > 0) && (FMC->KPKEYSTS & FMC_KPKEYSTS_KEYBUSY_Msk)) {}
1285 if (tout <= 0)
1286 {
1287 g_FMC_i32ErrCode = -1;
1288 return -1;
1289 }
1290
1291 u32KeySts = FMC->KPKEYSTS;
1292
1293 if (!(u32KeySts & FMC_KPKEYSTS_KEYMATCH_Msk))
1294 {
1295 /* Key mismatched! */
1296 g_FMC_i32ErrCode = -3;
1297 return -3;
1298 }
1299 else if (u32KeySts & FMC_KPKEYSTS_KEYLOCK_Msk)
1300 {
1301 /* Key matched, but failed to unlock! */
1302 g_FMC_i32ErrCode = -5;
1303 return -5;
1304 }
1305 return 0;
1306}
1307
1308 /* end of group FMC_EXPORTED_FUNCTIONS */
1310 /* end of group FMC_Driver */
1312 /* end of group Standard_Driver */
1314
1315/*** (C) COPYRIGHT 2016 Nuvoton Technology Corp. ***/
1316
1317
NuMicro peripheral access layer header file.
#define FMC_ISPCMD_READ_64
Definition: fmc.h:94
#define FMC_TIMEOUT_ERASE
Definition: fmc.h:103
#define FMC_ISPCMD_READ_CKS
Definition: fmc.h:85
#define FMC_ISPCMD_PROGRAM
Definition: fmc.h:86
#define FMC_ISPCMD_BLOCK_ERASE
Definition: fmc.h:89
#define FMC_CONFIG_BASE
Definition: fmc.h:46
#define FMC_TIMEOUT_CHKSUM
Definition: fmc.h:104
#define FMC_APROM_END
Definition: fmc.h:35
#define FMC_SPROM_BASE
Definition: fmc.h:39
#define FMC_ISPCMD_RUN_ALL1
Definition: fmc.h:91
#define READ_ALLONE_NOT
Definition: fmc.h:98
#define FMC_TIMEOUT_READ
Definition: fmc.h:101
#define FMC_ISPCMD_BANK_ERASE
Definition: fmc.h:88
#define FMC_MULTI_WORD_PROG_LEN
Definition: fmc.h:55
#define FMC_TIMEOUT_CHKALLONE
Definition: fmc.h:105
#define FMC_ISPCMD_PROGRAM_64
Definition: fmc.h:95
#define FMC_ISPCMD_PROGRAM_MUL
Definition: fmc.h:90
#define FMC_ISPCMD_RUN_CKS
Definition: fmc.h:92
#define FMC_ISPCMD_READ
Definition: fmc.h:80
#define FMC_OTP_BASE
Definition: fmc.h:51
#define FMC_ISPCMD_READ_ALL1
Definition: fmc.h:82
#define FMC_TIMEOUT_WRITE
Definition: fmc.h:102
#define READ_ALLONE_YES
Definition: fmc.h:97
#define READ_ALLONE_CMD_FAIL
Definition: fmc.h:99
#define FMC_XOM_BASE
Definition: fmc.h:41
#define FMC_KPROM_BASE
Definition: fmc.h:50
#define FMC_ISPCMD_PAGE_ERASE
Definition: fmc.h:87
int32_t FMC_Read_OTP(uint32_t otp_num, uint32_t *low_word, uint32_t *high_word)
Read the 64-bits data from the specified OTP.
Definition: fmc.c:795
void FMC_Close(void)
Disable FMC ISP function.
Definition: fmc.c:35
int32_t FMC_Lock_OTP(uint32_t otp_num)
Lock the specified OTP.
Definition: fmc.c:845
int32_t FMC_ReadConfig(uint32_t u32Config[], uint32_t u32Count)
Execute FMC_ISPCMD_READ command to read User Configuration.
Definition: fmc.c:946
int32_t g_FMC_i32ErrCode
Definition: fmc.c:28
int32_t FMC_CompareSPKey(uint32_t key[3])
Execute security key comparison.
Definition: fmc.c:1257
int32_t FMC_WriteMultiple(uint32_t u32Addr, uint32_t pu32Buf[], uint32_t u32Len)
Program Multi-Word data into specified address of flash.
Definition: fmc.c:620
int32_t FMC_Erase_SPROM(void)
Execute FMC_ISPCMD_PAGE_ERASE command to erase SPROM. The page size is 4096 bytes.
Definition: fmc.c:185
int32_t FMC_Erase_Block(uint32_t u32BlockAddr)
Execute FMC_ISPCMD_BLOCK_ERASE command to erase a flash block. The block size is 4 pages.
Definition: fmc.c:223
int32_t FMC_ConfigXOM(uint32_t xom_num, uint32_t xom_base, uint8_t xom_page)
Config XOM Region.
Definition: fmc.c:56
uint32_t FMC_GetChkSum(uint32_t u32addr, uint32_t u32count)
Run CRC32 checksum calculation and get result.
Definition: fmc.c:1039
int32_t FMC_WriteConfig(uint32_t u32Config[], uint32_t u32Count)
Execute ISP commands to erase then write User Configuration.
Definition: fmc.c:979
uint32_t FMC_CheckAllOne(uint32_t u32addr, uint32_t u32count)
Run flash all one verification and get result.
Definition: fmc.c:1091
int32_t FMC_GetXOMState(uint32_t xom_num)
Check the XOM is actived or not.
Definition: fmc.c:374
int32_t FMC_Erase(uint32_t u32PageAddr)
Execute FMC_ISPCMD_PAGE_ERASE command to erase a flash page. The page size is 4096 bytes.
Definition: fmc.c:143
uint32_t FMC_ReadDataFlashBaseAddr(void)
Get the base address of Data Flash if enabled.
Definition: fmc.c:500
void FMC_SetBootSource(int32_t i32BootSrc)
Set boot source from LDROM or APROM after next software reset.
Definition: fmc.c:515
int32_t FMC_Write(uint32_t u32Addr, uint32_t u32Data)
Execute ISP FMC_ISPCMD_PROGRAM to program a word to flash.
Definition: fmc.c:538
uint32_t FMC_Read(uint32_t u32Addr)
Execute FMC_ISPCMD_READ command to read a word from flash.
Definition: fmc.c:431
int32_t FMC_Is_OTP_Locked(uint32_t otp_num)
Check the OTP is locked or not.
Definition: fmc.c:891
int32_t FMC_Write_OTP(uint32_t otp_num, uint32_t low_word, uint32_t high_word)
Program a 64-bits data to the specified OTP.
Definition: fmc.c:728
int32_t FMC_GetBootSource(void)
Get the current boot source.
Definition: fmc.c:397
int32_t FMC_EraseXOM(uint32_t xom_num)
Execute Erase XOM Region.
Definition: fmc.c:301
int32_t FMC_Write8Bytes(uint32_t u32addr, uint32_t u32data0, uint32_t u32data1)
Execute ISP FMC_ISPCMD_PROGRAM_64 to program a double-word to flash.
Definition: fmc.c:577
int32_t FMC_Erase_Bank(uint32_t u32BankAddr)
Execute FMC_ISPCMD_BANK_ERASE command to erase a flash block.
Definition: fmc.c:259
void FMC_Open(void)
Enable FMC ISP function.
Definition: fmc.c:415
int32_t FMC_Read_64(uint32_t u32addr, uint32_t *u32data0, uint32_t *u32data1)
Execute FMC_ISPCMD_READ_64 command to read a double-word from flash.
Definition: fmc.c:463
int32_t FMC_SetSPKey(uint32_t key[3], uint32_t kpmax, uint32_t kemax, const int32_t lock_CONFIG, const int32_t lock_SPROM)
Setup security key.
Definition: fmc.c:1157
#define FMC_DISABLE_CFG_UPDATE()
Definition: fmc.h:124
#define FMC_ENABLE_CFG_UPDATE()
Definition: fmc.h:123
#define FMC
Definition: M480.h:391
#define FMC_MPSTS_D1_Msk
Definition: fmc_reg.h:1154
#define FMC_KPKEYSTS_KEYBUSY_Msk
Definition: fmc_reg.h:1097
#define FMC_ISPCTL_ISPFF_Msk
Definition: fmc_reg.h:1031
#define FMC_ISPSTS_ISPFF_Msk
Definition: fmc_reg.h:1067
#define FMC_ISPCTL_BS_Msk
Definition: fmc_reg.h:1016
#define FMC_KPCNT_KPMAX_Pos
Definition: fmc_reg.h:1126
#define FMC_KPKEYCNT_KPKEMAX_Msk
Definition: fmc_reg.h:1121
#define FMC_MPSTS_D2_Msk
Definition: fmc_reg.h:1157
#define FMC_KPKEYSTS_SPFLAG_Msk
Definition: fmc_reg.h:1115
#define FMC_KPKEYTRG_KPKEYGO_Msk
Definition: fmc_reg.h:1091
#define FMC_KPKEYTRG_TCEN_Msk
Definition: fmc_reg.h:1094
#define FMC_KPKEYSTS_KEYMATCH_Msk
Definition: fmc_reg.h:1103
#define FMC_ISPCTL_BL_Msk
Definition: fmc_reg.h:1034
#define FMC_ISPCTL_ISPEN_Msk
Definition: fmc_reg.h:1013
#define FMC_MPSTS_D3_Msk
Definition: fmc_reg.h:1160
#define FMC_KPCNT_KPMAX_Msk
Definition: fmc_reg.h:1127
#define FMC_KPKEYSTS_FORBID_Msk
Definition: fmc_reg.h:1106
#define FMC_KPKEYCNT_KPKEMAX_Pos
Definition: fmc_reg.h:1120
#define FMC_ISPTRG_ISPGO_Msk
Definition: fmc_reg.h:1046
#define FMC_KPKEYSTS_CFGFLAG_Msk
Definition: fmc_reg.h:1112
#define FMC_KPKEYSTS_KEYLOCK_Msk
Definition: fmc_reg.h:1100
#define FMC_MPSTS_MPBUSY_Msk
Definition: fmc_reg.h:1142
#define FMC_MPSTS_D0_Msk
Definition: fmc_reg.h:1151