clk.c 28 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751
  1. /**************************************************************************//**
  2. * @file clk.c
  3. * @version V3.00
  4. * $Revision: 35 $
  5. * $Date: 15/08/11 10:26a $
  6. * @brief M451 series CLK driver source file
  7. *
  8. * @note
  9. * Copyright (C) 2014~2015 Nuvoton Technology Corp. All rights reserved.
  10. *****************************************************************************/
  11. #include "M451Series.h"
  12. /** @addtogroup Standard_Driver Standard Driver
  13. @{
  14. */
  15. /** @addtogroup CLK_Driver CLK Driver
  16. @{
  17. */
  18. /** @addtogroup CLK_EXPORTED_FUNCTIONS CLK Exported Functions
  19. @{
  20. */
  21. /**
  22. * @brief Disable clock divider output function
  23. * @param None
  24. * @return None
  25. * @details This function disable clock divider output function.
  26. */
  27. void CLK_DisableCKO(void)
  28. {
  29. /* Disable CKO clock source */
  30. CLK_DisableModuleClock(CLKO_MODULE);
  31. }
  32. /**
  33. * @brief This function enable clock divider output module clock,
  34. * enable clock divider output function and set frequency selection.
  35. * @param[in] u32ClkSrc is frequency divider function clock source. Including :
  36. * - \ref CLK_CLKSEL1_CLKOSEL_HXT
  37. * - \ref CLK_CLKSEL1_CLKOSEL_LXT
  38. * - \ref CLK_CLKSEL1_CLKOSEL_HCLK
  39. * - \ref CLK_CLKSEL1_CLKOSEL_HIRC
  40. * @param[in] u32ClkDiv is divider output frequency selection. It could be 0~15.
  41. * @param[in] u32ClkDivBy1En is clock divided by one enabled.
  42. * @return None
  43. * @details Output selected clock to CKO. The output clock frequency is divided by u32ClkDiv. \n
  44. * The formula is: \n
  45. * CKO frequency = (Clock source frequency) / 2^(u32ClkDiv + 1) \n
  46. * This function is just used to set CKO clock.
  47. * User must enable I/O for CKO clock output pin by themselves. \n
  48. */
  49. void CLK_EnableCKO(uint32_t u32ClkSrc, uint32_t u32ClkDiv, uint32_t u32ClkDivBy1En)
  50. {
  51. /* CKO = clock source / 2^(u32ClkDiv + 1) */
  52. CLK->CLKOCTL = CLK_CLKOCTL_CLKOEN_Msk | u32ClkDiv | (u32ClkDivBy1En << CLK_CLKOCTL_DIV1EN_Pos);
  53. /* Enable CKO clock source */
  54. CLK_EnableModuleClock(CLKO_MODULE);
  55. /* Select CKO clock source */
  56. CLK_SetModuleClock(CLKO_MODULE, u32ClkSrc, 0);
  57. }
  58. /**
  59. * @brief Enter to Power-down mode
  60. * @param None
  61. * @return None
  62. * @details This function is used to let system enter to Power-down mode. \n
  63. * The register write-protection function should be disabled before using this function.
  64. */
  65. void CLK_PowerDown(void)
  66. {
  67. /* Set the processor uses deep sleep as its low power mode */
  68. SCB->SCR |= SCB_SCR_SLEEPDEEP_Msk;
  69. /* Set system Power-down enabled and Power-down entry condition */
  70. CLK->PWRCTL |= (CLK_PWRCTL_PDEN_Msk | CLK_PWRCTL_PDWTCPU_Msk);
  71. /* Chip enter Power-down mode after CPU run WFI instruction */
  72. __WFI();
  73. }
  74. /**
  75. * @brief Enter to Idle mode
  76. * @param None
  77. * @return None
  78. * @details This function let system enter to Idle mode. \n
  79. * The register write-protection function should be disabled before using this function.
  80. */
  81. void CLK_Idle(void)
  82. {
  83. /* Set the processor uses sleep as its low power mode */
  84. SCB->SCR &= ~SCB_SCR_SLEEPDEEP_Msk;
  85. /* Set chip in idle mode because of WFI command */
  86. CLK->PWRCTL &= ~CLK_PWRCTL_PDEN_Msk;
  87. /* Chip enter idle mode after CPU run WFI instruction */
  88. __WFI();
  89. }
  90. /**
  91. * @brief Get external high speed crystal clock frequency
  92. * @param None
  93. * @return External high frequency crystal frequency
  94. * @details This function get external high frequency crystal frequency. The frequency unit is Hz.
  95. */
  96. uint32_t CLK_GetHXTFreq(void)
  97. {
  98. if(CLK->PWRCTL & CLK_PWRCTL_HXTEN_Msk)
  99. return __HXT;
  100. else
  101. return 0;
  102. }
  103. /**
  104. * @brief Get external low speed crystal clock frequency
  105. * @param None
  106. * @return External low speed crystal clock frequency
  107. * @details This function get external low frequency crystal frequency. The frequency unit is Hz.
  108. */
  109. uint32_t CLK_GetLXTFreq(void)
  110. {
  111. if(CLK->PWRCTL & CLK_PWRCTL_LXTEN_Msk)
  112. return __LXT;
  113. else
  114. return 0;
  115. }
  116. /**
  117. * @brief Get PCLK0 frequency
  118. * @param None
  119. * @return PCLK0 frequency
  120. * @details This function get PCLK0 frequency. The frequency unit is Hz.
  121. */
  122. uint32_t CLK_GetPCLK0Freq(void)
  123. {
  124. SystemCoreClockUpdate();
  125. if(CLK->CLKSEL0 & CLK_CLKSEL0_PCLK0SEL_Msk)
  126. return SystemCoreClock / 2;
  127. else
  128. return SystemCoreClock;
  129. }
  130. /**
  131. * @brief Get PCLK1 frequency
  132. * @param None
  133. * @return PCLK1 frequency
  134. * @details This function get PCLK1 frequency. The frequency unit is Hz.
  135. */
  136. uint32_t CLK_GetPCLK1Freq(void)
  137. {
  138. SystemCoreClockUpdate();
  139. if(CLK->CLKSEL0 & CLK_CLKSEL0_PCLK1SEL_Msk)
  140. return SystemCoreClock / 2;
  141. else
  142. return SystemCoreClock;
  143. }
  144. /**
  145. * @brief Get HCLK frequency
  146. * @param None
  147. * @return HCLK frequency
  148. * @details This function get HCLK frequency. The frequency unit is Hz.
  149. */
  150. uint32_t CLK_GetHCLKFreq(void)
  151. {
  152. SystemCoreClockUpdate();
  153. return SystemCoreClock;
  154. }
  155. /**
  156. * @brief Get CPU frequency
  157. * @param None
  158. * @return CPU frequency
  159. * @details This function get CPU frequency. The frequency unit is Hz.
  160. */
  161. uint32_t CLK_GetCPUFreq(void)
  162. {
  163. SystemCoreClockUpdate();
  164. return SystemCoreClock;
  165. }
  166. /**
  167. * @brief Set HCLK frequency
  168. * @param[in] u32Hclk is HCLK frequency. The range of u32Hclk is 25 MHz ~ 72 MHz.
  169. * @return HCLK frequency
  170. * @details This function is used to set HCLK frequency. The frequency unit is Hz. \n
  171. * It would configure PLL frequency to 50MHz ~ 144MHz,
  172. * set HCLK clock divider as 2 and switch HCLK clock source to PLL. \n
  173. * The register write-protection function should be disabled before using this function.
  174. */
  175. uint32_t CLK_SetCoreClock(uint32_t u32Hclk)
  176. {
  177. uint32_t u32HIRCSTB;
  178. /* Read HIRC clock source stable flag */
  179. u32HIRCSTB = CLK->STATUS & CLK_STATUS_HIRCSTB_Msk;
  180. /* The range of u32Hclk is 25 MHz ~ 72 MHz */
  181. if(u32Hclk > FREQ_72MHZ)
  182. u32Hclk = FREQ_72MHZ;
  183. if(u32Hclk < FREQ_25MHZ)
  184. u32Hclk = FREQ_25MHZ;
  185. /* Switch HCLK clock source to HIRC clock for safe */
  186. CLK->PWRCTL |= CLK_PWRCTL_HIRCEN_Msk;
  187. CLK_WaitClockReady(CLK_STATUS_HIRCSTB_Msk);
  188. CLK->CLKSEL0 |= CLK_CLKSEL0_HCLKSEL_Msk;
  189. CLK->CLKDIV0 &= (~CLK_CLKDIV0_HCLKDIV_Msk);
  190. /* Configure PLL setting if HXT clock is enabled */
  191. if(CLK->PWRCTL & CLK_PWRCTL_HXTEN_Msk)
  192. u32Hclk = CLK_EnablePLL(CLK_PLLCTL_PLLSRC_HXT, (u32Hclk << 1));
  193. /* Configure PLL setting if HXT clock is not enabled */
  194. else
  195. {
  196. u32Hclk = CLK_EnablePLL(CLK_PLLCTL_PLLSRC_HIRC, (u32Hclk << 1));
  197. /* Read HIRC clock source stable flag */
  198. u32HIRCSTB = CLK->STATUS & CLK_STATUS_HIRCSTB_Msk;
  199. }
  200. /* Select HCLK clock source to PLL,
  201. Select HCLK clock source divider as 2
  202. and update system core clock
  203. */
  204. CLK_SetHCLK(CLK_CLKSEL0_HCLKSEL_PLL, CLK_CLKDIV0_HCLK(2));
  205. /* Disable HIRC if HIRC is disabled before setting core clock */
  206. if(u32HIRCSTB == 0)
  207. CLK->PWRCTL &= ~CLK_PWRCTL_HIRCEN_Msk;
  208. /* Return actually HCLK frequency is PLL frequency divide 2 */
  209. return u32Hclk >> 1;
  210. }
  211. /**
  212. * @brief This function set HCLK clock source and HCLK clock divider
  213. * @param[in] u32ClkSrc is HCLK clock source. Including :
  214. * - \ref CLK_CLKSEL0_HCLKSEL_HXT
  215. * - \ref CLK_CLKSEL0_HCLKSEL_LXT
  216. * - \ref CLK_CLKSEL0_HCLKSEL_PLL
  217. * - \ref CLK_CLKSEL0_HCLKSEL_LIRC
  218. * - \ref CLK_CLKSEL0_HCLKSEL_HIRC
  219. * @param[in] u32ClkDiv is HCLK clock divider. Including :
  220. * - \ref CLK_CLKDIV0_HCLK(x)
  221. * @return None
  222. * @details This function set HCLK clock source and HCLK clock divider. \n
  223. * The register write-protection function should be disabled before using this function.
  224. */
  225. void CLK_SetHCLK(uint32_t u32ClkSrc, uint32_t u32ClkDiv)
  226. {
  227. uint32_t u32HIRCSTB;
  228. /* Read HIRC clock source stable flag */
  229. u32HIRCSTB = CLK->STATUS & CLK_STATUS_HIRCSTB_Msk;
  230. /* Switch to HIRC for Safe. Avoid HCLK too high when applying new divider. */
  231. CLK->PWRCTL |= CLK_PWRCTL_HIRCEN_Msk;
  232. CLK_WaitClockReady(CLK_STATUS_HIRCSTB_Msk);
  233. CLK->CLKSEL0 = (CLK->CLKSEL0 & (~CLK_CLKSEL0_HCLKSEL_Msk)) | CLK_CLKSEL0_HCLKSEL_HIRC;
  234. /* Apply new Divider */
  235. CLK->CLKDIV0 = (CLK->CLKDIV0 & (~CLK_CLKDIV0_HCLKDIV_Msk)) | u32ClkDiv;
  236. /* Switch HCLK to new HCLK source */
  237. CLK->CLKSEL0 = (CLK->CLKSEL0 & (~CLK_CLKSEL0_HCLKSEL_Msk)) | u32ClkSrc;
  238. /* Update System Core Clock */
  239. SystemCoreClockUpdate();
  240. /* Disable HIRC if HIRC is disabled before switching HCLK source */
  241. if(u32HIRCSTB == 0)
  242. CLK->PWRCTL &= ~CLK_PWRCTL_HIRCEN_Msk;
  243. }
  244. /**
  245. * @brief This function set selected module clock source and module clock divider
  246. * @param[in] u32ModuleIdx is module index.
  247. * @param[in] u32ClkSrc is module clock source.
  248. * @param[in] u32ClkDiv is module clock divider.
  249. * @return None
  250. * @details Valid parameter combinations listed in following table:
  251. *
  252. * |Module index |Clock source |Divider |
  253. * | :---------------- | :----------------------------------- | :---------------------- |
  254. * |\ref WDT_MODULE |\ref CLK_CLKSEL1_WDTSEL_LXT | x |
  255. * |\ref WDT_MODULE |\ref CLK_CLKSEL1_WDTSEL_PCLK0_DIV2048 | x |
  256. * |\ref WDT_MODULE |\ref CLK_CLKSEL1_WDTSEL_LIRC | x |
  257. * |\ref RTC_MODULE |\ref CLK_CLKSEL3_RTCSEL_LXT | x |
  258. * |\ref RTC_MODULE |\ref CLK_CLKSEL3_RTCSEL_LIRC | x |
  259. * |\ref TMR0_MODULE |\ref CLK_CLKSEL1_TMR0SEL_HXT | x |
  260. * |\ref TMR0_MODULE |\ref CLK_CLKSEL1_TMR0SEL_LXT | x |
  261. * |\ref TMR0_MODULE |\ref CLK_CLKSEL1_TMR0SEL_PCLK0 | x |
  262. * |\ref TMR0_MODULE |\ref CLK_CLKSEL1_TMR0SEL_EXT_TRG | x |
  263. * |\ref TMR0_MODULE |\ref CLK_CLKSEL1_TMR0SEL_LIRC | x |
  264. * |\ref TMR0_MODULE |\ref CLK_CLKSEL1_TMR0SEL_HIRC | x |
  265. * |\ref TMR1_MODULE |\ref CLK_CLKSEL1_TMR1SEL_HXT | x |
  266. * |\ref TMR1_MODULE |\ref CLK_CLKSEL1_TMR1SEL_LXT | x |
  267. * |\ref TMR1_MODULE |\ref CLK_CLKSEL1_TMR1SEL_PCLK0 | x |
  268. * |\ref TMR1_MODULE |\ref CLK_CLKSEL1_TMR1SEL_EXT_TRG | x |
  269. * |\ref TMR1_MODULE |\ref CLK_CLKSEL1_TMR1SEL_LIRC | x |
  270. * |\ref TMR1_MODULE |\ref CLK_CLKSEL1_TMR1SEL_HIRC | x |
  271. * |\ref TMR2_MODULE |\ref CLK_CLKSEL1_TMR2SEL_HXT | x |
  272. * |\ref TMR2_MODULE |\ref CLK_CLKSEL1_TMR2SEL_LXT | x |
  273. * |\ref TMR2_MODULE |\ref CLK_CLKSEL1_TMR2SEL_PCLK1 | x |
  274. * |\ref TMR2_MODULE |\ref CLK_CLKSEL1_TMR2SEL_EXT_TRG | x |
  275. * |\ref TMR2_MODULE |\ref CLK_CLKSEL1_TMR2SEL_LIRC | x |
  276. * |\ref TMR2_MODULE |\ref CLK_CLKSEL1_TMR2SEL_HIRC | x |
  277. * |\ref TMR3_MODULE |\ref CLK_CLKSEL1_TMR3SEL_HXT | x |
  278. * |\ref TMR3_MODULE |\ref CLK_CLKSEL1_TMR3SEL_LXT | x |
  279. * |\ref TMR3_MODULE |\ref CLK_CLKSEL1_TMR3SEL_PCLK1 | x |
  280. * |\ref TMR3_MODULE |\ref CLK_CLKSEL1_TMR3SEL_EXT_TRG | x |
  281. * |\ref TMR3_MODULE |\ref CLK_CLKSEL1_TMR3SEL_LIRC | x |
  282. * |\ref TMR3_MODULE |\ref CLK_CLKSEL1_TMR3SEL_HIRC | x |
  283. * |\ref CLKO_MODULE |\ref CLK_CLKSEL1_CLKOSEL_HXT | x |
  284. * |\ref CLKO_MODULE |\ref CLK_CLKSEL1_CLKOSEL_LXT | x |
  285. * |\ref CLKO_MODULE |\ref CLK_CLKSEL1_CLKOSEL_HCLK | x |
  286. * |\ref CLKO_MODULE |\ref CLK_CLKSEL1_CLKOSEL_HIRC | x |
  287. * |\ref SPI0_MODULE |\ref CLK_CLKSEL2_SPI0SEL_HXT | x |
  288. * |\ref SPI0_MODULE |\ref CLK_CLKSEL2_SPI0SEL_PLL | x |
  289. * |\ref SPI0_MODULE |\ref CLK_CLKSEL2_SPI0SEL_PCLK0 | x |
  290. * |\ref SPI0_MODULE |\ref CLK_CLKSEL2_SPI0SEL_HIRC | x |
  291. * |\ref SPI1_MODULE |\ref CLK_CLKSEL2_SPI1SEL_HXT | x |
  292. * |\ref SPI1_MODULE |\ref CLK_CLKSEL2_SPI1SEL_PLL | x |
  293. * |\ref SPI1_MODULE |\ref CLK_CLKSEL2_SPI1SEL_PCLK1 | x |
  294. * |\ref SPI1_MODULE |\ref CLK_CLKSEL2_SPI1SEL_HIRC | x |
  295. * |\ref SPI2_MODULE |\ref CLK_CLKSEL2_SPI2SEL_HXT | x |
  296. * |\ref SPI2_MODULE |\ref CLK_CLKSEL2_SPI2SEL_PLL | x |
  297. * |\ref SPI2_MODULE |\ref CLK_CLKSEL2_SPI2SEL_PCLK0 | x |
  298. * |\ref SPI2_MODULE |\ref CLK_CLKSEL2_SPI2SEL_HIRC | x |
  299. * |\ref UART0_MODULE |\ref CLK_CLKSEL1_UARTSEL_HXT |\ref CLK_CLKDIV0_UART(x) |
  300. * |\ref UART0_MODULE |\ref CLK_CLKSEL1_UARTSEL_PLL |\ref CLK_CLKDIV0_UART(x) |
  301. * |\ref UART0_MODULE |\ref CLK_CLKSEL1_UARTSEL_LXT |\ref CLK_CLKDIV0_UART(x) |
  302. * |\ref UART0_MODULE |\ref CLK_CLKSEL1_UARTSEL_HIRC |\ref CLK_CLKDIV0_UART(x) |
  303. * |\ref UART1_MODULE |\ref CLK_CLKSEL1_UARTSEL_HXT |\ref CLK_CLKDIV0_UART(x) |
  304. * |\ref UART1_MODULE |\ref CLK_CLKSEL1_UARTSEL_PLL |\ref CLK_CLKDIV0_UART(x) |
  305. * |\ref UART1_MODULE |\ref CLK_CLKSEL1_UARTSEL_LXT |\ref CLK_CLKDIV0_UART(x) |
  306. * |\ref UART1_MODULE |\ref CLK_CLKSEL1_UARTSEL_HIRC |\ref CLK_CLKDIV0_UART(x) |
  307. * |\ref UART2_MODULE |\ref CLK_CLKSEL1_UARTSEL_HXT |\ref CLK_CLKDIV0_UART(x) |
  308. * |\ref UART2_MODULE |\ref CLK_CLKSEL1_UARTSEL_PLL |\ref CLK_CLKDIV0_UART(x) |
  309. * |\ref UART2_MODULE |\ref CLK_CLKSEL1_UARTSEL_LXT |\ref CLK_CLKDIV0_UART(x) |
  310. * |\ref UART2_MODULE |\ref CLK_CLKSEL1_UARTSEL_HIRC |\ref CLK_CLKDIV0_UART(x) |
  311. * |\ref UART3_MODULE |\ref CLK_CLKSEL1_UARTSEL_HXT |\ref CLK_CLKDIV0_UART(x) |
  312. * |\ref UART3_MODULE |\ref CLK_CLKSEL1_UARTSEL_LXT |\ref CLK_CLKDIV0_UART(x) |
  313. * |\ref UART3_MODULE |\ref CLK_CLKSEL1_UARTSEL_PLL |\ref CLK_CLKDIV0_UART(x) |
  314. * |\ref UART3_MODULE |\ref CLK_CLKSEL1_UARTSEL_HIRC |\ref CLK_CLKDIV0_UART(x) |
  315. * |\ref USBH_MODULE | x |\ref CLK_CLKDIV0_USB(x) |
  316. * |\ref USBD_MODULE | x |\ref CLK_CLKDIV0_USB(x) |
  317. * |\ref OTG_MODULE | x |\ref CLK_CLKDIV0_USB(x) |
  318. * |\ref EADC_MODULE | x |\ref CLK_CLKDIV0_EADC(x) |
  319. * |\ref SC0_MODULE |\ref CLK_CLKSEL3_SC0SEL_HXT |\ref CLK_CLKDIV1_SC0(x) |
  320. * |\ref SC0_MODULE |\ref CLK_CLKSEL3_SC0SEL_PLL |\ref CLK_CLKDIV1_SC0(x) |
  321. * |\ref SC0_MODULE |\ref CLK_CLKSEL3_SC0SEL_PCLK0 |\ref CLK_CLKDIV1_SC0(x) |
  322. * |\ref SC0_MODULE |\ref CLK_CLKSEL3_SC0SEL_HIRC |\ref CLK_CLKDIV1_SC0(x) |
  323. * |\ref PWM0_MODULE |\ref CLK_CLKSEL2_PWM0SEL_PLL | x |
  324. * |\ref PWM0_MODULE |\ref CLK_CLKSEL2_PWM0SEL_PCLK0 | x |
  325. * |\ref PWM1_MODULE |\ref CLK_CLKSEL2_PWM1SEL_PLL | x |
  326. * |\ref PWM1_MODULE |\ref CLK_CLKSEL2_PWM1SEL_PCLK1 | x |
  327. * |\ref WWDT_MODULE |\ref CLK_CLKSEL1_WWDTSEL_PCLK0_DIV2048 | x |
  328. * |\ref WWDT_MODULE |\ref CLK_CLKSEL1_WWDTSEL_LIRC | x |
  329. */
  330. void CLK_SetModuleClock(uint32_t u32ModuleIdx, uint32_t u32ClkSrc, uint32_t u32ClkDiv)
  331. {
  332. uint32_t u32sel = 0, u32div = 0;
  333. if(MODULE_CLKDIV_Msk(u32ModuleIdx) != MODULE_NoMsk)
  334. {
  335. /* Get clock divider control register address */
  336. u32div = (uint32_t)&CLK->CLKDIV0 + ((MODULE_CLKDIV(u32ModuleIdx)) * 4);
  337. /* Apply new divider */
  338. M32(u32div) = (M32(u32div) & (~(MODULE_CLKDIV_Msk(u32ModuleIdx) << MODULE_CLKDIV_Pos(u32ModuleIdx)))) | u32ClkDiv;
  339. }
  340. if(MODULE_CLKSEL_Msk(u32ModuleIdx) != MODULE_NoMsk)
  341. {
  342. /* Get clock select control register address */
  343. u32sel = (uint32_t)&CLK->CLKSEL0 + ((MODULE_CLKSEL(u32ModuleIdx)) * 4);
  344. /* Set new clock selection setting */
  345. M32(u32sel) = (M32(u32sel) & (~(MODULE_CLKSEL_Msk(u32ModuleIdx) << MODULE_CLKSEL_Pos(u32ModuleIdx)))) | u32ClkSrc;
  346. }
  347. }
  348. /**
  349. * @brief Set SysTick clock source
  350. * @param[in] u32ClkSrc is module clock source. Including:
  351. * - \ref CLK_CLKSEL0_STCLKSEL_HXT
  352. * - \ref CLK_CLKSEL0_STCLKSEL_LXT
  353. * - \ref CLK_CLKSEL0_STCLKSEL_HXT_DIV2
  354. * - \ref CLK_CLKSEL0_STCLKSEL_HCLK_DIV2
  355. * - \ref CLK_CLKSEL0_STCLKSEL_HIRC_DIV2
  356. * @return None
  357. * @details This function set SysTick clock source. \n
  358. * The register write-protection function should be disabled before using this function.
  359. */
  360. void CLK_SetSysTickClockSrc(uint32_t u32ClkSrc)
  361. {
  362. CLK->CLKSEL0 = (CLK->CLKSEL0 & ~CLK_CLKSEL0_STCLKSEL_Msk) | u32ClkSrc;
  363. }
  364. /**
  365. * @brief Enable clock source
  366. * @param[in] u32ClkMask is clock source mask. Including :
  367. * - \ref CLK_PWRCTL_HXTEN_Msk
  368. * - \ref CLK_PWRCTL_LXTEN_Msk
  369. * - \ref CLK_PWRCTL_HIRCEN_Msk
  370. * - \ref CLK_PWRCTL_LIRCEN_Msk
  371. * @return None
  372. * @details This function enable clock source. \n
  373. * The register write-protection function should be disabled before using this function.
  374. */
  375. void CLK_EnableXtalRC(uint32_t u32ClkMask)
  376. {
  377. CLK->PWRCTL |= u32ClkMask;
  378. }
  379. /**
  380. * @brief Disable clock source
  381. * @param[in] u32ClkMask is clock source mask. Including :
  382. * - \ref CLK_PWRCTL_HXTEN_Msk
  383. * - \ref CLK_PWRCTL_LXTEN_Msk
  384. * - \ref CLK_PWRCTL_HIRCEN_Msk
  385. * - \ref CLK_PWRCTL_LIRCEN_Msk
  386. * @return None
  387. * @details This function disable clock source. \n
  388. * The register write-protection function should be disabled before using this function.
  389. */
  390. void CLK_DisableXtalRC(uint32_t u32ClkMask)
  391. {
  392. CLK->PWRCTL &= ~u32ClkMask;
  393. }
  394. /**
  395. * @brief Enable module clock
  396. * @param[in] u32ModuleIdx is module index. Including :
  397. * - \ref PDMA_MODULE
  398. * - \ref ISP_MODULE
  399. * - \ref EBI_MODULE
  400. * - \ref USBH_MODULE
  401. * - \ref CRC_MODULE
  402. * - \ref WDT_MODULE
  403. * - \ref WWDT_MODULE
  404. * - \ref RTC_MODULE
  405. * - \ref TMR0_MODULE
  406. * - \ref TMR1_MODULE
  407. * - \ref TMR2_MODULE
  408. * - \ref TMR3_MODULE
  409. * - \ref CLKO_MODULE
  410. * - \ref ACMP01_MODULE
  411. * - \ref I2C0_MODULE
  412. * - \ref I2C1_MODULE
  413. * - \ref SPI0_MODULE
  414. * - \ref SPI1_MODULE
  415. * - \ref SPI2_MODULE
  416. * - \ref UART0_MODULE
  417. * - \ref UART1_MODULE
  418. * - \ref UART2_MODULE
  419. * - \ref UART3_MODULE
  420. * - \ref CAN0_MODULE
  421. * - \ref OTG_MODULE
  422. * - \ref USBD_MODULE
  423. * - \ref EADC_MODULE
  424. * - \ref SC0_MODULE
  425. * - \ref DAC_MODULE
  426. * - \ref PWM0_MODULE
  427. * - \ref PWM1_MODULE
  428. * - \ref TK_MODULE
  429. * @return None
  430. * @details This function is used to enable module clock.
  431. */
  432. void CLK_EnableModuleClock(uint32_t u32ModuleIdx)
  433. {
  434. *(volatile uint32_t *)((uint32_t)&CLK->AHBCLK + (MODULE_APBCLK(u32ModuleIdx) * 4)) |= 1 << MODULE_IP_EN_Pos(u32ModuleIdx);
  435. }
  436. /**
  437. * @brief Disable module clock
  438. * @param[in] u32ModuleIdx is module index. Including :
  439. * - \ref PDMA_MODULE
  440. * - \ref ISP_MODULE
  441. * - \ref EBI_MODULE
  442. * - \ref USBH_MODULE
  443. * - \ref CRC_MODULE
  444. * - \ref WDT_MODULE
  445. * - \ref WWDT_MODULE
  446. * - \ref RTC_MODULE
  447. * - \ref TMR0_MODULE
  448. * - \ref TMR1_MODULE
  449. * - \ref TMR2_MODULE
  450. * - \ref TMR3_MODULE
  451. * - \ref CLKO_MODULE
  452. * - \ref ACMP01_MODULE
  453. * - \ref I2C0_MODULE
  454. * - \ref I2C1_MODULE
  455. * - \ref SPI0_MODULE
  456. * - \ref SPI1_MODULE
  457. * - \ref SPI2_MODULE
  458. * - \ref UART0_MODULE
  459. * - \ref UART1_MODULE
  460. * - \ref UART2_MODULE
  461. * - \ref UART3_MODULE
  462. * - \ref CAN0_MODULE
  463. * - \ref OTG_MODULE
  464. * - \ref USBD_MODULE
  465. * - \ref EADC_MODULE
  466. * - \ref SC0_MODULE
  467. * - \ref DAC_MODULE
  468. * - \ref PWM0_MODULE
  469. * - \ref PWM1_MODULE
  470. * - \ref TK_MODULE
  471. * @return None
  472. * @details This function is used to disable module clock.
  473. */
  474. void CLK_DisableModuleClock(uint32_t u32ModuleIdx)
  475. {
  476. *(volatile uint32_t *)((uint32_t)&CLK->AHBCLK + (MODULE_APBCLK(u32ModuleIdx) * 4)) &= ~(1 << MODULE_IP_EN_Pos(u32ModuleIdx));
  477. }
  478. /**
  479. * @brief Set PLL frequency
  480. * @param[in] u32PllClkSrc is PLL clock source. Including :
  481. * - \ref CLK_PLLCTL_PLLSRC_HXT
  482. * - \ref CLK_PLLCTL_PLLSRC_HIRC
  483. * @param[in] u32PllFreq is PLL frequency.
  484. * @return PLL frequency
  485. * @details This function is used to configure PLLCTL register to set specified PLL frequency. \n
  486. * The register write-protection function should be disabled before using this function.
  487. */
  488. uint32_t CLK_EnablePLL(uint32_t u32PllClkSrc, uint32_t u32PllFreq)
  489. {
  490. uint32_t u32PllSrcClk, u32NR, u32NF, u32NO, u32CLK_SRC;
  491. uint32_t u32Tmp, u32Tmp2, u32Tmp3, u32Min, u32MinNF, u32MinNR;
  492. /* Disable PLL first to avoid unstable when setting PLL */
  493. CLK_DisablePLL();
  494. /* PLL source clock is from HXT */
  495. if(u32PllClkSrc == CLK_PLLCTL_PLLSRC_HXT)
  496. {
  497. /* Enable HXT clock */
  498. CLK->PWRCTL |= CLK_PWRCTL_HXTEN_Msk;
  499. /* Wait for HXT clock ready */
  500. CLK_WaitClockReady(CLK_STATUS_HXTSTB_Msk);
  501. /* Select PLL source clock from HXT */
  502. u32CLK_SRC = CLK_PLLCTL_PLLSRC_HXT;
  503. u32PllSrcClk = __HXT;
  504. /* u32NR start from 2 */
  505. u32NR = 2;
  506. }
  507. /* PLL source clock is from HIRC */
  508. else
  509. {
  510. /* Enable HIRC clock */
  511. CLK->PWRCTL |= CLK_PWRCTL_HIRCEN_Msk;
  512. /* Wait for HIRC clock ready */
  513. CLK_WaitClockReady(CLK_STATUS_HIRCSTB_Msk);
  514. /* Select PLL source clock from HIRC */
  515. u32CLK_SRC = CLK_PLLCTL_PLLSRC_HIRC;
  516. u32PllSrcClk = __HIRC;
  517. /* u32NR start from 4 when FIN = 22.1184MHz to avoid calculation overflow */
  518. u32NR = 4;
  519. }
  520. /* Select "NO" according to request frequency */
  521. if((u32PllFreq <= FREQ_500MHZ) && (u32PllFreq > FREQ_250MHZ))
  522. {
  523. u32NO = 0;
  524. }
  525. else if((u32PllFreq <= FREQ_250MHZ) && (u32PllFreq > FREQ_125MHZ))
  526. {
  527. u32NO = 1;
  528. u32PllFreq = u32PllFreq << 1;
  529. }
  530. else if((u32PllFreq <= FREQ_125MHZ) && (u32PllFreq >= FREQ_50MHZ))
  531. {
  532. u32NO = 3;
  533. u32PllFreq = u32PllFreq << 2;
  534. }
  535. else
  536. {
  537. /* Wrong frequency request. Just return default setting. */
  538. goto lexit;
  539. }
  540. /* Find best solution */
  541. u32Min = (uint32_t) - 1;
  542. u32MinNR = 0;
  543. u32MinNF = 0;
  544. for(; u32NR <= 33; u32NR++)
  545. {
  546. u32Tmp = u32PllSrcClk / u32NR;
  547. if((u32Tmp > 1600000) && (u32Tmp < 16000000))
  548. {
  549. for(u32NF = 2; u32NF <= 513; u32NF++)
  550. {
  551. u32Tmp2 = u32Tmp * u32NF;
  552. if((u32Tmp2 >= 200000000) && (u32Tmp2 <= 500000000))
  553. {
  554. u32Tmp3 = (u32Tmp2 > u32PllFreq) ? u32Tmp2 - u32PllFreq : u32PllFreq - u32Tmp2;
  555. if(u32Tmp3 < u32Min)
  556. {
  557. u32Min = u32Tmp3;
  558. u32MinNR = u32NR;
  559. u32MinNF = u32NF;
  560. /* Break when get good results */
  561. if(u32Min == 0)
  562. break;
  563. }
  564. }
  565. }
  566. }
  567. }
  568. /* Enable and apply new PLL setting. */
  569. CLK->PLLCTL = u32CLK_SRC | (u32NO << 14) | ((u32MinNR - 2) << 9) | (u32MinNF - 2);
  570. /* Wait for PLL clock stable */
  571. CLK_WaitClockReady(CLK_STATUS_PLLSTB_Msk);
  572. /* Return actual PLL output clock frequency */
  573. return u32PllSrcClk / ((u32NO + 1) * u32MinNR) * u32MinNF;
  574. lexit:
  575. /* Apply default PLL setting and return */
  576. if(u32PllClkSrc == CLK_PLLCTL_PLLSRC_HXT)
  577. CLK->PLLCTL = CLK_PLLCTL_72MHz_HXT; /* 72MHz */
  578. else
  579. CLK->PLLCTL = CLK_PLLCTL_72MHz_HIRC; /* 71.8848MHz */
  580. /* Wait for PLL clock stable */
  581. CLK_WaitClockReady(CLK_STATUS_PLLSTB_Msk);
  582. return CLK_GetPLLClockFreq();
  583. }
  584. /**
  585. * @brief Disable PLL
  586. * @param None
  587. * @return None
  588. * @details This function set PLL in Power-down mode. \n
  589. * The register write-protection function should be disabled before using this function.
  590. */
  591. void CLK_DisablePLL(void)
  592. {
  593. CLK->PLLCTL |= CLK_PLLCTL_PD_Msk;
  594. }
  595. /**
  596. * @brief This function check selected clock source status
  597. * @param[in] u32ClkMask is selected clock source. Including :
  598. * - \ref CLK_STATUS_HXTSTB_Msk
  599. * - \ref CLK_STATUS_LXTSTB_Msk
  600. * - \ref CLK_STATUS_HIRCSTB_Msk
  601. * - \ref CLK_STATUS_LIRCSTB_Msk
  602. * - \ref CLK_STATUS_PLLSTB_Msk
  603. * @retval 0 clock is not stable
  604. * @retval 1 clock is stable
  605. * @details To wait for clock ready by specified clock source stable flag or timeout (~300ms)
  606. */
  607. uint32_t CLK_WaitClockReady(uint32_t u32ClkMask)
  608. {
  609. int32_t i32TimeOutCnt = 2160000;
  610. while((CLK->STATUS & u32ClkMask) != u32ClkMask)
  611. {
  612. if(i32TimeOutCnt-- <= 0)
  613. return 0;
  614. }
  615. return 1;
  616. }
  617. /**
  618. * @brief Enable System Tick counter
  619. * @param[in] u32ClkSrc is System Tick clock source. Including:
  620. * - \ref CLK_CLKSEL0_STCLKSEL_HXT
  621. * - \ref CLK_CLKSEL0_STCLKSEL_LXT
  622. * - \ref CLK_CLKSEL0_STCLKSEL_HXT_DIV2
  623. * - \ref CLK_CLKSEL0_STCLKSEL_HCLK_DIV2
  624. * - \ref CLK_CLKSEL0_STCLKSEL_HIRC_DIV2
  625. * - \ref CLK_CLKSEL0_STCLKSEL_HCLK
  626. * @param[in] u32Count is System Tick reload value. It could be 0~0xFFFFFF.
  627. * @return None
  628. * @details This function set System Tick clock source, reload value, enable System Tick counter and interrupt. \n
  629. * The register write-protection function should be disabled before using this function.
  630. */
  631. void CLK_EnableSysTick(uint32_t u32ClkSrc, uint32_t u32Count)
  632. {
  633. /* Set System Tick counter disabled */
  634. SysTick->CTRL = 0;
  635. /* Set System Tick clock source */
  636. if( u32ClkSrc == CLK_CLKSEL0_STCLKSEL_HCLK )
  637. SysTick->CTRL |= SysTick_CTRL_CLKSOURCE_Msk;
  638. else
  639. CLK->CLKSEL0 = (CLK->CLKSEL0 & ~CLK_CLKSEL0_STCLKSEL_Msk) | u32ClkSrc;
  640. /* Set System Tick reload value */
  641. SysTick->LOAD = u32Count;
  642. /* Clear System Tick current value and counter flag */
  643. SysTick->VAL = 0;
  644. /* Set System Tick interrupt enabled and counter enabled */
  645. SysTick->CTRL |= SysTick_CTRL_TICKINT_Msk | SysTick_CTRL_ENABLE_Msk;
  646. }
  647. /**
  648. * @brief Disable System Tick counter
  649. * @param None
  650. * @return None
  651. * @details This function disable System Tick counter.
  652. */
  653. void CLK_DisableSysTick(void)
  654. {
  655. /* Set System Tick counter disabled */
  656. SysTick->CTRL = 0;
  657. }
  658. /*@}*/ /* end of group CLK_EXPORTED_FUNCTIONS */
  659. /*@}*/ /* end of group CLK_Driver */
  660. /*@}*/ /* end of group Standard_Driver */
  661. /*** (C) COPYRIGHT 2014~2015 Nuvoton Technology Corp. ***/