/**************************************************************************//**
 * @file     clk.c
 * @version  V1.00
 * $Revision: 5 $
 * $Date: 14/06/23 2:35p $
 * @brief    N572 CLK driver source file
 *
 * @note
 * Copyright (C) 2014 Nuvoton Technology Corp. All rights reserved.
*****************************************************************************/

#include  "N572.h"
/** @addtogroup N572_Device_Driver N572 Device Driver
  @{
*/

/** @addtogroup N572_CLK_Driver CLK Driver
  @{
*/

/** @addtogroup N572_CLK_EXPORTED_FUNCTIONS CLK Exported Functions
  @{
*/

/**
  * @brief  This function set PLL1 mode
  * @param  u32PllMode is PLL1 mode:
  *         - \ref PLL_NORMAL_MODE
  *         - \ref PLL_PWOERDOWN_MODE
  */
void CLK_SetPLL1Mode(uint32_t u32PllMode)
{
	/* F065 and F072 function */
	u32PllMode = u32PllMode<<CLK_PLLCON_PLL1PD_Pos;
	CLK->PLLCON = (CLK->PLLCON & (~CLK_PLLCON_PLL1PD_Msk)) | u32PllMode;
}

/**
  * @brief  This function set PLL2 mode
  * @param  u32PllMode is PLL2 mode:
  *         - \ref PLL_NORMAL_MODE
  *         - \ref PLL_PWOERDOWN_MODE
  */
void CLK_SetPLL2Mode(uint32_t u32PllMode)
{
	/* F065 and F072 function */
	u32PllMode = u32PllMode<<CLK_PLLCON_PLL2PD_Pos;
	CLK->PLLCON = (CLK->PLLCON & (~CLK_PLLCON_PLL2PD_Msk)) | u32PllMode;
}

/**
  * @brief  This function enable power down mode
  */
void CLK_EnablePowerDownMode(void)
{
	/* F065 and F072 function */
	uint8_t u8Lock;
	
	u8Lock = SYS_Unlock();
	CLK->PWRCTL = (CLK->PWRCTL & (~CLK_PWRCTL_PD_WAIT_CPU_Msk)) | CLK_PWRCTL_PD_WAIT_CPU_Msk;
	CLK->PWRCTL = (CLK->PWRCTL & (~CLK_PWRCTL_PWR_DOWN_Msk)) | CLK_PWRCTL_PWR_DOWN_Msk;
	SYS_Lock(u8Lock);
}

/**
  * @brief  This function disable power down mode
  */
void CLK_DisablePowerDownMode(void)
{
	/* F065 and F072 function */
	uint8_t u8Lock;
	
	u8Lock = SYS_Unlock();
	CLK->PWRCTL = CLK->PWRCTL & (~CLK_PWRCTL_PD_WAIT_CPU_Msk);
	CLK->PWRCTL = CLK->PWRCTL & (~CLK_PWRCTL_PWR_DOWN_Msk);
	SYS_Lock(u8Lock);
}

/**
  * @brief  This function clear wake up status flag
  */
void CLK_ClearWakeUpStatusFlag(void)
{
	/* F065 and F072 function */
	uint8_t u8Lock;
	
	u8Lock = SYS_Unlock();
	CLK->PWRCTL = (CLK->PWRCTL & (~CLK_PWRCTL_WINT_STS_Msk)) | CLK_PWRCTL_WINT_STS_Msk;
	SYS_Lock(u8Lock);
}

/**
  * @brief  This function enable wake up interrupt
  */
void CLK_EnableWakeUpInterrupt(void)
{
	/* F065 and F072 function */
	uint8_t u8Lock;
	
	u8Lock = SYS_Unlock();
	CLK->PWRCTL = (CLK->PWRCTL & (~CLK_PWRCTL_WINT_EN_Msk)) | CLK_PWRCTL_WINT_EN_Msk;
	SYS_Lock(u8Lock);
}

