
/******************************************************************************
*@file  : spl_rcc.c
*@brief : RCC SPL module driver.
******************************************************************************/

#include "acm32g103_spl_conf.h"


/******************************************************************************
*@brief : Resets the RCC clock configuration to the default reset state.
* @note   The default reset state of the clock configuration is given below:
*            - RC64M ON and used as system clock source
*            - XTH, PLL OFF
*            - AHB, APB1 and APB2 prescaler set to 1.
*            - LPTIM1 clock source: PCLK.
*            - FLTCLK clock source: 32 division of PCLK.
*            - LPUART1 clock source: RC32K.
*            - MCO1 ON, MCO1 division 80, MCO1 Output: HCLK
*            - MCO2 OFF
 *            - All interrupts disabled
* @note   This function doesn't modify the configuration of the
*            - Peripheral clocks  
*            - RC32K, XTL and RTC clocks 
*@param : None
*@return: None
******************************************************************************/
void RCC_DeInit(void)
{
    /* RC64M enable */
    RCC->RC64MCR |= RCC_RC64MCR_RC64MEN;
    while ((RCC->RC64MCR & RCC_RC64MCR_RC64MRDY) == 0);
    while ((RCC->RC64MCR & RCC_RC64MCR_RC64MRDY) == 0);

    /* RC64M as system clock */
    RCC->CCR1 = 0;
    
    /* AHB, APB1 and APB2 prescaler set to 1 */
    /* LPTIM1 clock source: PCLK */
    /* FLTCLK clock source: 32 division of PCLK */
    /* LPUART1 clock source: RC32K */
    RCC->CCR2 = 0x0000C000;
    while ((RCC->CCR2 & RCC_CCR2_DIVDONE) == 0);
    while ((RCC->CCR2 & RCC_CCR2_DIVDONE) == 0);

    RCC->RC64MCR &= ~RCC_RC64MCR_RC64MDIV;
    
    /* XTH disable */
    RCC->XTHCR = 0x0C;

    /* PLL disable */
    RCC->PLLCR = 0x08211008;

    /* Disable all interrupts */
    RCC->CIR &= ~0x00001f00;
    RCC->CIR |= 0x001f0000;
    
    /* MCO1 ON, MCO1 division 80, MCO1 Output: HCLK */
    /* MCO2 OFF */
    RCC->CIR = 0x3F8009F0;
}


/******************************************************************************
*@brief : Configures the External High Speed oscillator (XTH).
*@param   RCC_XTH: specifies the new state of the XTH.
*          This parameter can be one of the following values:
*            @arg RCC_XTH_OFF: turn OFF the XTH oscillator.
*            @arg RCC_XTH_ON: turn ON the XTH oscillator.
*            @arg RCC_XTH_BYPASS: XTH oscillator bypassed with external clock.
*@return: HAL None
******************************************************************************/
void RCC_XTHConfig(uint32_t RCC_XTH)
{
    uint32_t temp;
    
    /* Check the parameters */
    assert_param(IS_RCC_XTH(RCC_XTH));

    temp = RCC->XTHCR;
    temp &= ~(RCC_XTHCR_XTHEN | RCC_XTHCR_XTHBYP);
    
    if (RCC_XTH != RCC_XTH_OFF)
    {
        temp |= RCC_XTHCR_XTHRDYTIME_1 | RCC_XTHCR_XTHRDYTIME_0 | RCC_XTH;
    }
    RCC->XTHCR = temp;
}

/******************************************************************************
*@brief : Waits for XTH start-up.
*@param   None
*@return: An ErrorStatus enumeration value:
*          - SUCCESS: XTH oscillator is stable and ready to use
*          - ERROR: XTH oscillator not yet ready
******************************************************************************/
ErrorStatus RCC_WaitForXTHStartUp(void)
{
    __IO uint32_t timeout = 0;
    
    /* Wait till XTH is ready and if Time out is reached exit */
    while (1)
    {
        if (RCC->XTHCR & RCC_XTHCR_XTHRDY)
        {
            if (RCC->XTHCR & RCC_XTHCR_XTHRDY)
                return (SUCCESS);
        }
        
        if (timeout++ == XTH_STARTUP_TIMEOUT)
            return (ERROR);
    }
}

/******************************************************************************
*@brief : Returns the frequencies of the XTH;
*@param   None.
*@return: XTH frequency
******************************************************************************/
uint32_t RCC_GetXTHFreq(void)
{
    return XTH_VALUE;  
}

/******************************************************************************
*@brief : Configures the Internal High Speed oscillator (RC64M).
*@param   RCC_RC64M: specifies the new state of the RC64M.
*          This parameter can be one of the following values:
*            @arg RCC_RC64M_DIV1: RC64M without frequency division, 64MHz output.
*            @arg RCC_RC64M_DIV16: RC64M 16 frequency division, 4MHz output.
*@return: None
******************************************************************************/
void RCC_RC64MConfig(uint32_t RCC_RC64M_DIV)
{
    uint32_t temp;
    
    /* Check the parameters */
    assert_param(IS_RCC_RC64M_DIV(RCC_RC64M_DIV));
    
    temp = RCC->RC64MCR;
    temp &= ~(RCC_RC64MCR_RC64MDIV);
    temp |= RCC_RC64M_DIV;
    
    RCC->RC64MCR = temp;
}

/******************************************************************************
*@brief : Enables or disables the Internal High Speed oscillator (RC64M).
*@param   NewState: specifies the new state of the RC64M.
*         This parameter can be: ENABLE or DISABLE.
*@return: None
******************************************************************************/
void RCC_RC64MCmd(FunctionalState NewState)
{
    /* Check the parameters */
    assert_param(IS_RCC_FUNCTIONAL_STATE(NewState));
    
    if (NewState == DISABLE)
        RCC->RC64MCR &= ~RCC_RC64MCR_RC64MEN;
    else
        RCC->RC64MCR |= RCC_RC64MCR_RC64MEN;
}

/******************************************************************************
*@brief : Waits for RC64M start-up.
*@param   None
*@return: An ErrorStatus enumeration value:
*          - SUCCESS: RC64M oscillator is stable and ready to use
*          - ERROR: RC64M oscillator not yet ready
******************************************************************************/
ErrorStatus RCC_WaitForRC64MStartUp(void)
{
    __IO uint32_t timeout = 0;
    
    /* Wait till RC64M is ready and if Time out is reached exit */
    while (1)
    {
        if (RCC->RC64MCR & RCC_RC64MCR_RC64MRDY)
        {
            if (RCC->RC64MCR & RCC_RC64MCR_RC64MRDY)
                return (SUCCESS);
        }
        
        if (timeout++ == RC64M_STARTUP_TIMEOUT)
            return (ERROR);
    }
}

