M4521_BSP V3.02.000
The Board Support Package for M4521
fmc.c
Go to the documentation of this file.
1/**************************************************************************/
12#include <stdio.h>
13#include "M4521.h"
14
29
40void FMC_SetBootSource(int32_t i32BootSrc)
41{
42 if (i32BootSrc)
43 FMC->ISPCTL |= FMC_ISPCTL_BS_Msk; /* Boot from LDROM */
44 else
45 FMC->ISPCTL &= ~FMC_ISPCTL_BS_Msk;/* Boot from APROM */
46}
47
54void FMC_Close(void)
55{
56 FMC->ISPCTL &= ~FMC_ISPCTL_ISPEN_Msk;
57}
58
68{
69 FMC->ISPCTL &= ~FMC_ISPCTL_APUEN_Msk;
70}
71
81{
82 FMC->ISPCTL &= ~FMC_ISPCTL_CFGUEN_Msk;
83}
84
94{
95 FMC->ISPCTL &= ~FMC_ISPCTL_LDUEN_Msk;
96}
97
106{
107 FMC->ISPCTL |= FMC_ISPCTL_APUEN_Msk;
108}
109
118{
119 FMC->ISPCTL |= FMC_ISPCTL_CFGUEN_Msk;
120}
121
130{
131 FMC->ISPCTL |= FMC_ISPCTL_LDUEN_Msk;
132}
133
143int32_t FMC_GetBootSource(void)
144{
145 if (FMC->ISPCTL & FMC_ISPCTL_BS_Msk)
146 return 1;
147 else
148 return 0;
149}
150
159void FMC_Open(void)
160{
161 FMC->ISPCTL |= FMC_ISPCTL_ISPEN_Msk;
162}
163
171{
172 return FMC->DFBA;
173}
174
184uint32_t FMC_Read(uint32_t u32Addr)
185{
186 int32_t tout = FMC_TIMEOUT_READ;
187
188 FMC->ISPCMD = FMC_ISPCMD_READ;
189 FMC->ISPADDR = u32Addr;
190 FMC->ISPDAT = 0;
191 FMC->ISPTRG = 0x1;
192#if ISBEN
193 __ISB();
194#endif
195 while ((tout-- > 0) && (FMC->ISPTRG)) {}
196 if (tout <= 0)
197 {
198 g_FMC_i32ErrCode = -1;
199 return 0xFFFFFFFF;
200 }
201 return FMC->ISPDAT;
202}
203
210uint32_t FMC_ReadUID(uint8_t u8Index)
211{
212 uint32_t tout = FMC_TIMEOUT_READ;
213
215 FMC->ISPCMD = FMC_ISPCMD_READ_UID;
216 FMC->ISPADDR = (u8Index << 2);
217 FMC->ISPDAT = 0;
218 FMC->ISPTRG = 0x1;
219#if ISBEN
220 __ISB();
221#endif
222 while (tout-- > 0)
223 {
224 if (!(FMC->ISPTRG & FMC_ISPTRG_ISPGO_Msk)) /* Waiting for ISP Done */
225 return FMC->ISPDAT;
226 }
227 g_FMC_i32ErrCode = -1;
228 return 0xFFFFFFFF;
229}
230
240uint32_t FMC_ReadCID(void)
241{
242 uint32_t tout = FMC_TIMEOUT_READ;
243
245 FMC->ISPCMD = FMC_ISPCMD_READ_CID; /* Set ISP Command Code */
246 FMC->ISPADDR = 0x0; /* Must keep 0x0 when read CID */
247 FMC->ISPTRG = FMC_ISPTRG_ISPGO_Msk; /* Trigger to start ISP procedure */
248#if ISBEN
249 __ISB();
250#endif /* To make sure ISP/CPU be Synchronized */
251 while (tout-- > 0)
252 {
253 if (!(FMC->ISPTRG & FMC_ISPTRG_ISPGO_Msk)) /* Waiting for ISP Done */
254 {
255 if (FMC->ISPDAT != 0xDA)
256 g_FMC_i32ErrCode = -1;
257 return FMC->ISPDAT;
258 }
259 }
260 g_FMC_i32ErrCode = -1;
261 return 0xFFFFFFFF;
262}
263
273uint32_t FMC_ReadPID(void)
274{
275 uint32_t tout = FMC_TIMEOUT_READ;
276
278 FMC->ISPCMD = FMC_ISPCMD_READ_DID; /* Set ISP Command Code */
279 FMC->ISPADDR = 0x04; /* Must keep 0x4 when read PID */
280 FMC->ISPTRG = FMC_ISPTRG_ISPGO_Msk; /* Trigger to start ISP procedure */
281#if ISBEN
282 __ISB();
283#endif /* To make sure ISP/CPU be Synchronized */
284 while (tout-- > 0)
285 {
286 if (!(FMC->ISPTRG & FMC_ISPTRG_ISPGO_Msk)) /* Waiting for ISP Done */
287 return FMC->ISPDAT;
288 }
289 g_FMC_i32ErrCode = -1;
290 return 0xFFFFFFFF;
291}
292
302uint32_t FMC_ReadUCID(uint32_t u32Index)
303{
304 uint32_t tout = FMC_TIMEOUT_READ;
305
307 FMC->ISPCMD = FMC_ISPCMD_READ_UID; /* Set ISP Command Code */
308 FMC->ISPADDR = (0x04 * u32Index) + 0x10; /* The UCID is at offset 0x10 with word alignment. */
309 FMC->ISPTRG = FMC_ISPTRG_ISPGO_Msk; /* Trigger to start ISP procedure */
310#if ISBEN
311 __ISB();
312#endif /* To make sure ISP/CPU be Synchronized */
313 while (tout-- > 0)
314 {
315 if (!(FMC->ISPTRG & FMC_ISPTRG_ISPGO_Msk)) /* Waiting for ISP Done */
316 return FMC->ISPDAT;
317 }
318 g_FMC_i32ErrCode = -1;
319 return 0xFFFFFFFF;
320}
321
336int32_t FMC_Write(uint32_t u32Addr, uint32_t u32Data)
337{
338 int32_t tout = FMC_TIMEOUT_WRITE;
339
340 FMC->ISPCMD = FMC_ISPCMD_PROGRAM;
341 FMC->ISPADDR = u32Addr;
342 FMC->ISPDAT = u32Data;
343 FMC->ISPTRG = 0x1;
344#if ISBEN
345 __ISB();
346#endif
347 while ((tout-- > 0) && (FMC->ISPTRG)) {}
348 if (tout <= 0)
349 {
350 g_FMC_i32ErrCode = -1;
351 return -1;
352 }
353 if (FMC->ISPSTS & FMC_ISPSTS_ISPFF_Msk)
354 {
355 FMC->ISPSTS |= FMC_ISPSTS_ISPFF_Msk;
356 g_FMC_i32ErrCode = -1;
357 return -1;
358 }
359 return 0;
360}
361
377int32_t FMC_Write8(uint32_t u32Addr, uint32_t u32Data0, uint32_t u32Data1)
378{
379 int32_t tout = FMC_TIMEOUT_WRITE;
380
381 FMC->ISPCMD = FMC_ISPCMD_WRITE_8;
382 FMC->ISPADDR = u32Addr;
383 FMC->MPDAT0 = u32Data0;
384 FMC->MPDAT1 = u32Data1;
385 FMC->ISPTRG = 0x1;
386#if ISBEN
387 __ISB();
388#endif
389 while ((tout-- > 0) && (FMC->ISPTRG)) {}
390 if (tout <= 0)
391 {
392 g_FMC_i32ErrCode = -1;
393 return -1;
394 }
395 if (FMC->ISPSTS & FMC_ISPSTS_ISPFF_Msk)
396 {
397 FMC->ISPSTS |= FMC_ISPSTS_ISPFF_Msk;
398 g_FMC_i32ErrCode = -1;
399 return -1;
400 }
401 return 0;
402}
403
418int32_t FMC_Write256(uint32_t u32Addr, uint32_t *pu32Buf)
419{
420 int32_t i, idx;
421 volatile uint32_t *pu32IspData;
422 int32_t tout;
423
425 idx = 0;
426 FMC->ISPCMD = FMC_ISPCMD_MULTI_PROG;
427 FMC->ISPADDR = u32Addr;
428
429retrigger:
430
431 FMC->MPDAT0 = pu32Buf[idx + 0];
432 FMC->MPDAT1 = pu32Buf[idx + 1];
433 FMC->MPDAT2 = pu32Buf[idx + 2];
434 FMC->MPDAT3 = pu32Buf[idx + 3];
435 FMC->ISPTRG = 0x1;
436
437 pu32IspData = &FMC->MPDAT0;
438 idx += 4;
439
440 for(i = idx; i < 256 / 4; i += 4) // Max data length is 256 bytes (256/4 words)
441 {
442 __set_PRIMASK(1); // Mask interrupt to avoid status check coherence error
443 tout = FMC_TIMEOUT_WRITE;
444 do
445 {
446 if ((FMC->MPSTS & FMC_MPSTS_MPBUSY_Msk) == 0)
447 {
448 __set_PRIMASK(0);
449 FMC->ISPADDR = FMC->MPADDR & (~0xful);
450 idx = (FMC->ISPADDR - u32Addr) / 4;
451 goto retrigger;
452 }
453 }
454 while ((tout-- > 0) && (FMC->MPSTS & (3 << FMC_MPSTS_D0_Pos)));
455
456 if (tout <= 0)
457 {
458 g_FMC_i32ErrCode = -1;
459 __set_PRIMASK(0);
460 return -1;
461 }
462
463 tout = FMC_TIMEOUT_WRITE;
464 // Update new data for D0
465 pu32IspData[0] = pu32Buf[i];
466 pu32IspData[1] = pu32Buf[i + 1];
467 do
468 {
469 if ((FMC->MPSTS & FMC_MPSTS_MPBUSY_Msk) == 0)
470 {
471 __set_PRIMASK(0);
472 FMC->ISPADDR = FMC->MPADDR & (~0xful);
473 idx = (FMC->ISPADDR - u32Addr) / 4;
474 goto retrigger;
475 }
476 }
477 while ((tout-- > 0) && (FMC->MPSTS & (3 << FMC_MPSTS_D2_Pos)));
478
479 if (tout <= 0)
480 {
481 g_FMC_i32ErrCode = -1;
482 __set_PRIMASK(0);
483 return -1;
484 }
485
486 // Update new data for D2
487 pu32IspData[2] = pu32Buf[i + 2];
488 pu32IspData[3] = pu32Buf[i + 3];
489 __set_PRIMASK(0);
490 }
491
492 tout = FMC_TIMEOUT_WRITE;
493 while ((tout-- > 0) && (FMC->ISPSTS & FMC_ISPSTS_ISPBUSY_Msk)) { }
494 if (tout <= 0)
495 {
496 g_FMC_i32ErrCode = -1;
497 return -1;
498 }
499 return 0;
500}
501
516int32_t FMC_Erase(uint32_t u32Addr)
517{
518 int32_t tout = FMC_TIMEOUT_ERASE;
519
521 FMC->ISPCMD = FMC_ISPCMD_PAGE_ERASE;
522 FMC->ISPADDR = u32Addr;
523 FMC->ISPTRG = 0x1;
524#if ISBEN
525 __ISB();
526#endif
527 while ((tout-- > 0) && (FMC->ISPTRG)) {}
528 if (tout <= 0)
529 {
530 g_FMC_i32ErrCode = -1;
531 return -1;
532 }
533
534 if (FMC->ISPCTL & FMC_ISPCTL_ISPFF_Msk)
535 {
536 FMC->ISPCTL |= FMC_ISPCTL_ISPFF_Msk;
537 g_FMC_i32ErrCode = -1;
538 return -1;
539 }
540 return 0;
541}
542
554int32_t FMC_ReadConfig(uint32_t *u32Config, uint32_t u32Count)
555{
556 int32_t i;
557
558 for(i = 0; i < u32Count; i++)
559 u32Config[i] = FMC_Read(FMC_CONFIG_BASE + i * 4);
560
561 return 0;
562}
563
564
577int32_t FMC_WriteConfig(uint32_t *u32Config, uint32_t u32Count)
578{
579 int32_t i;
580
581 for(i = 0; i < u32Count; i++)
582 {
583 FMC_Write(FMC_CONFIG_BASE + i * 4, u32Config[i]);
584 if(FMC_Read(FMC_CONFIG_BASE + i * 4) != u32Config[i])
585 return -1;
586 }
587
588 return 0;
589}
590
602uint32_t FMC_GetCheckSum(uint32_t u32Addr, int32_t i32Size)
603{
604 uint32_t tout;
605
608 FMC->ISPADDR = u32Addr;
609 FMC->ISPDAT = i32Size;
610 FMC->ISPTRG = 0x1;
611#if ISBEN
612 __ISB();
613#endif
614 tout = FMC_TIMEOUT_CHKSUM;
615 while (tout-- > 0)
616 {
617 if (!FMC->ISPTRG) /* Waiting for ISP Done */
618 goto chksum;
619 }
620 g_FMC_i32ErrCode = -1;
621 return 0xFFFFFFFF;
622
623chksum:
624 FMC->ISPCMD = FMC_ISPCMD_CHECKSUM;
625 FMC->ISPTRG = 0x1;
626#if ISBEN
627 __ISB();
628#endif
629 tout = FMC_TIMEOUT_CHKSUM;
630 while (tout-- > 0)
631 {
632 if (!FMC->ISPTRG) /* Waiting for ISP Done */
633 return FMC->ISPDAT;
634 }
635 g_FMC_i32ErrCode = -1;
636 return 0xFFFFFFFF;
637}
638
651void FMC_EnableFreqOptimizeMode(uint32_t u32Mode)
652{
653 FMC->FTCTL &= ~FMC_FTCTL_FOM_Msk;
654 FMC->FTCTL |= (u32Mode << FMC_FTCTL_FOM_Pos);
655}
656
665{
666 FMC->FTCTL &= ~FMC_FTCTL_FOM_Msk;
667}
668 /* end of group FMC_EXPORTED_FUNCTIONS */
670 /* end of group FMC_Driver */
672 /* end of group Standard_Driver */
674
675/*** (C) COPYRIGHT 2022 Nuvoton Technology Corp. ***/
676
#define FMC_ISPSTS_ISPBUSY_Msk
Definition: M4521.h:2407
#define FMC_MPSTS_D2_Pos
Definition: M4521.h:2451
#define FMC_ISPCTL_ISPFF_Msk
Definition: M4521.h:2383
#define FMC_ISPSTS_ISPFF_Msk
Definition: M4521.h:2419
#define FMC_ISPCTL_BS_Msk
Definition: M4521.h:2371
#define FMC_ISPCTL_APUEN_Msk
Definition: M4521.h:2374
#define FMC_ISPCTL_CFGUEN_Msk
Definition: M4521.h:2377
#define FMC_FTCTL_FOM_Pos
Definition: M4521.h:2403
#define FMC_ISPCTL_ISPEN_Msk
Definition: M4521.h:2368
#define FMC_ISPTRG_ISPGO_Msk
Definition: M4521.h:2398
#define FMC_MPSTS_D0_Pos
Definition: M4521.h:2445
#define FMC_MPSTS_MPBUSY_Msk
Definition: M4521.h:2437
#define FMC_ISPCTL_LDUEN_Msk
Definition: M4521.h:2380
#define FMC_TIMEOUT_ERASE
Definition: fmc.h:87
#define FMC_ISPCMD_PROGRAM
Definition: fmc.h:65
#define FMC_ISPCMD_WRITE_8
Definition: fmc.h:66
#define FMC_ISPCMD_CAL_CHECKSUM
Definition: fmc.h:73
#define FMC_ISPCMD_READ_DID
Definition: fmc.h:70
#define FMC_CONFIG_BASE
Definition: fmc.h:46
#define FMC_ISPCMD_CHECKSUM
Definition: fmc.h:72
#define FMC_TIMEOUT_CHKSUM
Definition: fmc.h:88
#define FMC_ISPCMD_READ_CID
Definition: fmc.h:68
#define FMC_TIMEOUT_READ
Definition: fmc.h:85
#define FMC_ISPCMD_READ
Definition: fmc.h:64
#define FMC_ISPCMD_MULTI_PROG
Definition: fmc.h:74
#define FMC_TIMEOUT_WRITE
Definition: fmc.h:86
#define FMC_ISPCMD_READ_UID
Definition: fmc.h:69
#define FMC_ISPCMD_PAGE_ERASE
Definition: fmc.h:67
void FMC_DisableLDUpdate(void)
Disable LDROM update function.
Definition: fmc.c:93
void FMC_Close(void)
Disable ISP Functions.
Definition: fmc.c:54
int32_t FMC_Write256(uint32_t u32Addr, uint32_t *pu32Buf)
Program Multi-Word data into specified address of flash.
Definition: fmc.c:418
int32_t g_FMC_i32ErrCode
Definition: fmc.c:28
void FMC_EnableLDUpdate(void)
Enable LDROM update function.
Definition: fmc.c:129
int32_t FMC_ReadConfig(uint32_t *u32Config, uint32_t u32Count)
Read the User Configuration words.
Definition: fmc.c:554
uint32_t FMC_ReadCID(void)
Read company ID.
Definition: fmc.c:240
int32_t FMC_Erase(uint32_t u32Addr)
Flash page erase.
Definition: fmc.c:516
void FMC_DisableFreqOptimizeMode(void)
Disable Flash Access Frequency Optimization Mode.
Definition: fmc.c:664
void FMC_EnableAPUpdate(void)
Enable APROM update function.
Definition: fmc.c:105
int32_t FMC_Write8(uint32_t u32Addr, uint32_t u32Data0, uint32_t u32Data1)
Program 64-bit data into specified address of flash.
Definition: fmc.c:377
uint32_t FMC_ReadDataFlashBaseAddr(void)
Get the base address of Data Flash if enabled.
Definition: fmc.c:170
void FMC_EnableFreqOptimizeMode(uint32_t u32Mode)
Enable Flash Access Frequency Optimization Mode.
Definition: fmc.c:651
void FMC_SetBootSource(int32_t i32BootSrc)
Set boot source from LDROM or APROM after next software reset.
Definition: fmc.c:40
int32_t FMC_Write(uint32_t u32Addr, uint32_t u32Data)
Program 32-bit data into specified address of flash.
Definition: fmc.c:336
void FMC_DisableAPUpdate(void)
Disable APROM update function.
Definition: fmc.c:67
uint32_t FMC_Read(uint32_t u32Addr)
Read 32-bit Data from specified address of flash.
Definition: fmc.c:184
uint32_t FMC_ReadPID(void)
Read product ID.
Definition: fmc.c:273
int32_t FMC_GetBootSource(void)
Get the current boot source.
Definition: fmc.c:143
int32_t FMC_WriteConfig(uint32_t *u32Config, uint32_t u32Count)
Write User Configuration.
Definition: fmc.c:577
void FMC_DisableConfigUpdate(void)
Disable User Configuration update function.
Definition: fmc.c:80
void FMC_Open(void)
Enable FMC ISP function.
Definition: fmc.c:159
uint32_t FMC_GetCheckSum(uint32_t u32Addr, int32_t i32Size)
Get Flash Checksum.
Definition: fmc.c:602
void FMC_EnableConfigUpdate(void)
Enable User Configuration update function.
Definition: fmc.c:117
uint32_t FMC_ReadUCID(uint32_t u32Index)
To read UCID.
Definition: fmc.c:302
uint32_t FMC_ReadUID(uint8_t u8Index)
Read Unique ID.
Definition: fmc.c:210
#define FMC
Definition: M4521.h:13832