/**
  * @brief  This function disable wake up interrupt
  */
void CLK_DisableWakeUpInterrupt(void)
{
	/* F065 and F072 function */
	uint8_t u8Lock;
	
	u8Lock = SYS_Unlock();
	CLK->PWRCTL = CLK->PWRCTL & (~CLK_PWRCTL_WINT_EN_Msk);
	SYS_Lock(u8Lock);
}

/**
  * @brief  This function enable wake up delay
  */
void CLK_EnableWakeUpDelay(void)
{
	/* F065 and F072 function */
	uint8_t u8Lock;
	
	u8Lock = SYS_Unlock();
	CLK->PWRCTL = (CLK->PWRCTL & (~CLK_PWRCTL_WU_DLY_Msk)) | CLK_PWRCTL_WU_DLY_Msk;
	SYS_Lock(u8Lock);
}

/**
  * @brief  This function disable wake up delay
  */
void CLK_DisableWakeUpDelay(void)
{
	/* F065 and F072 function */
	uint8_t u8Lock;
	
	u8Lock = SYS_Unlock();
	CLK->PWRCTL = CLK->PWRCTL & (~CLK_PWRCTL_WU_DLY_Msk);
	SYS_Lock(u8Lock);
}

/**
  * @brief  This function enable LDO30 output
  */
void CLK_EnableLDO30(void)
{
	/* F065 and F072 function */
	uint8_t u8Lock;
	
	u8Lock = SYS_Unlock();
	CLK->PWRCTL = CLK->PWRCTL & (~CLK_PWRCTL_VOUTX_PD_Msk);
	SYS_Lock(u8Lock);
}

/**
  * @brief  This function disable LDO30 output
  */
void CLK_DisableLDO30(void)
{
	/* F065 and F072 function */
	uint8_t u8Lock;
	
	u8Lock = SYS_Unlock();
	CLK->PWRCTL = (CLK->PWRCTL & (~CLK_PWRCTL_VOUTX_PD_Msk)) | CLK_PWRCTL_VOUTX_PD_Msk;
	SYS_Lock(u8Lock);
}

/**
  * @brief      Get HCLK frequency  
  * @return     HCLK frequency
  * @details    This function get HCLK frequency. The frequency unit is Hz.
  */
uint32_t CLK_GetHCLKFreq(void)
{
	/* F065 and F072 function */
	SystemCoreClockUpdate();
	return SystemCoreClock;
}

#if( __CHIP_SERIES__ == __N572F065_SERIES__ )
/**
  * @brief  This function set PLL2 clock source and frequence
  * @param  u32PllClkSrc is clock source:
  *         - \ref PLL2_SRC_XTL_12M
  *         - \ref PLL2_SRC_XTL_6M
  *         - \ref PLL2_SRC_PLL1_FOUT
  * @param  u32PllFreq is clock frequence:
  *         - \ref NULL
  */
void CLK_SetPLL2(uint32_t u32PllClkSrc, uint32_t u32PllFreq)
{
	/* F065 function */
	CLK->PLLCON = (CLK->PLLCON & (~CLK_PLLCON_PLL_SRC_Msk)) | u32PllClkSrc;
}

/**
  * @brief  This function get PLL2 clock frequence
  * @return PLL2 clock frequence
  */
uint32_t CLK_GetPLL2ClockFreq(void)
{
	/* F065 function */
	return 48000000;
}

/**
  * @brief  This function enable clock source
  * @param  u32ClkMask is clock source mask:
  *         - \ref CLK_PWRCTL_XTL12M_EN_Msk
  *         - \ref CLK_PWRCTL_XTL32K_EN_Msk
  *         - \ref CLK_PWRCTL_OSC24M_EN_Msk
  * @return None
  */
void CLK_EnableXtalRC(uint32_t u32ClkMask)
{
	/* F065 function */
	uint8_t u8Lock;
	
	u8Lock = SYS_Unlock();
    CLK->PWRCTL |= u32ClkMask;
	SYS_Lock(u8Lock);
}

