/**************************************************************************//**
  * \file     Clock.c
  * \brief    Clock and power control driver file
  * \details
  * \author   Zhang Xuan
  * \version  V1.0.0
  * \date     25-Jul-2018
  * \par      History:
  *           V1.0.0 Initial release
  * \par      Copyright:
  *           (c) Heilongjiang TYW Electronics co., LTD
******************************************************************************/

/* Includes ------------------------------------------------------------------*/

#include "Clock.h"

/* Private typedef -----------------------------------------------------------*/
/* Private define ------------------------------------------------------------*/
/** Key to unlock one access to a System Controller configuration register by writing to SYSC0_PROTKEYR/SYSC1_PROTKEYR register */
#define   CLK_SYSC_UNLOCK_KEY               0x5CACCE55UL
/** Trigger to start state transition to RUN profile settings by writing to SYSC0_TRGRUNCNTR register */
#define   CLK_APPLY_RUN_PROFILE_TRIG        0xABU
/** Trigger to start state transition to PSS profile settings by writing to SYSC1_PSSENR register */
#define   CLK_APPLY_PSS_PROFILE_TRIG        0xBAU
/** Flags to identify startup mode **/
#define   CLK_WAKE_UP_FLAG                  0x5CA3A35CUL
/** Flags to identify sleep fail **/
#define   CLK_SLEEP_FAIL_FLAG               0x69A5965AUL

/* Private macro -------------------------------------------------------------*/
/* Private variables ---------------------------------------------------------*/
__no_init uint32_t ClkStartupModeFlag @(0x02000004);
__no_init uint32_t ClkSleepFailFlag   @(0x02000008);
__no_init uint32_t LED_Flag   @(0x0200000C);



#pragma location="BACKUP_RAM_CONTENT"
uint32_t ClkStartupTest;

#pragma location="BACKUP_RAM_CONTENT"
uint32_t ClkStartupMode;



void Set_LED_Flag(uint32_t m32)
{
  LED_Flag=m32;
}

uint32_t Read_LED_Flag(void)
{
  return LED_Flag;
}


/* Private function prototypes -----------------------------------------------*/
/* Private functions ---------------------------------------------------------*/

