1 /**************************************************************************//**
2 * @file clk.c
3 * @version V3.00
4 * @brief M2351 series Clock Controller (CLK) driver source file
5 *
6 * @copyright SPDX-License-Identifier: Apache-2.0
7 * @copyright Copyright (C) 2016-2020 Nuvoton Technology Corp. All rights reserved.
8 *****************************************************************************/
9 #include "NuMicro.h"
10 /** @addtogroup Standard_Driver Standard Driver
11 @{
12 */
13
14 /** @addtogroup CLK_Driver CLK Driver
15 @{
16 */
17
18
19 /** @addtogroup CLK_EXPORTED_FUNCTIONS CLK Exported Functions
20 @{
21 */
22
23
24 /**
25 * @brief Disable frequency output function
26 * @param None
27 * @return None
28 * @details This function disable frequency output function.
29 */
CLK_DisableCKO(void)30 void CLK_DisableCKO(void)
31 {
32 /* Disable CKO clock source */
33 CLK->APBCLK0 &= (~CLK_APBCLK0_CLKOCKEN_Msk);
34 }
35
36
37 /**
38 * @brief This function enable frequency divider module clock.
39 * enable frequency divider clock function and configure frequency divider.
40 * @param[in] u32ClkSrc is frequency divider function clock source. Including :
41 * - \ref CLK_CLKSEL1_CLKOSEL_HXT
42 * - \ref CLK_CLKSEL1_CLKOSEL_LXT
43 * - \ref CLK_CLKSEL1_CLKOSEL_HCLK
44 * - \ref CLK_CLKSEL1_CLKOSEL_HIRC
45 * @param[in] u32ClkDiv is divider output frequency selection.
46 * @param[in] u32ClkDivBy1En is frequency divided by one enable.
47 * @return None
48 *
49 * @details Output selected clock to CKO. The output clock frequency is divided by u32ClkDiv.
50 * The formula is:
51 * CKO frequency = (Clock source frequency) / 2^(u32ClkDiv + 1)
52 * This function is just used to set CKO clock.
53 * User must enable I/O for CKO clock output pin by themselves.
54 */
CLK_EnableCKO(uint32_t u32ClkSrc,uint32_t u32ClkDiv,uint32_t u32ClkDivBy1En)55 void CLK_EnableCKO(uint32_t u32ClkSrc, uint32_t u32ClkDiv, uint32_t u32ClkDivBy1En)
56 {
57 /* CKO = clock source / 2^(u32ClkDiv + 1) */
58 CLK->CLKOCTL = CLK_CLKOCTL_CLKOEN_Msk | u32ClkDiv | (u32ClkDivBy1En << CLK_CLKOCTL_DIV1EN_Pos);
59
60 /* Enable CKO clock source */
61 CLK->APBCLK0 |= CLK_APBCLK0_CLKOCKEN_Msk;
62
63 /* Select CKO clock source */
64 CLK->CLKSEL1 = (CLK->CLKSEL1 & (~CLK_CLKSEL1_CLKOSEL_Msk)) | (u32ClkSrc);
65
66 }
67
68 /**
69 * @brief Enter to Power-down mode
70 * @param None
71 * @return None
72 * @details This function is used to let system enter to Power-down mode. \n
73 * The register write-protection function should be disabled before using this function.
74 */
CLK_PowerDown(void)75 void CLK_PowerDown(void)
76 {
77 /* Set the processor uses deep sleep as its low power mode */
78 SCB->SCR |= SCB_SCR_SLEEPDEEP_Msk;
79
80 /* Set system Power-down enabled*/
81 CLK->PWRCTL |= CLK_PWRCTL_PDEN_Msk;
82
83 /* Chip enter Power-down mode after CPU run WFI instruction */
84 __WFI();
85 }
86
87
88
89 /**
90 * @brief Enter to Idle mode
91 * @param None
92 * @return None
93 * @details This function let system enter to Idle mode. \n
94 * The register write-protection function should be disabled before using this function.
95 */
CLK_Idle(void)96 void 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
108
109 /**
110 * @brief Get external high speed crystal clock frequency
111 * @param None
112 * @return External high frequency crystal frequency
113 * @details This function get external high frequency crystal frequency. The frequency unit is Hz.
114 */
115 __NONSECURE_ENTRY_WEAK
CLK_GetHXTFreq(void)116 uint32_t CLK_GetHXTFreq(void)
117 {
118 uint32_t u32Freq = 0UL;
119 uint32_t u32HXTEN = CLK->PWRCTL & CLK_PWRCTL_HXTEN_Msk;
120
121 if(u32HXTEN)
122 {
123 u32Freq = __HXT;
124 }
125 else
126 {
127 u32Freq = 0UL;
128 }
129
130 return u32Freq;
131 }
132
133 /**
134 * @brief Get external low speed crystal clock frequency
135 * @param None
136 * @return External low speed crystal clock frequency
137 * @details This function get external low frequency crystal frequency. The frequency unit is Hz.
138 */
139
140 __NONSECURE_ENTRY_WEAK
CLK_GetLXTFreq(void)141 uint32_t CLK_GetLXTFreq(void)
142 {
143 uint32_t u32Freq = 0UL;
144 uint32_t u32LXTEN = CLK->PWRCTL & CLK_PWRCTL_LXTEN_Msk;
145
146 if(u32LXTEN)
147 {
148 u32Freq = __LXT;
149 }
150 else
151 {
152 u32Freq = 0UL;
153 }
154
155 return u32Freq;
156 }
157
158 /**
159 * @brief Get HCLK frequency
160 * @param None
161 * @return HCLK frequency
162 * @details This function get HCLK frequency. The frequency unit is Hz.
163 */
164
165 __NONSECURE_ENTRY_WEAK
CLK_GetHCLKFreq(void)166 uint32_t CLK_GetHCLKFreq(void)
167 {
168 SystemCoreClockUpdate();
169 return SystemCoreClock;
170 }
171
172 /**
173 * @brief Get PCLK0 frequency
174 * @param None
175 * @return PCLK0 frequency
176 * @details This function get PCLK0 frequency. The frequency unit is Hz.
177 */
178
179 __NONSECURE_ENTRY_WEAK
CLK_GetPCLK0Freq(void)180 uint32_t CLK_GetPCLK0Freq(void)
181 {
182 SystemCoreClockUpdate();
183 return (SystemCoreClock >> ((CLK->PCLKDIV & CLK_PCLKDIV_APB0DIV_Msk) >> CLK_PCLKDIV_APB0DIV_Pos));
184 }
185
186 /**
187 * @brief Get PCLK1 frequency
188 * @param None
189 * @return PCLK1 frequency
190 * @details This function get PCLK1 frequency. The frequency unit is Hz.
191 */
192
193 __NONSECURE_ENTRY_WEAK
CLK_GetPCLK1Freq(void)194 uint32_t CLK_GetPCLK1Freq(void)
195 {
196 SystemCoreClockUpdate();
197 return (SystemCoreClock >> ((CLK->PCLKDIV & CLK_PCLKDIV_APB1DIV_Msk) >> CLK_PCLKDIV_APB1DIV_Pos));
198 }
199
200 /**
201 * @brief Get CPU frequency
202 * @param None
203 * @return CPU frequency
204 * @details This function get CPU frequency. The frequency unit is Hz.
205 */
206
207 __NONSECURE_ENTRY_WEAK
CLK_GetCPUFreq(void)208 uint32_t CLK_GetCPUFreq(void)
209 {
210 uint32_t u32Freq, u32HclkSrc, u32HclkDiv;
211 uint32_t au32ClkTbl[] = {__HXT, __LXT, 0UL, __LIRC, 0UL, __HIRC48, 0UL, __HIRC};
212 uint32_t u32PllReg, u32FIN, u32NF, u32NR, u32NO;
213 uint8_t au8NoTbl[4] = {1U, 2U, 2U, 4U};
214 uint32_t u32RTCCKEN = CLK->APBCLK0 & CLK_APBCLK0_RTCCKEN_Msk;
215
216 /* Update PLL Clock */
217 u32PllReg = CLK->PLLCTL;
218
219 if(u32PllReg & (CLK_PLLCTL_PD_Msk | CLK_PLLCTL_OE_Msk))
220 {
221 PllClock = 0UL; /* PLL is in power down mode or fix low */
222 }
223 else /* PLL is in normal mode */
224 {
225
226 /* PLL source clock */
227 if(u32PllReg & CLK_PLLCTL_PLLSRC_Msk)
228 {
229 u32FIN = __HIRC; /* PLL source clock from HIRC */
230 }
231 else
232 {
233 u32FIN = __HXT; /* PLL source clock from HXT */
234 }
235
236 /* Calculate PLL frequency */
237 if(u32PllReg & CLK_PLLCTL_BP_Msk)
238 {
239 PllClock = u32FIN; /* PLL is in bypass mode */
240 }
241 else
242 {
243 /* PLL is output enabled in normal work mode */
244 u32NO = au8NoTbl[((u32PllReg & CLK_PLLCTL_OUTDIV_Msk) >> CLK_PLLCTL_OUTDIV_Pos)];
245 u32NF = ((u32PllReg & CLK_PLLCTL_FBDIV_Msk) >> CLK_PLLCTL_FBDIV_Pos) + 2UL;
246 u32NR = ((u32PllReg & CLK_PLLCTL_INDIV_Msk) >> CLK_PLLCTL_INDIV_Pos) + 1UL;
247
248 /* u32FIN is shifted 2 bits to avoid overflow */
249 PllClock = (((u32FIN >> 2) * (u32NF << 1)) / (u32NR * u32NO) << 2);
250 }
251 }
252
253 /* HCLK clock source */
254 u32HclkSrc = CLK->CLKSEL0 & CLK_CLKSEL0_HCLKSEL_Msk;
255
256 if(u32HclkSrc == CLK_CLKSEL0_HCLKSEL_LXT)
257 {
258
259 if(u32RTCCKEN == 0UL)
260 {
261 CLK->APBCLK0 |= CLK_APBCLK0_RTCCKEN_Msk; /* Enable RTC clock to get LXT clock source */
262 }
263
264 if(RTC->LXTCTL & RTC_LXTCTL_C32KS_Msk)
265 {
266 u32Freq = __LIRC32; /* LXT clock source is LIRC32 */
267 }
268 else
269 {
270 u32Freq = __LXT; /* LXT clock source is external LXT */
271 }
272
273 if(u32RTCCKEN == 0UL)
274 {
275 CLK->APBCLK0 &= (~CLK_APBCLK0_RTCCKEN_Msk); /* Disable RTC clock if it is disabled before */
276 }
277
278 }
279 else if(u32HclkSrc == CLK_CLKSEL0_HCLKSEL_PLL)
280 {
281 u32Freq = PllClock;/* Use PLL clock */
282 }
283 else
284 {
285 u32Freq = au32ClkTbl[u32HclkSrc]; /* Use the clock sources directly */
286 }
287
288 /* HCLK clock source divider */
289 u32HclkDiv = (CLK->CLKDIV0 & CLK_CLKDIV0_HCLKDIV_Msk) + 1UL;
290
291 /* Update System Core Clock */
292 SystemCoreClock = u32Freq / u32HclkDiv;
293
294 /* Update Cycles per micro second */
295 CyclesPerUs = (SystemCoreClock + 500000UL) / 1000000UL;
296
297 return SystemCoreClock;
298 }
299
300 /**
301 * @brief Set HCLK frequency
302 * @param[in] u32Hclk is HCLK frequency.
303 * The range of u32Hclk is 24 MHz ~ 64 MHz if power level is PL0.
304 * The range of u32Hclk is 24 MHz ~ 48 MHz if power level is PL1.
305 * @return HCLK frequency
306 * @details This function is used to set HCLK frequency. The frequency unit is Hz. \n
307 * The register write-protection function should be disabled before using this function.
308 */
CLK_SetCoreClock(uint32_t u32Hclk)309 uint32_t CLK_SetCoreClock(uint32_t u32Hclk)
310 {
311 uint32_t u32HIRCSTB, u32PLSTATUS;
312
313 /* Read HIRC clock source stable flag */
314 u32HIRCSTB = CLK->STATUS & CLK_STATUS_HIRCSTB_Msk;
315
316 /* Read power level status */
317 u32PLSTATUS = SYS->PLSTS & SYS_PLSTS_PLSTATUS_Msk;
318
319 /* Check HCLK frequency range */
320 if((u32PLSTATUS == SYS_PLSTS_PLSTATUS_PL0) && (u32Hclk > FREQ_64MHZ))
321 {
322 u32Hclk = FREQ_64MHZ;
323 }
324 else if((u32PLSTATUS == SYS_PLSTS_PLSTATUS_PL1) && (u32Hclk > FREQ_48MHZ))
325 {
326 u32Hclk = FREQ_48MHZ;
327 }
328 else if(u32Hclk < FREQ_24MHZ)
329 {
330 u32Hclk = FREQ_24MHZ;
331 }
332
333 /* Switch HCLK clock source to HIRC clock for safe */
334 CLK->PWRCTL |= CLK_PWRCTL_HIRCEN_Msk;
335 CLK_WaitClockReady(CLK_STATUS_HIRCSTB_Msk);
336 CLK->CLKSEL0 |= CLK_CLKSEL0_HCLKSEL_Msk;
337 CLK->CLKDIV0 &= (~CLK_CLKDIV0_HCLKDIV_Msk);
338
339 /* Enable Flash access cycle auto-tuning function */
340 FMC->CYCCTL &= (~FMC_CYCCTL_FADIS_Msk);
341
342 /* Configure PLL setting if HXT clock is stable */
343 if(CLK->STATUS & CLK_STATUS_HXTSTB_Msk)
344 {
345 u32Hclk = CLK_EnablePLL(CLK_PLLCTL_PLLSRC_HXT, u32Hclk);
346 }
347 /* Configure PLL setting if HXT clock is not stable */
348 else
349 {
350 u32Hclk = CLK_EnablePLL(CLK_PLLCTL_PLLSRC_HIRC, u32Hclk);
351
352 /* Read HIRC clock source stable flag */
353 u32HIRCSTB = CLK->STATUS & CLK_STATUS_HIRCSTB_Msk;
354 }
355
356 /* Select HCLK clock source to PLL,
357 Select HCLK clock source divider as 1
358 and update system core clock
359 */
360 CLK_SetHCLK(CLK_CLKSEL0_HCLKSEL_PLL, CLK_CLKDIV0_HCLK(1UL));
361
362 /* Disable HIRC if HIRC is disabled before setting core clock */
363 if(u32HIRCSTB == 0UL)
364 {
365 CLK->PWRCTL &= ~CLK_PWRCTL_HIRCEN_Msk;
366 }
367
368 /* Return actually HCLK frequency is PLL frequency divide 1 */
369 return u32Hclk;
370 }
371
372
373 /**
374 * @brief Set HCLK clock source and HCLK clock divider
375 * @param[in] u32ClkSrc is HCLK clock source. Including :
376 * - \ref CLK_CLKSEL0_HCLKSEL_HXT
377 * - \ref CLK_CLKSEL0_HCLKSEL_LXT
378 * - \ref CLK_CLKSEL0_HCLKSEL_PLL
379 * - \ref CLK_CLKSEL0_HCLKSEL_LIRC
380 * - \ref CLK_CLKSEL0_HCLKSEL_HIRC48
381 * - \ref CLK_CLKSEL0_HCLKSEL_HIRC
382 * @param[in] u32ClkDiv is HCLK clock divider. Including :
383 * - \ref CLK_CLKDIV0_HCLK(x)
384 * @return None
385 * @details This function set HCLK clock source and HCLK clock divider.
386 * The register write-protection function should be disabled before using this function.
387 */
CLK_SetHCLK(uint32_t u32ClkSrc,uint32_t u32ClkDiv)388 void CLK_SetHCLK(uint32_t u32ClkSrc, uint32_t u32ClkDiv)
389 {
390 uint32_t u32HIRCSTB;
391
392 /* Read HIRC clock source stable flag */
393 u32HIRCSTB = CLK->STATUS & CLK_STATUS_HIRCSTB_Msk;
394
395 /* Switch to HIRC for Safe. Avoid HCLK too high when applying new divider. */
396 CLK->PWRCTL |= CLK_PWRCTL_HIRCEN_Msk;
397 CLK_WaitClockReady(CLK_STATUS_HIRCSTB_Msk);
398 CLK->CLKSEL0 = (CLK->CLKSEL0 & (~CLK_CLKSEL0_HCLKSEL_Msk)) | CLK_CLKSEL0_HCLKSEL_HIRC;
399
400 /* Enable Flash access cycle auto-tuning function */
401 FMC->CYCCTL &= (~FMC_CYCCTL_FADIS_Msk);
402
403 /* Apply new Divider */
404 CLK->CLKDIV0 = (CLK->CLKDIV0 & (~CLK_CLKDIV0_HCLKDIV_Msk)) | u32ClkDiv;
405
406 /* Disable Flash access cycle auto-tuning function and set Flash access cycle if HCLK switches to HIRC48 */
407 if(u32ClkSrc == CLK_CLKSEL0_HCLKSEL_HIRC48)
408 {
409 FMC->CYCCTL = (FMC->CYCCTL & (~FMC_CYCCTL_CYCLE_Msk)) | FMC_CYCCTL_FADIS_Msk | (3UL);
410 }
411
412 /* Switch HCLK to new HCLK source */
413 CLK->CLKSEL0 = (CLK->CLKSEL0 & (~CLK_CLKSEL0_HCLKSEL_Msk)) | u32ClkSrc;
414
415 /* Update System Core Clock */
416 SystemCoreClockUpdate();
417
418 /* Disable HIRC if HIRC is disabled before switching HCLK source */
419 if(u32HIRCSTB == 0UL)
420 {
421 CLK->PWRCTL &= ~CLK_PWRCTL_HIRCEN_Msk;
422 }
423 }
424 /**
425 * @brief This function set selected module clock source and module clock divider
426 * @param[in] u32ModuleIdx is module index.
427 * @param[in] u32ClkSrc is module clock source.
428 * @param[in] u32ClkDiv is module clock divider.
429 * @return None
430 * @details Valid parameter combinations listed in following table:
431 *
432 * |Module index |Clock source |Divider |
433 * | :---------------- | :----------------------------------- | :----------------------- |
434 * |\ref SDH0_MODULE |\ref CLK_CLKSEL0_SDH0SEL_HXT |\ref CLK_CLKDIV0_SDH0(x) |
435 * |\ref SDH0_MODULE |\ref CLK_CLKSEL0_SDH0SEL_PLL |\ref CLK_CLKDIV0_SDH0(x) |
436 * |\ref SDH0_MODULE |\ref CLK_CLKSEL0_SDH0SEL_HCLK |\ref CLK_CLKDIV0_SDH0(x) |
437 * |\ref SDH0_MODULE |\ref CLK_CLKSEL0_SDH0SEL_HIRC |\ref CLK_CLKDIV0_SDH0(x) |
438 * |\ref WDT_MODULE |\ref CLK_CLKSEL1_WDTSEL_LXT | x |
439 * |\ref WDT_MODULE |\ref CLK_CLKSEL1_WDTSEL_HCLK_DIV2048 | x |
440 * |\ref WDT_MODULE |\ref CLK_CLKSEL1_WDTSEL_LIRC | x |
441 * |\ref EADC_MODULE | x |\ref CLK_CLKDIV0_EADC(x) |
442 * |\ref TMR0_MODULE |\ref CLK_CLKSEL1_TMR0SEL_HXT | x |
443 * |\ref TMR0_MODULE |\ref CLK_CLKSEL1_TMR0SEL_LXT | x |
444 * |\ref TMR0_MODULE |\ref CLK_CLKSEL1_TMR0SEL_PCLK0 | x |
445 * |\ref TMR0_MODULE |\ref CLK_CLKSEL1_TMR0SEL_EXT_TRG | x |
446 * |\ref TMR0_MODULE |\ref CLK_CLKSEL1_TMR0SEL_LIRC | x |
447 * |\ref TMR0_MODULE |\ref CLK_CLKSEL1_TMR0SEL_HIRC | x |
448 * |\ref TMR1_MODULE |\ref CLK_CLKSEL1_TMR1SEL_HXT | x |
449 * |\ref TMR1_MODULE |\ref CLK_CLKSEL1_TMR1SEL_LXT | x |
450 * |\ref TMR1_MODULE |\ref CLK_CLKSEL1_TMR1SEL_PCLK0 | x |
451 * |\ref TMR1_MODULE |\ref CLK_CLKSEL1_TMR1SEL_EXT_TRG | x |
452 * |\ref TMR1_MODULE |\ref CLK_CLKSEL1_TMR1SEL_LIRC | x |
453 * |\ref TMR1_MODULE |\ref CLK_CLKSEL1_TMR1SEL_HIRC | x |
454 * |\ref TMR2_MODULE |\ref CLK_CLKSEL1_TMR2SEL_HXT | x |
455 * |\ref TMR2_MODULE |\ref CLK_CLKSEL1_TMR2SEL_LXT | x |
456 * |\ref TMR2_MODULE |\ref CLK_CLKSEL1_TMR2SEL_PCLK1 | x |
457 * |\ref TMR2_MODULE |\ref CLK_CLKSEL1_TMR2SEL_EXT_TRG | x |
458 * |\ref TMR2_MODULE |\ref CLK_CLKSEL1_TMR2SEL_LIRC | x |
459 * |\ref TMR2_MODULE |\ref CLK_CLKSEL1_TMR2SEL_HIRC | x |
460 * |\ref TMR3_MODULE |\ref CLK_CLKSEL1_TMR3SEL_HXT | x |
461 * |\ref TMR3_MODULE |\ref CLK_CLKSEL1_TMR3SEL_LXT | x |
462 * |\ref TMR3_MODULE |\ref CLK_CLKSEL1_TMR3SEL_PCLK1 | x |
463 * |\ref TMR3_MODULE |\ref CLK_CLKSEL1_TMR3SEL_EXT_TRG | x |
464 * |\ref TMR3_MODULE |\ref CLK_CLKSEL1_TMR3SEL_LIRC | x |
465 * |\ref TMR3_MODULE |\ref CLK_CLKSEL1_TMR3SEL_HIRC | x |
466 * |\ref UART0_MODULE |\ref CLK_CLKSEL1_UART0SEL_HXT |\ref CLK_CLKDIV0_UART0(x) |
467 * |\ref UART0_MODULE |\ref CLK_CLKSEL1_UART0SEL_PLL |\ref CLK_CLKDIV0_UART0(x) |
468 * |\ref UART0_MODULE |\ref CLK_CLKSEL1_UART0SEL_LXT |\ref CLK_CLKDIV0_UART0(x) |
469 * |\ref UART0_MODULE |\ref CLK_CLKSEL1_UART0SEL_HIRC |\ref CLK_CLKDIV0_UART0(x) |
470 * |\ref UART1_MODULE |\ref CLK_CLKSEL1_UART1SEL_HXT |\ref CLK_CLKDIV0_UART1(x) |
471 * |\ref UART1_MODULE |\ref CLK_CLKSEL1_UART1SEL_PLL |\ref CLK_CLKDIV0_UART1(x) |
472 * |\ref UART1_MODULE |\ref CLK_CLKSEL1_UART1SEL_LXT |\ref CLK_CLKDIV0_UART1(x) |
473 * |\ref UART1_MODULE |\ref CLK_CLKSEL1_UART1SEL_HIRC |\ref CLK_CLKDIV0_UART1(x) |
474 * |\ref UART2_MODULE |\ref CLK_CLKSEL3_UART2SEL_HXT |\ref CLK_CLKDIV4_UART2(x) |
475 * |\ref UART2_MODULE |\ref CLK_CLKSEL3_UART2SEL_PLL |\ref CLK_CLKDIV4_UART2(x) |
476 * |\ref UART2_MODULE |\ref CLK_CLKSEL3_UART2SEL_LXT |\ref CLK_CLKDIV4_UART2(x) |
477 * |\ref UART2_MODULE |\ref CLK_CLKSEL3_UART2SEL_HIRC |\ref CLK_CLKDIV4_UART2(x) |
478 * |\ref UART3_MODULE |\ref CLK_CLKSEL3_UART3SEL_HXT |\ref CLK_CLKDIV4_UART3(x) |
479 * |\ref UART3_MODULE |\ref CLK_CLKSEL3_UART3SEL_PLL |\ref CLK_CLKDIV4_UART3(x) |
480 * |\ref UART3_MODULE |\ref CLK_CLKSEL3_UART3SEL_LXT |\ref CLK_CLKDIV4_UART3(x) |
481 * |\ref UART3_MODULE |\ref CLK_CLKSEL3_UART3SEL_HIRC |\ref CLK_CLKDIV4_UART3(x) |
482 * |\ref UART4_MODULE |\ref CLK_CLKSEL3_UART4SEL_HXT |\ref CLK_CLKDIV4_UART4(x) |
483 * |\ref UART4_MODULE |\ref CLK_CLKSEL3_UART4SEL_PLL |\ref CLK_CLKDIV4_UART4(x) |
484 * |\ref UART4_MODULE |\ref CLK_CLKSEL3_UART4SEL_LXT |\ref CLK_CLKDIV4_UART4(x) |
485 * |\ref UART4_MODULE |\ref CLK_CLKSEL3_UART4SEL_HIRC |\ref CLK_CLKDIV4_UART4(x) |
486 * |\ref UART5_MODULE |\ref CLK_CLKSEL3_UART5SEL_HXT |\ref CLK_CLKDIV4_UART5(x) |
487 * |\ref UART5_MODULE |\ref CLK_CLKSEL3_UART5SEL_PLL |\ref CLK_CLKDIV4_UART5(x) |
488 * |\ref UART5_MODULE |\ref CLK_CLKSEL3_UART5SEL_LXT |\ref CLK_CLKDIV4_UART5(x) |
489 * |\ref UART5_MODULE |\ref CLK_CLKSEL3_UART5SEL_HIRC |\ref CLK_CLKDIV4_UART5(x) |
490 * |\ref CLKO_MODULE |\ref CLK_CLKSEL1_CLKOSEL_HXT | x |
491 * |\ref CLKO_MODULE |\ref CLK_CLKSEL1_CLKOSEL_LXT | x |
492 * |\ref CLKO_MODULE |\ref CLK_CLKSEL1_CLKOSEL_HCLK | x |
493 * |\ref CLKO_MODULE |\ref CLK_CLKSEL1_CLKOSEL_HIRC | x |
494 * |\ref WWDT_MODULE |\ref CLK_CLKSEL1_WWDTSEL_HCLK_DIV2048 | x |
495 * |\ref WWDT_MODULE |\ref CLK_CLKSEL1_WWDTSEL_LIRC | x |
496 * |\ref RTC_MODULE |\ref CLK_CLKSEL3_RTCSEL_LXT | x |
497 * |\ref RTC_MODULE |\ref CLK_CLKSEL3_RTCSEL_LIRC | x |
498 * |\ref I2S0_MODULE |\ref CLK_CLKSEL3_I2S0SEL_HXT | x |
499 * |\ref I2S0_MODULE |\ref CLK_CLKSEL3_I2S0SEL_PLL | x |
500 * |\ref I2S0_MODULE |\ref CLK_CLKSEL3_I2S0SEL_PCLK0 | x |
501 * |\ref I2S0_MODULE |\ref CLK_CLKSEL3_I2S0SEL_HIRC | x |
502 * |\ref QSPI0_MODULE |\ref CLK_CLKSEL2_QSPI0SEL_HXT | x |
503 * |\ref QSPI0_MODULE |\ref CLK_CLKSEL2_QSPI0SEL_PLL | x |
504 * |\ref QSPI0_MODULE |\ref CLK_CLKSEL2_QSPI0SEL_PCLK0 | x |
505 * |\ref QSPI0_MODULE |\ref CLK_CLKSEL2_QSPI0SEL_HIRC | x |
506 * |\ref SPI0_MODULE |\ref CLK_CLKSEL2_SPI0SEL_HXT | x |
507 * |\ref SPI0_MODULE |\ref CLK_CLKSEL2_SPI0SEL_PLL | x |
508 * |\ref SPI0_MODULE |\ref CLK_CLKSEL2_SPI0SEL_PCLK1 | x |
509 * |\ref SPI0_MODULE |\ref CLK_CLKSEL2_SPI0SEL_HIRC | x |
510 * |\ref SPI1_MODULE |\ref CLK_CLKSEL2_SPI1SEL_HXT | x |
511 * |\ref SPI1_MODULE |\ref CLK_CLKSEL2_SPI1SEL_PLL | x |
512 * |\ref SPI1_MODULE |\ref CLK_CLKSEL2_SPI1SEL_PCLK0 | x |
513 * |\ref SPI1_MODULE |\ref CLK_CLKSEL2_SPI1SEL_HIRC | x |
514 * |\ref SPI2_MODULE |\ref CLK_CLKSEL2_SPI2SEL_HXT | x |
515 * |\ref SPI2_MODULE |\ref CLK_CLKSEL2_SPI2SEL_PLL | x |
516 * |\ref SPI2_MODULE |\ref CLK_CLKSEL2_SPI2SEL_PCLK1 | x |
517 * |\ref SPI2_MODULE |\ref CLK_CLKSEL2_SPI2SEL_HIRC | x |
518 * |\ref SPI3_MODULE |\ref CLK_CLKSEL2_SPI3SEL_HXT | x |
519 * |\ref SPI3_MODULE |\ref CLK_CLKSEL2_SPI3SEL_PLL | x |
520 * |\ref SPI3_MODULE |\ref CLK_CLKSEL2_SPI3SEL_PCLK0 | x |
521 * |\ref SPI3_MODULE |\ref CLK_CLKSEL2_SPI3SEL_HIRC | x |
522 * |\ref SC0_MODULE |\ref CLK_CLKSEL3_SC0SEL_HXT |\ref CLK_CLKDIV1_SC0(x) |
523 * |\ref SC0_MODULE |\ref CLK_CLKSEL3_SC0SEL_PLL |\ref CLK_CLKDIV1_SC0(x) |
524 * |\ref SC0_MODULE |\ref CLK_CLKSEL3_SC0SEL_PCLK0 |\ref CLK_CLKDIV1_SC0(x) |
525 * |\ref SC0_MODULE |\ref CLK_CLKSEL3_SC0SEL_HIRC |\ref CLK_CLKDIV1_SC0(x) |
526 * |\ref SC1_MODULE |\ref CLK_CLKSEL3_SC1SEL_HXT |\ref CLK_CLKDIV1_SC1(x) |
527 * |\ref SC1_MODULE |\ref CLK_CLKSEL3_SC1SEL_PLL |\ref CLK_CLKDIV1_SC1(x) |
528 * |\ref SC1_MODULE |\ref CLK_CLKSEL3_SC1SEL_PCLK1 |\ref CLK_CLKDIV1_SC1(x) |
529 * |\ref SC1_MODULE |\ref CLK_CLKSEL3_SC1SEL_HIRC |\ref CLK_CLKDIV1_SC1(x) |
530 * |\ref SC2_MODULE |\ref CLK_CLKSEL3_SC2SEL_HXT |\ref CLK_CLKDIV1_SC2(x) |
531 * |\ref SC2_MODULE |\ref CLK_CLKSEL3_SC2SEL_PLL |\ref CLK_CLKDIV1_SC2(x) |
532 * |\ref SC2_MODULE |\ref CLK_CLKSEL3_SC2SEL_PCLK0 |\ref CLK_CLKDIV1_SC2(x) |
533 * |\ref SC2_MODULE |\ref CLK_CLKSEL3_SC2SEL_HIRC |\ref CLK_CLKDIV1_SC2(x) |
534 * |\ref USBH_MODULE |\ref CLK_CLKSEL0_USBSEL_HIRC48 |\ref CLK_CLKDIV0_USB(x) |
535 * |\ref USBH_MODULE |\ref CLK_CLKSEL0_USBSEL_PLL |\ref CLK_CLKDIV0_USB(x) |
536 * |\ref OTG_MODULE |\ref CLK_CLKSEL0_USBSEL_HIRC48 |\ref CLK_CLKDIV0_USB(x) |
537 * |\ref OTG_MODULE |\ref CLK_CLKSEL0_USBSEL_PLL |\ref CLK_CLKDIV0_USB(x) |
538 * |\ref USBD_MODULE |\ref CLK_CLKSEL0_USBSEL_HIRC48 |\ref CLK_CLKDIV0_USB(x) |
539 * |\ref USBD_MODULE |\ref CLK_CLKSEL0_USBSEL_PLL |\ref CLK_CLKDIV0_USB(x) |
540 */
CLK_SetModuleClock(uint32_t u32ModuleIdx,uint32_t u32ClkSrc,uint32_t u32ClkDiv)541 void CLK_SetModuleClock(uint32_t u32ModuleIdx, uint32_t u32ClkSrc, uint32_t u32ClkDiv)
542 {
543 uint32_t u32Sel = 0UL, u32Div = 0UL;
544 uint32_t au32SelTbl[4] = {0x0UL, 0x4UL, 0x8UL, 0xCUL};
545 uint32_t au32DivTbl[4] = {0x0UL, 0x4UL, 0x8UL, 0x10UL};
546
547 if(MODULE_CLKDIV_Msk(u32ModuleIdx) != MODULE_NoMsk)
548 {
549 /* Get clock divider control register address */
550 u32Div = (uint32_t)&CLK->CLKDIV0 + (au32DivTbl[MODULE_CLKDIV(u32ModuleIdx)]);
551 /* Apply new divider */
552 M32(u32Div) = (M32(u32Div) & (~(MODULE_CLKDIV_Msk(u32ModuleIdx) << MODULE_CLKDIV_Pos(u32ModuleIdx)))) | u32ClkDiv;
553 }
554
555 if(MODULE_CLKSEL_Msk(u32ModuleIdx) != MODULE_NoMsk)
556 {
557 /* Get clock select control register address */
558 u32Sel = (uint32_t)&CLK->CLKSEL0 + (au32SelTbl[MODULE_CLKSEL(u32ModuleIdx)]);
559 /* Set new clock selection setting */
560 M32(u32Sel) = (M32(u32Sel) & (~(MODULE_CLKSEL_Msk(u32ModuleIdx) << MODULE_CLKSEL_Pos(u32ModuleIdx)))) | u32ClkSrc;
561 }
562 }
563
564 /**
565 * @brief Set SysTick clock source
566 * @param[in] u32ClkSrc is module clock source. Including:
567 * - \ref CLK_CLKSEL0_STCLKSEL_HXT
568 * - \ref CLK_CLKSEL0_STCLKSEL_LXT
569 * - \ref CLK_CLKSEL0_STCLKSEL_HXT_DIV2
570 * - \ref CLK_CLKSEL0_STCLKSEL_HCLK_DIV2
571 * - \ref CLK_CLKSEL0_STCLKSEL_HIRC_DIV2
572 * @return None
573 * @details This function set SysTick clock source. \n
574 * The register write-protection function should be disabled before using this function.
575 */
CLK_SetSysTickClockSrc(uint32_t u32ClkSrc)576 void CLK_SetSysTickClockSrc(uint32_t u32ClkSrc)
577 {
578 CLK->CLKSEL0 = (CLK->CLKSEL0 & ~CLK_CLKSEL0_STCLKSEL_Msk) | u32ClkSrc;
579 }
580
581 /**
582 * @brief Enable clock source
583 * @param[in] u32ClkMask is clock source mask. Including :
584 * - \ref CLK_PWRCTL_HXTEN_Msk
585 * - \ref CLK_PWRCTL_LXTEN_Msk
586 * - \ref CLK_PWRCTL_HIRCEN_Msk
587 * - \ref CLK_PWRCTL_LIRCEN_Msk
588 * - \ref CLK_PWRCTL_HIRC48EN_Msk
589 * @return None
590 * @details This function enable clock source. \n
591 * The register write-protection function should be disabled before using this function.
592 */
CLK_EnableXtalRC(uint32_t u32ClkMask)593 void CLK_EnableXtalRC(uint32_t u32ClkMask)
594 {
595 CLK->PWRCTL |= u32ClkMask;
596 }
597
598 /**
599 * @brief Disable clock source
600 * @param[in] u32ClkMask is clock source mask. Including :
601 * - \ref CLK_PWRCTL_HXTEN_Msk
602 * - \ref CLK_PWRCTL_LXTEN_Msk
603 * - \ref CLK_PWRCTL_HIRCEN_Msk
604 * - \ref CLK_PWRCTL_LIRCEN_Msk
605 * - \ref CLK_PWRCTL_HIRC48EN_Msk
606 * @return None
607 * @details This function disable clock source. \n
608 * The register write-protection function should be disabled before using this function.
609 */
CLK_DisableXtalRC(uint32_t u32ClkMask)610 void CLK_DisableXtalRC(uint32_t u32ClkMask)
611 {
612 CLK->PWRCTL &= ~u32ClkMask;
613 }
614
615 /**
616 * @brief This function enable module clock
617 * @param[in] u32ModuleIdx is module index. Including :
618 * - \ref PDMA0_MODULE
619 * - \ref PDMA1_MODULE
620 * - \ref ISP_MODULE
621 * - \ref EBI_MODULE
622 * - \ref SDH0_MODULE
623 * - \ref CRC_MODULE
624 * - \ref CRPT_MODULE
625 * - \ref FMCIDLE_MODULE
626 * - \ref USBH_MODULE
627 * - \ref WDT_MODULE
628 * - \ref WWDT_MODULE
629 * - \ref RTC_MODULE
630 * - \ref TMR0_MODULE
631 * - \ref TMR1_MODULE
632 * - \ref TMR2_MODULE
633 * - \ref TMR3_MODULE
634 * - \ref CLKO_MODULE
635 * - \ref ACMP01_MODULE
636 * - \ref I2C0_MODULE
637 * - \ref I2C1_MODULE
638 * - \ref I2C2_MODULE
639 * - \ref QSPI0_MODULE
640 * - \ref SPI0_MODULE
641 * - \ref SPI1_MODULE
642 * - \ref SPI2_MODULE
643 * - \ref SPI3_MODULE
644 * - \ref UART0_MODULE
645 * - \ref UART1_MODULE
646 * - \ref UART2_MODULE
647 * - \ref UART3_MODULE
648 * - \ref UART4_MODULE
649 * - \ref UART5_MODULE
650 * - \ref CAN0_MODULE
651 * - \ref OTG_MODULE
652 * - \ref USBD_MODULE
653 * - \ref EADC_MODULE
654 * - \ref I2S0_MODULE
655 * - \ref SC0_MODULE
656 * - \ref SC1_MODULE
657 * - \ref SC2_MODULE
658 * - \ref USCI0_MODULE
659 * - \ref USCI1_MODULE
660 * - \ref DAC_MODULE
661 * - \ref EPWM0_MODULE
662 * - \ref EPWM1_MODULE
663 * - \ref BPWM0_MODULE
664 * - \ref BPWM1_MODULE
665 * - \ref QEI0_MODULE
666 * - \ref QEI1_MODULE
667 * - \ref QEI0_MODULE
668 * - \ref TRNG_MODULE
669 * - \ref ECAP0_MODULE
670 * - \ref ECAP1_MODULE
671 * @return None
672 * @details This function enable module clock.
673 */
CLK_EnableModuleClock(uint32_t u32ModuleIdx)674 void CLK_EnableModuleClock(uint32_t u32ModuleIdx)
675 {
676 uint32_t u32TmpVal = 0UL, u32TmpAddr = 0UL;
677
678 u32TmpVal = (1UL << MODULE_IP_EN_Pos(u32ModuleIdx));
679 u32TmpAddr = (uint32_t)&CLK->AHBCLK;
680 u32TmpAddr += ((MODULE_APBCLK(u32ModuleIdx) * 4UL));
681
682 *(volatile uint32_t *)u32TmpAddr |= u32TmpVal;
683 }
684
685 /**
686 * @brief This function disable module clock
687 * @param[in] u32ModuleIdx is module index
688 * - \ref PDMA0_MODULE
689 * - \ref PDMA1_MODULE
690 * - \ref ISP_MODULE
691 * - \ref EBI_MODULE
692 * - \ref SDH0_MODULE
693 * - \ref CRC_MODULE
694 * - \ref CRPT_MODULE
695 * - \ref FMCIDLE_MODULE
696 * - \ref USBH_MODULE
697 * - \ref WDT_MODULE
698 * - \ref WWDT_MODULE
699 * - \ref RTC_MODULE
700 * - \ref TMR0_MODULE
701 * - \ref TMR1_MODULE
702 * - \ref TMR2_MODULE
703 * - \ref TMR3_MODULE
704 * - \ref CLKO_MODULE
705 * - \ref ACMP01_MODULE
706 * - \ref I2C0_MODULE
707 * - \ref I2C1_MODULE
708 * - \ref I2C2_MODULE
709 * - \ref QSPI0_MODULE
710 * - \ref SPI0_MODULE
711 * - \ref SPI1_MODULE
712 * - \ref SPI2_MODULE
713 * - \ref SPI3_MODULE
714 * - \ref UART0_MODULE
715 * - \ref UART1_MODULE
716 * - \ref UART2_MODULE
717 * - \ref UART3_MODULE
718 * - \ref UART4_MODULE
719 * - \ref UART5_MODULE
720 * - \ref CAN0_MODULE
721 * - \ref OTG_MODULE
722 * - \ref USBD_MODULE
723 * - \ref EADC_MODULE
724 * - \ref I2S0_MODULE
725 * - \ref SC0_MODULE
726 * - \ref SC1_MODULE
727 * - \ref SC2_MODULE
728 * - \ref USCI0_MODULE
729 * - \ref USCI1_MODULE
730 * - \ref DAC_MODULE
731 * - \ref EPWM0_MODULE
732 * - \ref EPWM1_MODULE
733 * - \ref BPWM0_MODULE
734 * - \ref BPWM1_MODULE
735 * - \ref QEI0_MODULE
736 * - \ref QEI1_MODULE
737 * - \ref QEI0_MODULE
738 * - \ref TRNG_MODULE
739 * - \ref ECAP0_MODULE
740 * - \ref ECAP1_MODULE
741 * @return None
742 * @details This function disable module clock.
743 */
CLK_DisableModuleClock(uint32_t u32ModuleIdx)744 void CLK_DisableModuleClock(uint32_t u32ModuleIdx)
745 {
746 uint32_t u32TmpVal = 0UL, u32TmpAddr = 0UL;
747
748 u32TmpVal = ~(1UL << MODULE_IP_EN_Pos(u32ModuleIdx));
749 u32TmpAddr = (uint32_t)&CLK->AHBCLK;
750 u32TmpAddr += ((MODULE_APBCLK(u32ModuleIdx) * 4UL));
751
752 *(uint32_t *)u32TmpAddr &= u32TmpVal;
753 }
754
755
756 /**
757 * @brief Set PLL frequency
758 * @param[in] u32PllClkSrc is PLL clock source. Including :
759 * - \ref CLK_PLLCTL_PLLSRC_HXT
760 * - \ref CLK_PLLCTL_PLLSRC_HIRC
761 * @param[in] u32PllFreq is PLL frequency. The range of u32PllFreq is 24 MHz ~ 144 MHz.
762 * @return PLL frequency
763 * @details This function is used to configure PLLCTL register to set specified PLL frequency. \n
764 * The register write-protection function should be disabled before using this function.
765 */
CLK_EnablePLL(uint32_t u32PllClkSrc,uint32_t u32PllFreq)766 uint32_t CLK_EnablePLL(uint32_t u32PllClkSrc, uint32_t u32PllFreq)
767 {
768 uint32_t u32PllSrcClk, u32NR, u32NF, u32NO, u32PllClk;
769 uint32_t u32Tmp, u32Tmp2, u32Tmp3, u32Min, u32MinNF, u32MinNR;
770
771 /* Disable PLL first to avoid unstable when setting PLL */
772 CLK_DisablePLL();
773
774 /* PLL source clock is from HXT */
775 if(u32PllClkSrc == CLK_PLLCTL_PLLSRC_HXT)
776 {
777
778 /* Enable HXT clock */
779 CLK->PWRCTL |= CLK_PWRCTL_HXTEN_Msk;
780
781 /* Wait for HXT clock ready */
782 CLK_WaitClockReady(CLK_STATUS_HXTSTB_Msk);
783
784 /* Select PLL source clock from HXT */
785 u32PllSrcClk = __HXT;
786 }
787
788 /* PLL source clock is from HIRC */
789 else
790 {
791
792 /* Enable HIRC clock */
793 CLK->PWRCTL |= CLK_PWRCTL_HIRCEN_Msk;
794
795 /* Wait for HIRC clock ready */
796 CLK_WaitClockReady(CLK_STATUS_HIRCSTB_Msk);
797
798 /* Select PLL source clock from HIRC */
799 u32PllSrcClk = __HIRC;
800 }
801
802 /* Check PLL frequency range */
803 if((u32PllFreq <= FREQ_144MHZ) && (u32PllFreq >= FREQ_24MHZ))
804 {
805
806 /* Select "NO" according to request frequency */
807 if((u32PllFreq < FREQ_48MHZ) && (u32PllFreq >= FREQ_24MHZ))
808 {
809 u32NO = 3UL;
810 u32PllFreq = u32PllFreq << 2;
811 }
812 else if((u32PllFreq < FREQ_96MHZ) && (u32PllFreq >= FREQ_48MHZ))
813 {
814 u32NO = 1UL;
815 u32PllFreq = u32PllFreq << 1;
816 }
817 else
818 {
819 u32NO = 0UL;
820 }
821
822 /* u32NR start from 3 to avoid calculation overflow */
823 u32NR = 3UL;
824
825 /* Find best solution */
826 u32Min = (uint32_t) - 1;
827 u32MinNR = 0UL;
828 u32MinNF = 0UL;
829
830 for(; u32NR <= 32UL; u32NR++)
831 {
832 u32Tmp = u32PllSrcClk / u32NR;
833 if((u32Tmp >= FREQ_2MHZ) && (u32Tmp <= FREQ_8MHZ))
834 {
835 for(u32NF = 2UL; u32NF <= 513UL; u32NF++)
836 {
837 u32Tmp2 = (u32Tmp * u32NF) << 1;
838 if((u32Tmp2 >= FREQ_96MHZ) && (u32Tmp2 <= FREQ_200MHZ))
839 {
840 u32Tmp3 = (u32Tmp2 > u32PllFreq) ? u32Tmp2 - u32PllFreq : u32PllFreq - u32Tmp2;
841 if(u32Tmp3 < u32Min)
842 {
843 u32Min = u32Tmp3;
844 u32MinNR = u32NR;
845 u32MinNF = u32NF;
846
847 /* Break when get good results */
848 if(u32Min == 0UL)
849 {
850 break;
851 }
852 }
853 }
854 }
855 }
856 }
857
858 /* Enable and apply new PLL setting. */
859 CLK->PLLCTL = u32PllClkSrc | (u32NO << 14) | ((u32MinNR - 1UL) << 9) | (u32MinNF - 2UL);
860
861 /* Actual PLL output clock frequency */
862 u32PllClk = u32PllSrcClk / ((u32NO + 1UL) * u32MinNR) * (u32MinNF << 1);
863
864 }
865 else
866 {
867
868 /* Wrong frequency request. Just return default setting. */
869 if((SYS->PLSTS & SYS_PLSTS_PLSTATUS_Msk) == SYS_PLCTL_PLSEL_PL0)
870 {
871
872 /* Apply default PLL setting and return */
873 CLK->PLLCTL = u32PllClkSrc | CLK_PLLCTL_64MHz_HXT;
874
875 /* Actual PLL output clock frequency */
876 u32PllClk = FREQ_64MHZ;
877
878 }
879 else
880 {
881
882 /* Apply default PLL setting and return */
883 CLK->PLLCTL = u32PllClkSrc | CLK_PLLCTL_48MHz_HXT;
884
885 /* Actual PLL output clock frequency */
886 u32PllClk = FREQ_48MHZ;
887 }
888
889 }
890
891 /* Wait for PLL clock stable */
892 CLK_WaitClockReady(CLK_STATUS_PLLSTB_Msk);
893
894 /* Return actual PLL output clock frequency */
895 return u32PllClk;
896 }
897
898 /**
899 * @brief Disable PLL
900 * @param None
901 * @return None
902 * @details This function set PLL in Power-down mode. \n
903 * The register write-protection function should be disabled before using this function.
904 */
CLK_DisablePLL(void)905 void CLK_DisablePLL(void)
906 {
907 CLK->PLLCTL |= CLK_PLLCTL_PD_Msk;
908 }
909
910 /**
911 * @brief This function check selected clock source status
912 * @param[in] u32ClkMask is selected clock source. Including :
913 * - \ref CLK_STATUS_HXTSTB_Msk
914 * - \ref CLK_STATUS_LXTSTB_Msk
915 * - \ref CLK_STATUS_HIRCSTB_Msk
916 * - \ref CLK_STATUS_LIRCSTB_Msk
917 * - \ref CLK_STATUS_PLLSTB_Msk
918 * - \ref CLK_STATUS_HIRC48STB_Msk
919 * - \ref CLK_STATUS_EXTLXTSTB_Msk
920 * - \ref CLK_STATUS_LIRC32STB_Msk
921 * @retval 0 clock is not stable
922 * @retval 1 clock is stable
923 * @details To wait for clock ready by specified clock source stable flag or timeout (~300ms)
924 */
CLK_WaitClockReady(uint32_t u32ClkMask)925 uint32_t CLK_WaitClockReady(uint32_t u32ClkMask)
926 {
927 int32_t i32TimeOutCnt = 2400000;
928 uint32_t u32Ret = 1U;
929
930 while((CLK->STATUS & u32ClkMask) != u32ClkMask)
931 {
932 if(i32TimeOutCnt-- <= 0)
933 {
934 u32Ret = 0U;
935 break;
936 }
937 }
938 return u32Ret;
939 }
940
941 /**
942 * @brief Enable System Tick counter
943 * @param[in] u32ClkSrc is System Tick clock source. Including:
944 * - \ref CLK_CLKSEL0_STCLKSEL_HXT
945 * - \ref CLK_CLKSEL0_STCLKSEL_LXT
946 * - \ref CLK_CLKSEL0_STCLKSEL_HXT_DIV2
947 * - \ref CLK_CLKSEL0_STCLKSEL_HCLK_DIV2
948 * - \ref CLK_CLKSEL0_STCLKSEL_HIRC_DIV2
949 * - \ref CLK_CLKSEL0_STCLKSEL_HCLK
950 * @param[in] u32Count is System Tick reload value. It could be 0~0xFFFFFF.
951 * @return None
952 * @details This function set System Tick clock source, reload value, enable System Tick counter and interrupt. \n
953 * The register write-protection function should be disabled before using this function.
954 */
CLK_EnableSysTick(uint32_t u32ClkSrc,uint32_t u32Count)955 void CLK_EnableSysTick(uint32_t u32ClkSrc, uint32_t u32Count)
956 {
957 /* Set System Tick counter disabled */
958 SysTick->CTRL = 0UL;
959
960 /* Set System Tick clock source */
961 if(u32ClkSrc == CLK_CLKSEL0_STCLKSEL_HCLK)
962 {
963 SysTick->CTRL |= SysTick_CTRL_CLKSOURCE_Msk;
964 }
965 else
966 {
967 CLK->CLKSEL0 = (CLK->CLKSEL0 & ~CLK_CLKSEL0_STCLKSEL_Msk) | u32ClkSrc;
968 }
969
970 /* Set System Tick reload value */
971 SysTick->LOAD = u32Count;
972
973 /* Clear System Tick current value and counter flag */
974 SysTick->VAL = 0UL;
975
976 /* Set System Tick interrupt enabled and counter enabled */
977 SysTick->CTRL |= SysTick_CTRL_TICKINT_Msk | SysTick_CTRL_ENABLE_Msk;
978 }
979
980 /**
981 * @brief Disable System Tick counter
982 * @param None
983 * @return None
984 * @details This function disable System Tick counter.
985 */
CLK_DisableSysTick(void)986 void CLK_DisableSysTick(void)
987 {
988 /* Set System Tick counter disabled */
989 SysTick->CTRL = 0UL;
990 }
991
992 /**
993 * @brief Power-down mode selected
994 * @param[in] u32PDMode is power down mode index. Including :
995 * - \ref CLK_PMUCTL_PDMSEL_PD
996 * - \ref CLK_PMUCTL_PDMSEL_LLPD
997 * - \ref CLK_PMUCTL_PDMSEL_FWPD
998 * - \ref CLK_PMUCTL_PDMSEL_ULLPD
999 * - \ref CLK_PMUCTL_PDMSEL_SPD
1000 * - \ref CLK_PMUCTL_PDMSEL_DPD
1001 * @return None
1002 * @details This function is used to set power-down mode.
1003 */
CLK_SetPowerDownMode(uint32_t u32PDMode)1004 void CLK_SetPowerDownMode(uint32_t u32PDMode)
1005 {
1006 CLK->PMUCTL = (CLK->PMUCTL & (~CLK_PMUCTL_PDMSEL_Msk)) | (u32PDMode);
1007 }
1008
1009 /**
1010 * @brief Set Wake-up pin trigger type at Deep Power down mode
1011 * @param[in] u32TriggerType Wake-up pin trigger type
1012 * - \ref CLK_DPDWKPIN_RISING
1013 * - \ref CLK_DPDWKPIN_FALLING
1014 * - \ref CLK_DPDWKPIN_BOTHEDGE
1015 * @return None
1016 * @details This function is used to enable Wake-up pin trigger type.
1017 */
1018
CLK_EnableDPDWKPin(uint32_t u32TriggerType)1019 void CLK_EnableDPDWKPin(uint32_t u32TriggerType)
1020 {
1021 CLK->PMUCTL = (CLK->PMUCTL & (~CLK_PMUCTL_WKPINEN_Msk)) | (u32TriggerType);
1022 }
1023
1024 /**
1025 * @brief Get power manager wake up source
1026 * @param[in] None
1027 * @return None
1028 * @details This function get power manager wake up source.
1029 */
1030
CLK_GetPMUWKSrc(void)1031 uint32_t CLK_GetPMUWKSrc(void)
1032 {
1033 return (CLK->PMUSTS);
1034 }
1035
1036 /**
1037 * @brief Set specified GPIO as wake up source at Standby Power-down mode
1038 * @param[in] u32Port GPIO port. It could be 0~3.
1039 * @param[in] u32Pin The pin of specified GPIO port. It could be 0 ~ 15.
1040 * @param[in] u32TriggerType Wake-up pin trigger type
1041 * - \ref CLK_SPDWKPIN_RISING
1042 * - \ref CLK_SPDWKPIN_FALLING
1043 * @param[in] u32DebounceEn Standby Power-down mode wake-up pin de-bounce function
1044 * - \ref CLK_SPDWKPIN_DEBOUNCEEN
1045 * - \ref CLK_SPDWKPIN_DEBOUNCEDIS
1046 * @return None
1047 * @details This function is used to set specified GPIO as wake up source at Standby Power-down mode.
1048 */
1049
CLK_EnableSPDWKPin(uint32_t u32Port,uint32_t u32Pin,uint32_t u32TriggerType,uint32_t u32DebounceEn)1050 void CLK_EnableSPDWKPin(uint32_t u32Port, uint32_t u32Pin, uint32_t u32TriggerType, uint32_t u32DebounceEn)
1051 {
1052 uint32_t u32TmpAddr = 0UL;
1053 uint32_t u32TmpVal = 0UL;
1054
1055 /* GPx Stand-by Power-down Wake-up Pin Select */
1056 u32TmpAddr = (uint32_t)&CLK->PASWKCTL;
1057 u32TmpAddr += (0x4UL * u32Port);
1058
1059 u32TmpVal = inpw((uint32_t *)u32TmpAddr);
1060 u32TmpVal = (u32TmpVal & ~(CLK_PASWKCTL_WKPSEL_Msk | CLK_PASWKCTL_PRWKEN_Msk | CLK_PASWKCTL_PFWKEN_Msk | CLK_PASWKCTL_DBEN_Msk | CLK_PASWKCTL_WKEN_Msk)) |
1061 (u32Pin << CLK_PASWKCTL_WKPSEL_Pos) | u32TriggerType | u32DebounceEn | CLK_SPDWKPIN_ENABLE;
1062 outpw((uint32_t *)u32TmpAddr, u32TmpVal);
1063 }
1064
1065 /**
1066 * @brief Get PLL clock frequency
1067 * @param None
1068 * @return PLL frequency
1069 * @details This function get PLL frequency. The frequency unit is Hz.
1070 */
1071
1072 __NONSECURE_ENTRY_WEAK
CLK_GetPLLClockFreq(void)1073 uint32_t CLK_GetPLLClockFreq(void)
1074 {
1075 uint32_t u32PllFreq = 0UL, u32PllReg;
1076 uint32_t u32FIN, u32NF, u32NR, u32NO;
1077 uint8_t au8NoTbl[4] = {1U, 2U, 2U, 4U};
1078
1079 u32PllReg = CLK->PLLCTL;
1080
1081 if(u32PllReg & (CLK_PLLCTL_PD_Msk | CLK_PLLCTL_OE_Msk))
1082 {
1083 u32PllFreq = 0UL; /* PLL is in power down mode or fix low */
1084 }
1085 else /* PLL is in normal mode */
1086 {
1087
1088 /* PLL source clock */
1089 if(u32PllReg & CLK_PLLCTL_PLLSRC_Msk)
1090 {
1091 u32FIN = __HIRC; /* PLL source clock from HIRC */
1092 }
1093 else
1094 {
1095 u32FIN = __HXT; /* PLL source clock from HXT */
1096 }
1097
1098 /* Calculate PLL frequency */
1099 if(u32PllReg & CLK_PLLCTL_BP_Msk)
1100 {
1101 u32PllFreq = u32FIN; /* PLL is in bypass mode */
1102 }
1103 else
1104 {
1105 /* PLL is output enabled in normal work mode */
1106 u32NO = au8NoTbl[((u32PllReg & CLK_PLLCTL_OUTDIV_Msk) >> CLK_PLLCTL_OUTDIV_Pos)];
1107 u32NF = ((u32PllReg & CLK_PLLCTL_FBDIV_Msk) >> CLK_PLLCTL_FBDIV_Pos) + 2UL;
1108 u32NR = ((u32PllReg & CLK_PLLCTL_INDIV_Msk) >> CLK_PLLCTL_INDIV_Pos) + 1UL;
1109
1110 /* u32FIN is shifted 2 bits to avoid overflow */
1111 u32PllFreq = (((u32FIN >> 2) * (u32NF << 1)) / (u32NR * u32NO) << 2);
1112 }
1113 }
1114
1115 return u32PllFreq;
1116 }
1117
1118 /**
1119 * @brief Get selected module clock source
1120 * @param[in] u32ModuleIdx is module index.
1121 * - \ref SDH0_MODULE
1122 * - \ref USBH_MODULE
1123 * - \ref WDT_MODULE
1124 * - \ref WWDT_MODULE
1125 * - \ref RTC_MODULE
1126 * - \ref TMR0_MODULE
1127 * - \ref TMR1_MODULE
1128 * - \ref TMR2_MODULE
1129 * - \ref TMR3_MODULE
1130 * - \ref CLKO_MODULE
1131 * - \ref QSPI0_MODULE
1132 * - \ref SPI0_MODULE
1133 * - \ref SPI1_MODULE
1134 * - \ref SPI2_MODULE
1135 * - \ref SPI3_MODULE
1136 * - \ref UART0_MODULE
1137 * - \ref UART1_MODULE
1138 * - \ref UART2_MODULE
1139 * - \ref UART3_MODULE
1140 * - \ref UART4_MODULE
1141 * - \ref UART5_MODULE
1142 * - \ref OTG_MODULE
1143 * - \ref USBD_MODULE
1144 * - \ref I2S0_MODULE
1145 * - \ref SC0_MODULE
1146 * - \ref SC1_MODULE
1147 * - \ref SC2_MODULE
1148 * - \ref EPWM0_MODULE
1149 * - \ref EPWM1_MODULE
1150 * - \ref BPWM0_MODULE
1151 * - \ref BPWM1_MODULE
1152 * @return Selected module clock source setting
1153 * @details This function get selected module clock source.
1154 */
1155
1156 __NONSECURE_ENTRY_WEAK
CLK_GetModuleClockSource(uint32_t u32ModuleIdx)1157 uint32_t CLK_GetModuleClockSource(uint32_t u32ModuleIdx)
1158 {
1159 uint32_t u32TmpVal = 0UL, u32TmpAddr = 0UL;
1160 uint32_t au32SelTbl[4] = {0x0UL, 0x4UL, 0x8UL, 0xCUL};
1161
1162 /* Get clock source selection setting */
1163 if(u32ModuleIdx == EPWM0_MODULE)
1164 {
1165 u32TmpVal = ((CLK->CLKSEL2 & CLK_CLKSEL2_EPWM0SEL_Msk) >> CLK_CLKSEL2_EPWM0SEL_Pos);
1166 }
1167 else if(u32ModuleIdx == EPWM1_MODULE)
1168 {
1169 u32TmpVal = ((CLK->CLKSEL2 & CLK_CLKSEL2_EPWM1SEL_Msk) >> CLK_CLKSEL2_EPWM1SEL_Pos);
1170 }
1171 else if(u32ModuleIdx == BPWM0_MODULE)
1172 {
1173 u32TmpVal = ((CLK->CLKSEL2 & CLK_CLKSEL2_BPWM0SEL_Msk) >> CLK_CLKSEL2_BPWM0SEL_Pos);
1174 }
1175 else if(u32ModuleIdx == BPWM1_MODULE)
1176 {
1177 u32TmpVal = ((CLK->CLKSEL2 & CLK_CLKSEL2_BPWM1SEL_Msk) >> CLK_CLKSEL2_BPWM1SEL_Pos);
1178 }
1179 else if(MODULE_CLKSEL_Msk(u32ModuleIdx) != MODULE_NoMsk)
1180 {
1181 /* Get clock select control register address */
1182 u32TmpAddr = (uint32_t)&CLK->CLKSEL0 + (au32SelTbl[MODULE_CLKSEL(u32ModuleIdx)]);
1183
1184 /* Get clock source selection setting */
1185 u32TmpVal = ((inpw((uint32_t *)u32TmpAddr) & (MODULE_CLKSEL_Msk(u32ModuleIdx) << MODULE_CLKSEL_Pos(u32ModuleIdx))) >> MODULE_CLKSEL_Pos(u32ModuleIdx));
1186 }
1187
1188 return u32TmpVal;
1189 }
1190
1191 /**
1192 * @brief Get selected module clock divider number
1193 * @param[in] u32ModuleIdx is module index.
1194 * - \ref SDH0_MODULE
1195 * - \ref USBH_MODULE
1196 * - \ref UART0_MODULE
1197 * - \ref UART1_MODULE
1198 * - \ref UART2_MODULE
1199 * - \ref UART3_MODULE
1200 * - \ref UART4_MODULE
1201 * - \ref UART5_MODULE
1202 * - \ref OTG_MODULE
1203 * - \ref USBD_MODULE
1204 * - \ref SC0_MODULE
1205 * - \ref SC1_MODULE
1206 * - \ref SC2_MODULE
1207 * - \ref EADC_MODULE
1208 * @return Selected module clock divider number setting
1209 * @details This function get selected module clock divider number.
1210 */
1211
1212 __NONSECURE_ENTRY_WEAK
CLK_GetModuleClockDivider(uint32_t u32ModuleIdx)1213 uint32_t CLK_GetModuleClockDivider(uint32_t u32ModuleIdx)
1214 {
1215 uint32_t u32TmpVal = 0UL, u32TmpAddr = 0UL;
1216 uint32_t au32DivTbl[4] = {0x0UL, 0x4UL, 0x8UL, 0x10UL};
1217
1218 if(MODULE_CLKDIV_Msk(u32ModuleIdx) != MODULE_NoMsk)
1219 {
1220 /* Get clock divider control register address */
1221 u32TmpAddr = (uint32_t)&CLK->CLKDIV0 + (au32DivTbl[MODULE_CLKDIV(u32ModuleIdx)]);
1222 /* Get clock divider number setting */
1223 u32TmpVal = ((inpw((uint32_t *)u32TmpAddr) & (MODULE_CLKDIV_Msk(u32ModuleIdx) << MODULE_CLKDIV_Pos(u32ModuleIdx))) >> MODULE_CLKDIV_Pos(u32ModuleIdx));
1224 }
1225
1226 return u32TmpVal;
1227 }
1228
1229
1230 /*@}*/ /* end of group CLK_EXPORTED_FUNCTIONS */
1231
1232 /*@}*/ /* end of group CLK_Driver */
1233
1234 /*@}*/ /* end of group Standard_Driver */
1235
1236