/**
  * @brief  This function disable clock source
  * @param  u32ClkMask is clock source mask:
  *         - \ref CLK_PWRCTL_XTL12M_EN_Msk
  *         - \ref CLK_PWRCTL_XTL32K_EN_Msk
  *         - \ref CLK_PWRCTL_OSC24M_EN_Msk
  * @return None
  */
void CLK_DisableXtalRC(uint32_t u32ClkMask)
{
	/* F065 function */
	uint8_t u8Lock;
	
	u8Lock = SYS_Unlock();
    CLK->PWRCTL &= ~u32ClkMask;
	SYS_Lock(u8Lock);
}

/**
  * @brief  This function set HCLK clock source and HCLK clock divider
  * @param  u32ClkSrc is HCLK clock source :
  *         - \ref CLK_CLKSEL0_HCLKSEL_XTL_32K
  *         - \ref CLK_CLKSEL0_HCLKSEL_XTL_12M_6M
  *         - \ref CLK_CLKSEL0_HCLKSEL_PLL1_FOUT
  *         - \ref CLK_CLKSEL0_HCLKSEL_PLL2_FOUT
  *         - \ref CLK_CLKSEL0_HCLKSEL_RC_24M
  * @param  u32ClkDiv is HCLK clock divider :
  *         - \ref CLK_CLKDIV_HCLK(x)
  * @return None
  */
void CLK_SetHCLK(uint32_t u32ClkSrc, uint32_t u32ClkDiv)
{
	/* F065 function */
	uint8_t u8Lock;
	
	u8Lock = SYS_Unlock();
	CLK->CLKSEL0 = (CLK->CLKSEL0 & ~CLK_CLKSEL0_HCLKSEL_Msk) | u32ClkSrc;
	CLK->CLKDIV = (CLK->CLKDIV & ~CLK_CLKDIV_HCLKDIV_Msk) | u32ClkDiv;
	SYS_Lock(u8Lock);
	
	SystemCoreClockUpdate();
}

/**
  * @brief  This function enable module clock
  * @param  u32ModuleIdx is module index :
  *         - \ref ISP_MODULE
  *         - \ref WDT_MODULE
  *         - \ref RTC_MODULE
  *         - \ref TMR0_MODULE
  *         - \ref TMR1_MODULE
  *         - \ref TMR2_MODULE
  *         - \ref TMRF_MODULE
  *         - \ref SPI0_MODULE
  *         - \ref SPI1_MODULE
  *         - \ref PWM_MODULE
  *         - \ref USBD_MODULE
  *         - \ref ADC_MODULE
  *         - \ref APU_MODULE
  * @return None
  */
void CLK_EnableModuleClock(uint32_t u32ModuleIdx)
{
	/* F065 function */
	uint8_t u8Lock;
	
	u8Lock = SYS_Unlock();
	*(volatile uint32_t *)((uint32_t)&CLK->AHBCLK+(MODULE_AHPBCLK(u32ModuleIdx)*4))  |= 1<<MODULE_IP_EN_Pos(u32ModuleIdx);
	SYS_Lock(u8Lock);
}

/**
  * @brief  This function disable module clock
  * @param  u32ModuleIdx is module index :
  *         - \ref ISP_MODULE
  *         - \ref WDT_MODULE
  *         - \ref RTC_MODULE
  *         - \ref TMR0_MODULE
  *         - \ref TMR1_MODULE
  *         - \ref TMR2_MODULE
  *         - \ref TMRF_MODULE
  *         - \ref SPI0_MODULE
  *         - \ref SPI1_MODULE
  *         - \ref PWM_MODULE
  *         - \ref USBD_MODULE
	*         - \ref ADC_MODULE
  *         - \ref APU_MODULE
  * @return None
  */