/******************************************************************************
*@brief : Returns RC64M infact value
*@return: RC64M val
******************************************************************************/
uint32_t HAL_RCC_GetRC64MValue(void)
{
    uint32_t rc64mTrim;
    uint32_t rc64mVal;
    
    rc64mTrim = *(volatile uint32_t *)EFLASH_NVR_RC64M_TRIM_ADDR;
    
    if((rc64mTrim>>16) == ((~rc64mTrim)&0xffff))
    {
        rc64mVal = *(volatile uint32_t *)EFLASH_NVR_RC64M_VAL_ADDR * 16000U;
    }
    else
    {
        rc64mVal = 64000000;
    }
    
    return rc64mVal;  
}

/******************************************************************************
*@brief : Returns the frequencies of the RC64M;
*@param   None.
*@return: RC64M frequency
******************************************************************************/
uint32_t RCC_GetRC64MFreq(void)
{
    uint32_t freq;
    
    freq = HAL_RCC_GetRC64MValue();
    if (RCC->RC64MCR & RCC_RC64MCR_RC64MDIV)
        freq = freq >> 4;
    
    return (freq);
}

/** @defgroup RCC_XTL_Drive_Capacity.
  */

/******************************************************************************
*@brief : Configures the External Low Speed oscillator (XTL).
*@param   Drive: specifies the drive capability of the XTL.
*                This parameter can be one of the following values:
*                  @arg RCC_XTL_DRIVE0: Normal power drive 0(minimum).
*                  @arg RCC_XTL_DRIVE1: Normal power drive 0.
*                  @arg RCC_XTL_DRIVE2: Normal power drive 0.
*                  @arg RCC_XTL_DRIVE3: Normal power drive 0(maximum).
*                  @arg RCC_XTL_LOWPOWER_DRIVE0: Low power drive 0(minimum).
*                  @arg RCC_XTL_LOWPOWER_DRIVE1: Low power drive 1.
*                  @arg RCC_XTL_LOWPOWER_DRIVE2: Low power drive 2.
*                  @arg RCC_XTL_LOWPOWER_DRIVE3: Low power drive 3(maximum).
*@param   BypassState: specifies the new state of the XTL Bypass.
*                      This parameter can be: ENABLE or DISABLE.
*@return: None
******************************************************************************/
void RCC_XTLConfig(uint32_t Drive, FunctionalState BypassState)
{
    uint32_t temp;
    
    temp = RCC->STDBYCTRL;
    temp &= ~(RCC_STDBYCTRL_XTLDRV_2 | RCC_STDBYCTRL_XTLDRV_1 | RCC_STDBYCTRL_XTLDRV_0 | RCC_STDBYCTRL_XTLBYP);
    if (BypassState != DISABLE)
        temp |= RCC_STDBYCTRL_XTLBYP;
    temp |= Drive;
    RCC->STDBYCTRL = temp;
}

/******************************************************************************
*@brief : Enables or disables the External Low Speed oscillator (XTL).
*@param   NewState: specifies the new state of the XTL.
*         This parameter can be: ENABLE or DISABLE.
*@return: None
******************************************************************************/
void RCC_XTLCmd(FunctionalState NewState)
{
    /* Check the parameters */
    assert_param(IS_RCC_FUNCTIONAL_STATE(NewState));
    
    if (NewState == DISABLE)
        RCC->STDBYCTRL &= ~RCC_STDBYCTRL_XTLEN;
    else
        RCC->STDBYCTRL |= RCC_STDBYCTRL_XTLEN;
}

/******************************************************************************
*@brief : Waits for XTL start-up.
*@param   None
*@return: An ErrorStatus enumeration value:
*          - SUCCESS: XTL oscillator is stable and ready to use
*          - ERROR: XTL oscillator not yet ready
******************************************************************************/
ErrorStatus RCC_WaitForXTLStartUp(void)
{
    __IO uint32_t timeout = 0;
    
    /* Wait till XTL is ready and if Time out is reached exit */
    while (1)
    {
        if (RCC->STDBYCTRL & RCC_STDBYCTRL_XTLRDY)
        {
            if (RCC->STDBYCTRL & RCC_STDBYCTRL_XTLRDY)
                return (SUCCESS);
        }
        
        if (timeout++ == XTL_STARTUP_TIMEOUT)
            return (ERROR);
    }
}

/******************************************************************************
*@brief : Returns the frequencies of the XTL;
*@param   None.
*@return: XTL frequency
******************************************************************************/
uint32_t RCC_GetXTLFreq(void)
{
    return (32678u);  
}

/******************************************************************************
*@brief : Enables or disables the Internal Low Speed oscillator (RC32K).
*@param   NewState: specifies the new state of the RC32K.
*         This parameter can be: ENABLE or DISABLE.
*@return: None
******************************************************************************/
void RCC_RC32KCmd(FunctionalState NewState)
{
    /* Check the parameters */
    assert_param(IS_RCC_FUNCTIONAL_STATE(NewState));
    
    if (NewState == DISABLE)
        RCC->STDBYCTRL &= ~RCC_STDBYCTRL_RC32EN;
    else
        RCC->STDBYCTRL |= RCC_STDBYCTRL_RC32EN;
}

/******************************************************************************
*@brief : Waits for RC32K start-up.
*@param   None
*@return: An ErrorStatus enumeration value:
*          - SUCCESS: RC32K oscillator is stable and ready to use
*          - ERROR: RC32K oscillator not yet ready
******************************************************************************/
ErrorStatus RCC_WaitForRC32KStartUp(void)
{
    __IO uint32_t timeout = 0;
    
    /* Wait till RC32K is ready and if Time out is reached exit */
    while (1)
    {
        if (RCC->STDBYCTRL & RCC_STDBYCTRL_RC32KRDY)
        {
            if (RCC->STDBYCTRL & RCC_STDBYCTRL_RC32KRDY)
                return (SUCCESS);
        }
        
        if (timeout++ == RC32K_STARTUP_TIMEOUT)
            return (ERROR);
    }
}

/******************************************************************************
*@brief : Returns the frequencies of the RC32K;
*@return: RC32K frequency
******************************************************************************/
uint32_t RCC_GetRC32KFreq(void)
{
    uint32_t rc32kTrim;
    uint32_t rc32kVal;
    
    rc32kTrim = *(volatile uint32_t *)EFLASH_NVR_RC32K_TRIM_ADDR;
    
    if((rc32kTrim>>16) == ((~rc32kTrim)&0xffff))
    {
        rc32kVal = *(volatile uint32_t *)EFLASH_NVR_RC32K_VAL_ADDR * 10U;
    }
    else
    {
        rc32kVal = 32768;
    }
    
    return rc32kVal;  
}

