M4521_BSP V3.02.000
The Board Support Package for M4521
clk.c
Go to the documentation of this file.
1/**************************************************************************/
13#include "M4521.h"
14
23int32_t g_CLK_i32ErrCode = 0;
36{
37 /* Disable CKO clock source */
39}
40
58void CLK_EnableCKO(uint32_t u32ClkSrc, uint32_t u32ClkDiv, uint32_t u32ClkDivBy1En)
59{
60 /* CKO = clock source / 2^(u32ClkDiv + 1) */
61 CLK->CLKOCTL = CLK_CLKOCTL_CLKOEN_Msk | u32ClkDiv | (u32ClkDivBy1En << CLK_CLKOCTL_DIV1EN_Pos);
62
63 /* Enable CKO clock source */
65
66 /* Select CKO clock source */
67 CLK_SetModuleClock(CLKO_MODULE, u32ClkSrc, 0);
68}
69
77void CLK_PowerDown(void)
78{
79 /* Set the processor uses deep sleep as its low power mode */
80 SCB->SCR |= SCB_SCR_SLEEPDEEP_Msk;
81
82 /* Set system Power-down enabled and Power-down entry condition */
84
85 /* Chip enter Power-down mode after CPU run WFI instruction */
86 __WFI();
87}
88
96void CLK_Idle(void)
97{
98 /* Set the processor uses sleep as its low power mode */
99 SCB->SCR &= ~SCB_SCR_SLEEPDEEP_Msk;
100
101 /* Set chip in idle mode because of WFI command */
102 CLK->PWRCTL &= ~CLK_PWRCTL_PDEN_Msk;
103
104 /* Chip enter idle mode after CPU run WFI instruction */
105 __WFI();
106}
107
114uint32_t CLK_GetHXTFreq(void)
115{
116 if(CLK->PWRCTL & CLK_PWRCTL_HXTEN_Msk)
117 return __HXT;
118 else
119 return 0;
120}
121
122
129uint32_t CLK_GetLXTFreq(void)
130{
131 if(CLK->PWRCTL & CLK_PWRCTL_LXTEN_Msk)
132 return __LXT;
133 else
134 return 0;
135}
136
143uint32_t CLK_GetPCLK0Freq(void)
144{
146 if(CLK->CLKSEL0 & CLK_CLKSEL0_PCLK0SEL_Msk)
147 return SystemCoreClock / 2;
148 else
149 return SystemCoreClock;
150}
151
152
159uint32_t CLK_GetPCLK1Freq(void)
160{
162 if(CLK->CLKSEL0 & CLK_CLKSEL0_PCLK1SEL_Msk)
163 return SystemCoreClock / 2;
164 else
165 return SystemCoreClock;
166}
167
168
175uint32_t CLK_GetHCLKFreq(void)
176{
178 return SystemCoreClock;
179}
180
181
188uint32_t CLK_GetCPUFreq(void)
189{
191 return SystemCoreClock;
192}
193
194
204uint32_t CLK_SetCoreClock(uint32_t u32Hclk)
205{
206 uint32_t u32HIRCSTB;
207
208 /* Read HIRC clock source stable flag */
209 u32HIRCSTB = CLK->STATUS & CLK_STATUS_HIRCSTB_Msk;
210
211 /* The range of u32Hclk is 25 MHz ~ 72 MHz */
212 if(u32Hclk > FREQ_72MHZ)
213 u32Hclk = FREQ_72MHZ;
214 if(u32Hclk < FREQ_25MHZ)
215 u32Hclk = FREQ_25MHZ;
216
217 /* Switch HCLK clock source to HIRC clock for safe */
218 CLK->PWRCTL |= CLK_PWRCTL_HIRCEN_Msk;
220 CLK->CLKSEL0 |= CLK_CLKSEL0_HCLKSEL_Msk;
221 CLK->CLKDIV0 &= (~CLK_CLKDIV0_HCLKDIV_Msk);
222
223 /* Configure PLL setting if HXT clock is stable */
224 if(CLK->STATUS & CLK_STATUS_HXTSTB_Msk)
225 u32Hclk = CLK_EnablePLL(CLK_PLLCTL_PLLSRC_HXT, (u32Hclk << 1));
226
227 /* Configure PLL setting if HXT clock is not stable */
228 else
229 {
230 u32Hclk = CLK_EnablePLL(CLK_PLLCTL_PLLSRC_HIRC, (u32Hclk << 1));
231
232 /* Read HIRC clock source stable flag */
233 u32HIRCSTB = CLK->STATUS & CLK_STATUS_HIRCSTB_Msk;
234 }
235
236 /* Select HCLK clock source to PLL,
237 Select HCLK clock source divider as 2
238 and update system core clock
239 */
241
242 /* Disable HIRC if HIRC is disabled before setting core clock */
243 if(u32HIRCSTB == 0)
244 CLK->PWRCTL &= ~CLK_PWRCTL_HIRCEN_Msk;
245
246 /* Return actually HCLK frequency is PLL frequency divide 2 */
247 return u32Hclk >> 1;
248}
249
264void CLK_SetHCLK(uint32_t u32ClkSrc, uint32_t u32ClkDiv)
265{
266 uint32_t u32HIRCSTB;
267
268 /* Read HIRC clock source stable flag */
269 u32HIRCSTB = CLK->STATUS & CLK_STATUS_HIRCSTB_Msk;
270
271 /* Switch to HIRC for Safe. Avoid HCLK too high when applying new divider. */
272 CLK->PWRCTL |= CLK_PWRCTL_HIRCEN_Msk;
274 CLK->CLKSEL0 = (CLK->CLKSEL0 & (~CLK_CLKSEL0_HCLKSEL_Msk)) | CLK_CLKSEL0_HCLKSEL_HIRC;
275
276 /* Apply new Divider */
277 CLK->CLKDIV0 = (CLK->CLKDIV0 & (~CLK_CLKDIV0_HCLKDIV_Msk)) | u32ClkDiv;
278
279 /* Switch HCLK to new HCLK source */
280 CLK->CLKSEL0 = (CLK->CLKSEL0 & (~CLK_CLKSEL0_HCLKSEL_Msk)) | u32ClkSrc;
281
282 /* Update System Core Clock */
284
285 /* Disable HIRC if HIRC is disabled before switching HCLK source */
286 if(u32HIRCSTB == 0)
287 CLK->PWRCTL &= ~CLK_PWRCTL_HIRCEN_Msk;
288}
289
370void CLK_SetModuleClock(uint32_t u32ModuleIdx, uint32_t u32ClkSrc, uint32_t u32ClkDiv)
371{
372 uint32_t u32sel = 0, u32div = 0;
373
374 if(MODULE_CLKDIV_Msk(u32ModuleIdx) != MODULE_NoMsk)
375 {
376 /* Get clock divider control register address */
377 u32div = (uint32_t)&CLK->CLKDIV0 + ((MODULE_CLKDIV(u32ModuleIdx)) * 4);
378 /* Apply new divider */
379 M32(u32div) = (M32(u32div) & (~(MODULE_CLKDIV_Msk(u32ModuleIdx) << MODULE_CLKDIV_Pos(u32ModuleIdx)))) | u32ClkDiv;
380 }
381
382 if(MODULE_CLKSEL_Msk(u32ModuleIdx) != MODULE_NoMsk)
383 {
384 /* Get clock select control register address */
385 u32sel = (uint32_t)&CLK->CLKSEL0 + ((MODULE_CLKSEL(u32ModuleIdx)) * 4);
386 /* Set new clock selection setting */
387 M32(u32sel) = (M32(u32sel) & (~(MODULE_CLKSEL_Msk(u32ModuleIdx) << MODULE_CLKSEL_Pos(u32ModuleIdx)))) | u32ClkSrc;
388 }
389}
390
391
404void CLK_SetSysTickClockSrc(uint32_t u32ClkSrc)
405{
406 CLK->CLKSEL0 = (CLK->CLKSEL0 & ~CLK_CLKSEL0_STCLKSEL_Msk) | u32ClkSrc;
407
408}
409
421void CLK_EnableXtalRC(uint32_t u32ClkMask)
422{
423 CLK->PWRCTL |= u32ClkMask;
424}
425
437void CLK_DisableXtalRC(uint32_t u32ClkMask)
438{
439 CLK->PWRCTL &= ~u32ClkMask;
440}
441
473void CLK_EnableModuleClock(uint32_t u32ModuleIdx)
474{
475 *(volatile uint32_t *)((uint32_t)&CLK->AHBCLK + (MODULE_APBCLK(u32ModuleIdx) * 4)) |= 1 << MODULE_IP_EN_Pos(u32ModuleIdx);
476}
477
509void CLK_DisableModuleClock(uint32_t u32ModuleIdx)
510{
511 *(volatile uint32_t *)((uint32_t)&CLK->AHBCLK + (MODULE_APBCLK(u32ModuleIdx) * 4)) &= ~(1 << MODULE_IP_EN_Pos(u32ModuleIdx));
512}
513
514
525uint32_t CLK_EnablePLL(uint32_t u32PllClkSrc, uint32_t u32PllFreq)
526{
527 uint32_t u32PllSrcClk, u32NR, u32NF, u32NO, u32CLK_SRC;
528 uint32_t u32Tmp, u32Tmp2, u32Tmp3, u32Min, u32MinNF, u32MinNR;
529
530 /* Disable PLL first to avoid unstable when setting PLL */
532
533 /* PLL source clock is from HXT */
534 if(u32PllClkSrc == CLK_PLLCTL_PLLSRC_HXT)
535 {
536 /* Enable HXT clock */
537 CLK->PWRCTL |= CLK_PWRCTL_HXTEN_Msk;
538
539 /* Wait for HXT clock ready */
541
542 /* Select PLL source clock from HXT */
543 u32CLK_SRC = CLK_PLLCTL_PLLSRC_HXT;
544 u32PllSrcClk = __HXT;
545
546 /* u32NR start from 2 */
547 u32NR = 2;
548 }
549
550 /* PLL source clock is from HIRC */
551 else
552 {
553 /* Enable HIRC clock */
554 CLK->PWRCTL |= CLK_PWRCTL_HIRCEN_Msk;
555
556 /* Wait for HIRC clock ready */
558
559 /* Select PLL source clock from HIRC */
560 u32CLK_SRC = CLK_PLLCTL_PLLSRC_HIRC;
561 u32PllSrcClk = __HIRC;
562
563 /* u32NR start from 4 when FIN = 22.1184MHz to avoid calculation overflow */
564 u32NR = 4;
565 }
566
567 /* Select "NO" according to request frequency */
568 if((u32PllFreq <= FREQ_500MHZ) && (u32PllFreq > FREQ_250MHZ))
569 {
570 u32NO = 0;
571 }
572 else if((u32PllFreq <= FREQ_250MHZ) && (u32PllFreq > FREQ_125MHZ))
573 {
574 u32NO = 1;
575 u32PllFreq = u32PllFreq << 1;
576 }
577 else if((u32PllFreq <= FREQ_125MHZ) && (u32PllFreq >= FREQ_50MHZ))
578 {
579 u32NO = 3;
580 u32PllFreq = u32PllFreq << 2;
581 }
582 else
583 {
584 /* Wrong frequency request. Just return default setting. */
585 goto lexit;
586 }
587
588 /* Find best solution */
589 u32Min = (uint32_t) - 1;
590 u32MinNR = 0;
591 u32MinNF = 0;
592 for(; u32NR <= 33; u32NR++)
593 {
594 u32Tmp = u32PllSrcClk / u32NR;
595 if((u32Tmp > 1600000) && (u32Tmp < 16000000))
596 {
597 for(u32NF = 2; u32NF <= 513; u32NF++)
598 {
599 u32Tmp2 = u32Tmp * u32NF;
600 if((u32Tmp2 >= 200000000) && (u32Tmp2 <= 500000000))
601 {
602 u32Tmp3 = (u32Tmp2 > u32PllFreq) ? u32Tmp2 - u32PllFreq : u32PllFreq - u32Tmp2;
603 if(u32Tmp3 < u32Min)
604 {
605 u32Min = u32Tmp3;
606 u32MinNR = u32NR;
607 u32MinNF = u32NF;
608
609 /* Break when get good results */
610 if(u32Min == 0)
611 break;
612 }
613 }
614 }
615 }
616 }
617
618 /* Enable and apply new PLL setting. */
619 CLK->PLLCTL = u32CLK_SRC | (u32NO << 14) | ((u32MinNR - 2) << 9) | (u32MinNF - 2);
620
621 /* Wait for PLL clock stable */
623
624 /* Return actual PLL output clock frequency */
625 return u32PllSrcClk / ((u32NO + 1) * u32MinNR) * u32MinNF;
626
627lexit:
628
629 /* Apply default PLL setting and return */
630 if(u32PllClkSrc == CLK_PLLCTL_PLLSRC_HXT)
631 CLK->PLLCTL = CLK_PLLCTL_72MHz_HXT; /* 72MHz */
632 else
633 CLK->PLLCTL = CLK_PLLCTL_72MHz_HIRC; /* 71.8848MHz */
634
635 /* Wait for PLL clock stable */
637
638 return CLK_GetPLLClockFreq();
639
640}
641
650{
651 CLK->PLLCTL |= CLK_PLLCTL_PD_Msk;
652}
653
654
669uint32_t CLK_WaitClockReady(uint32_t u32ClkMask)
670{
671 uint32_t u32TimeOutCnt = SystemCoreClock / 2;
672 uint32_t u32Ret = 1U;
673
675
676 while((CLK->STATUS & u32ClkMask) != u32ClkMask)
677 {
678 if(--u32TimeOutCnt == 0)
679 {
680 u32Ret = 0U;
681 break;
682 }
683 }
684
685 if(u32TimeOutCnt == 0)
687
688 return u32Ret;
689}
690
705void CLK_EnableSysTick(uint32_t u32ClkSrc, uint32_t u32Count)
706{
707 /* Set System Tick counter disabled */
708 SysTick->CTRL = 0;
709
710 /* Set System Tick clock source */
711 if( u32ClkSrc == CLK_CLKSEL0_STCLKSEL_HCLK )
712 SysTick->CTRL |= SysTick_CTRL_CLKSOURCE_Msk;
713 else
714 CLK->CLKSEL0 = (CLK->CLKSEL0 & ~CLK_CLKSEL0_STCLKSEL_Msk) | u32ClkSrc;
715
716 /* Set System Tick reload value */
717 SysTick->LOAD = u32Count;
718
719 /* Clear System Tick current value and counter flag */
720 SysTick->VAL = 0;
721
722 /* Set System Tick interrupt enabled and counter enabled */
723 SysTick->CTRL |= SysTick_CTRL_TICKINT_Msk | SysTick_CTRL_ENABLE_Msk;
724}
725
733{
734 /* Set System Tick counter disabled */
735 SysTick->CTRL = 0;
736}
737
738 /* end of group CLK_EXPORTED_FUNCTIONS */
740 /* end of group CLK_Driver */
742 /* end of group Standard_Driver */
744
745/*** (C) COPYRIGHT 2022 Nuvoton Technology Corp. ***/
int32_t g_CLK_i32ErrCode
Definition: clk.c:23
#define CLKO_MODULE
Definition: clk.h:257
#define CLK_CLKSEL0_STCLKSEL_HCLK
Definition: clk.h:56
#define CLK_PLLCTL_PLLSRC_HXT
Definition: clk.h:164
#define CLK_PLLCTL_72MHz_HXT
Definition: clk.h:174
#define FREQ_250MHZ
Definition: clk.h:38
#define MODULE_NoMsk
Definition: clk.h:193
#define MODULE_CLKSEL_Msk(x)
Definition: clk.h:187
#define CLK_CLKDIV0_HCLK(x)
Definition: clk.h:149
#define CLK_CLKSEL0_HCLKSEL_HIRC
Definition: clk.h:49
#define FREQ_25MHZ
Definition: clk.h:33
#define CLK_CLKSEL0_HCLKSEL_PLL
Definition: clk.h:47
#define FREQ_72MHZ
Definition: clk.h:35
#define FREQ_125MHZ
Definition: clk.h:36
#define CLK_PLLCTL_PLLSRC_HIRC
Definition: clk.h:165
#define MODULE_CLKSEL_Pos(x)
Definition: clk.h:188
#define FREQ_50MHZ
Definition: clk.h:34
#define MODULE_CLKDIV_Pos(x)
Definition: clk.h:191
#define MODULE_IP_EN_Pos(x)
Definition: clk.h:192
#define MODULE_CLKDIV_Msk(x)
Definition: clk.h:190
#define CLK_PLLCTL_72MHz_HIRC
Definition: clk.h:176
#define MODULE_CLKDIV(x)
Definition: clk.h:189
#define MODULE_APBCLK(x)
Definition: clk.h:185
#define CLK_TIMEOUT_ERR
Definition: clk.h:315
#define FREQ_500MHZ
Definition: clk.h:39
#define MODULE_CLKSEL(x)
Definition: clk.h:186
void CLK_Idle(void)
Enter to Idle mode.
Definition: clk.c:96
void CLK_SetSysTickClockSrc(uint32_t u32ClkSrc)
Set SysTick clock source.
Definition: clk.c:404
uint32_t CLK_GetHCLKFreq(void)
Get HCLK frequency.
Definition: clk.c:175
uint32_t CLK_EnablePLL(uint32_t u32PllClkSrc, uint32_t u32PllFreq)
Set PLL frequency.
Definition: clk.c:525
void CLK_DisableCKO(void)
Disable clock divider output function.
Definition: clk.c:35
void CLK_EnableModuleClock(uint32_t u32ModuleIdx)
Enable module clock.
Definition: clk.c:473
void CLK_EnableCKO(uint32_t u32ClkSrc, uint32_t u32ClkDiv, uint32_t u32ClkDivBy1En)
This function enable clock divider output module clock, enable clock divider output function and set ...
Definition: clk.c:58
void CLK_DisableModuleClock(uint32_t u32ModuleIdx)
Disable module clock.
Definition: clk.c:509
uint32_t CLK_WaitClockReady(uint32_t u32ClkMask)
This function check selected clock source status.
Definition: clk.c:669
uint32_t CLK_GetLXTFreq(void)
Get external low speed crystal clock frequency.
Definition: clk.c:129
uint32_t CLK_GetPCLK1Freq(void)
Get PCLK1 frequency.
Definition: clk.c:159
void CLK_PowerDown(void)
Enter to Power-down mode.
Definition: clk.c:77
uint32_t CLK_GetPCLK0Freq(void)
Get PCLK0 frequency.
Definition: clk.c:143
void CLK_DisablePLL(void)
Disable PLL.
Definition: clk.c:649
uint32_t CLK_GetCPUFreq(void)
Get CPU frequency.
Definition: clk.c:188
void CLK_SetHCLK(uint32_t u32ClkSrc, uint32_t u32ClkDiv)
This function set HCLK clock source and HCLK clock divider.
Definition: clk.c:264
__STATIC_INLINE uint32_t CLK_GetPLLClockFreq(void)
Get PLL clock frequency.
Definition: clk.h:332
void CLK_DisableXtalRC(uint32_t u32ClkMask)
Disable clock source.
Definition: clk.c:437
void CLK_DisableSysTick(void)
Disable System Tick counter.
Definition: clk.c:732
void CLK_SetModuleClock(uint32_t u32ModuleIdx, uint32_t u32ClkSrc, uint32_t u32ClkDiv)
This function set selected module clock source and module clock divider.
Definition: clk.c:370
void CLK_EnableXtalRC(uint32_t u32ClkMask)
Enable clock source.
Definition: clk.c:421
void CLK_EnableSysTick(uint32_t u32ClkSrc, uint32_t u32Count)
Enable System Tick counter.
Definition: clk.c:705
uint32_t CLK_SetCoreClock(uint32_t u32Hclk)
Set HCLK frequency.
Definition: clk.c:204
uint32_t CLK_GetHXTFreq(void)
Get external high speed crystal clock frequency.
Definition: clk.c:114
#define CLK_PWRCTL_LXTEN_Msk
Definition: M4521.h:1452
#define CLK_STATUS_PLLSTB_Msk
Definition: M4521.h:1668
#define CLK_PWRCTL_PDEN_Msk
Definition: M4521.h:1470
#define CLK_CLKOCTL_CLKOEN_Msk
Definition: M4521.h:1683
#define CLK_CLKSEL0_PCLK1SEL_Msk
Definition: M4521.h:1575
#define CLK_CLKSEL0_HCLKSEL_Msk
Definition: M4521.h:1566
#define CLK_PLLCTL_PD_Msk
Definition: M4521.h:1647
#define CLK_PWRCTL_HIRCEN_Msk
Definition: M4521.h:1455
#define CLK_CLKSEL0_PCLK0SEL_Msk
Definition: M4521.h:1572
#define CLK_PWRCTL_HXTEN_Msk
Definition: M4521.h:1449
#define CLK_STATUS_HXTSTB_Msk
Definition: M4521.h:1662
#define CLK_STATUS_HIRCSTB_Msk
Definition: M4521.h:1674
#define CLK_CLKOCTL_DIV1EN_Pos
Definition: M4521.h:1685
#define CLK_PWRCTL_PDWTCPU_Msk
Definition: M4521.h:1473
#define CLK
Definition: M4521.h:13822
#define M32(adr)
Definition: M4521.h:13941
#define __HIRC
Definition: system_M4521.h:37
#define __HXT
Definition: system_M4521.h:35
uint32_t SystemCoreClock
Definition: system_M4521.c:24
#define __LXT
Definition: system_M4521.h:36
void SystemCoreClockUpdate(void)
Updates the SystemCoreClock with current core Clock retrieved from cpu registers.
Definition: system_M4521.c:32