/**************************************************************************//**
  * \brief      Configures clocks
  * \details    This function will configure a RUN profile according to the
                settings in Clock_Config.h. It will synchronously wait for the
                completion of the state transition to the new RUN profile.
  * \retval     None
******************************************************************************/
void Clock_Init(void)
{
  /*===========================================================================
  Step 1 : disable PSS profile update
  ============================================================================*/
  /* This setting is for wakeup from shutdown mode. */
  /* note: SYSC1 was cleared by hardware after PSS profile is updated, but SYSC0 was not cleared. */
  SYSC0_PROTKEYR        = CLK_SYSC_UNLOCK_KEY;
  SYSC0_PSSENR_0_PSSEN0 = 0x00U;
  
  /*===========================================================================
  Step 2 : Set main oscillator and main PLL stabilization time
  ===========================================================================*/  
  #if (CLK_MAIN_OSC_FREQ == 4000000UL)
    
  /* Stop main source clock timer  */
  SYSC0_PROTKEYR                  =   CLK_SYSC_UNLOCK_KEY;    /* unlock SYSC0 */
  SYSC_6.unMOCTTRGR.stcField      =   (stc_sysc_6_mocttrgr_field_t){      .u1CGCPT      = 1U,
                                                                          .u1CSTOP      = 1U,
                                                                          .u1TCLR       = 1U };
                                                                          
  /* Disable main source clock timer interrupt */
  SYSC0_PROTKEYR                  =   CLK_SYSC_UNLOCK_KEY;    /* unlock SYSC0 */
  SYSC_6.unMOCTINTER.stcField     =   (stc_sysc_6_moctinter_field_t){     .u1INTE       = 0U };
  
  /* Clear main source clock timer interrupt flag */
  SYSC0_PROTKEYR                  =   CLK_SYSC_UNLOCK_KEY;    /* unlock SYSC0 */
  SYSC_6.unMOCTICLR.stcField      =   (stc_sysc_6_mocticlr_field_t){      .u1INTC       = 1U };
  
  /* Wait while timer setting is applied */
  while (SYSC_MOCTSTR_BUSY){}
  
  /* Main Clock settings */
  SYSC0_PROTKEYR                  =   CLK_SYSC_UNLOCK_KEY;    
  SYSC_7.unMOSCCNTR.stcField      =   (stc_sysc_7_mosccntr_field_t){      .u1DIV2SEL    = 0U,    /* Main clock not divided by 2 */
                                                                          .u2MCGAIN     = 0U,    /* Main clock gain characteristic for 4MHz */
                                                                          .u1MCMODE     = 0U,    /* Main clock amplifier oscillation mdoe */
                                                                          .u1FCIMEN     = 0U };  /* Fast clock input mode is disabled */

  #ifdef __DEBUG
  /* Set main source clock timer operation mode */
  SYSC0_PROTKEYR                  =   CLK_SYSC_UNLOCK_KEY;    /* unlock SYSC0 */
  SYSC_6.unMOCTCNTR.stcField      =   (stc_sysc_6_moctcntr_field_t){      .u1MODE       = 0U,
                                                                          .u1DBGEN      = 1U };
  #else
  /* Set main source clock timer operation mode */
  SYSC0_PROTKEYR                  =   CLK_SYSC_UNLOCK_KEY;    /* unlock SYSC0 */
  SYSC_6.unMOCTCNTR.stcField      =   (stc_sysc_6_moctcntr_field_t){      .u1MODE       = 0U,
                                                                          .u1DBGEN      = 0U };
  #endif
  
  /* Set main oscillation stabilization time to 8.192ms */
  SYSC0_PROTKEYR                  =   CLK_SYSC_UNLOCK_KEY;    /* unlock SYSC0 */
  SYSC_6.unMOCTCPR.stcField       =   (stc_sysc_6_moctcpr_field_t){       .u4PSCL       = 6U,
                                                                          .u16CMPR      = 0x0200U };
  /* trigger configuration capture */
  SYSC0_PROTKEYR                  =   CLK_SYSC_UNLOCK_KEY;    /* unlock SYSC0 */
  SYSC_6.unMOCTTRGR.stcField      =   (stc_sysc_6_mocttrgr_field_t){      .u1CGCPT      = 1U };

  /* Set PLL / SSCG stabilization time */
  SYSC0_PROTKEYR                  =   CLK_SYSC_UNLOCK_KEY;    /* unlock SYSC0 */
  SYSC_7.unPLLSSCGSTCNTR.stcField = (stc_sysc_7_pllsscgstcntr_field_t){   .u4PLLSTABS   = 0xFU,
                                                                          .u4SSCGSTABS  = 0xFU, };

  #elif (CLK_MAIN_OSC_FREQ == 8000000UL)
  
  /* Stop main source clock timer */
  SYSC0_PROTKEYR        =   CLK_SYSC_UNLOCK_KEY;    /* unlock SYSC0 */
  SYSC_MOCTTRGR         =   0x00000007UL;           /* CGCPT = 1 */
                                                    /* CSTOP = 1 */
                                                    /* TCLR  = 1 */
                                                                          
  /* Disable main source clock timer interrupt  */
  SYSC0_PROTKEYR        =   CLK_SYSC_UNLOCK_KEY;    /* unlock SYSC0 */
  SYSC_MOCTINTER        =   0x00000000UL;           /* INTE = 0 */
  
  /* Clear main source clock timer interrupt flag */
  SYSC0_PROTKEYR        =   CLK_SYSC_UNLOCK_KEY;    /* unlock SYSC0 */
  SYSC_MOCTICLR         =   0x00000001UL;           /* INTC = 1 */
  
  /* Wait while timer setting is applied */
  while (SYSC_MOCTSTR_BUSY){}
  
  /* Main Clock settings */
  SYSC0_PROTKEYR        =   CLK_SYSC_UNLOCK_KEY;
  SYSC_MOSCCNTR         =   0x04000000UL;            /* FCIMEN  = 0, Fast clock input mode is disabled */
                                                     /* DIV2SEL = 0, Main clock not divided by 2 */
                                                     /* MCGAIN  = 1, Main clock gain characteristic for 8MHz */
                                                     /* MCMODE  = 0, Main clock amplifier oscillation mdoe */
  #ifdef __DEBUG
  /* Set main source clock timer operation mode */
  SYSC0_PROTKEYR        =   CLK_SYSC_UNLOCK_KEY;    /* unlock SYSC0 */
  SYSC_MOCTCNTR         =   0x00000002UL;           /* MODE  = 0 */
                                                    /* DBGEN = 1 */
  #else
  /* Set main source clock timer operation mode */
  SYSC0_PROTKEYR        =   CLK_SYSC_UNLOCK_KEY;    /* unlock SYSC0 */
  SYSC_MOCTCNTR         =   0x00000000UL;           /* MODE  = 0 */
                                                    /* DBGEN = 0 */
  #endif
  
  /* Set main oscillation stabilization time to 4.096ms */
  SYSC0_PROTKEYR        =   CLK_SYSC_UNLOCK_KEY;    /* unlock SYSC0 */
  SYSC_MOCTCPR	        =   0x00060200UL;           /* CMPR = 0x0200U          */
                                                    /* PSCL = 6(divided by 64) */
  
  /* trigger configuration capture */
  SYSC0_PROTKEYR        =   CLK_SYSC_UNLOCK_KEY;    /* unlock SYSC0 */
  SYSC_MOCTTRGR         =   0x00000001UL;           /* CGCPT = 1 */
                                                    /* CSTOP = 0 */
                                                    /* TCLR  = 0 */
  
  /* Set PLL / SSCG stabilization time */
  SYSC0_PROTKEYR        =   CLK_SYSC_UNLOCK_KEY;    /* unlock SYSC0 */
  SYSC_PLLSSCGSTCNTR    =   0x000000FFUL;           /* PLLSTABS  = 0xF */
                                                    /* SSCGSTABS = 0xF */
  
  #else
    #error Unsupported main oscillator frequency
  #endif
  
  /*===========================================================================
  Step 4 : Configure low-voltage detection and clock supervisor
  ===========================================================================*/
  /***`
  Low-voltage detection setting
  LVDL1 => 1.2V internal regulator voltage monitoring
  LVDH1 => 3.3V / 5.0V external power supply monitoring
  LVDH2 => Reserved 
  ***/
  SYSC0_PROTKEYR        =   CLK_SYSC_UNLOCK_KEY;
  SYSC0_RUNLVDCFGR      =   0x01000F00UL;           /* LVDH2E = 0, LVDH2 stop operation     */
                                                    /* LVDH2V = 0, LVDH2 voltage   = N.A.   */
                                                    /* LVDH2S = 0, LVDH2 operation = Reset  */
                                                    /* LVDH1E = 1, LVDH1 enable operation   */
                                                    /* LVDH1V = 7, LVDH1 voltage   = 2.60V  */
                                                    /* LVDH1S = 0, LVDH1 operation = Reset  */
                                                    /* LVDL1E = 1, LVDL1 enable operation   */
                                                    /* LVDL1V = 0, LVDL1 voltage   = 0.875V */
                                                    /* LVDL1S = 0, LVDL1 operation = Reset  */
                                                    
  /*===========================================================================
  Step 5 : Configure run profile
  ===========================================================================*/
  /* Enable power domains */
  SYSC0_PROTKEYR        =   CLK_SYSC_UNLOCK_KEY;    /* unlock SYSC0 */
  SYSC0_RUNPDCFGR       =   0x00030100UL;	    /* PD2EN   = 1, switch on PD2 (always on) */
                                                    /* PD4_0EN = 1, switch on PD4_0           */
                                                    /* PD4_1EN = 1, switch on PD4_1           */
  
  /* Enable oscillators */
  SYSC0_PROTKEYR        =   CLK_SYSC_UNLOCK_KEY;    /* unlock SYSC0 */
  SYSC0_RUNCKSRER       =   CLK_CFG_SYSC0_RUNCKSRER;

  /* Write Main PLL0 settings */
  SYSC0_PROTKEYR        =   CLK_SYSC_UNLOCK_KEY;    /* unlock SYSC0 */
  SYSC0_RUNPLL0CNTR     =   CLK_CFG_SYSC0_RUNPLL0CNTR;
  
  /* Clock gear */
  SYSC0_PROTKEYR        =   CLK_SYSC_UNLOCK_KEY;    /* unlock SYSC0 */
  SYSC_PLL0CGCNTR       =   0x00044801UL;           /* PLLCGEN  = 1, Enable           */
                                                    /* PLLCGSTR	= 0, No operation     */
                                                    /* PLLCGSTS = 0, Read only        */
                                                    /* PLLCGSSN = 8, Start step = 8   */
                                                    /* PLLCGSTP = 1, step width = 2   */
                                                    /* PLLCGLP  = 4, 4 loops per step */
  
  /*------------------------------------------------------------------ */
  /* Write SSCG PLL0 settings */
  SYSC0_PROTKEYR        =   CLK_SYSC_UNLOCK_KEY;    /* unlock SYSC0 */
  SYSC0_RUNSSCG0CNTR0   =   CLK_CFG_SYSC0_RUNSSCG0CNTR0;
  
  SYSC0_PROTKEYR        =   CLK_SYSC_UNLOCK_KEY;    /* unlock SYSC0 */
  SYSC0_RUNSSCG0CNTR1   =   CLK_CFG_SYSC0_RUNSSCG0CNTR1;

  /* Clock gear */
  SYSC0_PROTKEYR        =   CLK_SYSC_UNLOCK_KEY;    /* unlock SYSC0 */
  SYSC_SSCG0CGCNTR      =   0x00044801UL;           /* SSCGCGEN  = 1, Enable           */
                                                    /* SSCGCGSTR = 0, No operation     */
                                                    /* SSCGCGSTS = 0, Read only        */
                                                    /* SSCGCGSSN = 8, Start step = 8   */
                                                    /* SSCGCGSTP = 1, step width = 2   */
                                                    /* SSCGCGLP  = 4, 4 loops per step */
  
  /*------------------------------------------------------------------ */
  /* Select clock sources */
  SYSC0_PROTKEYR        =   CLK_SYSC_UNLOCK_KEY;    /* unlock SYSC0 */ 
  SYSC0_RUNCKSELR	=   0x00000005UL;           /* CDMCUCCSL = 5, Clock domain MCUC clock = SSCG0 */
                                                                                         
  SYSC1_PROTKEYR        =   CLK_SYSC_UNLOCK_KEY;    /* unlock SYSC1 */
  SYSC1_RUNCKSELR0      =   0x00000005UL;           /* CD0CSL    = 5, CD0 clock domain = SSCG0            */
                                                    /* LCP0ACSL  = 0, LCP0A clock = CD0                   */
                                                    /* LCP1ACSL  = 0, LCP1A clock = CD0                   */
                                                    /* LAPP0ACSL = 0, LAPP0A clock = default (N.A.)       */
                                                    /* LAPP1ACSL = 0, LAPP1A clock = default (N.A.)       */
                                                    /* HSSPICSL  = 0, Hsspi clock domain = default (N.A.) */
                                                                                         
  SYSC1_PROTKEYR        =   CLK_SYSC_UNLOCK_KEY;    /* unlock SYSC1 */
  SYSC1_RUNCKSELR1      =   0x00000000UL;           /* CD1CSL = 0, CD1 clock domain = default (N.A.) */
                                                    /* CD2CSL = 0, CD2 clock domain = default (N.A.) */
                                                    /* CD3CSL = 0, CD3 clock domain = default (N.A.) */
                                                    /* CD4CSL = 0, CD4 clock domain = default (N.A.) */
  
  SYSC1_PROTKEYR        =   CLK_SYSC_UNLOCK_KEY;    /* unlock SYSC1 */
  SYSC1_RUNCKSELR2      =   0x00000400UL;           /* CD5CSL = 0, CD5 clock domain = default (N.A.) */
                                                    /* TRCCSL = 4, TRC clock = PLL0                  */
  
  /*------------------------------------------------------------------ */
  /* Enable clocks */
  SYSC1_PROTKEYR        =   CLK_SYSC_UNLOCK_KEY;
  SYSC1_RUNCKER0        =   CLK_CFG_SYSC1_RUNCKER0;
  
  SYSC1_PROTKEYR        =   CLK_SYSC_UNLOCK_KEY;    /* unlock SYSC1 */
  SYSC1_RUNCKER1        =   0x00000000UL;           /* ENCLKHSSPI = 0, Disable HSSPI */
                                                    /* ENCLKCD1   = 0, Disable CD1   */
                                                    /* ENCLKCD1A0 = 0, Disable CD1A0 */
                                                    /* ENCLKCD1A1 = 0, Disable CD1A1 */
                                                    /* ENCLKCD1B0 = 0, Disable CD1B0 */
                                                    /* ENCLKCD1B1 = 0, Disable CD1B1 */
                                                    /* ENCLKCD2   = 0, Disable CD2   */
                                                    /* ENCLKCD2A0 = 0, Disable CD2A0 */
                                                    /* ENCLKCD2A1 = 0, Disable CD2A1 */
                                                    /* ENCLKCD2B0 = 0, Disable CD2B0 */
                                                    /* ENCLKCD2B1 = 0, Disable CD2B1 */
                                                    /* ENCLKCD3   = 0, Disable CD3   */
                                                    /* ENCLKCD3A0 = 0, Disable CD3A0 */
                                                    /* ENCLKCD3A1 = 0, Disable CD3A1 */
                                                    /* ENCLKCD3B0 = 0, Disable CD3B0 */
                                                    /* ENCLKCD3B1 = 0, Disable CD3B1 */
  
  SYSC1_PROTKEYR        =   CLK_SYSC_UNLOCK_KEY;    /* unlock SYSC1 */
  SYSC1_RUNCKER2        =   0x00000000UL;           /* ENCLKCD4   = 0,Disable CD4   */
                                                    /* ENCLKCD4A0 = 0,Disable CD4A0 */
                                                    /* ENCLKCD4A1 = 0,Disable CD4A1 */
                                                    /* ENCLKCD4B0 = 0,Disable CD4B0 */
                                                    /* ENCLKCD4B1 = 0,Disable CD4B1 */
                                                    /* ENCLKCD5   = 0,Disable CD5   */
                                                    /* ENCLKCD5A0 = 0,Disable CD5A0 */
                                                    /* ENCLKCD5A1 = 0,Disable CD5A1 */
                                                    /* ENCLKCD5B0 = 0,Disable CD5B0 */
                                                    /* ENCLKCD5B1 = 0,Disable CD5B1 */
  
  /*------------------------------------------------------------------*/
  /* Set clock dividers (valid setting for all main-PLL frequencies) */
  SYSC0_PROTKEYR        =   CLK_SYSC_UNLOCK_KEY;    /* unlock SYSC0 */
  SYSC0_RUNCKDIVR       =   CLK_CFG_SYSC0_RUNCKDIVR;
  
  /* Set clock dividers (valid setting for all main-PLL frequencies) */
  SYSC1_PROTKEYR        =   CLK_SYSC_UNLOCK_KEY;    /* unlock SYSC1 */
  SYSC1_RUNCKDIVR0      =   CLK_CFG_SYSC1_RUNCKDIVR0;

  SYSC1_PROTKEYR        =   CLK_SYSC_UNLOCK_KEY;    /* unlock SYSC1 */
  SYSC1_RUNCKDIVR1      =   CLK_CFG_SYSC1_RUNCKDIVR1;

  SYSC1_PROTKEYR        =   CLK_SYSC_UNLOCK_KEY;    /* unlock SYSC1 */
  SYSC1_RUNCKDIVR2      =   CLK_CFG_SYSC1_RUNCKDIVR2;

  SYSC1_PROTKEYR        =   CLK_SYSC_UNLOCK_KEY;    /* unlock SYSC1 */
  SYSC1_RUNCKDIVR3      =   CLK_CFG_SYSC1_RUNCKDIVR3;
  
  SYSC1_PROTKEYR        =   CLK_SYSC_UNLOCK_KEY;    /* unlock SYSC1 */
  SYSC1_RUNCKDIVR4      =   0x00000000UL;           /* HSSPIDIV = 0, HSSPI clock divider = 1 */
  
  SYSC1_PROTKEYR        =   CLK_SYSC_UNLOCK_KEY;    /* unlock SYSC1 */
  SYSC1_RUNCKDIVR5      =   0x00000000UL;           /* CD1DIV   = 0, CD1DIV clock divider = 1   */
                                                    /* CD1A0DIV = 0, CD1A0DIV clock divider = 1 */
                                                    /* CD1A1DIV = 0, CD1A1DIV clock divider = 1 */
                                                    /* CD1B0DIV = 0, CD1B0DIV clock divider = 1 */
                                                    /* CD1B1DIV = 0, CD1B1DIV clock divider = 1 */
  
  SYSC1_PROTKEYR        =   CLK_SYSC_UNLOCK_KEY;    /* unlock SYSC1 */
  SYSC1_RUNCKDIVR6      =   0x00000000UL;           /* CD2DIV   = 0, CD2DIV clock divider = 1   */
                                                    /* CD2A0DIV = 0, CD2A0DIV clock divider = 1 */
                                                    /* CD2A1DIV = 0, CD2A1DIV clock divider = 1 */
                                                    /* CD2B0DIV = 0, CD2B0DIV clock divider = 1 */
                                                    /* CD2B1DIV = 0, CD2B1DIV clock divider = 1 */
  
  SYSC1_PROTKEYR        =   CLK_SYSC_UNLOCK_KEY;    /* unlock SYSC1 */
  SYSC1_RUNCKDIVR7      =   0x00000000UL;           /* CD3DIV   = 0, CD3DIV clock divider = 1   */
                                                    /* CD3A0DIV = 0, CD3A0DIV clock divider = 1 */
                                                    /* CD3A1DIV = 0, CD3A1DIV clock divider = 1 */
                                                    /* CD3B0DIV = 0, CD3B0DIV clock divider = 1 */
                                                    /* CD3B1DIV = 0, CD3B1DIV clock divider = 1 */
  
  SYSC1_PROTKEYR        =   CLK_SYSC_UNLOCK_KEY;    /* unlock SYSC1 */
  SYSC1_RUNCKDIVR8      =   0x00000000UL;           /* CD4DIV   = 0, CD4DIV clock divider = 1   */
                                                    /* CD4A0DIV = 0, CD4A0DIV clock divider = 1 */
                                                    /* CD4A1DIV = 0, CD4A1DIV clock divider = 1 */
                                                    /* CD4B0DIV = 0, CD4B0DIV clock divider = 1 */
                                                    /* CD4B1DIV = 0, CD4B1DIV clock divider = 1 */
  
  SYSC1_PROTKEYR        =   CLK_SYSC_UNLOCK_KEY;    /* unlock SYSC1 */
  SYSC1_RUNCKDIVR9      =   0x00000000UL;           /* CD5DIV   = 0, CD5DIV clock divider = 1   */
                                                    /* CD5A0DIV = 0, CD5A0DIV clock divider = 1 */
                                                    /* CD5A1DIV = 0, CD5A1DIV clock divider = 1 */
                                                    /* CD5B0DIV = 0, CD5B0DIV clock divider = 1 */
                                                    /* CD5B1DIV = 0, CD5B1DIV clock divider = 1 */
  
  WDT_Clear();
  
  /*------------------------------------------------------------------*/
  /* RUN Profile update enable */
  SYSC1_PROTKEYR                  =   CLK_SYSC_UNLOCK_KEY;    /* unlock SYSC1 */
  SYSC1_RUNENR_0_RUNEN1           =   CLK_APPLY_RUN_PROFILE_TRIG;

  /* Write the trigger value to apply the RUN profile */
  SYSC0_PROTKEYR                  =   CLK_SYSC_UNLOCK_KEY;    /* unlock SYSC0 */
  SYSC0_TRGRUNCNTR                =   CLK_APPLY_RUN_PROFILE_TRIG;    /* trigger RUN-->RUN transition */
    
  /* Wait until the RUN profile is applied */
  while (SYSC0_SYSSTSR_RUNDF0 == 0U){}
  
  /* Clear RUN Profile Done flag (SYSC_SYSSTSR_RUNDN)  */
  SYSC0_PROTKEYR                  =   CLK_SYSC_UNLOCK_KEY;    /* unlock SYSC0 */
  SYSC0_SYSICLR_RUNDFCLR0         =   1U;

  /*------------------------------------------------------------------*/
  /* Clock gear (Trigger) */
  /* Trigger (SSCG) PLL Clock gearing if it is not already geared up */

  if (SYSC_PLL0CGCNTR_PLLCGSTS == 0U)    /* Gear up status: 0 - stop gear at min frequency */
  {
    SYSC0_PROTKEYR                =   CLK_SYSC_UNLOCK_KEY;     /* unlock SYSC0 */
    SYSC_PLL0CGCNTR_PLLCGSTR      =   1U;                      /* Start gear operation (PLL0) */
  }

  if (SYSC_SSCG0CGCNTR_SSCGCGSTS == 0U)  /* Gear up status: 0 - stop gear at min frequency */
  {
    SYSC0_PROTKEYR                =   CLK_SYSC_UNLOCK_KEY;     /* unlock SYSC0 */
    SYSC_SSCG0CGCNTR_SSCGCGSTR    =   1U;                      /* Start gear operation (SSCG0) */
  }

  /*------------------------------------------------------------------*/
  /* Ensure that PLL clock gearing has also finished */
  while ((SYSC_PLL0CGCNTR_PLLCGSTS) != 2U){}                    /* Gear up status: 2 - stop gear at max frequency */
  while ((SYSC_SSCG0CGCNTR_SSCGCGSTS) != 2U){}                  /* Gear up status: 2 - stop gear at max frequency */
  
  /*===========================================================================
  Step 6 : Release GPIO
  ============================================================================*/
  if(SYSC0_SPECFGR_HOLDIO_PD2) 
  {
    SYSC0_PROTKEYR                =   CLK_SYSC_UNLOCK_KEY;    /* unlock SYSC0 */
    SYSC0_SPECFGR                 =   0x00000000U;
    
    ClkStartupModeFlag            =   CLK_WAKE_UP_FLAG;
  }
  else
  {
    if (ClkSleepFailFlag == CLK_SLEEP_FAIL_FLAG)
    {
      ClkStartupModeFlag          =   CLK_SLEEP_FAIL_FLAG;
    }
    else
    {
      ClkStartupModeFlag          =   0x00000000UL;
    }
  }
  ClkSleepFailFlag            =   0x00000000UL;
}