void CLK_DisableModuleClock(uint32_t u32ModuleIdx)
{
	/* F065 function */
	uint8_t u8Lock;
	
	u8Lock = SYS_Unlock();
	*(volatile uint32_t *)((uint32_t)&CLK->AHBCLK+(MODULE_AHPBCLK(u32ModuleIdx)*4))  &= ~(1<<MODULE_IP_EN_Pos(u32ModuleIdx));
	SYS_Lock(u8Lock);
}

/**
  * @brief  This function set selected module clock source and module clock divider
  * @param  u32ModuleIdx is module index.
  * @param  u32ClkSrc is module clock source.
  * @param  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_HCLK_DIV2048  | x                            |
  * |\ref WDT_MODULE       |\ref CLK_CLKSEL1_WDTSEL_XTL_32K       | x                            |
  * |\ref WDT_MODULE       |\ref CLK_CLKSEL1_WDTSEL_XTL_12M_6M    | x                            |
  * |\ref WDT_MODULE       |\ref CLK_CLKSEL1_WDTSEL_RC_24M        | x                            |
  * |\ref ADC_MODULE       |\ref CLK_CLKSEL1_ADCSEL_PLL2_FOUT     |\ref CLK_CLKDIV_ADC(x)        |
  * |\ref ADC_MODULE       |\ref CLK_CLKSEL1_ADCSEL_XTL_12M_6M    |\ref CLK_CLKDIV_ADC(x)        |
  * |\ref ADC_MODULE       |\ref CLK_CLKSEL1_ADCSEL_RC_24M        |\ref CLK_CLKDIV_ADC(x)        |
  * |\ref TMR0_MODULE      |\ref CLK_CLKSEL1_TMR0SEL_HCLK         | x                            |
  * |\ref TMR0_MODULE      |\ref CLK_CLKSEL1_TMR0SEL_XTL_32K      | x                            |
  * |\ref TMR0_MODULE      |\ref CLK_CLKSEL1_TMR0SEL_XTL_12M_6M   | x                            |
  * |\ref TMR0_MODULE      |\ref CLK_CLKSEL1_TMR0SEL_EXT          | x                            |
  * |\ref TMR0_MODULE      |\ref CLK_CLKSEL1_TMR0SEL_RC_24M       | x                            |
  * |\ref TMR1_MODULE      |\ref CLK_CLKSEL1_TMR1SEL_HCLK         | x                            |
  * |\ref TMR1_MODULE      |\ref CLK_CLKSEL1_TMR1SEL_XTL_32K      | x                            |
  * |\ref TMR1_MODULE      |\ref CLK_CLKSEL1_TMR1SEL_XTL_12M_6M   | x                            |
  * |\ref TMR1_MODULE      |\ref CLK_CLKSEL1_TMR1SEL_EXT          | x                            |
  * |\ref TMR1_MODULE      |\ref CLK_CLKSEL1_TMR1SEL_RC_24M       | x                            |
  * |\ref TMR2_MODULE      |\ref CLK_CLKSEL1_TMR2SEL_HCLK         | x                            |
  * |\ref TMR2_MODULE      |\ref CLK_CLKSEL1_TMR2SEL_XTL_32K      | x                            |
  * |\ref TMR2_MODULE      |\ref CLK_CLKSEL1_TMR2SEL_XTL_12M_6M   | x                            |
  * |\ref TMR2_MODULE      |\ref CLK_CLKSEL1_TMR2SEL_EXT          | x                            |
  * |\ref TMR2_MODULE      |\ref CLK_CLKSEL1_TMR2SEL_RC_24M       | x                            |
  * |\ref TMRF_MODULE      |\ref CLK_CLKSEL1_TMRFSEL_XTL_32K_DIV32         			| x                            |
  * |\ref TMRF_MODULE      |\ref CLK_CLKSEL1_TMRFSEL_XTL_32K_DIV128        			| x                            |
  * |\ref TMRF_MODULE      |\ref CLK_CLKSEL1_TMRFSEL_XTL_12M_6M_DIV16384       	| x                            |
  * |\ref TMRF_MODULE      |\ref CLK_CLKSEL1_TMRFSEL_XTL_12M_6M_DIV16384_DIV4  	| x                            |
  * |\ref TMRF_MODULE      |\ref CLK_CLKSEL1_TMRFSEL_RC_24M_DIV32768         		| x                            |
  * |\ref TMRF_MODULE      |\ref CLK_CLKSEL1_TMRFSEL_RC_24M_DIV32768_DIV4       | x                            |
  * |\ref PWM_MODULE       |\ref CLK_CLKSEL1_PWMSEL_HCLK         | x                            |
  * |\ref PWM_MODULE       |\ref CLK_CLKSEL1_PWMSEL_XTL_32K      | x                            |
  * |\ref PWM_MODULE       |\ref CLK_CLKSEL1_PWMSEL_XTL_12M_6M   | x                            |
  * |\ref PWM_MODULE       |\ref CLK_CLKSEL1_PWMSEL_RC_24M       | x                            |
  */