/******************************************************************************
*@brief : Configures the main PLL clock source, multiplication and division factors.
*@param   RCC_PLLSource: specifies the PLL entry clock source.
*         This parameter can be one of the following values:
*            @arg RCC_PLLSOURCE_RC64M_DIV16: The 16 division of RC64M is selected as PLL clock entry
*            @arg RCC_PLLSOURCE_XTH: XTH oscillator clock is selected as PLL clock entry
*@param   PLLM: Output frequency division control field.
*         This parameter must be a number between 0 and 3.
*@param   PLLN: the frequency division factor of the reference frequency.
*         This parameter must be a number between 0 and 7.
*@param   PLLF: the frequency multiplication factor of the reference frequency.
*         This parameter must be a number between 0 and 31.
*@return: None
******************************************************************************/
void RCC_PLLConfig(uint32_t RCC_PLLSource, uint32_t PLLM, uint32_t PLLN, uint32_t PLLF)
{
    uint32_t temp;
    uint32_t run_dly;
    
    /* Check the parameters */
    assert_param(IS_RCC_PLLSOURCE(RCC_PLLSource));
    assert_param(IS_RCC_PLLM(PLLM));
    assert_param(IS_RCC_PLLN(PLLN));
    assert_param(IS_RCC_PLLF(PLLF));
    
    run_dly = 0x10ul << RCC_PLLCR_PLLRUNDLY_Pos;
    temp = RCC->PLLCR;
    temp &= ~(RCC_PLLCR_PLLLOCKSEL | RCC_PLLCR_PLLSLEEP | RCC_PLLCR_PLLSRCSEL | \
              RCC_PLLCR_PLLRUNDLY | RCC_PLLCR_PLLM | RCC_PLLCR_PLLN | RCC_PLLCR_PLLF);

    temp |= RCC_PLLCR_PLLLOCKSEL | run_dly | RCC_PLLSource | (PLLM << RCC_PLLCR_PLLM_Pos) | (PLLN << RCC_PLLCR_PLLN_Pos) | (PLLF << RCC_PLLCR_PLLF_Pos);
    RCC->PLLCR = temp;
}

/******************************************************************************
*@brief : Enables or disables the PLL.
*@param   NewState: specifies the new state of the PLL.
*         This parameter can be: ENABLE or DISABLE.
*@return: None
******************************************************************************/
void RCC_PLLCmd(FunctionalState NewState)
{
    /* Check the parameters */
    assert_param(IS_RCC_FUNCTIONAL_STATE(NewState));
    
    if (NewState == DISABLE)
    {
        RCC->PLLCR &= ~RCC_PLLCR_PLLEN;
        RCC->PLLCR |= RCC_PLLCR_PLLSLEEP;
    }
    else
    {
        RCC->PLLCR |= RCC_PLLCR_PLLEN;
        RCC->PLLCR &= ~RCC_PLLCR_PLLSLEEP;
    }
}

/******************************************************************************
*@brief : Enables or disables the PLL Update.
*@param   NewState: specifies the new state of the PLL Update.
*         This parameter can be: ENABLE or DISABLE.
*@return: None
******************************************************************************/
void RCC_PLLUpdateCmd(FunctionalState NewState)
{
    /* Check the parameters */
    assert_param(IS_RCC_FUNCTIONAL_STATE(NewState));
    
    if (NewState != DISABLE)
    {
        RCC->PLLCR |= RCC_PLLCR_PLLUPDATEEN;
    }
}

/******************************************************************************
*@brief : Waits for PLL start-up.
*@param   None
*@return: An ErrorStatus enumeration value:
*          - SUCCESS: PLL is stable and ready to use
*          - ERROR: PLL not yet ready
******************************************************************************/
ErrorStatus RCC_WaitForPLLStartUp(void)
{
    __IO uint32_t timeout = 0;
    
    /* Wait till PLL is ready and if Time out is reached exit */
    while (1)
    {
        if (RCC->PLLCR & RCC_PLLCR_PLLFREERUN)
        {
            if (RCC->PLLCR & RCC_PLLCR_PLLFREERUN)
                return (SUCCESS);
        }
        
        if (timeout++ == PLL_STARTUP_TIMEOUT)
            return (ERROR);
    }
}

/******************************************************************************
*@brief : Returns the frequencies of the PLL;
*@return: PLL frequency
******************************************************************************/
uint32_t RCC_GetPLLFreq(void)
{
    uint32_t freq;
    uint32_t pllm;
    uint32_t plln;
    uint32_t pllf;
    
    /* check PLL clock source */
    if (RCC->PLLCR & RCC_PLLCR_PLLSRCSEL_1)
        freq = RCC_GetXTHFreq();
    else
        freq = RCC_GetRC64MFreq();
    
    pllm = (RCC->PLLCR & RCC_PLLCR_PLLM_Msk) >> RCC_PLLCR_PLLM_Pos;
    plln = (RCC->PLLCR & RCC_PLLCR_PLLN_Msk) >> RCC_PLLCR_PLLN_Pos;
    pllf = (RCC->PLLCR & RCC_PLLCR_PLLF_Msk) >> RCC_PLLCR_PLLF_Pos;
    
    freq = freq * (pllf + 15) / (plln + 1);
    freq = freq >> pllm;
    
    return (freq);
}

/******************************************************************************
*@brief : Configures the system clock (SYSCLK).
*@param   RCC_SYSCLKSource: specifies the clock source used as system clock.
*          This parameter can be one of the following values:
*            @arg RCC_SYSCLKSOURCE_RC64M: 
*            @arg RCC_SYSCLKSOURCE_RC32K: 
*            @arg RCC_SYSCLKSOURCE_XTH: 
*            @arg RCC_SYSCLKSOURCE_XTL: 
*            @arg RCC_SYSCLKSOURCE_PLLCLK: 
*@return: None
******************************************************************************/
void RCC_SYSCLKConfig(uint32_t RCC_SYSCLKSource)
{
    uint32_t temp;

    /* Check the parameters */
    assert_param(IS_RCC_SYSCLK_SOURCE(RCC_SYSCLKSource));

    EFLASH_SET_RDWAIT(EFLASH_RDWAIT_ENSURE_OK);
    
    temp = RCC->CCR1;

    temp &= ~RCC_CCR1_SYSCLKSEL;

    temp |= RCC_SYSCLKSource;

    RCC->CCR1 = temp;
    
}

