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