mbed library sources. Supersedes mbed-src.

Fork of mbed-dev by mbed official

Revision:
149:156823d33999
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/targets/TARGET_NUVOTON/TARGET_M451/device/StdDriver/m451_clk.c	Fri Oct 28 11:17:30 2016 +0100
@@ -0,0 +1,751 @@
+/**************************************************************************//**
+ * @file     clk.c
+ * @version  V3.00
+ * $Revision: 35 $
+ * $Date: 15/08/11 10:26a $
+ * @brief    M451 series CLK driver source file
+ *
+ * @note
+ * Copyright (C) 2014~2015 Nuvoton Technology Corp. All rights reserved.
+ *****************************************************************************/
+
+#include "M451Series.h"
+
+/** @addtogroup Standard_Driver Standard Driver
+  @{
+*/
+
+/** @addtogroup CLK_Driver CLK Driver
+  @{
+*/
+
+/** @addtogroup CLK_EXPORTED_FUNCTIONS CLK Exported Functions
+  @{
+*/
+
+/**
+  * @brief      Disable clock divider output function
+  * @param      None
+  * @return     None
+  * @details    This function disable clock divider output function.
+  */
+void CLK_DisableCKO(void)
+{
+    /* Disable CKO clock source */
+    CLK_DisableModuleClock(CLKO_MODULE);
+}
+
+/**
+  * @brief      This function enable clock divider output module clock,
+  *             enable clock divider output function and set frequency selection.
+  * @param[in]  u32ClkSrc is frequency divider function clock source. Including :
+  *             - \ref CLK_CLKSEL1_CLKOSEL_HXT
+  *             - \ref CLK_CLKSEL1_CLKOSEL_LXT
+  *             - \ref CLK_CLKSEL1_CLKOSEL_HCLK
+  *             - \ref CLK_CLKSEL1_CLKOSEL_HIRC
+  * @param[in]  u32ClkDiv is divider output frequency selection. It could be 0~15.
+  * @param[in]  u32ClkDivBy1En is clock divided by one enabled.
+  * @return     None
+  * @details    Output selected clock to CKO. The output clock frequency is divided by u32ClkDiv. \n
+  *             The formula is: \n
+  *                 CKO frequency = (Clock source frequency) / 2^(u32ClkDiv + 1) \n
+  *             This function is just used to set CKO clock.
+  *             User must enable I/O for CKO clock output pin by themselves. \n
+  */
+void CLK_EnableCKO(uint32_t u32ClkSrc, uint32_t u32ClkDiv, uint32_t u32ClkDivBy1En)
+{
+    /* CKO = clock source / 2^(u32ClkDiv + 1) */
+    CLK->CLKOCTL = CLK_CLKOCTL_CLKOEN_Msk | u32ClkDiv | (u32ClkDivBy1En << CLK_CLKOCTL_DIV1EN_Pos);
+
+    /* Enable CKO clock source */
+    CLK_EnableModuleClock(CLKO_MODULE);
+
+    /* Select CKO clock source */
+    CLK_SetModuleClock(CLKO_MODULE, u32ClkSrc, 0);
+}
+
+/**
+  * @brief      Enter to Power-down mode
+  * @param      None
+  * @return     None
+  * @details    This function is used to let system enter to Power-down mode. \n
+  *             The register write-protection function should be disabled before using this function. 
+  */
+void CLK_PowerDown(void)
+{
+    /* Set the processor uses deep sleep as its low power mode */
+    SCB->SCR |= SCB_SCR_SLEEPDEEP_Msk;
+
+    /* Set system Power-down enabled and Power-down entry condition */
+    CLK->PWRCTL |= (CLK_PWRCTL_PDEN_Msk | CLK_PWRCTL_PDWTCPU_Msk);
+
+    /* Chip enter Power-down mode after CPU run WFI instruction */
+    __WFI();
+}
+
+/**
+  * @brief      Enter to Idle mode
+  * @param      None
+  * @return     None
+  * @details    This function let system enter to Idle mode. \n
+  *             The register write-protection function should be disabled before using this function.
+  */
+void CLK_Idle(void)
+{
+    /* Set the processor uses sleep as its low power mode */
+    SCB->SCR &= ~SCB_SCR_SLEEPDEEP_Msk;
+
+    /* Set chip in idle mode because of WFI command */
+    CLK->PWRCTL &= ~CLK_PWRCTL_PDEN_Msk;
+
+    /* Chip enter idle mode after CPU run WFI instruction */
+    __WFI();
+}
+
+/**
+  * @brief      Get external high speed crystal clock frequency
+  * @param      None
+  * @return     External high frequency crystal frequency
+  * @details    This function get external high frequency crystal frequency. The frequency unit is Hz.
+  */
+uint32_t CLK_GetHXTFreq(void)
+{
+    if(CLK->PWRCTL & CLK_PWRCTL_HXTEN_Msk)
+        return __HXT;
+    else
+        return 0;
+}
+
+
+/**
+  * @brief      Get external low speed crystal clock frequency
+  * @param      None
+  * @return     External low speed crystal clock frequency
+  * @details    This function get external low frequency crystal frequency. The frequency unit is Hz.
+  */
+uint32_t CLK_GetLXTFreq(void)
+{
+    if(CLK->PWRCTL & CLK_PWRCTL_LXTEN_Msk)
+        return __LXT;
+    else
+        return 0;
+}
+
+/**
+  * @brief      Get PCLK0 frequency
+  * @param      None
+  * @return     PCLK0 frequency
+  * @details    This function get PCLK0 frequency. The frequency unit is Hz.
+  */
+uint32_t CLK_GetPCLK0Freq(void)
+{
+    SystemCoreClockUpdate();
+    if(CLK->CLKSEL0 & CLK_CLKSEL0_PCLK0SEL_Msk)
+        return SystemCoreClock / 2;
+    else
+        return SystemCoreClock;
+}
+
+
+/**
+  * @brief      Get PCLK1 frequency
+  * @param      None
+  * @return     PCLK1 frequency
+  * @details    This function get PCLK1 frequency. The frequency unit is Hz.
+  */
+uint32_t CLK_GetPCLK1Freq(void)
+{
+    SystemCoreClockUpdate();
+    if(CLK->CLKSEL0 & CLK_CLKSEL0_PCLK1SEL_Msk)
+        return SystemCoreClock / 2;
+    else
+        return SystemCoreClock;
+}
+
+
+/**
+  * @brief      Get HCLK frequency
+  * @param      None
+  * @return     HCLK frequency
+  * @details    This function get HCLK frequency. The frequency unit is Hz.
+  */
+uint32_t CLK_GetHCLKFreq(void)
+{
+    SystemCoreClockUpdate();
+    return SystemCoreClock;
+}
+
+
+/**
+  * @brief      Get CPU frequency
+  * @param      None
+  * @return     CPU frequency
+  * @details    This function get CPU frequency. The frequency unit is Hz.
+  */
+uint32_t CLK_GetCPUFreq(void)
+{
+    SystemCoreClockUpdate();
+    return SystemCoreClock;
+}
+
+
+/**
+  * @brief      Set HCLK frequency
+  * @param[in]  u32Hclk is HCLK frequency. The range of u32Hclk is 25 MHz ~ 72 MHz.
+  * @return     HCLK frequency
+  * @details    This function is used to set HCLK frequency. The frequency unit is Hz. \n
+  *             It would configure PLL frequency to 50MHz ~ 144MHz,
+  *             set HCLK clock divider as 2 and switch HCLK clock source to PLL. \n
+  *             The register write-protection function should be disabled before using this function.
+  */
+uint32_t CLK_SetCoreClock(uint32_t u32Hclk)
+{
+    uint32_t u32HIRCSTB;
+
+    /* Read HIRC clock source stable flag */
+    u32HIRCSTB = CLK->STATUS & CLK_STATUS_HIRCSTB_Msk;
+
+    /* The range of u32Hclk is 25 MHz ~ 72 MHz */
+    if(u32Hclk > FREQ_72MHZ)
+        u32Hclk = FREQ_72MHZ;
+    if(u32Hclk < FREQ_25MHZ)
+        u32Hclk = FREQ_25MHZ;
+
+    /* Switch HCLK clock source to HIRC clock for safe */
+    CLK->PWRCTL |= CLK_PWRCTL_HIRCEN_Msk;
+    CLK_WaitClockReady(CLK_STATUS_HIRCSTB_Msk);
+    CLK->CLKSEL0 |= CLK_CLKSEL0_HCLKSEL_Msk;
+    CLK->CLKDIV0 &= (~CLK_CLKDIV0_HCLKDIV_Msk);
+
+    /* Configure PLL setting if HXT clock is enabled */
+    if(CLK->PWRCTL & CLK_PWRCTL_HXTEN_Msk)
+        u32Hclk = CLK_EnablePLL(CLK_PLLCTL_PLLSRC_HXT, (u32Hclk << 1));
+
+    /* Configure PLL setting if HXT clock is not enabled */
+    else
+    {
+        u32Hclk = CLK_EnablePLL(CLK_PLLCTL_PLLSRC_HIRC, (u32Hclk << 1));
+
+        /* Read HIRC clock source stable flag */
+        u32HIRCSTB = CLK->STATUS & CLK_STATUS_HIRCSTB_Msk;
+    }
+
+    /* Select HCLK clock source to PLL,
+       Select HCLK clock source divider as 2
+       and update system core clock
+    */
+    CLK_SetHCLK(CLK_CLKSEL0_HCLKSEL_PLL, CLK_CLKDIV0_HCLK(2));
+
+    /* Disable HIRC if HIRC is disabled before setting core clock */
+    if(u32HIRCSTB == 0)
+        CLK->PWRCTL &= ~CLK_PWRCTL_HIRCEN_Msk;
+
+    /* Return actually HCLK frequency is PLL frequency divide 2 */
+    return u32Hclk >> 1;
+}
+
+/**
+  * @brief      This function set HCLK clock source and HCLK clock divider
+  * @param[in]  u32ClkSrc is HCLK clock source. Including :
+  *             - \ref CLK_CLKSEL0_HCLKSEL_HXT
+  *             - \ref CLK_CLKSEL0_HCLKSEL_LXT
+  *             - \ref CLK_CLKSEL0_HCLKSEL_PLL
+  *             - \ref CLK_CLKSEL0_HCLKSEL_LIRC
+  *             - \ref CLK_CLKSEL0_HCLKSEL_HIRC
+  * @param[in]  u32ClkDiv is HCLK clock divider. Including :
+  *             - \ref CLK_CLKDIV0_HCLK(x)
+  * @return     None
+  * @details    This function set HCLK clock source and HCLK clock divider. \n
+  *             The register write-protection function should be disabled before using this function.
+  */
+void CLK_SetHCLK(uint32_t u32ClkSrc, uint32_t u32ClkDiv)
+{
+    uint32_t u32HIRCSTB;
+
+    /* Read HIRC clock source stable flag */
+    u32HIRCSTB = CLK->STATUS & CLK_STATUS_HIRCSTB_Msk;
+
+    /* Switch to HIRC for Safe. Avoid HCLK too high when applying new divider. */
+    CLK->PWRCTL |= CLK_PWRCTL_HIRCEN_Msk;
+    CLK_WaitClockReady(CLK_STATUS_HIRCSTB_Msk);
+    CLK->CLKSEL0 = (CLK->CLKSEL0 & (~CLK_CLKSEL0_HCLKSEL_Msk)) | CLK_CLKSEL0_HCLKSEL_HIRC;
+
+    /* Apply new Divider */
+    CLK->CLKDIV0 = (CLK->CLKDIV0 & (~CLK_CLKDIV0_HCLKDIV_Msk)) | u32ClkDiv;
+
+    /* Switch HCLK to new HCLK source */
+    CLK->CLKSEL0 = (CLK->CLKSEL0 & (~CLK_CLKSEL0_HCLKSEL_Msk)) | u32ClkSrc;
+
+    /* Update System Core Clock */
+    SystemCoreClockUpdate();
+
+    /* Disable HIRC if HIRC is disabled before switching HCLK source */
+    if(u32HIRCSTB == 0)
+        CLK->PWRCTL &= ~CLK_PWRCTL_HIRCEN_Msk;
+}
+
+/**
+  * @brief      This function set selected module clock source and module clock divider
+  * @param[in]  u32ModuleIdx is module index.
+  * @param[in]  u32ClkSrc is module clock source.
+  * @param[in]  u32ClkDiv is module clock divider.
+  * @return     None
+  * @details    Valid parameter combinations listed in following table:
+  *
+  * |Module index        |Clock source                           |Divider                  |
+  * | :----------------  | :-----------------------------------  | :---------------------- |
+  * |\ref WDT_MODULE     |\ref CLK_CLKSEL1_WDTSEL_LXT            | x                       |
+  * |\ref WDT_MODULE     |\ref CLK_CLKSEL1_WDTSEL_PCLK0_DIV2048  | x                       |
+  * |\ref WDT_MODULE     |\ref CLK_CLKSEL1_WDTSEL_LIRC           | x                       |
+  * |\ref RTC_MODULE     |\ref CLK_CLKSEL3_RTCSEL_LXT            | x                       |
+  * |\ref RTC_MODULE     |\ref CLK_CLKSEL3_RTCSEL_LIRC           | x                       |
+  * |\ref TMR0_MODULE    |\ref CLK_CLKSEL1_TMR0SEL_HXT           | x                       |
+  * |\ref TMR0_MODULE    |\ref CLK_CLKSEL1_TMR0SEL_LXT           | x                       |
+  * |\ref TMR0_MODULE    |\ref CLK_CLKSEL1_TMR0SEL_PCLK0         | x                       |
+  * |\ref TMR0_MODULE    |\ref CLK_CLKSEL1_TMR0SEL_EXT_TRG       | x                       |
+  * |\ref TMR0_MODULE    |\ref CLK_CLKSEL1_TMR0SEL_LIRC          | x                       |
+  * |\ref TMR0_MODULE    |\ref CLK_CLKSEL1_TMR0SEL_HIRC          | x                       |
+  * |\ref TMR1_MODULE    |\ref CLK_CLKSEL1_TMR1SEL_HXT           | x                       |
+  * |\ref TMR1_MODULE    |\ref CLK_CLKSEL1_TMR1SEL_LXT           | x                       |
+  * |\ref TMR1_MODULE    |\ref CLK_CLKSEL1_TMR1SEL_PCLK0         | x                       |
+  * |\ref TMR1_MODULE    |\ref CLK_CLKSEL1_TMR1SEL_EXT_TRG       | x                       |
+  * |\ref TMR1_MODULE    |\ref CLK_CLKSEL1_TMR1SEL_LIRC          | x                       |
+  * |\ref TMR1_MODULE    |\ref CLK_CLKSEL1_TMR1SEL_HIRC          | x                       |
+  * |\ref TMR2_MODULE    |\ref CLK_CLKSEL1_TMR2SEL_HXT           | x                       |
+  * |\ref TMR2_MODULE    |\ref CLK_CLKSEL1_TMR2SEL_LXT           | x                       |
+  * |\ref TMR2_MODULE    |\ref CLK_CLKSEL1_TMR2SEL_PCLK1         | x                       |
+  * |\ref TMR2_MODULE    |\ref CLK_CLKSEL1_TMR2SEL_EXT_TRG       | x                       |
+  * |\ref TMR2_MODULE    |\ref CLK_CLKSEL1_TMR2SEL_LIRC          | x                       |
+  * |\ref TMR2_MODULE    |\ref CLK_CLKSEL1_TMR2SEL_HIRC          | x                       |
+  * |\ref TMR3_MODULE    |\ref CLK_CLKSEL1_TMR3SEL_HXT           | x                       |
+  * |\ref TMR3_MODULE    |\ref CLK_CLKSEL1_TMR3SEL_LXT           | x                       |
+  * |\ref TMR3_MODULE    |\ref CLK_CLKSEL1_TMR3SEL_PCLK1         | x                       |
+  * |\ref TMR3_MODULE    |\ref CLK_CLKSEL1_TMR3SEL_EXT_TRG       | x                       |
+  * |\ref TMR3_MODULE    |\ref CLK_CLKSEL1_TMR3SEL_LIRC          | x                       |
+  * |\ref TMR3_MODULE    |\ref CLK_CLKSEL1_TMR3SEL_HIRC          | x                       |
+  * |\ref CLKO_MODULE    |\ref CLK_CLKSEL1_CLKOSEL_HXT           | x                       |
+  * |\ref CLKO_MODULE    |\ref CLK_CLKSEL1_CLKOSEL_LXT           | x                       |
+  * |\ref CLKO_MODULE    |\ref CLK_CLKSEL1_CLKOSEL_HCLK          | x                       |
+  * |\ref CLKO_MODULE    |\ref CLK_CLKSEL1_CLKOSEL_HIRC          | x                       |
+  * |\ref SPI0_MODULE    |\ref CLK_CLKSEL2_SPI0SEL_HXT           | x                       |
+  * |\ref SPI0_MODULE    |\ref CLK_CLKSEL2_SPI0SEL_PLL           | x                       |
+  * |\ref SPI0_MODULE    |\ref CLK_CLKSEL2_SPI0SEL_PCLK0         | x                       |
+  * |\ref SPI0_MODULE    |\ref CLK_CLKSEL2_SPI0SEL_HIRC          | x                       |
+  * |\ref SPI1_MODULE    |\ref CLK_CLKSEL2_SPI1SEL_HXT           | x                       |
+  * |\ref SPI1_MODULE    |\ref CLK_CLKSEL2_SPI1SEL_PLL           | x                       |
+  * |\ref SPI1_MODULE    |\ref CLK_CLKSEL2_SPI1SEL_PCLK1         | x                       |
+  * |\ref SPI1_MODULE    |\ref CLK_CLKSEL2_SPI1SEL_HIRC          | x                       |
+  * |\ref SPI2_MODULE    |\ref CLK_CLKSEL2_SPI2SEL_HXT           | x                       |
+  * |\ref SPI2_MODULE    |\ref CLK_CLKSEL2_SPI2SEL_PLL           | x                       |
+  * |\ref SPI2_MODULE    |\ref CLK_CLKSEL2_SPI2SEL_PCLK0         | x                       |
+  * |\ref SPI2_MODULE    |\ref CLK_CLKSEL2_SPI2SEL_HIRC          | x                       |
+  * |\ref UART0_MODULE   |\ref CLK_CLKSEL1_UARTSEL_HXT           |\ref CLK_CLKDIV0_UART(x) |
+  * |\ref UART0_MODULE   |\ref CLK_CLKSEL1_UARTSEL_PLL           |\ref CLK_CLKDIV0_UART(x) |
+  * |\ref UART0_MODULE   |\ref CLK_CLKSEL1_UARTSEL_LXT           |\ref CLK_CLKDIV0_UART(x) |
+  * |\ref UART0_MODULE   |\ref CLK_CLKSEL1_UARTSEL_HIRC          |\ref CLK_CLKDIV0_UART(x) |
+  * |\ref UART1_MODULE   |\ref CLK_CLKSEL1_UARTSEL_HXT           |\ref CLK_CLKDIV0_UART(x) |
+  * |\ref UART1_MODULE   |\ref CLK_CLKSEL1_UARTSEL_PLL           |\ref CLK_CLKDIV0_UART(x) |
+  * |\ref UART1_MODULE   |\ref CLK_CLKSEL1_UARTSEL_LXT           |\ref CLK_CLKDIV0_UART(x) |
+  * |\ref UART1_MODULE   |\ref CLK_CLKSEL1_UARTSEL_HIRC          |\ref CLK_CLKDIV0_UART(x) |
+  * |\ref UART2_MODULE   |\ref CLK_CLKSEL1_UARTSEL_HXT           |\ref CLK_CLKDIV0_UART(x) |
+  * |\ref UART2_MODULE   |\ref CLK_CLKSEL1_UARTSEL_PLL           |\ref CLK_CLKDIV0_UART(x) |
+  * |\ref UART2_MODULE   |\ref CLK_CLKSEL1_UARTSEL_LXT           |\ref CLK_CLKDIV0_UART(x) |
+  * |\ref UART2_MODULE   |\ref CLK_CLKSEL1_UARTSEL_HIRC          |\ref CLK_CLKDIV0_UART(x) |
+  * |\ref UART3_MODULE   |\ref CLK_CLKSEL1_UARTSEL_HXT           |\ref CLK_CLKDIV0_UART(x) |
+  * |\ref UART3_MODULE   |\ref CLK_CLKSEL1_UARTSEL_LXT           |\ref CLK_CLKDIV0_UART(x) |
+  * |\ref UART3_MODULE   |\ref CLK_CLKSEL1_UARTSEL_PLL           |\ref CLK_CLKDIV0_UART(x) |
+  * |\ref UART3_MODULE   |\ref CLK_CLKSEL1_UARTSEL_HIRC          |\ref CLK_CLKDIV0_UART(x) |
+  * |\ref USBH_MODULE    | x                                     |\ref CLK_CLKDIV0_USB(x)  |
+  * |\ref USBD_MODULE    | x                                     |\ref CLK_CLKDIV0_USB(x)  |
+  * |\ref OTG_MODULE     | x                                     |\ref CLK_CLKDIV0_USB(x)  |
+  * |\ref EADC_MODULE    | x                                     |\ref CLK_CLKDIV0_EADC(x) |
+  * |\ref SC0_MODULE     |\ref CLK_CLKSEL3_SC0SEL_HXT            |\ref CLK_CLKDIV1_SC0(x)  |
+  * |\ref SC0_MODULE     |\ref CLK_CLKSEL3_SC0SEL_PLL            |\ref CLK_CLKDIV1_SC0(x)  |
+  * |\ref SC0_MODULE     |\ref CLK_CLKSEL3_SC0SEL_PCLK0          |\ref CLK_CLKDIV1_SC0(x)  |
+  * |\ref SC0_MODULE     |\ref CLK_CLKSEL3_SC0SEL_HIRC           |\ref CLK_CLKDIV1_SC0(x)  |
+  * |\ref PWM0_MODULE    |\ref CLK_CLKSEL2_PWM0SEL_PLL           | x                       |
+  * |\ref PWM0_MODULE    |\ref CLK_CLKSEL2_PWM0SEL_PCLK0         | x                       |
+  * |\ref PWM1_MODULE    |\ref CLK_CLKSEL2_PWM1SEL_PLL           | x                       |
+  * |\ref PWM1_MODULE    |\ref CLK_CLKSEL2_PWM1SEL_PCLK1         | x                       |
+  * |\ref WWDT_MODULE    |\ref CLK_CLKSEL1_WWDTSEL_PCLK0_DIV2048 | x                       |
+  * |\ref WWDT_MODULE    |\ref CLK_CLKSEL1_WWDTSEL_LIRC          | x                       |
+  */
+void CLK_SetModuleClock(uint32_t u32ModuleIdx, uint32_t u32ClkSrc, uint32_t u32ClkDiv)
+{
+    uint32_t u32sel = 0, u32div = 0;
+
+    if(MODULE_CLKDIV_Msk(u32ModuleIdx) != MODULE_NoMsk)
+    {
+        /* Get clock divider control register address */
+        u32div = (uint32_t)&CLK->CLKDIV0 + ((MODULE_CLKDIV(u32ModuleIdx)) * 4);
+        /* Apply new divider */
+        M32(u32div) = (M32(u32div) & (~(MODULE_CLKDIV_Msk(u32ModuleIdx) << MODULE_CLKDIV_Pos(u32ModuleIdx)))) | u32ClkDiv;
+    }
+
+    if(MODULE_CLKSEL_Msk(u32ModuleIdx) != MODULE_NoMsk)
+    {
+        /* Get clock select control register address */
+        u32sel = (uint32_t)&CLK->CLKSEL0 + ((MODULE_CLKSEL(u32ModuleIdx)) * 4);
+        /* Set new clock selection setting */
+        M32(u32sel) = (M32(u32sel) & (~(MODULE_CLKSEL_Msk(u32ModuleIdx) << MODULE_CLKSEL_Pos(u32ModuleIdx)))) | u32ClkSrc;
+    }
+}
+
+
+/**
+  * @brief      Set SysTick clock source
+  * @param[in]  u32ClkSrc is module clock source. Including:
+  *             - \ref CLK_CLKSEL0_STCLKSEL_HXT
+  *             - \ref CLK_CLKSEL0_STCLKSEL_LXT
+  *             - \ref CLK_CLKSEL0_STCLKSEL_HXT_DIV2
+  *             - \ref CLK_CLKSEL0_STCLKSEL_HCLK_DIV2
+  *             - \ref CLK_CLKSEL0_STCLKSEL_HIRC_DIV2
+  * @return     None
+  * @details    This function set SysTick clock source. \n
+  *             The register write-protection function should be disabled before using this function.
+  */
+void CLK_SetSysTickClockSrc(uint32_t u32ClkSrc)
+{
+    CLK->CLKSEL0 = (CLK->CLKSEL0 & ~CLK_CLKSEL0_STCLKSEL_Msk) | u32ClkSrc;
+
+}
+
+/**
+  * @brief      Enable clock source
+  * @param[in]  u32ClkMask is clock source mask. Including :
+  *             - \ref CLK_PWRCTL_HXTEN_Msk
+  *             - \ref CLK_PWRCTL_LXTEN_Msk
+  *             - \ref CLK_PWRCTL_HIRCEN_Msk
+  *             - \ref CLK_PWRCTL_LIRCEN_Msk
+  * @return     None
+  * @details    This function enable clock source. \n
+  *             The register write-protection function should be disabled before using this function.
+  */
+void CLK_EnableXtalRC(uint32_t u32ClkMask)
+{
+    CLK->PWRCTL |= u32ClkMask;
+}
+
+/**
+  * @brief      Disable clock source
+  * @param[in]  u32ClkMask is clock source mask. Including :
+  *             - \ref CLK_PWRCTL_HXTEN_Msk
+  *             - \ref CLK_PWRCTL_LXTEN_Msk
+  *             - \ref CLK_PWRCTL_HIRCEN_Msk
+  *             - \ref CLK_PWRCTL_LIRCEN_Msk
+  * @return     None
+  * @details    This function disable clock source. \n
+  *             The register write-protection function should be disabled before using this function.
+  */
+void CLK_DisableXtalRC(uint32_t u32ClkMask)
+{
+    CLK->PWRCTL &= ~u32ClkMask;
+}
+
+/**
+  * @brief      Enable module clock
+  * @param[in]  u32ModuleIdx is module index. Including :
+  *             - \ref PDMA_MODULE
+  *             - \ref ISP_MODULE
+  *             - \ref EBI_MODULE
+  *             - \ref USBH_MODULE
+  *             - \ref CRC_MODULE
+  *             - \ref WDT_MODULE
+  *             - \ref WWDT_MODULE
+  *             - \ref RTC_MODULE
+  *             - \ref TMR0_MODULE
+  *             - \ref TMR1_MODULE
+  *             - \ref TMR2_MODULE
+  *             - \ref TMR3_MODULE
+  *             - \ref CLKO_MODULE
+  *             - \ref ACMP01_MODULE
+  *             - \ref I2C0_MODULE
+  *             - \ref I2C1_MODULE
+  *             - \ref SPI0_MODULE
+  *             - \ref SPI1_MODULE
+  *             - \ref SPI2_MODULE
+  *             - \ref UART0_MODULE
+  *             - \ref UART1_MODULE
+  *             - \ref UART2_MODULE
+  *             - \ref UART3_MODULE
+  *             - \ref CAN0_MODULE
+  *             - \ref OTG_MODULE
+  *             - \ref USBD_MODULE
+  *             - \ref EADC_MODULE
+  *             - \ref SC0_MODULE
+  *             - \ref DAC_MODULE
+  *             - \ref PWM0_MODULE
+  *             - \ref PWM1_MODULE
+  *             - \ref TK_MODULE
+  * @return     None
+  * @details    This function is used to enable module clock.
+  */
+void CLK_EnableModuleClock(uint32_t u32ModuleIdx)
+{
+    *(volatile uint32_t *)((uint32_t)&CLK->AHBCLK + (MODULE_APBCLK(u32ModuleIdx) * 4))  |= 1 << MODULE_IP_EN_Pos(u32ModuleIdx);
+}
+
+/**
+  * @brief      Disable module clock
+  * @param[in]  u32ModuleIdx is module index. Including :
+  *             - \ref PDMA_MODULE
+  *             - \ref ISP_MODULE
+  *             - \ref EBI_MODULE
+  *             - \ref USBH_MODULE
+  *             - \ref CRC_MODULE
+  *             - \ref WDT_MODULE
+  *             - \ref WWDT_MODULE
+  *             - \ref RTC_MODULE
+  *             - \ref TMR0_MODULE
+  *             - \ref TMR1_MODULE
+  *             - \ref TMR2_MODULE
+  *             - \ref TMR3_MODULE
+  *             - \ref CLKO_MODULE
+  *             - \ref ACMP01_MODULE
+  *             - \ref I2C0_MODULE
+  *             - \ref I2C1_MODULE
+  *             - \ref SPI0_MODULE
+  *             - \ref SPI1_MODULE
+  *             - \ref SPI2_MODULE
+  *             - \ref UART0_MODULE
+  *             - \ref UART1_MODULE
+  *             - \ref UART2_MODULE
+  *             - \ref UART3_MODULE
+  *             - \ref CAN0_MODULE
+  *             - \ref OTG_MODULE
+  *             - \ref USBD_MODULE
+  *             - \ref EADC_MODULE
+  *             - \ref SC0_MODULE
+  *             - \ref DAC_MODULE
+  *             - \ref PWM0_MODULE
+  *             - \ref PWM1_MODULE
+  *             - \ref TK_MODULE
+  * @return     None
+  * @details    This function is used to disable module clock.
+  */
+void CLK_DisableModuleClock(uint32_t u32ModuleIdx)
+{
+    *(volatile uint32_t *)((uint32_t)&CLK->AHBCLK + (MODULE_APBCLK(u32ModuleIdx) * 4))  &= ~(1 << MODULE_IP_EN_Pos(u32ModuleIdx));
+}
+
+
+/**
+  * @brief      Set PLL frequency
+  * @param[in]  u32PllClkSrc is PLL clock source. Including :
+  *             - \ref CLK_PLLCTL_PLLSRC_HXT
+  *             - \ref CLK_PLLCTL_PLLSRC_HIRC
+  * @param[in]  u32PllFreq is PLL frequency.
+  * @return     PLL frequency
+  * @details    This function is used to configure PLLCTL register to set specified PLL frequency. \n
+  *             The register write-protection function should be disabled before using this function.
+  */
+uint32_t CLK_EnablePLL(uint32_t u32PllClkSrc, uint32_t u32PllFreq)
+{
+    uint32_t u32PllSrcClk, u32NR, u32NF, u32NO, u32CLK_SRC;
+    uint32_t u32Tmp, u32Tmp2, u32Tmp3, u32Min, u32MinNF, u32MinNR;
+
+    /* Disable PLL first to avoid unstable when setting PLL */
+    CLK_DisablePLL();
+
+    /* PLL source clock is from HXT */
+    if(u32PllClkSrc == CLK_PLLCTL_PLLSRC_HXT)
+    {
+        /* Enable HXT clock */
+        CLK->PWRCTL |= CLK_PWRCTL_HXTEN_Msk;
+
+        /* Wait for HXT clock ready */
+        CLK_WaitClockReady(CLK_STATUS_HXTSTB_Msk);
+
+        /* Select PLL source clock from HXT */
+        u32CLK_SRC = CLK_PLLCTL_PLLSRC_HXT;
+        u32PllSrcClk = __HXT;
+
+        /* u32NR start from 2 */
+        u32NR = 2;
+    }
+
+    /* PLL source clock is from HIRC */
+    else
+    {
+        /* Enable HIRC clock */
+        CLK->PWRCTL |= CLK_PWRCTL_HIRCEN_Msk;
+
+        /* Wait for HIRC clock ready */
+        CLK_WaitClockReady(CLK_STATUS_HIRCSTB_Msk);
+
+        /* Select PLL source clock from HIRC */
+        u32CLK_SRC = CLK_PLLCTL_PLLSRC_HIRC;
+        u32PllSrcClk = __HIRC;
+
+        /* u32NR start from 4 when FIN = 22.1184MHz to avoid calculation overflow */
+        u32NR = 4;
+    }
+
+    /* Select "NO" according to request frequency */
+    if((u32PllFreq <= FREQ_500MHZ) && (u32PllFreq > FREQ_250MHZ))
+    {
+        u32NO = 0;
+    }
+    else if((u32PllFreq <= FREQ_250MHZ) && (u32PllFreq > FREQ_125MHZ))
+    {
+        u32NO = 1;
+        u32PllFreq = u32PllFreq << 1;
+    }
+    else if((u32PllFreq <= FREQ_125MHZ) && (u32PllFreq >= FREQ_50MHZ))
+    {
+        u32NO = 3;
+        u32PllFreq = u32PllFreq << 2;
+    }
+    else
+    {
+        /* Wrong frequency request. Just return default setting. */
+        goto lexit;
+    }
+
+    /* Find best solution */
+    u32Min = (uint32_t) - 1;
+    u32MinNR = 0;
+    u32MinNF = 0;
+    for(; u32NR <= 33; u32NR++)
+    {
+        u32Tmp = u32PllSrcClk / u32NR;
+        if((u32Tmp > 1600000) && (u32Tmp < 16000000))
+        {
+            for(u32NF = 2; u32NF <= 513; u32NF++)
+            {
+                u32Tmp2 = u32Tmp * u32NF;
+                if((u32Tmp2 >= 200000000) && (u32Tmp2 <= 500000000))
+                {
+                    u32Tmp3 = (u32Tmp2 > u32PllFreq) ? u32Tmp2 - u32PllFreq : u32PllFreq - u32Tmp2;
+                    if(u32Tmp3 < u32Min)
+                    {
+                        u32Min = u32Tmp3;
+                        u32MinNR = u32NR;
+                        u32MinNF = u32NF;
+
+                        /* Break when get good results */
+                        if(u32Min == 0)
+                            break;
+                    }
+                }
+            }
+        }
+    }
+
+    /* Enable and apply new PLL setting. */
+    CLK->PLLCTL = u32CLK_SRC | (u32NO << 14) | ((u32MinNR - 2) << 9) | (u32MinNF - 2);
+
+    /* Wait for PLL clock stable */
+    CLK_WaitClockReady(CLK_STATUS_PLLSTB_Msk);
+
+    /* Return actual PLL output clock frequency */
+    return u32PllSrcClk / ((u32NO + 1) * u32MinNR) * u32MinNF;
+
+lexit:
+
+    /* Apply default PLL setting and return */
+    if(u32PllClkSrc == CLK_PLLCTL_PLLSRC_HXT)
+        CLK->PLLCTL = CLK_PLLCTL_72MHz_HXT; /* 72MHz */
+    else
+        CLK->PLLCTL = CLK_PLLCTL_72MHz_HIRC; /* 71.8848MHz */
+
+    /* Wait for PLL clock stable */
+    CLK_WaitClockReady(CLK_STATUS_PLLSTB_Msk);
+
+    return CLK_GetPLLClockFreq();
+
+}
+
+/**
+  * @brief      Disable PLL
+  * @param      None
+  * @return     None
+  * @details    This function set PLL in Power-down mode. \n
+  *             The register write-protection function should be disabled before using this function.
+  */
+void CLK_DisablePLL(void)
+{
+    CLK->PLLCTL |= CLK_PLLCTL_PD_Msk;
+}
+
+
+/**
+  * @brief      This function check selected clock source status
+  * @param[in]  u32ClkMask is selected clock source. Including :
+  *             - \ref CLK_STATUS_HXTSTB_Msk
+  *             - \ref CLK_STATUS_LXTSTB_Msk
+  *             - \ref CLK_STATUS_HIRCSTB_Msk
+  *             - \ref CLK_STATUS_LIRCSTB_Msk
+  *             - \ref CLK_STATUS_PLLSTB_Msk
+  * @retval     0  clock is not stable
+  * @retval     1  clock is stable
+  * @details    To wait for clock ready by specified clock source stable flag or timeout (~300ms)
+  */
+uint32_t CLK_WaitClockReady(uint32_t u32ClkMask)
+{    
+    int32_t i32TimeOutCnt = 2160000;
+
+    while((CLK->STATUS & u32ClkMask) != u32ClkMask)
+    {
+        if(i32TimeOutCnt-- <= 0)
+            return 0;
+    }
+
+    return 1;
+}
+
+/**
+  * @brief      Enable System Tick counter
+  * @param[in]  u32ClkSrc is System Tick clock source. Including:
+  *             - \ref CLK_CLKSEL0_STCLKSEL_HXT
+  *             - \ref CLK_CLKSEL0_STCLKSEL_LXT
+  *             - \ref CLK_CLKSEL0_STCLKSEL_HXT_DIV2
+  *             - \ref CLK_CLKSEL0_STCLKSEL_HCLK_DIV2
+  *             - \ref CLK_CLKSEL0_STCLKSEL_HIRC_DIV2
+  *             - \ref CLK_CLKSEL0_STCLKSEL_HCLK
+  * @param[in]  u32Count is System Tick reload value. It could be 0~0xFFFFFF.
+  * @return     None
+  * @details    This function set System Tick clock source, reload value, enable System Tick counter and interrupt. \n
+  *             The register write-protection function should be disabled before using this function. 
+  */
+void CLK_EnableSysTick(uint32_t u32ClkSrc, uint32_t u32Count) 
+{
+    /* Set System Tick counter disabled */
+    SysTick->CTRL = 0;    
+
+    /* Set System Tick clock source */
+    if( u32ClkSrc == CLK_CLKSEL0_STCLKSEL_HCLK )         
+        SysTick->CTRL |= SysTick_CTRL_CLKSOURCE_Msk;
+    else
+        CLK->CLKSEL0 = (CLK->CLKSEL0 & ~CLK_CLKSEL0_STCLKSEL_Msk) | u32ClkSrc; 
+
+    /* Set System Tick reload value */
+    SysTick->LOAD = u32Count;   
+    
+    /* Clear System Tick current value and counter flag */
+    SysTick->VAL = 0;           
+    
+    /* Set System Tick interrupt enabled and counter enabled */    
+    SysTick->CTRL |= SysTick_CTRL_TICKINT_Msk | SysTick_CTRL_ENABLE_Msk;       
+}
+
+/**
+  * @brief      Disable System Tick counter
+  * @param      None 
+  * @return     None
+  * @details    This function disable System Tick counter.
+  */
+void CLK_DisableSysTick(void) 
+{    
+    /* Set System Tick counter disabled */
+	SysTick->CTRL = 0;    
+}
+
+
+/*@}*/ /* end of group CLK_EXPORTED_FUNCTIONS */
+
+/*@}*/ /* end of group CLK_Driver */
+
+/*@}*/ /* end of group Standard_Driver */
+
+/*** (C) COPYRIGHT 2014~2015 Nuvoton Technology Corp. ***/