/******************************************************************************
*@brief : Returns the clock source used as system clock.
*@param   None
*@return: The clock source used as system clock.
*          This parameter can be one of the following values:
*            - RCC_SYSCLKSOURCE_RC64M: 
*            - RCC_SYSCLKSOURCE_RC32K: 
*            - RCC_SYSCLKSOURCE_XTH: 
*            - RCC_SYSCLKSOURCE_XTL: 
*            - RCC_SYSCLKSOURCE_PLLCLK: 
******************************************************************************/
uint32_t RCC_GetSYSCLKSource(void)
{
  return ((uint32_t)(RCC->CCR1 & RCC_CCR1_SYSCLKSEL));
}

/******************************************************************************
*@brief : Configures the AHB clock (HCLK).
*@param : RCC_SYSDiv0: defines the system clock divider0.  
*         This clock is derived from the system clock (SYSCLK).
*          This parameter can be one of the following values:
*            @arg RCC_SYSDIV0_DIV_1: 
*            @arg RCC_SYSDIV0_DIV_2: 
*            @arg RCC_SYSDIV0_DIV_3: 
*            @arg RCC_SYSDIV0_DIV_4: 
*            @arg RCC_SYSDIV0_DIV_5: 
*            @arg RCC_SYSDIV0_DIV_6: 
*            @arg RCC_SYSDIV0_DIV_7: 
*            @arg RCC_SYSDIV0_DIV_8: 
*            @arg RCC_SYSDIV0_DIV_9: 
*            @arg RCC_SYSDIV0_DIV_10: 
*            @arg RCC_SYSDIV0_DIV_11: 
*            @arg RCC_SYSDIV0_DIV_12: 
*            @arg RCC_SYSDIV0_DIV_13: 
*            @arg RCC_SYSDIV0_DIV_14: 
*            @arg RCC_SYSDIV0_DIV_15: 
*            @arg RCC_SYSDIV0_DIV_16: 
*@param : RCC_SYSDiv1: defines the system clock divider1.  
*         This clock is derived from the system clock divider0.
*          This parameter can be one of the following values:
*            @arg RCC_SYSDIV1_DIV_1: 
*            @arg RCC_SYSDIV1_DIV_2: 
*            @arg RCC_SYSDIV1_DIV_3: 
*            @arg RCC_SYSDIV1_DIV_4: 
*            @arg RCC_SYSDIV1_DIV_5: 
*            @arg RCC_SYSDIV1_DIV_6: 
*            @arg RCC_SYSDIV1_DIV_7: 
*            @arg RCC_SYSDIV1_DIV_8: 
*            @arg RCC_SYSDIV1_DIV_9: 
*            @arg RCC_SYSDIV1_DIV_10: 
*            @arg RCC_SYSDIV1_DIV_11: 
*            @arg RCC_SYSDIV1_DIV_12: 
*            @arg RCC_SYSDIV1_DIV_13: 
*            @arg RCC_SYSDIV1_DIV_14: 
*            @arg RCC_SYSDIV1_DIV_15: 
*            @arg RCC_SYSDIV1_DIV_16: 
*@return: None
******************************************************************************/
void RCC_HCLKConfig(uint32_t RCC_SYSDvi0, uint32_t RCC_SYSDvi1)
{
    uint32_t temp;

    /* Check the parameters */
    assert_param(IS_RCC_SYSCLK_DIV0(RCC_SYSDvi0));
    assert_param(IS_RCC_SYSCLK_DIV1(RCC_SYSDvi1));

    temp = RCC->CCR2;
    temp &= ~(RCC_CCR2_SYSDIV0 );
    temp |= RCC_SYSDvi0;
    RCC->CCR2 = temp;
    while ((RCC->CCR2 & RCC_CCR2_DIVDONE) == 0);
    while ((RCC->CCR2 & RCC_CCR2_DIVDONE) == 0);
    
    temp = RCC->CCR2;
    temp &= ~(RCC_CCR2_SYSDIV1);
    temp |= RCC_SYSDvi1;
    RCC->CCR2 = temp;
    while ((RCC->CCR2 & RCC_CCR2_DIVDONE) == 0);
    while ((RCC->CCR2 & RCC_CCR2_DIVDONE) == 0);
    
    
    EFLASH_SetRdwaitBySysCoreClock(RCC_GetHCLKFreq());
}

/******************************************************************************
*@brief : Configures the Low Speed APB1 clock (PCLK1).
*@param : RCC_PCLK1Div: defines the APB1 clock divider.  
*         This clock is derived from the AHB clock (HCLK).
*          This parameter can be one of the following values:
*            @arg RCC_PCLK1_DIV_1: 
*            @arg RCC_PCLK1_DIV_2: 
*            @arg RCC_PCLK1_DIV_4: 
*            @arg RCC_PCLK1_DIV_8: 
*            @arg RCC_PCLK1_DIV_16: 
*@return: None
******************************************************************************/
void RCC_PCLK1Config(uint32_t RCC_PCLK1Div)
{
    uint32_t temp;

    /* Check the parameters */
    assert_param(IS_RCC_PCLK1_DIV(RCC_PCLK1Div));

    temp = RCC->CCR2;
    temp &= ~RCC_CCR2_PCLK1DIV;
    temp |= RCC_PCLK1Div;
    RCC->CCR2 = temp;
}

/******************************************************************************
*@brief : Configures the Low Speed APB2 clock (PCLK2).
*@param : RCC_PCLK1Div: defines the APB2 clock divider.  
*         This clock is derived from the AHB clock (HCLK).
*          This parameter can be one of the following values:
*            @arg RCC_PCLK2_DIV_1: 
*            @arg RCC_PCLK2_DIV_2: 
*            @arg RCC_PCLK2_DIV_4: 
*            @arg RCC_PCLK2_DIV_8: 
*            @arg RCC_PCLK2_DIV_16: 
*@return: None
******************************************************************************/
void RCC_PCLK2Config(uint32_t RCC_PCLK2Div)
{
    uint32_t temp;

    /* Check the parameters */
    assert_param(IS_RCC_PCLK2_DIV(RCC_PCLK2Div));

    temp = RCC->CCR2;
    temp &= ~RCC_CCR2_PCLK2DIV;
    temp |= RCC_PCLK2Div;
    RCC->CCR2 = temp;
}