void CLK_SetModuleClock(uint32_t u32ModuleIdx, uint32_t u32ClkSrc, uint32_t u32ClkDiv)
{
	/* F065 function */
	uint32_t u32tmp=0,u32sel=0,u32div=0;
	uint8_t u8Lock;
	
	u8Lock = SYS_Unlock();
    
	if(MODULE_CLKDIV_Msk(u32ModuleIdx)!=MODULE_NoMsk)
	{
		u32div =(uint32_t)&CLK->CLKDIV+((MODULE_CLKDIV(u32ModuleIdx))*4);
		u32tmp = *(volatile uint32_t *)(u32div);
		u32tmp = ( u32tmp & ~(MODULE_CLKDIV_Msk(u32ModuleIdx)<<MODULE_CLKDIV_Pos(u32ModuleIdx)) ) | u32ClkDiv;
		*(volatile uint32_t *)(u32div) = u32tmp;
    }
		
	if(MODULE_CLKSEL_Msk(u32ModuleIdx)!=MODULE_NoMsk)
	{
		u32sel = (uint32_t)&CLK->CLKSEL0+((MODULE_CLKSEL(u32ModuleIdx))*4);
		u32tmp = *(volatile uint32_t *)(u32sel);
		u32tmp = ( u32tmp & ~(MODULE_CLKSEL_Msk(u32ModuleIdx)<<MODULE_CLKSEL_Pos(u32ModuleIdx)) ) | u32ClkSrc;
		*(volatile uint32_t *)(u32sel) = u32tmp;
	}
	
	SYS_Lock(u8Lock);
}
#endif

#if( __CHIP_SERIES__ == __N572F072_SERIES__ )
/**
  * @brief  This function set PLL2 clock source and frequence
  * @param  u32PllClkSrc is clock source:
  *         - \ref PLL2_SRC_RC_48M
  *         - \ref PLL2_SRC_PLL1_FOUT
  * @param  u32PllFreq is clock frequence:
  *         - \ref PLL2_30M
  *         - \ref PLL2_36M
  *         - \ref PLL2_42M
  *         - \ref PLL2_48M
  */
void CLK_SetPLL2(uint32_t u32PllClkSrc, uint32_t u32PllFreq)
{
	/* F072 function */
	CLK->PLLCON = (CLK->PLLCON & (~CLK_PLLCON_PLL2_SRC_Msk)) | u32PllClkSrc;
	
	CLK->PLLCON = (CLK->PLLCON & (~CLK_PLLCON_PLL2_FRQ_Msk)) | u32PllFreq;
}

/**
  * @brief  This function get PLL2 clock frequence
  * @return PLL2 clock frequence
  */
uint32_t CLK_GetPLL2ClockFreq(void)
{
	/* F072 function */
	switch ((CLK->PLLCON & CLK_PLLCON_PLL2_FRQ_Msk)>>CLK_PLLCON_PLL2_FRQ_Pos)
	{
		case 0x00: return 30000000;
		case 0x01: return 36000000;
		case 0x02: return 42000000;
		case 0x03: return 48000000;
	}
	return 0;
}

