M471M/R1/S BSP V3.01.000
The Board Support Package for M4521
clk.c
Go to the documentation of this file.
1/**************************************************************************/
9#include "NuMicro.h"
10
30{
31 /* Disable CKO clock source */
33}
34
52void CLK_EnableCKO(uint32_t u32ClkSrc, uint32_t u32ClkDiv, uint32_t u32ClkDivBy1En)
53{
54 /* CKO = clock source / 2^(u32ClkDiv + 1) */
55 CLK->CLKOCTL = CLK_CLKOCTL_CLKOEN_Msk | u32ClkDiv | (u32ClkDivBy1En << CLK_CLKOCTL_DIV1EN_Pos);
56
57 /* Enable CKO clock source */
59
60 /* Select CKO clock source */
61 CLK_SetModuleClock(CLKO_MODULE, u32ClkSrc, 0);
62}
63
71void CLK_PowerDown(void)
72{
73 /* Set the processor uses deep sleep as its low power mode */
74 SCB->SCR |= SCB_SCR_SLEEPDEEP_Msk;
75
76 /* Set system Power-down enabled and Power-down entry condition */
78
79 /* Chip enter Power-down mode after CPU run WFI instruction */
80 __WFI();
81}
82
90void CLK_Idle(void)
91{
92 /* Set the processor uses sleep as its low power mode */
93 SCB->SCR &= ~SCB_SCR_SLEEPDEEP_Msk;
94
95 /* Set chip in idle mode because of WFI command */
96 CLK->PWRCTL &= ~CLK_PWRCTL_PDEN_Msk;
97
98 /* Chip enter idle mode after CPU run WFI instruction */
99 __WFI();
100}
101
108uint32_t CLK_GetHXTFreq(void)
109{
110 if(CLK->PWRCTL & CLK_PWRCTL_HXTEN_Msk)
111 return __HXT;
112 else
113 return 0;
114}
115
116
123uint32_t CLK_GetLXTFreq(void)
124{
125 if(CLK->PWRCTL & CLK_PWRCTL_LXTEN_Msk)
126 return __LXT;
127 else
128 return 0;
129}
130
137uint32_t CLK_GetPCLK0Freq(void)
138{
140 if(CLK->CLKSEL0 & CLK_CLKSEL0_PCLK0SEL_Msk)
141 return SystemCoreClock / 2;
142 else
143 return SystemCoreClock;
144}
145
146
153uint32_t CLK_GetPCLK1Freq(void)
154{
156 if(CLK->CLKSEL0 & CLK_CLKSEL0_PCLK1SEL_Msk)
157 return SystemCoreClock / 2;
158 else
159 return SystemCoreClock;
160}
161
162
169uint32_t CLK_GetHCLKFreq(void)
170{
172 return SystemCoreClock;
173}
174
175
182uint32_t CLK_GetCPUFreq(void)
183{
185 return SystemCoreClock;
186}
187
188
198uint32_t CLK_SetCoreClock(uint32_t u32Hclk)
199{
200 uint32_t u32HIRCSTB;
201
202 /* Read HIRC clock source stable flag */
203 u32HIRCSTB = CLK->STATUS & CLK_STATUS_HIRCSTB_Msk;
204
205 /* The range of u32Hclk is 25 MHz ~ 72 MHz */
206 if(u32Hclk > FREQ_72MHZ)
207 u32Hclk = FREQ_72MHZ;
208 if(u32Hclk < FREQ_25MHZ)
209 u32Hclk = FREQ_25MHZ;
210
211 /* Switch HCLK clock source to HIRC clock for safe */
212 CLK->PWRCTL |= CLK_PWRCTL_HIRCEN_Msk;
214 CLK->CLKSEL0 |= CLK_CLKSEL0_HCLKSEL_Msk;
215 CLK->CLKDIV0 &= (~CLK_CLKDIV0_HCLKDIV_Msk);
216
217 /* Configure PLL setting if HXT clock is stable */
218 if(CLK->STATUS & CLK_STATUS_HXTSTB_Msk)
219 u32Hclk = CLK_EnablePLL(CLK_PLLCTL_PLLSRC_HXT, (u32Hclk << 1));
220
221 /* Configure PLL setting if HXT clock is not stable */
222 else
223 {
224 u32Hclk = CLK_EnablePLL(CLK_PLLCTL_PLLSRC_HIRC, (u32Hclk << 1));
225
226 /* Read HIRC clock source stable flag */
227 u32HIRCSTB = CLK->STATUS & CLK_STATUS_HIRCSTB_Msk;
228 }
229
230 /* Select HCLK clock source to PLL,
231 Select HCLK clock source divider as 2
232 and update system core clock
233 */
235
236 /* Disable HIRC if HIRC is disabled before setting core clock */
237 if(u32HIRCSTB == 0)
238 CLK->PWRCTL &= ~CLK_PWRCTL_HIRCEN_Msk;
239
240 /* Return actually HCLK frequency is PLL frequency divide 2 */
241 return u32Hclk >> 1;
242}
243
258void CLK_SetHCLK(uint32_t u32ClkSrc, uint32_t u32ClkDiv)
259{
260 uint32_t u32HIRCSTB;
261
262 /* Read HIRC clock source stable flag */
263 u32HIRCSTB = CLK->STATUS & CLK_STATUS_HIRCSTB_Msk;
264
265 /* Switch to HIRC for Safe. Avoid HCLK too high when applying new divider. */
266 CLK->PWRCTL |= CLK_PWRCTL_HIRCEN_Msk;
268 CLK->CLKSEL0 = (CLK->CLKSEL0 & (~CLK_CLKSEL0_HCLKSEL_Msk)) | CLK_CLKSEL0_HCLKSEL_HIRC;
269
270 /* Apply new Divider */
271 CLK->CLKDIV0 = (CLK->CLKDIV0 & (~CLK_CLKDIV0_HCLKDIV_Msk)) | u32ClkDiv;
272
273 /* Switch HCLK to new HCLK source */
274 CLK->CLKSEL0 = (CLK->CLKSEL0 & (~CLK_CLKSEL0_HCLKSEL_Msk)) | u32ClkSrc;
275
276 /* Update System Core Clock */
278
279 /* Disable HIRC if HIRC is disabled before switching HCLK source */
280 if(u32HIRCSTB == 0)
281 CLK->PWRCTL &= ~CLK_PWRCTL_HIRCEN_Msk;
282}
283
364void CLK_SetModuleClock(uint32_t u32ModuleIdx, uint32_t u32ClkSrc, uint32_t u32ClkDiv)
365{
366 uint32_t u32sel = 0, u32div = 0;
367
368 if(MODULE_CLKDIV_Msk(u32ModuleIdx) != MODULE_NoMsk)
369 {
370 /* Get clock divider control register address */
371 u32div = (uint32_t)&CLK->CLKDIV0 + ((MODULE_CLKDIV(u32ModuleIdx)) * 4);
372 /* Apply new divider */
373 M32(u32div) = (M32(u32div) & (~(MODULE_CLKDIV_Msk(u32ModuleIdx) << MODULE_CLKDIV_Pos(u32ModuleIdx)))) | u32ClkDiv;
374 }
375
376 if(MODULE_CLKSEL_Msk(u32ModuleIdx) != MODULE_NoMsk)
377 {
378 /* Get clock select control register address */
379 u32sel = (uint32_t)&CLK->CLKSEL0 + ((MODULE_CLKSEL(u32ModuleIdx)) * 4);
380 /* Set new clock selection setting */
381 M32(u32sel) = (M32(u32sel) & (~(MODULE_CLKSEL_Msk(u32ModuleIdx) << MODULE_CLKSEL_Pos(u32ModuleIdx)))) | u32ClkSrc;
382 }
383}
384
385
398void CLK_SetSysTickClockSrc(uint32_t u32ClkSrc)
399{
400 CLK->CLKSEL0 = (CLK->CLKSEL0 & ~CLK_CLKSEL0_STCLKSEL_Msk) | u32ClkSrc;
401
402}
403
415void CLK_EnableXtalRC(uint32_t u32ClkMask)
416{
417 CLK->PWRCTL |= u32ClkMask;
418}
419
431void CLK_DisableXtalRC(uint32_t u32ClkMask)
432{
433 CLK->PWRCTL &= ~u32ClkMask;
434}
435
467void CLK_EnableModuleClock(uint32_t u32ModuleIdx)
468{
469 *(volatile uint32_t *)((uint32_t)&CLK->AHBCLK + (MODULE_APBCLK(u32ModuleIdx) * 4)) |= 1 << MODULE_IP_EN_Pos(u32ModuleIdx);
470}
471
503void CLK_DisableModuleClock(uint32_t u32ModuleIdx)
504{
505 *(volatile uint32_t *)((uint32_t)&CLK->AHBCLK + (MODULE_APBCLK(u32ModuleIdx) * 4)) &= ~(1 << MODULE_IP_EN_Pos(u32ModuleIdx));
506}
507
508
519uint32_t CLK_EnablePLL(uint32_t u32PllClkSrc, uint32_t u32PllFreq)
520{
521 uint32_t u32PllSrcClk, u32NR, u32NF, u32NO, u32CLK_SRC;
522 uint32_t u32Tmp, u32Tmp2, u32Tmp3, u32Min, u32MinNF, u32MinNR;
523
524 /* Disable PLL first to avoid unstable when setting PLL */
526
527 /* PLL source clock is from HXT */
528 if(u32PllClkSrc == CLK_PLLCTL_PLLSRC_HXT)
529 {
530 /* Enable HXT clock */
531 CLK->PWRCTL |= CLK_PWRCTL_HXTEN_Msk;
532
533 /* Wait for HXT clock ready */
535
536 /* Select PLL source clock from HXT */
537 u32CLK_SRC = CLK_PLLCTL_PLLSRC_HXT;
538 u32PllSrcClk = __HXT;
539
540 /* u32NR start from 2 */
541 u32NR = 2;
542 }
543
544 /* PLL source clock is from HIRC */
545 else
546 {
547 /* Enable HIRC clock */
548 CLK->PWRCTL |= CLK_PWRCTL_HIRCEN_Msk;
549
550 /* Wait for HIRC clock ready */
552
553 /* Select PLL source clock from HIRC */
554 u32CLK_SRC = CLK_PLLCTL_PLLSRC_HIRC;
555 u32PllSrcClk = __HIRC;
556
557 /* u32NR start from 4 when FIN = 22.1184MHz to avoid calculation overflow */
558 u32NR = 4;
559 }
560
561 /* Select "NO" according to request frequency */
562 if((u32PllFreq <= FREQ_500MHZ) && (u32PllFreq > FREQ_250MHZ))
563 {
564 u32NO = 0;
565 }
566 else if((u32PllFreq <= FREQ_250MHZ) && (u32PllFreq > FREQ_125MHZ))
567 {
568 u32NO = 1;
569 u32PllFreq = u32PllFreq << 1;
570 }
571 else if((u32PllFreq <= FREQ_125MHZ) && (u32PllFreq >= FREQ_50MHZ))
572 {
573 u32NO = 3;
574 u32PllFreq = u32PllFreq << 2;
575 }
576 else
577 {
578 /* Wrong frequency request. Just return default setting. */
579 goto lexit;
580 }
581
582 /* Find best solution */
583 u32Min = (uint32_t) - 1;
584 u32MinNR = 0;
585 u32MinNF = 0;
586 for(; u32NR <= 33; u32NR++)
587 {
588 u32Tmp = u32PllSrcClk / u32NR;
589 if((u32Tmp > 1600000) && (u32Tmp < 16000000))
590 {
591 for(u32NF = 2; u32NF <= 513; u32NF++)
592 {
593 u32Tmp2 = u32Tmp * u32NF;
594 if((u32Tmp2 >= 200000000) && (u32Tmp2 <= 500000000))
595 {
596 u32Tmp3 = (u32Tmp2 > u32PllFreq) ? u32Tmp2 - u32PllFreq : u32PllFreq - u32Tmp2;
597 if(u32Tmp3 < u32Min)
598 {
599 u32Min = u32Tmp3;
600 u32MinNR = u32NR;
601 u32MinNF = u32NF;
602
603 /* Break when get good results */
604 if(u32Min == 0)
605 break;
606 }
607 }
608 }
609 }
610 }
611
612 /* Enable and apply new PLL setting. */
613 CLK->PLLCTL = u32CLK_SRC | (u32NO << 14) | ((u32MinNR - 2) << 9) | (u32MinNF - 2);
614
615 /* Wait for PLL clock stable */
617
618 /* Return actual PLL output clock frequency */
619 return u32PllSrcClk / ((u32NO + 1) * u32MinNR) * u32MinNF;
620
621lexit:
622
623 /* Apply default PLL setting and return */
624 if(u32PllClkSrc == CLK_PLLCTL_PLLSRC_HXT)
625 CLK->PLLCTL = CLK_PLLCTL_72MHz_HXT; /* 72MHz */
626 else
627 CLK->PLLCTL = CLK_PLLCTL_72MHz_HIRC; /* 71.8848MHz */
628
629 /* Wait for PLL clock stable */
631
632 return CLK_GetPLLClockFreq();
633
634}
635
644{
645 CLK->PLLCTL |= CLK_PLLCTL_PD_Msk;
646}
647
648
661uint32_t CLK_WaitClockReady(uint32_t u32ClkMask)
662{
663 int32_t i32TimeOutCnt = 2160000;
664
665 while((CLK->STATUS & u32ClkMask) != u32ClkMask)
666 {
667 if(i32TimeOutCnt-- <= 0)
668 return 0;
669 }
670
671 return 1;
672}
673
688void CLK_EnableSysTick(uint32_t u32ClkSrc, uint32_t u32Count)
689{
690 /* Set System Tick counter disabled */
691 SysTick->CTRL = 0;
692
693 /* Set System Tick clock source */
694 if( u32ClkSrc == CLK_CLKSEL0_STCLKSEL_HCLK )
695 SysTick->CTRL |= SysTick_CTRL_CLKSOURCE_Msk;
696 else
697 CLK->CLKSEL0 = (CLK->CLKSEL0 & ~CLK_CLKSEL0_STCLKSEL_Msk) | u32ClkSrc;
698
699 /* Set System Tick reload value */
700 SysTick->LOAD = u32Count;
701
702 /* Clear System Tick current value and counter flag */
703 SysTick->VAL = 0;
704
705 /* Set System Tick interrupt enabled and counter enabled */
706 SysTick->CTRL |= SysTick_CTRL_TICKINT_Msk | SysTick_CTRL_ENABLE_Msk;
707}
708
716{
717 /* Set System Tick counter disabled */
718 SysTick->CTRL = 0;
719}
720
721 /* end of group CLK_EXPORTED_FUNCTIONS */
723 /* end of group CLK_Driver */
725 /* end of group Standard_Driver */
727
NuMicro peripheral access layer header file.
#define CLKO_MODULE
Definition: clk.h:253
#define CLK_CLKSEL0_STCLKSEL_HCLK
Definition: clk.h:52
#define CLK_PLLCTL_PLLSRC_HXT
Definition: clk.h:160
#define CLK_PLLCTL_72MHz_HXT
Definition: clk.h:170
#define FREQ_250MHZ
Definition: clk.h:34
#define MODULE_NoMsk
Definition: clk.h:189
#define MODULE_CLKSEL_Msk(x)
Definition: clk.h:183
#define CLK_CLKDIV0_HCLK(x)
Definition: clk.h:145
#define CLK_CLKSEL0_HCLKSEL_HIRC
Definition: clk.h:45
#define FREQ_25MHZ
Definition: clk.h:29
#define CLK_CLKSEL0_HCLKSEL_PLL
Definition: clk.h:43
#define FREQ_72MHZ
Definition: clk.h:31
#define FREQ_125MHZ
Definition: clk.h:32
#define CLK_PLLCTL_PLLSRC_HIRC
Definition: clk.h:161
#define MODULE_CLKSEL_Pos(x)
Definition: clk.h:184
#define FREQ_50MHZ
Definition: clk.h:30
#define MODULE_CLKDIV_Pos(x)
Definition: clk.h:187
#define MODULE_IP_EN_Pos(x)
Definition: clk.h:188
#define MODULE_CLKDIV_Msk(x)
Definition: clk.h:186
#define CLK_PLLCTL_72MHz_HIRC
Definition: clk.h:172
#define MODULE_CLKDIV(x)
Definition: clk.h:185
#define MODULE_APBCLK(x)
Definition: clk.h:181
#define FREQ_500MHZ
Definition: clk.h:35
#define MODULE_CLKSEL(x)
Definition: clk.h:182
void CLK_Idle(void)
Enter to Idle mode.
Definition: clk.c:90
void CLK_SetSysTickClockSrc(uint32_t u32ClkSrc)
Set SysTick clock source.
Definition: clk.c:398
uint32_t CLK_GetHCLKFreq(void)
Get HCLK frequency.
Definition: clk.c:169
uint32_t CLK_EnablePLL(uint32_t u32PllClkSrc, uint32_t u32PllFreq)
Set PLL frequency.
Definition: clk.c:519
void CLK_DisableCKO(void)
Disable clock divider output function.
Definition: clk.c:29
void CLK_EnableModuleClock(uint32_t u32ModuleIdx)
Enable module clock.
Definition: clk.c:467
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:52
void CLK_DisableModuleClock(uint32_t u32ModuleIdx)
Disable module clock.
Definition: clk.c:503
uint32_t CLK_WaitClockReady(uint32_t u32ClkMask)
This function check selected clock source status.
Definition: clk.c:661
uint32_t CLK_GetLXTFreq(void)
Get external low speed crystal clock frequency.
Definition: clk.c:123
uint32_t CLK_GetPCLK1Freq(void)
Get PCLK1 frequency.
Definition: clk.c:153
void CLK_PowerDown(void)
Enter to Power-down mode.
Definition: clk.c:71
uint32_t CLK_GetPCLK0Freq(void)
Get PCLK0 frequency.
Definition: clk.c:137
void CLK_DisablePLL(void)
Disable PLL.
Definition: clk.c:643
uint32_t CLK_GetCPUFreq(void)
Get CPU frequency.
Definition: clk.c:182
void CLK_SetHCLK(uint32_t u32ClkSrc, uint32_t u32ClkDiv)
This function set HCLK clock source and HCLK clock divider.
Definition: clk.c:258
__STATIC_INLINE uint32_t CLK_GetPLLClockFreq(void)
Get PLL clock frequency.
Definition: clk.h:326
void CLK_DisableXtalRC(uint32_t u32ClkMask)
Disable clock source.
Definition: clk.c:431
void CLK_DisableSysTick(void)
Disable System Tick counter.
Definition: clk.c:715
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:364
void CLK_EnableXtalRC(uint32_t u32ClkMask)
Enable clock source.
Definition: clk.c:415
void CLK_EnableSysTick(uint32_t u32ClkSrc, uint32_t u32Count)
Enable System Tick counter.
Definition: clk.c:688
uint32_t CLK_SetCoreClock(uint32_t u32Hclk)
Set HCLK frequency.
Definition: clk.c:198
uint32_t CLK_GetHXTFreq(void)
Get external high speed crystal clock frequency.
Definition: clk.c:108
#define CLK_PWRCTL_LXTEN_Msk
Definition: M471M_R1_S.h:1448
#define CLK_STATUS_PLLSTB_Msk
Definition: M471M_R1_S.h:1664
#define CLK_PWRCTL_PDEN_Msk
Definition: M471M_R1_S.h:1466
#define CLK_CLKOCTL_CLKOEN_Msk
Definition: M471M_R1_S.h:1679
#define CLK_CLKSEL0_PCLK1SEL_Msk
Definition: M471M_R1_S.h:1571
#define CLK_CLKSEL0_HCLKSEL_Msk
Definition: M471M_R1_S.h:1562
#define CLK_PLLCTL_PD_Msk
Definition: M471M_R1_S.h:1643
#define CLK_PWRCTL_HIRCEN_Msk
Definition: M471M_R1_S.h:1451
#define CLK_CLKSEL0_PCLK0SEL_Msk
Definition: M471M_R1_S.h:1568
#define CLK_PWRCTL_HXTEN_Msk
Definition: M471M_R1_S.h:1445
#define CLK_STATUS_HXTSTB_Msk
Definition: M471M_R1_S.h:1658
#define CLK_STATUS_HIRCSTB_Msk
Definition: M471M_R1_S.h:1670
#define CLK_CLKOCTL_DIV1EN_Pos
Definition: M471M_R1_S.h:1681
#define CLK_PWRCTL_PDWTCPU_Msk
Definition: M471M_R1_S.h:1469
#define CLK
Definition: M471M_R1_S.h:13818
#define M32(adr)
Definition: M471M_R1_S.h:13937
#define __HIRC
#define __HXT
uint32_t SystemCoreClock
#define __LXT
void SystemCoreClockUpdate(void)
Updates the SystemCoreClock with current core Clock retrieved from cpu registers.