/******************************************************************************
*@brief : Returns the frequencies of the SYSCLK.
*@param : None
*@return: SYSCLK frequency.
******************************************************************************/
uint32_t RCC_GetSYSCLKFreq(void)
{
    uint32_t temp;
    uint32_t freq;
    
    /* check system clock source */
    temp = RCC->CCR1 & RCC_CCR1_SYSCLKSEL_Msk;
    switch (temp)
    {
        case RCC_SYSCLKSOURCE_RC64M :       /* system clock source : RC64M */
            
            freq = RCC_GetRC64MFreq();
            break;
            
        case RCC_SYSCLKSOURCE_RC32K :       /* system clock source : RC32K */
		
            freq = RCC_GetRC32KFreq();
            break;
            
        case RCC_SYSCLKSOURCE_XTH :         /* system clock source : XTH */
            
            freq = RCC_GetXTHFreq();
            break;
            
        case RCC_SYSCLKSOURCE_XTL :         /* system clock source : XTL */
            
            freq = RCC_GetXTLFreq();
            break;
            
        case RCC_SYSCLKSOURCE_PLLCLK :      /* system clock source : PLLCLK */
        default :                           /* system clock source : PLLCLK */
            
            freq = RCC_GetPLLFreq();
            break;
    }
    
    return (freq);
}


/******************************************************************************
*@brief : Returns the frequencies of the HCLK.
*@param : None
*@return: HCLK frequency.
******************************************************************************/
uint32_t RCC_GetHCLKFreq(void)
{
    uint32_t temp;
    uint32_t freq;
    
    freq = RCC_GetSYSCLKFreq();
    
    temp = ((RCC->CCR2 & RCC_CCR2_SYSDIV0_Msk) >> RCC_CCR2_SYSDIV0_Pos) + 1;
    temp = temp * (((RCC->CCR2 & RCC_CCR2_SYSDIV1_Msk) >> RCC_CCR2_SYSDIV1_Pos) + 1);
    freq = freq / temp;
    
    return (freq);
}

/******************************************************************************
*@brief : Returns the frequencies of the PCLK1.
*@param : None.
*@return: PCLK1 frequency.
******************************************************************************/
uint32_t RCC_GetPCLK1Freq(void)
{
    uint32_t temp;
    uint32_t freq;
    
    freq = RCC_GetHCLKFreq();
    
    temp = RCC->CCR2 & RCC_CCR2_PCLK1DIV_Msk;
    switch (temp)
    {
        case RCC_PCLK1_DIV_1 : 
            break;
        case RCC_PCLK1_DIV_2 : 
            freq = freq >> 1;
            break;
        case RCC_PCLK1_DIV_4 : 
            freq = freq >> 2;
            break;
        case RCC_PCLK1_DIV_8 : 
            freq = freq >> 3;
            break;
        case RCC_PCLK1_DIV_16 :
            freq = freq >> 4;
            break;
        default :
            break;
    }
    
    return (freq);
}

/******************************************************************************
*@brief : Returns the frequencies of the PCLK2.
*@param : None.
*@return: PCLK2 frequency.
******************************************************************************/
uint32_t RCC_GetPCLK2Freq(void)
{
    uint32_t temp;
    uint32_t freq;
    
    freq = RCC_GetHCLKFreq();
    
    temp = RCC->CCR2 & RCC_CCR2_PCLK2DIV_Msk;
    switch (temp)
    {
        case RCC_PCLK2_DIV_1 : 
            break;
        case RCC_PCLK2_DIV_2 : 
            freq = freq >> 1;
            break;
        case RCC_PCLK2_DIV_4 : 
            freq = freq >> 2;
            break;
        case RCC_PCLK2_DIV_8 : 
            freq = freq >> 3;
            break;
        case RCC_PCLK2_DIV_16 : 
            freq = freq >> 4;
            break;
        default :
            break;
    }
    
    return (freq);
}

/******************************************************************************
*@brief : Returns the frequencies of different on chip clocks;
*         SYSCLK, HCLK, PCLK1 and PCLK2.
*@param : RCC_Clocks: pointer to a RCC_ClocksTypeDef structure which will 
*          hold the clocks frequencies.
*@return: None
******************************************************************************/
void RCC_GetClocksFreq(RCC_ClocksTypeDef* RCC_Clocks)
{
    RCC_Clocks->SYSCLK_Frequency = RCC_GetSYSCLKFreq();
    RCC_Clocks->HCLK_Frequency = RCC_GetHCLKFreq();
    RCC_Clocks->PCLK1_Frequency = RCC_GetPCLK1Freq();
    RCC_Clocks->PCLK2_Frequency = RCC_GetPCLK2Freq();
}

/******************************************************************************
*@brief : Configure LPTIM1 clock (LPTIM1CLK).
*@param : ClockSource: LPTIM1 clock source.
*         This parameter must be a value of @ref RCC_LPTIM1_CLK_Source.
*             @arg RCC_LPTIM1CLKSOURCE_PCLK: PCLK clock selected as PLTIM1 source
*             @arg RCC_LPTIM1CLKSOURCE_RC32K: RC32K clock selected as PLTIM1 source
*             @arg RCC_LPTIM1CLKSOURCE_RC64M: RC64M clock selected as PLTIM1 source
*             @arg RCC_LPTIM1CLKSOURCE_XTL: XTL clock selected as PLTIM1 source
*@return: None
******************************************************************************/
void RCC_LPTIM1CLKConfig(uint32_t RCC_LPTIM1CLKSource)
{
    uint32_t temp;
    
    /* Check the parameters */
    assert_param(IS_RCC_LPTIM1_CLKSOURCE(RCC_LPTIM1CLKSource));
    
    /* LPTIM1 clok source configuration */
    temp = RCC->CCR2;
    temp &= ~RCC_CCR2_LPTIM1CLKSEL_Msk;
    temp |= RCC_LPTIM1CLKSource;
    RCC->CCR2 = temp;
}

/******************************************************************************
*@brief : Returns the LPTIM1 clock frequency
*@return: LPTIM1 clock frequency
******************************************************************************/
uint32_t RCC_GetLPTIM1CLKFreq(void)
{
//    uint32_t div;
    uint32_t source;
    uint32_t freq;
    
    /* check LPTIM1 clock source */
    source = RCC->CCR2 & RCC_CCR2_LPTIM1CLKSEL;
    switch (source)
    {
        case RCC_LPTIM1CLKSOURCE_PCLK :             /* LPTIM1 clock source : PCLK */
            
            freq = RCC_GetPCLK1Freq();
            break;
        
        case RCC_LPTIM1CLKSOURCE_RC32K :            /* LPTIM1 clock source : RC32K */
            
            freq = RCC_GetRC32KFreq();
            break;
        
        case RCC_LPTIM1CLKSOURCE_RC64M :            /* LPTIM1 clock source : RC64M */
            
            freq = RCC_GetRC64MFreq();
            break;
            
        case RCC_LPTIM1CLKSOURCE_XTL :              /* LPTIM1 clock source : XTL */
            
            freq = RCC_GetXTLFreq();
            break;
        
        default :
            
            freq = 0U;
            break;
    }
    
    return (freq);
}