/**
  * @brief  This function enable clock source
  * @param  u32ClkMask is clock source mask:
  *         - \ref CLK_PWRCTL_XTL32K_EN_Msk
  *         - \ref CLK_PWRCTL_OSC48M_EN_Msk
  * @return None
  */
void CLK_EnableXtalRC(uint32_t u32ClkMask)
{
	/* F072 function */
	uint8_t u8Lock;
	
	u8Lock = SYS_Unlock();
    CLK->PWRCTL |= u32ClkMask;
	SYS_Lock(u8Lock);
}

/**
 * @brief  This function disable clock source
 * @param  u32ClkMask is clock source mask:
 *                - \ref CLK_PWRCTL_XTL32K_EN_Msk
 *                - \ref CLK_PWRCTL_OSC48M_EN_Msk
 * @return None
 */
void CLK_DisableXtalRC(uint32_t u32ClkMask)
{
	/* F072 function */
	uint8_t u8Lock;
	
	u8Lock = SYS_Unlock();
    CLK->PWRCTL &= ~u32ClkMask;
	SYS_Lock(u8Lock);
}

/**
  * @brief  This function set HCLK clock source and HCLK clock divider
  * @param  u32ClkSrc is HCLK clock source :
  *         - \ref CLK_CLKSEL0_HCLKSEL_XTL_32K
  *         - \ref CLK_CLKSEL0_HCLKSEL_PLL1_FOUT
  *         - \ref CLK_CLKSEL0_HCLKSEL_PLL2_FOUT
  *         - \ref CLK_CLKSEL0_HCLKSEL_RC_48M
  * @param  u32ClkDiv is HCLK clock divider :
  *         - \ref CLK_CLKDIV_HCLK(x)
  * @return None
  */
void CLK_SetHCLK(uint32_t u32ClkSrc, uint32_t u32ClkDiv)
{
	/* F072 function */
	uint8_t u8Lock;
	
	u8Lock = SYS_Unlock();
	CLK->CLKSEL0 = (CLK->CLKSEL0 & ~CLK_CLKSEL0_HCLKSEL_Msk) | u32ClkSrc;
	CLK->CLKDIV = (CLK->CLKDIV & ~CLK_CLKDIV_HCLKDIV_Msk) | u32ClkDiv;
	SYS_Lock(u8Lock);
	
	SystemCoreClockUpdate();
}

/**
  * @brief  This function enable module clock
  * @param  u32ModuleIdx is module index :
  *         - \ref ISP_MODULE
  *         - \ref APU_MODULE
  *         - \ref WDT_MODULE
  *         - \ref RTC_MODULE
  *         - \ref TMR0_MODULE
  *         - \ref TMR1_MODULE
  *         - \ref TMR2_MODULE
  *         - \ref TMRF_MODULE
  *         - \ref SPI0_MODULE
  *         - \ref SPI1_MODULE
  *         - \ref PWM_MODULE
  *         - \ref ADC_MODULE
  * @return None
  */
void CLK_EnableModuleClock(uint32_t u32ModuleIdx)
{
	/* F072 function */
	uint8_t u8Lock;
	
	u8Lock = SYS_Unlock();
	*(volatile uint32_t *)((uint32_t)&CLK->AHBCLK+(MODULE_AHPBCLK(u32ModuleIdx)*4))  |= 1<<MODULE_IP_EN_Pos(u32ModuleIdx);
	SYS_Lock(u8Lock);
}

/**
  * @brief  This function disable module clock
  * @param  u32ModuleIdx is module index :
  *         - \ref ISP_MODULE
  *         - \ref APU_MODULE
  *         - \ref WDT_MODULE
  *         - \ref RTC_MODULE
  *         - \ref TMR0_MODULE
  *         - \ref TMR1_MODULE
  *         - \ref TMR2_MODULE
  *         - \ref TMRF_MODULE
  *         - \ref SPI0_MODULE
  *         - \ref SPI1_MODULE
  *         - \ref PWM_MODULE
  *         - \ref ADC_MODULE
  * @return None
  */
