MINI58_BSP V3.01.005
The Board Support Package for Mini58 Series MCU
clk.c
Go to the documentation of this file.
1/**************************************************************************/
12#include "Mini58Series.h"
31{
32 /* Disable CKO clock source */
33 CLK->APBCLK &= (~CLK_APBCLK_CLKOCKEN_Msk);
34}
35
54void CLK_EnableCKO(uint32_t u32ClkSrc, uint32_t u32ClkDiv, uint32_t u32ClkDivBy1En)
55{
56 /* CKO = clock source / 2^(u32ClkDiv + 1) */
57 CLK->CLKOCTL = CLK_CLKOCTL_CLKOEN_Msk | u32ClkDiv | u32ClkDivBy1En<<CLK_CLKOCTL_DIV1EN_Pos;
58
59 /* Enable CKO clock source */
61
62 /* Select CKO clock source */
63 CLK->CLKSEL2 = (CLK->CLKSEL2 & (~CLK_CLKSEL2_CLKOSEL_Msk)) | u32ClkSrc;
64}
65
70void CLK_PowerDown(void)
71{
72 SCB->SCR = SCB_SCR_SLEEPDEEP_Msk;
74 __WFI();
75}
76
81void CLK_Idle(void)
82{
83 CLK->PWRCTL &= ~(CLK_PWRCTL_PDEN_Msk);
84 __WFI();
85}
86
91uint32_t CLK_GetHXTFreq(void)
92{
94 return __HXT;
95 else
96 return 0;
97}
98
103uint32_t CLK_GetLXTFreq(void)
104{
106 return __XTAL;
107 else
108 return 0;
109}
110
115uint32_t CLK_GetHCLKFreq(void)
116{
118 return SystemCoreClock;
119}
120
121
126uint32_t CLK_GetCPUFreq(void)
127{
129 return SystemCoreClock;
130}
131
141uint32_t CLK_SetCoreClock(uint32_t u32Hclk)
142{
143 uint32_t u32HIRCSTB;
144
145 /* Read HIRC clock source stable flag */
146 u32HIRCSTB = CLK->STATUS & CLK_STATUS_HIRCSTB_Msk;
147
148 /* The range of u32Hclk is 25 MHz ~ 50 MHz */
149 if(u32Hclk > FREQ_50MHZ)
150 u32Hclk = FREQ_50MHZ;
151 if(u32Hclk < FREQ_25MHZ)
152 u32Hclk = FREQ_25MHZ;
153
154 /* Switch HCLK clock source to HIRC clock for safe */
155 CLK->PWRCTL |= CLK_PWRCTL_HIRCEN_Msk;
157 CLK->CLKSEL0 |= CLK_CLKSEL0_HCLKSEL_Msk;
158 CLK->CLKDIV &= (~CLK_CLKDIV_HCLKDIV_Msk);
159
160 /* Configure PLL setting if HXT clock is enabled */
162 u32Hclk = CLK_EnablePLL(CLK_PLLCTL_PLLSRC_HXT, (u32Hclk << 1));
163
164 /* Configure PLL setting if HXT clock is not enabled */
165 else
166 {
167 u32Hclk = CLK_EnablePLL(CLK_PLLCTL_PLLSRC_HIRC, (u32Hclk << 1));
168
169 /* Read HIRC clock source stable flag */
170 u32HIRCSTB = CLK->STATUS & CLK_STATUS_HIRCSTB_Msk;
171 }
172
173 /* Select HCLK clock source to PLL,
174 Select HCLK clock source divider as 2
175 and update system core clock
176 */
178
179 /* Disable HIRC if HIRC is disabled before setting core clock */
180 if(u32HIRCSTB == 0)
181 CLK->PWRCTL &= ~CLK_PWRCTL_HIRCEN_Msk;
182
183 /* Return actually HCLK frequency is PLL frequency divide 2 */
184 return u32Hclk >> 1;
185}
186
197void CLK_SetHCLK(uint32_t u32ClkSrc, uint32_t u32ClkDiv)
198{
199 /* Apply new Divider */
200 CLK->CLKDIV = (CLK->CLKDIV & ~CLK_CLKDIV_HCLKDIV_Msk) | u32ClkDiv;
201
202 /* Switch HCLK to new HCLK source */
203 CLK->CLKSEL0 = (CLK->CLKSEL0 & ~CLK_CLKSEL0_HCLKSEL_Msk) | u32ClkSrc;
204
205 /* Update System Core Clock */
207}
208
258void CLK_SetModuleClock(uint32_t u32ModuleIdx, uint32_t u32ClkSrc, uint32_t u32ClkDiv)
259{
260 uint32_t u32tmp=0,u32sel=0,u32div=0;
261
262 if(MODULE_CLKSEL_Msk(u32ModuleIdx)!=MODULE_NoMsk)
263 {
264 u32sel = (uint32_t)&CLK->CLKSEL0+((MODULE_CLKSEL(u32ModuleIdx))*4);
265 u32tmp = *(volatile uint32_t *)(u32sel);
266 u32tmp = ( u32tmp & ~(MODULE_CLKSEL_Msk(u32ModuleIdx)<<MODULE_CLKSEL_Pos(u32ModuleIdx)) ) | u32ClkSrc;
267 *(volatile uint32_t *)(u32sel) = u32tmp;
268 }
269
270 if(MODULE_CLKDIV_Msk(u32ModuleIdx)!=MODULE_NoMsk)
271 {
272 u32div =(uint32_t)&CLK->CLKDIV+((MODULE_CLKDIV(u32ModuleIdx))*4);
273 u32tmp = *(volatile uint32_t *)(u32div);
274 u32tmp = ( u32tmp & ~(MODULE_CLKDIV_Msk(u32ModuleIdx)<<MODULE_CLKDIV_Pos(u32ModuleIdx)) ) | u32ClkDiv;
275 *(volatile uint32_t *)(u32div) = u32tmp;
276 }
277}
278
288void CLK_SetSysTickClockSrc(uint32_t u32ClkSrc)
289{
290 CLK->CLKSEL0 = (CLK->CLKSEL0 & ~CLK_CLKSEL0_STCLKSEL_Msk) | u32ClkSrc;
291}
292
306void CLK_EnableSysTick(uint32_t u32ClkSrc, uint32_t u32Count)
307{
308 SysTick->CTRL=0;
309 if( u32ClkSrc== CLK_CLKSEL0_STCLKSEL_HCLK ) /* Set System Tick clock source */
310 SysTick->CTRL |= SysTick_CTRL_CLKSOURCE_Msk;
311 else
312 {
313 SysTick->CTRL &= ~SysTick_CTRL_CLKSOURCE_Msk;
314 CLK->CLKSEL0 = (CLK->CLKSEL0 & ~CLK_CLKSEL0_STCLKSEL_Msk) | u32ClkSrc;
315 }
316 SysTick->LOAD = u32Count; /* Set System Tick reload value */
317 SysTick->VAL = 0; /* Clear System Tick current value and counter flag */
318 SysTick->CTRL |= SysTick_CTRL_ENABLE_Msk; /* Set System Tick counter enabled */
319}
320
327{
328 SysTick->CTRL = 0; /* Set System Tick counter disabled */
329}
330
339void CLK_EnableXtalRC(uint32_t u32ClkMask)
340{
341 if(u32ClkMask & CLK_PWRCTL_XTLEN_Msk)
342 CLK->PWRCTL = (CLK->PWRCTL & ~CLK_PWRCTL_XTLEN_Msk) | u32ClkMask;
343 else
344 CLK->PWRCTL |= u32ClkMask;
345}
346
355void CLK_DisableXtalRC(uint32_t u32ClkMask)
356{
357 CLK->PWRCTL &=~u32ClkMask;
358}
359
380void CLK_EnableModuleClock(uint32_t u32ModuleIdx)
381{
382 *(volatile uint32_t *)((uint32_t)&CLK->AHBCLK+(MODULE_APBCLK(u32ModuleIdx)*4)) |= 1<<MODULE_IP_EN_Pos(u32ModuleIdx);
383}
384
405void CLK_DisableModuleClock(uint32_t u32ModuleIdx)
406{
407 *(volatile uint32_t *)((uint32_t)&CLK->AHBCLK+(MODULE_APBCLK(u32ModuleIdx)*4)) &= ~(1<<MODULE_IP_EN_Pos(u32ModuleIdx));
408}
409
420uint32_t CLK_EnablePLL(uint32_t u32PllClkSrc, uint32_t u32PllFreq)
421{
422 uint32_t u32PllSrcClk, u32NR, u32NF, u32NO, u32CLK_SRC, u32NRT;
423 uint32_t u32Tmp, u32Tmp2, u32Tmp3, u32Min, u32MinNF, u32MinNR,u32Best;
424
425 /* Disable PLL first to avoid unstable when setting PLL */
427
428 /* PLL source clock is from HXT */
429 if(u32PllClkSrc == CLK_PLLCTL_PLLSRC_HXT)
430 {
431 /* Enable HXT clock */
432 CLK->PWRCTL = (CLK->PWRCTL & ~CLK_PWRCTL_XTLEN_Msk) | CLK_PWRCTL_XTLEN_HXT ;
433
434 /* Wait for HXT clock ready */
436
437 /* Select PLL source clock from HXT */
438 u32CLK_SRC = CLK_PLLCTL_PLLSRC_HXT;
439 u32PllSrcClk = __XTAL;
440
441 /* u32NR start from 2 */
442 u32NRT = 2;
443 }
444
445 /* PLL source clock is from HIRC */
446 else
447 {
448 /* Enable HIRC clock */
449 CLK->PWRCTL |= CLK_PWRCTL_HIRCEN_Msk;
450
451 /* Wait for HIRC clock ready */
453
454 /* Select PLL source clock from HIRC */
455 u32CLK_SRC = CLK_PLLCTL_PLLSRC_HIRC;
456 u32PllSrcClk = __HIRC;
457
458 /* u32NR start from 4 when FIN = 22.1184MHz to avoid calculation overflow */
459 u32NRT = 4;
460 }
461
462 /* Select "NO" according to request frequency */
463 if((u32PllFreq <= FREQ_200MHZ) && (u32PllFreq > FREQ_100MHZ))
464 {
465 u32NO = 0;
466 u32PllFreq = u32PllFreq;
467 }
468 else if((u32PllFreq <= FREQ_100MHZ) && (u32PllFreq >= FREQ_50MHZ))
469 {
470 u32NO = 1;
471 u32PllFreq = u32PllFreq << 1;
472 }
473 else if((u32PllFreq < FREQ_50MHZ) && (u32PllFreq >= FREQ_25MHZ))
474 {
475 u32NO = 3;
476 u32PllFreq = u32PllFreq << 2;
477 }
478 else
479 {
480 /* Wrong frequency request. Just return default setting. */
481 goto lexit;
482 }
483
484 /* Find best solution */
485 u32Min = (uint32_t) - 1;
486 u32MinNR = 0;
487 u32MinNF = 0;
488 for(u32NR=u32NRT; u32NR <= 33; u32NR++)
489 {
490 u32Tmp = u32PllSrcClk / u32NR;
491 if((u32Tmp > 1600000) && (u32Tmp < 15000000))
492 {
493 for(u32NF = 2; u32NF <= 513; u32NF++)
494 {
495 u32Tmp2 = u32Tmp * u32NF;
496 if((u32Tmp2 >= 100000000) && (u32Tmp2 <= 200000000))
497 {
498 u32Tmp3 = (u32Tmp2 > u32PllFreq) ? u32Tmp2 - u32PllFreq : u32PllFreq - u32Tmp2;
499 if(u32Tmp3 < u32Min)
500 {
501 u32Min = u32Tmp3;
502 u32MinNR = u32NR;
503 u32MinNF = u32NF;
504 /* Break when get good results */
505 if(u32Min == 0)
506 {
507 /* Enable and apply new PLL setting. */
508 CLK->PLLCTL = u32CLK_SRC | (u32NO << 14) | ((u32MinNR - 2) << 9) | (u32MinNF - 2);
509
510 /* Wait for PLL clock stable */
512
513 /* Return actual PLL output clock frequency */
514 return u32PllSrcClk / ((u32NO + 1) * u32MinNR) * u32MinNF;
515 }
516 }
517 }
518 }
519 }
520 }
521
522
523 /* Find best solution */
524 u32Best = u32Min;
525 u32Min = (uint32_t) - 1;
526 u32MinNR = 0;
527 u32MinNF = 0;
528 for(u32NR=u32NRT; u32NR <= 33; u32NR++)
529 {
530 u32Tmp = u32PllSrcClk / u32NR;
531 if((u32Tmp > 1600000) && (u32Tmp < 15000000))
532 {
533 for(u32NF = 2; u32NF <= 513; u32NF++)
534 {
535 u32Tmp2 = u32Tmp * u32NF;
536 if((u32Tmp2 >= 100000000) && (u32Tmp2 <= 200000000))
537 {
538 u32Tmp3 = (u32Tmp2 > u32PllFreq) ? u32Tmp2 - u32PllFreq : u32PllFreq - u32Tmp2;
539 if(u32Tmp3 < u32Min)
540 {
541 u32Min = u32Tmp3;
542 u32MinNR = u32NR;
543 u32MinNF = u32NF;
544
545 /* Break when get good results */
546 if(u32Min == u32Best)
547 {
548 /* Enable and apply new PLL setting. */
549 CLK->PLLCTL = u32CLK_SRC | (u32NO << 14) | ((u32MinNR - 2) << 9) | (u32MinNF - 2);
550
551 /* Wait for PLL clock stable */
553
554 /* Return actual PLL output clock frequency */
555 return u32PllSrcClk / ((u32NO + 1) * u32MinNR) * u32MinNF;
556 }
557 }
558 }
559 }
560 }
561 }
562
563
564lexit:
565
566 /* Apply default PLL setting and return */
567 if(u32PllClkSrc == CLK_PLLCTL_PLLSRC_HXT)
568 CLK->PLLCTL = CLK_PLLCTL_72MHz_HXT; /* 72MHz */
569 else
570 CLK->PLLCTL = CLK_PLLCTL_72MHz_HIRC; /* 71.8848MHz */
571
572 /* Wait for PLL clock stable */
574
575 return CLK_GetPLLClockFreq();
576
577}
578
587{
588 CLK->PLLCTL |= CLK_PLLCTL_PD_Msk;
589}
590
600int32_t CLK_SysTickDelay(uint32_t us)
601{
602 int32_t tout = SystemCoreClock * ((us / 1000000) + 1) + (SystemCoreClock / 2);
603
604 SysTick->LOAD = us * CyclesPerUs;
605 SysTick->VAL = (0x00);
606 SysTick->CTRL = SysTick_CTRL_CLKSOURCE_Msk | SysTick_CTRL_ENABLE_Msk;
607
608 /* Waiting for down-count to zero */
609 while (((SysTick->CTRL & SysTick_CTRL_COUNTFLAG_Msk) == 0) &&
610 (tout-- > 0));
611 if ((SysTick->CTRL & SysTick_CTRL_COUNTFLAG_Msk) == 0)
612 return -1; /* time out */
613 SysTick->CTRL = 0;
614 return 0;
615}
616
630uint32_t CLK_WaitClockReady(uint32_t u32ClkMask)
631{
632 int32_t i32TimeOutCnt = 2160000;
633
634 while((CLK->STATUS & u32ClkMask) != u32ClkMask)
635 {
636 if(i32TimeOutCnt-- <= 0)
637 return 0;
638 }
639 return 1;
640}
641
642 /* end of group Mini58_CLK_EXPORTED_FUNCTIONS */
644 /* end of group Mini58_CLK_Driver */
646 /* end of group Mini58_Device_Driver */
648
649/*** (C) COPYRIGHT 2022 Nuvoton Technology Corp. ***/
Mini58 series peripheral access layer header file. This file contains all the peripheral register's d...
#define CLK_CLKSEL0_STCLKSEL_HCLK
Definition: clk.h:65
#define CLK_PLLCTL_PLLSRC_HXT
Definition: clk.h:122
#define CLK_PLLCTL_72MHz_HXT
Definition: clk.h:132
#define MODULE_NoMsk
Definition: clk.h:151
#define MODULE_CLKSEL_Msk(x)
Definition: clk.h:145
#define CLK_PWRCTL_XTLEN_HXT
Definition: clk.h:48
#define FREQ_100MHZ
Definition: clk.h:38
#define FREQ_25MHZ
Definition: clk.h:35
#define CLK_CLKSEL0_HCLKSEL_PLL
Definition: clk.h:58
#define CLK_PWRCTL_XTLEN_LXT
Definition: clk.h:50
#define CLK_PLLCTL_PLLSRC_HIRC
Definition: clk.h:123
#define MODULE_CLKSEL_Pos(x)
Definition: clk.h:146
#define CLK_CLKDIV_HCLK(x)
Definition: clk.h:117
#define FREQ_50MHZ
Definition: clk.h:36
#define MODULE_CLKDIV_Pos(x)
Definition: clk.h:149
#define MODULE_IP_EN_Pos(x)
Definition: clk.h:150
#define MODULE_CLKDIV_Msk(x)
Definition: clk.h:148
#define CLK_PLLCTL_72MHz_HIRC
Definition: clk.h:136
#define MODULE_CLKDIV(x)
Definition: clk.h:147
#define FREQ_200MHZ
Definition: clk.h:39
#define MODULE_APBCLK(x)
Definition: clk.h:143
#define MODULE_CLKSEL(x)
Definition: clk.h:144
void CLK_Idle(void)
This function let system enter to Idle mode.
Definition: clk.c:81
void CLK_SetSysTickClockSrc(uint32_t u32ClkSrc)
This function set SysTick clock source.
Definition: clk.c:288
uint32_t CLK_GetHCLKFreq(void)
This function get HCLK frequency. The frequency unit is Hz.
Definition: clk.c:115
uint32_t CLK_EnablePLL(uint32_t u32PllClkSrc, uint32_t u32PllFreq)
Set PLL frequency.
Definition: clk.c:420
void CLK_DisableCKO(void)
This function disable frequency output function.
Definition: clk.c:30
void CLK_EnableModuleClock(uint32_t u32ModuleIdx)
This function enable module clock.
Definition: clk.c:380
void CLK_EnableCKO(uint32_t u32ClkSrc, uint32_t u32ClkDiv, uint32_t u32ClkDivBy1En)
This function enable frequency divider module clock, enable frequency divider clock function and conf...
Definition: clk.c:54
void CLK_DisableModuleClock(uint32_t u32ModuleIdx)
This function disable module clock.
Definition: clk.c:405
uint32_t CLK_WaitClockReady(uint32_t u32ClkMask)
This function check selected clock source status.
Definition: clk.c:630
uint32_t CLK_GetLXTFreq(void)
This function get external low frequency crystal frequency. The frequency unit is Hz.
Definition: clk.c:103
void CLK_PowerDown(void)
This function let system enter to Power-down mode.
Definition: clk.c:70
void CLK_DisablePLL(void)
Disable PLL.
Definition: clk.c:586
uint32_t CLK_GetCPUFreq(void)
This function get CPU frequency. The frequency unit is Hz.
Definition: clk.c:126
int32_t CLK_SysTickDelay(uint32_t us)
This function execute delay function.
Definition: clk.c:600
void CLK_SetHCLK(uint32_t u32ClkSrc, uint32_t u32ClkDiv)
This function set HCLK clock source and HCLK clock divider.
Definition: clk.c:197
__STATIC_INLINE uint32_t CLK_GetPLLClockFreq(void)
Get PLL clock frequency.
Definition: clk.h:197
void CLK_DisableXtalRC(uint32_t u32ClkMask)
This function disable clock source.
Definition: clk.c:355
void CLK_DisableSysTick(void)
Disable System Tick counter.
Definition: clk.c:326
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:258
void CLK_EnableXtalRC(uint32_t u32ClkMask)
This function enable clock source.
Definition: clk.c:339
void CLK_EnableSysTick(uint32_t u32ClkSrc, uint32_t u32Count)
Enable System Tick counter.
Definition: clk.c:306
uint32_t CLK_SetCoreClock(uint32_t u32Hclk)
Set HCLK frequency.
Definition: clk.c:141
uint32_t CLK_GetHXTFreq(void)
This function get external high frequency crystal frequency. The frequency unit is Hz.
Definition: clk.c:91
#define CLK_STATUS_PLLSTB_Msk
#define CLK_PWRCTL_PDEN_Msk
#define CLK_CLKOCTL_CLKOEN_Msk
#define CLK_CLKSEL0_HCLKSEL_Msk
#define CLK_PLLCTL_PD_Msk
#define CLK_PWRCTL_HIRCEN_Msk
#define CLK_STATUS_XTLSTB_Msk
#define CLK_APBCLK_CLKOCKEN_Msk
#define CLK_PWRCTL_XTLEN_Msk
#define CLK_STATUS_HIRCSTB_Msk
#define CLK_CLKOCTL_DIV1EN_Pos
#define CLK_PWRCTL_PDWKIF_Msk
#define CLK
Pointer to CLK register structure.
#define __HIRC
#define __HXT
uint32_t CyclesPerUs
#define __XTAL
uint32_t SystemCoreClock
void SystemCoreClockUpdate(void)
Updates the SystemCoreClock with current core Clock retrieved from CPU registers.