/******************************************************************************
*@brief : Configure FLTCLK (LVD and COMP) clock source.
*@param : ClockSource: LVD and COMP clock source.
*         This parameter must be a value of @ref RCC_FLT_CLK_Source.
*             @arg RCC_FLTCLKSOURCE_PCLK_DIV32: clock after pclk 32 frequency division selected as FLTCLK source
*             @arg RCC_FLTCLKSOURCE_RC32K: RC32K clock selected as FLTCLK source
*@return: HAL status
******************************************************************************/
void RCC_FLTCLKConfig(uint32_t ClockSource)
{
    uint32_t temp;
    
    /* Check the parameters */
    assert_param(IS_RCC_FLTCLK_CLKSOURCE(ClockSource));
    
    /* FLTCLK clok source configuration */
    temp = RCC->CCR2;
    temp &= ~RCC_CCR2_FLTCLKSEL_Msk;
    temp |= ClockSource;
    RCC->CCR2 = temp;
}

/******************************************************************************
*@brief : Returns the FLTCLK clock frequency
*@return: FLTCLK frequency
******************************************************************************/
uint32_t RCC_GetFLTCLKFreq(void)
{
    uint32_t source;
    uint32_t freq;
    
    /* check FLTCLK clock source */
    source = RCC->CCR2 & RCC_CCR2_FLTCLKSEL_Msk;
    switch (source)
    {
        case RCC_FLTCLKSOURCE_PCLK_DIV32 :          /* LPTIM1 clock source : PCLK 32 frequency division */
            
            freq = RCC_GetPCLK1Freq();
            freq = freq >> 5;
            break;
        
        case RCC_FLTCLKSOURCE_RC32K :               /* LPTIM1 clock source : RC32K */
            
            freq = RCC_GetRC32KFreq();
            break;
        
        default :
            
            freq = 0U;
            break;
    }
    
    return (freq);
}

/******************************************************************************
*@brief : Configure LPUART1 clock source.
*@param : ClockSource: LPUART1 clock source.
*         This parameter must be a value of @ref RCC_LPUART1_CLK_Source.
*             @arg RCC_LPUART1CLKSOURCE_RC32K: RC32K clock selected as LPUART1 source
*             @arg RCC_LPUART1CLKSOURCE_XTL: XTL clock selected as LPUART1 source
*             @arg RCC_LPUART1CLKSOURCE_PCLK_DIV4: clock after pclk 4 frequency division selected as LPUART1 source
*             @arg RCC_LPUART1CLKSOURCE_PCLK_DIV8: clock after pclk 8 frequency division selected as LPUART1 source
*             @arg RCC_LPUART1CLKSOURCE_PCLK_DIV16: clock after pclk 16 frequency division selected as LPUART1 source
*             @arg RCC_LPUART1CLKSOURCE_PCLK_DIV32: clock after pclk 32 frequency division selected as LPUART1 source
*@return: None
******************************************************************************/
void RCC_LPUART1CLKConfig(uint32_t ClockSource)
{
    uint32_t temp;
//    uint32_t timeout;
    
    /* Check the parameters */
    assert_param(IS_RCC_LPUART1_CLKSOURCE(ClockSource));
    
    /* LPUART1 clok source configuration */
    temp = RCC->CCR2;
    temp &= ~(RCC_CCR2_LPUART1CLKSEL_Msk | RCC_CCR2_LPUART1DIV_Msk);
    temp |= ClockSource;
    RCC->CCR2 = temp;
}

/******************************************************************************
*@brief : Returns the LPUART1 clock frequency
*@return: LPUART1 frequency
******************************************************************************/
uint32_t RCC_GetLPUART1CLKFreq(void)
{
    uint32_t source;
    uint32_t div;
    uint32_t freq;
    
    /* check LPUART1 clock source */
    source = RCC->CCR2 & RCC_CCR2_LPUART1CLKSEL_Msk;
    switch (source)
    {
        case 0U :                                   /* LPTIM1 clock source : RC32K */
            
            freq = RCC_GetRC32KFreq();
            break;
        
        case RCC_CCR2_LPUART1CLKSEL_0 :                 /* LPTIM1 clock source : XTL */
            
            freq = RCC_GetXTLFreq();
            break;
        
        case RCC_CCR2_LPUART1CLKSEL_1 :                 /* LPTIM1 clock source : PCLK1 division */
        default :
            
            freq = RCC_GetPCLK1Freq();
            div = RCC->CCR2 & RCC_CCR2_LPUART1DIV_Msk;
            switch (div)
            {
                case 0U :                           /* LPTIM1 clock source : PCLK1 4 frequency division */
                    
                    freq = freq >> 2;
                    break;
                
                case RCC_CCR2_LPUART1DIV_0 :         /* LPTIM1 clock source : PCLK1 8 frequency division */
                    
                    freq = freq >> 3;
                    break;
                
                case RCC_CCR2_LPUART1DIV_1 :         /* LPTIM1 clock source : PCLK1 16 frequency division */
                    
                    freq = freq >> 4;
                    break;
                
                case (RCC_CCR2_LPUART1DIV_1 | RCC_CCR2_LPUART1DIV_0) :    /* LPTIM1 clock source : PCLK1 32 frequency division */
                    
                    freq = freq >> 5;
                    break;
                
                default :
                    
                    freq = 0U;
                    break;
            }
            break;
    }
    
    return (freq);
}

/******************************************************************************
*@brief : Configures the RTC clock (RTCCLK).
*@param : RCC_RTCCLKSource: specifies the RTC clock source.
*         This parameter must be a value of @ref RCC_RTC_Clock_Source.
*             @arg RCC_RTCCLKSOURCE_RC32K: RC32K clock selected as RTC source
*             @arg RCC_RTCCLKSOURCE_XTL: XTL clock selected as RTC source
*@return: None
******************************************************************************/
void RCC_RTCCLKConfig(uint32_t RCC_RTCCLKSource)
{
    uint32_t temp;
//    uint32_t timeout;
    
    /* Check the parameters */
//    assert_param(IS_RCC_RTC_CLKSOURCE(RCC_RTCCLKSource));
    
    /* RTC clok source configuration */
    temp = RCC->STDBYCTRL;
    temp &= ~RCC_STDBYCTRL_RTCSEL;
    temp |= RCC_RTCCLKSource;
    RCC->STDBYCTRL = temp;
}