void CLK_DisableModuleClock(uint32_t u32ModuleIdx)
{
	/* F072 function */
	uint8_t u8Lock;
	
	u8Lock = SYS_Unlock();
	*(volatile uint32_t *)((uint32_t)&CLK->AHBCLK+(MODULE_AHPBCLK(u32ModuleIdx)*4))  &= ~(1<<MODULE_IP_EN_Pos(u32ModuleIdx));
	SYS_Lock(u8Lock);
}

/**
  * @brief  This function set selected module clock source and module clock divider
  * @param  u32ModuleIdx is module index.
  * @param  u32ClkSrc is module clock source.
  * @param  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_HCLK_DIV2048  | x                            |
  * |\ref WDT_MODULE       |\ref CLK_CLKSEL1_WDTSEL_XTL_32K       | x                            |
  * |\ref WDT_MODULE       |\ref CLK_CLKSEL1_WDTSEL_PLL1_FOUT     | x                            |
  * |\ref WDT_MODULE       |\ref CLK_CLKSEL1_WDTSEL_RC_48M        | x                            |
  * |\ref ADC_MODULE       |\ref CLK_CLKSEL1_ADCSEL_PLL2_FOUT     |\ref CLK_CLKDIV_ADC(x)        |
  * |\ref ADC_MODULE       |\ref CLK_CLKSEL1_ADCSEL_HCLK          |\ref CLK_CLKDIV_ADC(x)        |
  * |\ref ADC_MODULE       |\ref CLK_CLKSEL1_ADCSEL_RC_48M        |\ref CLK_CLKDIV_ADC(x)        |
  * |\ref TMR0_MODULE      |\ref CLK_CLKSEL1_TMR0SEL_HCLK         | x                            |
  * |\ref TMR0_MODULE      |\ref CLK_CLKSEL1_TMR0SEL_XTL_32K      | x                            |
  * |\ref TMR0_MODULE      |\ref CLK_CLKSEL1_TMR0SEL_EXT          | x                            |
  * |\ref TMR0_MODULE      |\ref CLK_CLKSEL1_TMR0SEL_RC_48M       | x                            |
  * |\ref TMR1_MODULE      |\ref CLK_CLKSEL1_TMR1SEL_HCLK         | x                            |
  * |\ref TMR1_MODULE      |\ref CLK_CLKSEL1_TMR1SEL_XTL_32K      | x                            |
  * |\ref TMR1_MODULE      |\ref CLK_CLKSEL1_TMR1SEL_EXT          | x                            |
  * |\ref TMR1_MODULE      |\ref CLK_CLKSEL1_TMR1SEL_RC_48M       | x                            |
  * |\ref TMR2_MODULE      |\ref CLK_CLKSEL1_TMR2SEL_HCLK         | x                            |
  * |\ref TMR2_MODULE      |\ref CLK_CLKSEL1_TMR2SEL_XTL_32K      | x                            |
  * |\ref TMR2_MODULE      |\ref CLK_CLKSEL1_TMR2SEL_EXT          | x                            |
  * |\ref TMR2_MODULE      |\ref CLK_CLKSEL1_TMR2SEL_RC_48M       | x                            |
  * |\ref TMRF_MODULE      |\ref CLK_CLKSEL1_TMRFSEL_XTL_32K_DIV32         | x                            |
  * |\ref TMRF_MODULE      |\ref CLK_CLKSEL1_TMRFSEL_XTL_32K_DIV128        | x                            |
  * |\ref TMRF_MODULE      |\ref CLK_CLKSEL1_TMRFSEL_RC_48M_DIV65536       | x                            |
  * |\ref TMRF_MODULE      |\ref CLK_CLKSEL1_TMRFSEL_RC_48M_DIV65536_DIV4  | x                            |
  * |\ref PWM_MODULE       |\ref CLK_CLKSEL1_PWMSEL_HCLK         | x                            |
  * |\ref PWM_MODULE       |\ref CLK_CLKSEL1_PWMSEL_XTL_32K      | x                            |
  * |\ref PWM_MODULE       |\ref CLK_CLKSEL1_PWMSEL_RC_48M       | x                            |
  */