/**************************************************************************//**
  * \brief      Configures clocks
  * \details    This function will configure a RUN profile according to the
                settings in Clock_Config.h. It will synchronously wait for the
                completion of the state transition to the new RUN profile.
  * \retval     None
******************************************************************************/
void Clock_Enter_Sleep_Mode(void)
{
  
  /*===========================================================================
  Step 1 : Config backup RAM and GPIO
  ============================================================================*/
  SYSC0_PROTKEYR        =   CLK_SYSC_UNLOCK_KEY;    /* unlock SYSC0 */
  SYSC0_SPECFGR         =   0x01000200UL;           /* EXVRSTCNT  = 1, Always set                  */
                                                    /* IO35RSTC	  = 0, I/O reset released          */
                                                    /* IO3RSTC    = 0, I/O reset released          */
                                                    /* PSSPADCTRL = 0, Do not perform Hi-z control */
                                                    /* HOLDIO_PD2 = 1, Retain control              */

  /*===========================================================================
  Step 2 : Stop clocks
  ============================================================================*/
  if (SYSC_SSCG0CGCNTR_SSCGCGSTS == 2U)  /* Gear status: 2 - Clock gear operation reaches maximum frequency */
  {
    SYSC0_PROTKEYR                =   CLK_SYSC_UNLOCK_KEY;     /* unlock SYSC0 */
    SYSC_SSCG0CGCNTR_SSCGCGSTR    =   1U;                      /* Start gear operation (SSCG0) */
  }
  
  if (SYSC_PLL0CGCNTR_PLLCGSTS == 2U)     /* Gear status: 2 - Clock gear operation reaches maximum frequency */
  {
    SYSC0_PROTKEYR                =   CLK_SYSC_UNLOCK_KEY;     /* unlock SYSC0 */
    SYSC_PLL0CGCNTR_PLLCGSTR      =   1U;                      /* Start gear operation (PLL0) */
  }
  
  /* ------------------------------------------------------------------ */
  /* Ensure that PLL clock gearing has also finished */ 
  while ((SYSC_PLL0CGCNTR_PLLCGSTS) != 0U){}                   /* Gear down status: 0 - Clock gear operation reaches minimum frequency */
  while ((SYSC_SSCG0CGCNTR_SSCGCGSTS) != 0U){}                 /* Gear down status: 0 - Clock gear operation reaches minimum frequency */
  
  /*------------------------------------------------------------------*/
  /* Stop clocks*/
  SYSC0_PROTKEYR        =   CLK_SYSC_UNLOCK_KEY;
  SYSC0_RUNCKSRER       =   0x00000007UL;           /* CROSCEN	= 1, Enable oscillation of the low-speed CR clock  */
                                                    /* SCROSCEN = 1, Enable oscillation of the high-speed CR clock */
                                                    /* MOSCEN	= 1, Enable Main Oscillation                       */
                                                    /* SOSCEN	= 0, Disable Sub Oscillation                       */
                                                    /* PLL0EN	= 0, Disable PLL0                                  */
                                                    /* SSCG0EN	= 0, Disable SSCG0                                 */

  SYSC0_PROTKEYR        =   CLK_SYSC_UNLOCK_KEY;
  SYSC0_RUNCKSELR       =   0x00000000UL;           /* CDMCUCCSL = 0, Clock domain MCUC clock = High-speed CR clock */

  SYSC1_PROTKEYR        =   CLK_SYSC_UNLOCK_KEY;
  SYSC1_RUNCKSELR0      =   0x00000000UL;           /* HSSPICSL  = 0, Hsspi clock domain = High-speed CR clock */
                                                    /* LAPP1ACSL = 0, LAPP1A clock = CD0                       */
                                                    /* LAPP0ACSL = 0, LAPP0A clock = CD0                       */
                                                    /* LCP1ACSL  = 0, LCP1A clock  = CD0                       */
                                                    /* LCP0ACSL  = 0, LCP0A clock  = CD0                       */
                                                    /* CD0CSL    = 0, CD0 clock domain   = High-speed CR clock */
                                                                          
  SYSC1_PROTKEYR        =   CLK_SYSC_UNLOCK_KEY;
  SYSC1_RUNCKSELR1      =   0x00000000UL;           /* CD4CSL = 0, CD4 clock domain = High-speed CR clock */
                                                    /* CD3CSL = 0, CD3 clock domain = High-speed CR clock */
                                                    /* CD2CSL = 0, CD2 clock domain = High-speed CR clock */
                                                    /* CD1CSL = 0, CD1 clock domain = High-speed CR clock */
                                                                          
  SYSC1_PROTKEYR        =   CLK_SYSC_UNLOCK_KEY;
  SYSC1_RUNCKSELR2      =   0x00000000UL;           /* TRCCSL = 0, TRC clock        = High-speed CR clock */
                                                    /* CD5CSL = 0, CD5 clock domain = High-speed CR clock */

  SYSC1_PROTKEYR        =   CLK_SYSC_UNLOCK_KEY;
  SYSC1_RUNCKDIVR0      =   0x00000000UL;           /* SYSDIV = 0, SYS clock divider = No division */
                                                    /* ATBDIV = 0, ATB clock divider = No division */
                                                    /* DBGDIV = 0, DBG clock divider = No division */
                                                    /* TRCDIV = 0, TRC clock divider = No division */
                                                    /* HPMDIV = 0, HPM clock divider = No division */
                                                                    
  SYSC0_PROTKEYR        =   CLK_SYSC_UNLOCK_KEY;
  SYSC0_RUNCKDIVR       =   0x00000000UL;           /* MCUCHDIV = 0, AHB clock divider = No division */
  
  /* while (SYSC0_SYSRUNPEFR & 0x7FBU){} */
  
  /* RUN Profile update enable */
  SYSC1_PROTKEYR                  =   CLK_SYSC_UNLOCK_KEY;    /* unlock SYSC1 */
  SYSC1_RUNENR_0_RUNEN1           =   CLK_APPLY_RUN_PROFILE_TRIG;

  /* Write the trigger value to apply the RUN profile */
  SYSC0_PROTKEYR                  =   CLK_SYSC_UNLOCK_KEY;    /* unlock SYSC0 */
  SYSC0_TRGRUNCNTR                =   CLK_APPLY_RUN_PROFILE_TRIG;    /* trigger RUN-->RUN transition */
    
  /* Wait until the RUN profile is applied */
  while (SYSC0_SYSSTSR_RUNDF0 == 0U){}
  WDT_Clear();
  
  /* Clear RUN Profile Done flag (SYSC_SYSSTSR_RUNDN) */
  SYSC0_PROTKEYR                  =   CLK_SYSC_UNLOCK_KEY;    /* unlock SYSC0 */
  SYSC0_SYSICLR_RUNDFCLR0         =   1U;

  /*===========================================================================
  Step 3 : Configure PSS profile
  ===========================================================================*/
  /* Configure power domains */
  SYSC0_PROTKEYR        =   CLK_SYSC_UNLOCK_KEY;
  SYSC_MOSCCNTR         =   0x84000000UL;            /* FCIMEN  = 0, Fast clock input mode is disabled */
                                                     /* DIV2SEL = 0, Main clock not divided by 2 */
                                                     /* MCGAIN  = 1, Main clock gain characteristic for 8MHz */
                                                     /* MCMODE  = 1, Main clock amplifier oscillation stop mdoe */

                                                     
  /* Configure power domains */
  SYSC0_PROTKEYR        =   CLK_SYSC_UNLOCK_KEY;
  SYSC0_PSSPDCFGR       =   0x00030000UL;           /* PD2EN   = 0, switch off PD2 (Peripheral)   */
                                                    /* PD4_0EN = 1, switch on PD4_0 (Backup RAM0) */
                                                    /* PD4_1EN = 1, switch on PD4_1 (Backup RAM1) */
                                                                          
  /* Configure oscillators */
  SYSC0_PROTKEYR        =   CLK_SYSC_UNLOCK_KEY;
  SYSC0_PSSCKSRER       =   0x00000006UL;           /* SSCG0EN  = 0, Disable SSCG0                                  */
                                                    /* PLL0EN   = 0, Disable PLL0                                   */
                                                    /* SOSCEN   = 0, Disable Sub Oscillation                        */
                                                    /* MOSCEN   = 1, Enable Main Oscillation                        */
                                                    /* CROSCEN  = 0, Disable oscillation of the high-speed CR clock */
                                                    /* SCROSCEN = 1, Enable oscillation of the low-speed CR clock   */
  
  /* Select clock sources */                                           
  SYSC0_PROTKEYR        =   CLK_SYSC_UNLOCK_KEY;
  SYSC0_PSSCKSELR       =   0x00000007UL;           /* CDMCUCCSL = 7, Clock domain MCUC clock = Clock fixed at "L" */

  SYSC0_PROTKEYR        =   CLK_SYSC_UNLOCK_KEY;
  SYSC0_PSSCKER         =   0x00000000UL;           /* ENCLKMCUCH = 0, Disable AHB clock */
  
  /* Set clock dividers */
  SYSC0_PROTKEYR        =   CLK_SYSC_UNLOCK_KEY;
  SYSC0_PSSCKDIVR       =   0x00000000UL;           /* MCUCHDIV = 0, AHB clock divider = No division */

/* ------------------------------------------------------------------ */
/***
  Low-voltage detection setting
  LVDL1 => 1.2V internal regulator voltage monitoring
  LVDH1 => 3.3V / 5.0V external power supply monitoring
  LVDH2 => Reserved 
***/
  SYSC0_PROTKEYR        =   CLK_SYSC_UNLOCK_KEY;
  SYSC0_PSSLVDCFGR      =   0x01000F00UL;           /* LVDH2E = 0, LVDH2 stop operation     */
                                                    /* LVDH2V = 0, LVDH2 voltage   = N.A.   */
                                                    /* LVDH2S = 0, LVDH2 operation = Reset  */
                                                    /* LVDH1E = 1, LVDH1 enable operation   */
                                                    /* LVDH1V = 7, LVDH1 voltage   = 2.60V  */
                                                    /* LVDH1S = 0, LVDH1 operation = Reset  */
                                                    /* LVDL1E = 1, LVDL1 enable operation   */
                                                    /* LVDL1V = 0, LVDL1 voltage   = 0.875V */
                                                    /* LVDL1S = 0, LVDL1 operation = Reset  */
  
/* Clock Supervisor Setting */
  SYSC0_PROTKEYR        =   CLK_SYSC_UNLOCK_KEY;
  SYSC0_PSSCSVCFGR      =   0x00000000UL;           /* SSCG0CSVE = 0, Disable the SSCG PLL0 clock supervisor     */
                                                    /* PLL0CSVE  = 0, Disable the PLL0 clock supervisor          */
                                                    /* SCRCSVE   = 0, Disable the Low-speed CR clock supervisor  */
                                                    /* CRCSVE    = 0, Disable the High-speed CR clock supervisor */
                                                    /* MOCSVE    = 0, Disable the main clock supervisor          */
                                                    /* SOCSVE    = 0, Disable the sub clock supervisor           */

  /* Regulator Setting */
  SYSC0_PROTKEYR        =   CLK_SYSC_UNLOCK_KEY;
  SYSC0_PSSREGCFGR      =   0x00000080UL;           /* RMSEL = 1, Standby mode */
  
  /* ------------------------------------------------------------------ */
  /* Select clock sources */
  SYSC1_PROTKEYR        =   CLK_SYSC_UNLOCK_KEY;
  SYSC1_PSSCKSELR0      =   0x01000001UL;           /* CD0CSL    = 1, CD0 clock domain   = Low-speed CR clock */
                                                    /* LCP0ACSL  = 0, LCP0A clock  = CD0                      */
                                                    /* LCP1ACSL  = 0, LCP1A clock  = CD0                      */
                                                    /* LAPP0ACSL = 0, LAPP0A clock = CD0                      */
                                                    /* LAPP1ACSL = 0, LAPP1A clock = CD0                      */
                                                    /* HSSPICSL  = 1, Hsspi clock domain = Low-speed CR clock */

  SYSC1_PROTKEYR        =   CLK_SYSC_UNLOCK_KEY;
  SYSC1_PSSCKSELR1      =   0x01010101UL;           /* CD4CSL = 1, CD4 clock domain = Low-speed CR clock */
                                                    /* CD3CSL = 1, CD3 clock domain = Low-speed CR clock */
                                                    /* CD2CSL = 1, CD2 clock domain = Low-speed CR clock */
                                                    /* CD1CSL = 1, CD1 clock domain = Low-speed CR clock */
    
  SYSC1_PROTKEYR        =   CLK_SYSC_UNLOCK_KEY;
  SYSC1_PSSCKSELR2      =   0x00000101UL;           /* TRCCSL = 1, TRC clock        = Low-speed CR clock */
                                                    /* CD5CSL = 1, CD5 clock domain = Low-speed CR clock */
                                                                    
  /* ------------------------------------------------------------------ */
  /* Disable clock sources */
  SYSC1_PROTKEYR                  =   CLK_SYSC_UNLOCK_KEY; 
  SYSC1_PSSCKER0                  =   0x00000000UL;

  SYSC1_PROTKEYR                  =   CLK_SYSC_UNLOCK_KEY;
  SYSC1_PSSCKER1                  =   0x00000000UL;
  
  SYSC1_PROTKEYR                  =   CLK_SYSC_UNLOCK_KEY;
  SYSC1_PSSCKER2                  =   0x00000000UL;

  /* ------------------------------------------------------------------ */
  /* Clear clock dividers */
  SYSC1_PROTKEYR                  =   CLK_SYSC_UNLOCK_KEY;
  SYSC1_PSSCKDIVR0                =   0x00000000UL;
  
  SYSC1_PROTKEYR                  =   CLK_SYSC_UNLOCK_KEY;
  SYSC1_PSSCKDIVR1                =   0x00000000UL;
  
  SYSC1_PROTKEYR                  =   CLK_SYSC_UNLOCK_KEY;
  SYSC1_PSSCKDIVR2                =   0x00000000UL;
  
  SYSC1_PROTKEYR                  =   CLK_SYSC_UNLOCK_KEY;
  SYSC1_PSSCKDIVR3                =   0x00000000UL;
  
  SYSC1_PROTKEYR                  =   CLK_SYSC_UNLOCK_KEY;
  SYSC1_PSSCKDIVR4                =   0x00000000UL;
  
  SYSC1_PROTKEYR                  =   CLK_SYSC_UNLOCK_KEY;
  SYSC1_PSSCKDIVR5                =   0x00000000UL;
  
  SYSC1_PROTKEYR                  =   CLK_SYSC_UNLOCK_KEY;
  SYSC1_PSSCKDIVR6                =   0x00000000UL;
  
  SYSC1_PROTKEYR                  =   CLK_SYSC_UNLOCK_KEY;
  SYSC1_PSSCKDIVR7                =   0x00000000UL;
  
  SYSC1_PROTKEYR                  =   CLK_SYSC_UNLOCK_KEY;
  SYSC1_PSSCKDIVR8                =   0x00000000UL;
  
  SYSC1_PROTKEYR                  =   CLK_SYSC_UNLOCK_KEY;
  SYSC1_PSSCKDIVR9                =   0x00000000UL;

  /* while(SYSC0_SYSPSSPEFR & 0x7FBU){} */
  
  /* PSS profile update enable */
  SYSC0_PROTKEYR                  =   CLK_SYSC_UNLOCK_KEY;  
  SYSC0_SYSICLR_PSSDFCLR0         =   1U;

  /* Write the trigger value to apply the PSS profile */
  SYSC1_PROTKEYR                  =   CLK_SYSC_UNLOCK_KEY;
  SYSC1_PSSENR_0_PSSEN1           =   CLK_APPLY_PSS_PROFILE_TRIG;
  
  SYSC0_PROTKEYR                  =   CLK_SYSC_UNLOCK_KEY;
  SYSC0_PSSENR_0_PSSEN0           =   CLK_APPLY_PSS_PROFILE_TRIG;
  
  /* Wait until the PSS profile is applied */
  while (SYSC0_SYSSTSR_PSSSTS0 == 1U){}
  WDT_Clear();
  
  DSB();
  ISB();
  
  __WFI();
  
  LED_Flag =0x9AA9A99Au;
  ClkSleepFailFlag = CLK_SLEEP_FAIL_FLAG;
  NOP();
  NOP();
  NOP();
  NOP();
  NOP();
  NOP();
  NOP();
  NOP();  
  RESET();
}

Clk_Startup_Mode_en_t Clock_Get_Startup_Mode(void)
{
  Clk_Startup_Mode_en_t Mode;
  
  if (ClkStartupModeFlag == CLK_WAKE_UP_FLAG)
  {
    Mode = CLK_STARTUP_WAKE_UP;
  }
  else if (ClkStartupModeFlag == CLK_SLEEP_FAIL_FLAG)
  {
    Mode = CLK_STARTUP_SLEEP_FAIL;
  }
  else
  {
    Mode = CLK_STARTUP_PWR_ON;
  }
  
  return Mode;
}