/******************************************************************************
*@brief : Enables or disables the RTC clock.
*@param : NewState: specifies the new state of the RTCCLK.
*         This parameter can be: ENABLE or DISABLE.
*@return: None
******************************************************************************/
void RCC_RTCCLKCmd(FunctionalState NewState)
{
    /* Check the parameters */
    assert_param(IS_RCC_FUNCTIONAL_STATE(NewState));
    
    if (NewState == DISABLE)
    {
        RCC->STDBYCTRL &= ~RCC_STDBYCTRL_RTCEN;
    }
    else
    {
        RCC->STDBYCTRL |= RCC_STDBYCTRL_RTCEN;
    }
}

/******************************************************************************
*@brief : Returns the RTC clock frequency
*@param : None.
*@return: RTC clock frequency
******************************************************************************/
uint32_t RCC_GetRTCCLKFreq(void)
{
    uint32_t temp;
    
    temp = RCC->STDBYCTRL & RCC_STDBYCTRL_RTCSEL;
    
    if (temp == RCC_RTCCLKSOURCE_RC32K)
        return (RCC_GetRC32KFreq());
    
    if (temp == RCC_RTCCLKSOURCE_XTL)
        return (RCC_GetXTLFreq());
    
    return (0);
}

/******************************************************************************
*@brief : Selects the clock source to output on MCO1 pin.
*@param   RCC_MCOSource: specifies the clock source to output.
*          This parameter can be one of the following values:
*            @arg RCC_MCO_NONE: 
*            @arg RCC_MCO_HCLK: 
*            @arg RCC_MCO_RC64M: 
*            @arg RCC_MCO_RC32K: 
*            @arg RCC_MCO_XTH: 
*            @arg RCC_MCO_XTL: 
*            @arg RCC_MCO_PLLCLK: 
*            @arg RCC_MCO_PCLK1: 
*            @arg RCC_MCO_PCLK2: 
*            @arg RCC_MCO_SYSCLK: 
*            @arg RCC_MCO_TIMCLK1: 
*            @arg RCC_MCO_TIMCLK2: 
*            @arg RCC_MCO_LPUART1CLK: 
*            @arg RCC_MCO_FCLKDIV8: 
*            @arg RCC_MCO_USBPHYPLL48M: 
*            @arg RCC_MCO_RTC_PCLK: 
*@param   RCC_MCO1Div: specifies the MCO1 prescaler.
*          This parameter must be a number between Min_Data = 1 and Max_Data = 65536.
*@param   RCC_MCO1Pol: specifies the MCO1 prescaler.
*          This parameter can be one of the following values:
*            @arg RCC_MCO1_POL_LOW: Low level when the clock stops.
*            @arg RCC_MCO1_POL_HIGH: High level when the clock stops.
*@return: None
******************************************************************************/
void RCC_MCO1Config(uint32_t RCC_MCOSource, uint32_t RCC_MCO1Div, uint32_t RCC_MCO1Pol)
{
    uint32_t temp;

    /* Check the parameters */
//    assert_param(IS_RCC_MCO_OUTPUT(RCC_MCOSource));
    assert_param(IS_RCC_MCO1_DIV(RCC_MCO1Div));  
    assert_param(IS_RCC_MCO1_POL(RCC_MCO1Pol));  

    temp = RCC->CLKOCR;

    temp &= ~(RCC_CLKOCR_BUZZER1POL | RCC_CLKOCR_BUZZER1DIV | RCC_CLKOCR_CLKTESTSEL);

    temp |= RCC_MCOSource | RCC_MCO1Pol | ((RCC_MCO1Div - 1) << RCC_CLKOCR_BUZZER1DIV_Pos) | \
            RCC_CLKOCR_MCOSEL;

    /* Store the new value */
    RCC->CLKOCR = temp;
}

/******************************************************************************
*@brief : Enables or disables the MCO1.
*@param   NewState: specifies the new state of the MCO1.
*         This parameter can be: ENABLE or DISABLE.
*@return: None
******************************************************************************/
void RCC_MCO1Cmd(FunctionalState NewState)
{
    /* Check the parameters */
    assert_param(IS_RCC_FUNCTIONAL_STATE(NewState));
    
    if (NewState == DISABLE)
    {
        RCC->CLKOCR &= ~RCC_CLKOCR_BUZZER1EN;
    }
    else
    {
        RCC->CLKOCR |= RCC_CLKOCR_BUZZER1EN | RCC_CLKOCR_MCOSEL;
    }
}

/******************************************************************************
*@brief : Selects the clock source to output on MCO2 pin.
*@param   RCC_MCO2Source: specifies the clock source to output.
*          This parameter can be one of the following values:
*            @arg RCC_MCO_NONE: 
*            @arg RCC_MCO_HCLK: 
*            @arg RCC_MCO_RC64M: 
*            @arg RCC_MCO_RC32K: 
*            @arg RCC_MCO_XTH: 
*            @arg RCC_MCO_XTL: 
*            @arg RCC_MCO_PLLCLK: 
*            @arg RCC_MCO_PCLK1: 
*            @arg RCC_MCO_PCLK2: 
*            @arg RCC_MCO_SYSCLK: 
*            @arg RCC_MCO_TIMCLK1: 
*            @arg RCC_MCO_TIMCLK2: 
*            @arg RCC_MCO_LPUART1CLK: 
*            @arg RCC_MCO_FCLKDIV8: 
*            @arg RCC_MCO_USBPHYPLL48M: 
*            @arg RCC_MCO_RTC_PCLK: 
*@param   RCC_MCO2Div: specifies the MCO2 prescaler.
*          This parameter must be a number between Min_Data = 1 and Max_Data = 64.
*@param   RCC_MCO2Pol: specifies the MCO2 prescaler.
*          This parameter can be one of the following values:
*            @arg RCC_MCO2_POL_LOW: Low level when the clock stops.
*            @arg RCC_MCO2_POL_HIGH: High level when the clock stops.
*@return: None
******************************************************************************/
void RCC_MCO2Config(uint32_t RCC_MCOSource, uint32_t RCC_MCO2Div, uint32_t RCC_MCO2Pol)
{
    uint32_t temp;

    /* Check the parameters */
//    assert_param(IS_RCC_MCO_OUTPUT(RCC_MCOSource));
    assert_param(IS_RCC_MCO2_DIV(RCC_MCO2Div));  
    assert_param(IS_RCC_MCO2_POL(RCC_MCO2Pol));  

    temp = RCC->CLKOCR;

    temp &= ~(RCC_CLKOCR_BUZZER2POL | RCC_CLKOCR_BUZZER1DIV | RCC_CLKOCR_CLKTESTSEL);

    temp |= RCC_MCOSource | RCC_MCO2Pol | ((RCC_MCO2Div - 1) << RCC_CLKOCR_BUZZER2DIV_Pos) | \
            RCC_CLKOCR_MCOSEL;

    /* Store the new value */
    RCC->CLKOCR = temp;
}