void CLK_SetModuleClock(uint32_t u32ModuleIdx, uint32_t u32ClkSrc, uint32_t u32ClkDiv)
{
	/* F072 function */
	uint32_t u32tmp=0,u32sel=0,u32div=0;
	uint8_t u8Lock;
	
	u8Lock = SYS_Unlock();
    
	if(MODULE_CLKDIV_Msk(u32ModuleIdx)!=MODULE_NoMsk)
	{
		u32div =(uint32_t)&CLK->CLKDIV+((MODULE_CLKDIV(u32ModuleIdx))*4);
		u32tmp = *(volatile uint32_t *)(u32div);
		u32tmp = ( u32tmp & ~(MODULE_CLKDIV_Msk(u32ModuleIdx)<<MODULE_CLKDIV_Pos(u32ModuleIdx)) ) | u32ClkDiv;
		*(volatile uint32_t *)(u32div) = u32tmp;
    }
		
	if(MODULE_CLKSEL_Msk(u32ModuleIdx)!=MODULE_NoMsk)
	{
		u32sel = (uint32_t)&CLK->CLKSEL0+((MODULE_CLKSEL(u32ModuleIdx))*4);
		u32tmp = *(volatile uint32_t *)(u32sel);
		u32tmp = ( u32tmp & ~(MODULE_CLKSEL_Msk(u32ModuleIdx)<<MODULE_CLKSEL_Pos(u32ModuleIdx)) ) | u32ClkSrc;
		*(volatile uint32_t *)(u32sel) = u32tmp;
	}
	SYS_Lock(u8Lock);
}

/**
  * @brief  This function set SysTick clock source
  * @param  u32ClkSrc is SysTick clock source. Including :
  *         - \ref CLK_CLKSEL0_STCLKSEL_HCLK_DIV2
  *         - \ref CLK_CLKSEL0_STCLKSEL_XTL_32K
  * @return None
  */
void CLK_SetSysTickClockSrc(uint32_t u32ClkSrc)
{
	/* F072 function */
	uint8_t u8Lock;
	
	u8Lock = SYS_Unlock();
	CLK->CLKSEL0 = (CLK->CLKSEL0 & ~CLK_CLKSEL0_STCLKSEL_Pos) | u32ClkSrc ;
	SYS_Lock(u8Lock);
}

/**
  * @brief  This function execute delay function.
  * @param  us  Delay time. The Max value is 2^24 / CPU Clock(MHz). Ex:
  *                            48MHz => 349525us
  * @return None
  * @details    Use the SysTick to generate the delay time and the UNIT is in us.
  *             The SysTick clock source is from HCLK, i.e the same as system core clock.
  */
void CLK_SysTickDelay(uint32_t us)
{
	/* F072 function */
	SysTick->LOAD = us * CyclesPerUs;
	SysTick->VAL  =  (0x00);
	SysTick->CTRL = SysTick_CTRL_CLKSOURCE_Msk | SysTick_CTRL_ENABLE_Msk;

    /* Waiting for down-count to zero */
	while((SysTick->CTRL & SysTick_CTRL_COUNTFLAG_Msk) == 0);
}
#endif

/*@}*/ /* end of group N572_CLK_EXPORTED_FUNCTIONS */

/*@}*/ /* end of group N572_CLK_Driver */

/*@}*/ /* end of group N572_Device_Driver */

/*** (C) COPYRIGHT 2014 Nuvoton Technology Corp. ***/