/******************************************************************************
*@brief : Enables or disables the MCO1.
*@param : NewState: specifies the new state of the MCO1.
*         This parameter can be: ENABLE or DISABLE.
*@return: None
******************************************************************************/
void RCC_MCO2Cmd(FunctionalState NewState)
{
    /* Check the parameters */
    assert_param(IS_RCC_FUNCTIONAL_STATE(NewState));
    
    if (NewState == DISABLE)
    {
        RCC->CLKOCR &= ~RCC_CLKOCR_BUZZER2EN;
    }
    else
    {
        RCC->CLKOCR |= RCC_CLKOCR_BUZZER2EN | RCC_CLKOCR_MCOSEL;
    }
}

/******************************************************************************
*@brief : Enables or disables the specified RCC interrupts.
*@param   RCC_IT: specifies the RCC interrupt sources to be enabled or disabled.
*          This parameter can be any combination of the following values:
*            @arg RCC_IT_RC32K: RC32K ready interrupt.
*            @arg RCC_IT_XTL: XTL ready interrupt.
*            @arg RCC_IT_RC64M: RC64M ready interrupt.
*            @arg RCC_IT_XTH: XTH ready interrupt.
*            @arg RCC_IT_PLLL: PLLready interrupt.
*@param   NewState: new state of the specified RCC interrupts.
*          This parameter can be: ENABLE or DISABLE.
*@return: None
******************************************************************************/
void RCC_ITConfig(uint8_t RCC_IT, FunctionalState NewState)
{
    /* Check the parameters */
    assert_param(IS_RCC_IT(RCC_IT));
    assert_param(IS_RCC_FUNCTIONAL_STATE(NewState));
    
    if (NewState != DISABLE)
    {
        RCC->CIR |= RCC_IT;
    }
    else
    {
        RCC->CIR &= ~RCC_IT;
    }
}

/******************************************************************************
*@brief : Enables or disables the specified RCC interrupts.
*@param   RCC_IT_Flag: specifies the RCC interrupt flag.
*          This parameter can be one of the following values:
*            @arg RCC_IT_FLAG_RC32K: RC32K ready interrupt.
*            @arg RCC_IT_FLAG_XTL: XTL ready interrupt flag.
*            @arg RCC_IT_FLAG_RC64M: RC64M ready interrupt flag.
*            @arg RCC_IT_FLAG_XTH: XTH ready interrupt flag.
*            @arg RCC_IT_FLAG_PLLL: PLLready interrupt flag.
*@return: The new state of RCC_IT_Flag (SET or RESET).
******************************************************************************/
FlagStatus RCC_GetITFlag(uint8_t RCC_IT_Flag)
{
    /* Check the parameters */
    assert_param(IS_RCC_IT_FLAG(RCC_IT_Flag));
    
    if (RCC->CIR & RCC_IT_Flag)
        return (SET);
    else
        return (RESET);
}

/******************************************************************************
*@brief : Clear the specified RCC interrupt flag.
*@param   RCC_IT_Flag: specifies the RCC interrupt flag.
*          This parameter can be one of the following values:
*            @arg RCC_IT_FLAG_RC32K: RC32K ready interrupt.
*            @arg RCC_IT_FLAG_XTL: XTL ready interrupt flag.
*            @arg RCC_IT_FLAG_RC64M: RC64M ready interrupt flag.
*            @arg RCC_IT_FLAG_XTH: XTH ready interrupt flag.
*            @arg RCC_IT_FLAG_PLLL: PLLready interrupt flag.
*@return: None.
******************************************************************************/
void RCC_ClearITFlag(uint8_t RCC_IT_Flag)
{
    /* Check the parameters */
    assert_param(IS_RCC_IT_FLAG(RCC_IT_Flag));
    
    RCC->CIR |= RCC_IT_Flag << 16;
}

/******************************************************************************
*@brief : Software reset
*@param : None
*@return: None
******************************************************************************/
void RCC_SoftwareReset(void)
{
    RCC->RCR &= ~RCC_RCR_SRSTNOMAP;
}


/******************************************************************************
*@brief : Software reset
*@param : None
*@return: None
******************************************************************************/
void RCC_ClearAllResetFlag(void)
{
    RCC->RSR |= RCC_RSR_RSTFLAGCLR;
}


/******************************************************************************
*@brief : Returns the reset source.
*@param : None
*@return: reset source
*          This parameter can be any combination of the following values:
*            @arg RCC_RESETSOURCE_PWR: 
*            @arg RCC_RESETSOURCE_POR12: 
*            @arg RCC_RESETSOURCE_SOFT: 
*            @arg RCC_RESETSOURCE_NOMAP: 
*            @arg RCC_RESETSOURCE_EFC: 
*            @arg RCC_RESETSOURCE_RSTN: 
*            @arg RCC_RESETSOURCE_SYSREQ: 
*            @arg RCC_RESETSOURCE_LOCKUP: 
*            @arg RCC_RESETSOURCE_IWDT: 
*            @arg RCC_RESETSOURCE_WDT: 
*            @arg RCC_RESETSOURCE_LVD: 
******************************************************************************/
uint32_t RCC_GetResetSource(void)
{
    return (RCC->RSR & (RCC_RESETSOURCE_PWR | RCC_RESETSOURCE_POR12 | RCC_RESETSOURCE_SOFT | \
                        RCC_RESETSOURCE_NOMAP | RCC_RESETSOURCE_EFC | RCC_RESETSOURCE_RSTN | \
                        RCC_RESETSOURCE_SYSREQ | RCC_RESETSOURCE_LOCKUP | RCC_RESETSOURCE_IWDT | \
                        RCC_RESETSOURCE_WDT | RCC_RESETSOURCE_LVD));
}

/** @defgroup  RCC_Reset_Source RCC Reset Source
  * @{
  */

/******************************************************************************
*@brief : Standby software reset
*@param : None
*@return: None
******************************************************************************/
void RCC_StandbyReset(void)
{
    /* check RTC clock source */
    RCC->STDBYCTRL &= ~RCC_STDBYCTRL_STDBYRST;
}





/************************ (C) COPYRIGHT AISINOCHIP *****END OF FILE****/
