Beispiel #1
0
/*-------------------------------------------------------------------------------*/
void FBE(void)
	{
	
		MCG->C6 &= ~MCG_C6_CME0_MASK; 					//External clock monitor is disabled for OSC0.

    MCG->C2 |= MCG_C2_RANGE0(3) |						// Very high frequency range selected for the crystal oscillator 
               MCG_C2_EREFS0_MASK  ; 				//Oscillator requested
		
    MCG->C4 &= ~MCG_C4_DRST_DRS_MASK;   // Reset DCO Range
    MCG->C4 &= ~MCG_C4_DMX32_MASK;			// DCO Maximum Frequency
    MCG->C4 |= MCG_C4_DRST_DRS(1);			// 31.25 * 1280 = 40000kHz
    
    MCG->C6 &= ~MCG_C6_PLLS_MASK;				// Select FLL
			
    MCG->C1 &= ~MCG_C1_CLKS_MASK;				// Reset Clock Source Select
    MCG->C1 |= MCG_C1_CLKS(2) | 				//External reference clock is selected
						 	MCG_C1_FRDIV(3)| 					// Divide Factor is 256
							MCG_C1_IRCLKEN_MASK;			//MCGIRCLK active
					// Output of FLL is selected for MCGOUTCLK
    
    while((MCG->S & MCG_S_OSCINIT0_MASK) == 0); 		// wait for osc init
    while((MCG->S & MCG_S_PLLST_MASK) != 0); 				// wait for FLL
    while((MCG->S & MCG_S_CLKST_MASK) != MCG_S_CLKST(2)); // wait for EXTAL is selected
		 SIM->CLKDIV1 = SIM_CLKDIV1_OUTDIV1(1 - 1) |  				// core/system clock = MCGOUTCLK / 1 = 8 / 1 = 8MHz
     SIM_CLKDIV1_OUTDIV4(1 - 1);   // flash/bus clock = core/system / 1 = 8MHz
	
	}
Beispiel #2
0
status_t CLOCK_BootToBlpeMode(mcg_oscsel_t oscsel)
{
    CLOCK_SetExternalRefClkConfig(oscsel);

    /* Set to FBE mode. */
    MCG->C1 =
        ((MCG->C1 & ~(MCG_C1_CLKS_MASK | MCG_C1_IREFS_MASK)) | (MCG_C1_CLKS(kMCG_ClkOutSrcExternal)    /* CLKS = 2 */
                                                                | MCG_C1_IREFS(kMCG_FllSrcExternal))); /* IREFS = 0 */

    /* If use external crystal as clock source, wait for it stable. */
    {
        if (MCG->C2 & MCG_C2_EREFS_MASK)
        {
            while (!(MCG->S & MCG_S_OSCINIT0_MASK))
            {
            }
        }
    }

    /* Wait for MCG_S[CLKST] and MCG_S[IREFST]. */
    while ((MCG->S & (MCG_S_IREFST_MASK | MCG_S_CLKST_MASK)) !=
           (MCG_S_IREFST(kMCG_FllSrcExternal) | MCG_S_CLKST(kMCG_ClkOutStatExt)))
    {
    }

    /* In FBE now, start to enter BLPE. */
    MCG->C2 |= MCG_C2_LP_MASK;

    return kStatus_Success;
}
Beispiel #3
0
void MCG_LITE_Init (tMCG_LITE mcglite)
{   
  // switch to HIRC mode when moving between LIRC2 and LIRC8 modes
  if (((MCG_S&MCG_S_CLKST(0x1)) && (mcglite.C1&MCG_C1_CLKS(0x1))) &&
      ((MCG_C2&MCG_C2_IRCS_MASK) != (mcglite.C2&MCG_C2_IRCS_MASK)))
  {
    MCG_MC |= MCG_MC_HIRCEN_MASK;
    MCG_C1 = MCG_C1_CLKS(0x0);
    WAIT_FOR_STATUS_FLAG (MCG_C1, CLKS, CLKST);
  }
  // set LIRC first divider  
  MCG_SC = mcglite.SC;
  // configure external clock if selected (if not let the previous configuration)
  // or switch between 2MHz and 8Mhz LIRC
  MCG_C2 = (MCG_C2&0x3C)|mcglite.C2;
  // if oscilator selected as ext. clock source wait for initialization cycles done
  if (MCG_C2 & MCG_C2_EREFS0_MASK) 
  { 
    WAIT_FOR_STATUS_FLAG (MCG_C2, EREFS0, OSCINIT0); 
  }
  // Enable HIRC if required
  // Note: do not disable HIRC yet if currently in HIRC mode
  MCG_MC |= (mcglite.MC&MCG_MC_HIRCEN_MASK);
  // select clock source
  MCG_C1 = mcglite.C1;
  // Write all correct required data
  MCG_C2 = mcglite.C2;
  // wait for proper clock source selection (valid for all modes EXTCLK, HIRC, LIRC)
  WAIT_FOR_STATUS_FLAG (MCG_C1, CLKS, CLKST);
  // disable HIRC if required and select second LIRC divider
  MCG_MC = mcglite.MC;
}
Beispiel #4
0
void PEE(void)
{
	  MCG->C6 &= ~MCG_C6_CME0_MASK;

    MCG->C2 &= ~MCG_C2_LP_MASK;
    MCG->C2 |= MCG_C2_RANGE0(3) |// Very high frequency range selected for the crystal oscillator 
               MCG_C2_EREFS0_MASK ;

    MCG->C5 &= ~MCG_C5_PRDIV0_MASK;
    MCG->C5 |= MCG_C5_PRDIV0(2 - 1); // External clock div 4
    
    MCG->C6 &= ~MCG_C6_VDIV0_MASK;
    MCG->C6 |= MCG_C6_VDIV0(24 - 24) | // Mul 24. 8 / 4 * 24 = 48MHz
               MCG_C6_CME0_MASK |
               MCG_C6_PLLS_MASK;
		
		MCG->C1 &= ~MCG_C1_CLKS_MASK;
    MCG->C1 |= ~MCG_C1_CLKS_MASK | // Output of PLL is selected for MCGOUTCLK
								MCG_C1_FRDIV(3) |
								MCG_C1_IRCLKEN_MASK;
	
    while((MCG->S & MCG_S_OSCINIT0_MASK) == 0); // wait for osc init.
    while((MCG->S & MCG_S_PLLST_MASK) != MCG_S_PLLST_MASK); // wait for PLL
    while((MCG->S & MCG_S_CLKST_MASK) != MCG_S_CLKST(3)); // wait for PLL is selected
		
		SIM->CLKDIV1 = SIM_CLKDIV1_OUTDIV1(2 - 1) |  // core/system clock = MCGOUTCLK / 2 = 96 / 2 = 48MHz
									 SIM_CLKDIV1_OUTDIV4(2 - 1);   // flash/bus clock = core/system / 2 = 24MHz
}
Beispiel #5
0
/**
 * @brief Initialize the PLL Bypassed External Mode.
 *
 * MCGOUTCLK is derived from external reference clock (oscillator).
 * PLL output is not used.
 * Clock source is the external reference clock (oscillator).
 * The PLL loop will locks to VDIV times the frequency
 * corresponding by PRDIV.
 * Previous allowed mode are FBE or BLPE.
 */
static void kinetis_mcg_set_pbe(void)
{
    /* select external reference clock and divide factor */
    MCG->C1 = (uint8_t)(MCG_C1_CLKS(2) | MCG_C1_FRDIV(KINETIS_MCG_ERC_FRDIV));

    /* Wait until ERC is selected */
    while ((MCG->S & MCG_S_CLKST_MASK) != MCG_S_CLKST(2));

    /* PLL is not disabled in bypass mode */
    MCG->C2 &= ~(uint8_t)(MCG_C2_LP_MASK);

    /* set external reference devider */
    MCG->C5 = (uint8_t)(MCG_C5_PRDIV0(KINETIS_MCG_PLL_PRDIV));

    /* set external reference devider */
    MCG->C6 = (uint8_t)(MCG_C6_VDIV0(KINETIS_MCG_PLL_VDIV0));

    /* select PLL */
    MCG->C6 |= (uint8_t)(MCG_C6_PLLS_MASK);

    /* Wait until the source of the PLLS clock is PLL */
    while ((MCG->S & MCG_S_PLLST_MASK) == 0);

    /* Wait until PLL locked */
    while ((MCG->S & MCG_S_LOCK0_MASK) == 0);

    current_mode = KINETIS_MCG_PBE;
}
Beispiel #6
0
void FBE_Mode(void)
{		
	/* MCG->C1: CLKS=2,FRDIV=3,IREFS=0,IRCLKEN=1,IREFSTEN=0 */
	MCG->C1 &= ~MCG_C1_IREFS_MASK;	// External reference clock is selected.
	MCG->C1 |= MCG_C1_CLKS(2)|      
						 MCG_C1_FRDIV(3); 		// Output of FLL is selected for MCGOUTCLK, Divide Factor is 256
	
	/* MCG_C2: LOCRE0=0,RANGE0=3,HGO0=0,EREFS0=1,LP=0,IRCS=0 */
	MCG->C2 |= MCG_C2_RANGE0(3) | 	// Very high frequency range selected for the crystal oscillator 
             MCG_C2_EREFS0_MASK;  // Oscillator requested
	
	/* OSC0->CR: ERCLKEN=1,??=0,EREFSTEN=0,??=0,SC2P=1,SC4P=0,SC8P=0,SC16P=0 */
  OSC0->CR = (uint8_t)0x80U;
	
	/* MCG->C4: DMX32=0,DRST_DRS=1 */
	MCG->C4 &= ~MCG_C4_DMX32_MASK;
	MCG->C4 |= MCG_C4_DRST_DRS_MASK; // MCGFLLCLK: 31.25kHz * 1280 = 40MHz

	/* MCG->C6: LOLIE0=0,PLLS=0,CME0=0,VDIV0=0 */
	MCG->C6 &= ~MCG_C6_CME0_MASK;		 // External clock monitor is disabled for OSC0
	MCG->C6 &= ~MCG_C6_PLLS_MASK;		 // FLL is selected
	
  while((MCG->S & MCG_S_IREFST_MASK) != 0); 						// wait for External clock is selected
  while((MCG->S & MCG_S_CLKST_MASK) != MCG_S_CLKST(2)); // wait for EXTAL is selected

	/* SIM->CLKDIV1: OUTDIV1=0,OUTDIV4=0,*/
	/* OUTDIV1 = 0 (Divide-by-1), OUTDIV4 = 0 (Divide-by-1) */
	SIM->CLKDIV1 &= ~SIM_CLKDIV1_OUTDIV1_MASK;  // MCGOUTCLK = 8MHz; Core clock = 8/1 = 8 MHz
	SIM->CLKDIV1 &= ~SIM_CLKDIV1_OUTDIV4_MASK;   // Bus clock = 8/1 = 8MHz
}
Beispiel #7
0
/**
 * @brief Initialize the PLL Engaged External Mode.
 *
 * MCGOUTCLK is derived from PLL.
 * PLL output is used.
 * Previous and next allowed mode is PBE.
 */
static void kinetis_mcg_set_pee(void)
{
    MCG->C1 &= ~(uint8_t)(MCG_C1_CLKS_MASK);

    /* Wait until output of the PLL is selected */
    while ((MCG->S & MCG_S_CLKST_MASK) != MCG_S_CLKST(3));

    current_mode = KINETIS_MCG_PEE;
}
Beispiel #8
0
/*
** ===================================================================
**     Method      :  Cpu_SetOperationMode (component MK40DN512MD10)
**
**     Description :
**         This method requests to change the component's operation
**         mode (RUN, WAIT, SLEEP, STOP). The target operation mode
**         will be entered immediately.
**         See <Operation mode settings> for further details of the
**         operation modes mapping to low power modes of the cpu.
**     Parameters  :
**         NAME            - DESCRIPTION
**         OperationMode   - Requested driver
**                           operation mode
**         ModeChangeCallback - Callback to
**                           notify the upper layer once a mode has been
**                           changed. Parameter is ignored, only for
**                           compatibility of API with other components.
**       * ModeChangeCallbackParamPtr
**                           - Pointer to callback parameter to notify
**                           the upper layer once a mode has been
**                           changed. Parameter is ignored, only for
**                           compatibility of API with other components.
**     Returns     :
**         ---             - Error code
**                           ERR_OK - OK
**                           ERR_PARAM_MODE - Invalid operation mode
** ===================================================================
*/
LDD_TError Cpu_SetOperationMode(LDD_TDriverOperationMode OperationMode, LDD_TCallback ModeChangeCallback, LDD_TCallbackParam *ModeChangeCallbackParamPtr)
{
  (void) ModeChangeCallback;           /* Parameter is not used, suppress unused argument warning */
  (void) ModeChangeCallbackParamPtr;   /* Parameter is not used, suppress unused argument warning */
  switch (OperationMode) {
    case DOM_RUN:
      /* SCB_SCR: SLEEPDEEP=0,SLEEPONEXIT=0 */
      SCB_SCR &= (uint32_t)~0x06UL;
      if  (ClockConfigurationID != 2U) {
        if ((MCG_S & MCG_S_CLKST_MASK) != MCG_S_CLKST(3)) { /* If in PBE mode, switch to PEE. PEE to PBE transition was caused by wakeup from low power mode. */
          /* MCG_C1: CLKS=0,IREFS=0 */
          MCG_C1 &= (uint8_t)~(uint8_t)0xC4U;
          while( (MCG_S & MCG_S_LOCK0_MASK) == 0x00U) { /* Wait for PLL lock */
          }
        }
      }
      break;
    case DOM_WAIT:
      /* SCB_SCR: SLEEPDEEP=0 */
      SCB_SCR &= (uint32_t)~0x04UL;
      /* SCB_SCR: SLEEPONEXIT=0 */
      SCB_SCR &= (uint32_t)~0x02UL;
      PE_WFI();
      break;
    case DOM_SLEEP:
      /* SCB_SCR: SLEEPDEEP=0 */
      SCB_SCR &= (uint32_t)~0x04UL;
      /* SMC_PMCTRL: STOPM=0 */
      SMC_PMCTRL &= (uint8_t)~(uint8_t)0x07U;
      /* SCB_SCR: SLEEPONEXIT=1 */
      SCB_SCR |= (uint32_t)0x02UL;
      PE_WFI();
      break;
    case DOM_STOP:
    /* Clear LLWU flags */
      /* LLWU_F1: WUF7=1,WUF6=1,WUF5=1,WUF4=1,WUF3=1,WUF2=1,WUF1=1,WUF0=1 */
      LLWU_F1 = (uint8_t)0xFFU;
      /* LLWU_F2: WUF15=1,WUF14=1,WUF13=1,WUF12=1,WUF11=1,WUF10=1,WUF9=1,WUF8=1 */
      LLWU_F2 = (uint8_t)0xFFU;
      /* LLWU_F3: MWUF7=1,MWUF6=1,MWUF5=1,MWUF4=1,MWUF3=1,MWUF2=1,MWUF1=1,MWUF0=1 */
      LLWU_F3 = (uint8_t)0xFFU;
      /* SCB_SCR: SLEEPONEXIT=0 */
      SCB_SCR &= (uint32_t)~0x02UL;
      /* SCB_SCR: SLEEPDEEP=1 */
      SCB_SCR |= (uint32_t)0x04UL;
      /* SMC_PMCTRL: STOPM=3 */
      SMC_PMCTRL = (uint8_t)((SMC_PMCTRL & (uint8_t)~(uint8_t)0x04U) | (uint8_t)0x03U);
      PE_WFI();
      break;
    default:
      return ERR_PARAM_MODE;
  }
  return ERR_OK;
}
Beispiel #9
0
/**
 * @brief Initialize the FLL Engaged External Mode.
 *
 * MCGOUTCLK is derived from the FLL clock.
 * Clock source is the external reference clock (IRC or oscillator).
 * The FLL loop will lock the DCO frequency to the FLL-Factor.
 */
static void kinetis_mcg_set_fee(void)
{
    kinetis_mcg_enable_osc();
    kinetis_mcg_set_fll_factor(KINETIS_MCG_FLL_FACTOR_FEE);

    /* select external reference clock and divide factor */
    MCG->C1 = (uint8_t)(MCG_C1_CLKS(0) | MCG_C1_FRDIV(KINETIS_MCG_ERC_FRDIV));

    /* Wait until output of FLL is selected */
    while ((MCG->S & MCG_S_CLKST_MASK) != MCG_S_CLKST(0));

    kinetis_mcg_disable_pll();
    current_mode = KINETIS_MCG_FEE;
}
Beispiel #10
0
/**
 * @brief Initialize the FLL Bypassed External Mode.
 *
 * MCGOUTCLK is derived from external reference clock (oscillator).
 * FLL output is not used.
 * Clock source is the external reference clock (oscillator).
 * The FLL loop will lock the DCO frequency to the FLL-Factor.
 */
static void kinetis_mcg_set_fbe(void)
{
    kinetis_mcg_enable_osc();
    kinetis_mcg_set_fll_factor(KINETIS_MCG_FLL_FACTOR_FEE);

    /* FLL is not disabled in bypass mode */
    MCG->C2 &= ~(uint8_t)(MCG_C2_LP_MASK);

    /* select external reference clock and divide factor */
    MCG->C1 = (uint8_t)(MCG_C1_CLKS(2) | MCG_C1_FRDIV(KINETIS_MCG_ERC_FRDIV));

    /* Wait until ERC is selected */
    while ((MCG->S & MCG_S_CLKST_MASK) != MCG_S_CLKST(2));

    kinetis_mcg_disable_pll();
    current_mode = KINETIS_MCG_FBE;
}
Beispiel #11
0
/* ===================================================================*/
LDD_TError Cpu_SetOperationMode(LDD_TDriverOperationMode OperationMode, LDD_TCallback ModeChangeCallback, LDD_TCallbackParam *ModeChangeCallbackParamPtr)
{
  (void) ModeChangeCallback;           /* Parameter is not used, suppress unused argument warning */
  (void) ModeChangeCallbackParamPtr;   /* Parameter is not used, suppress unused argument warning */
  switch (OperationMode) {
    case DOM_RUN:
      /* SCB_SCR: SLEEPDEEP=0,SLEEPONEXIT=0 */
      SCB_SCR &= (uint32_t)~(uint32_t)(
                  SCB_SCR_SLEEPDEEP_MASK |
                  SCB_SCR_SLEEPONEXIT_MASK
                 );
      if  (ClockConfigurationID != 2U) {
        if ((MCG_S & MCG_S_CLKST_MASK) != MCG_S_CLKST(3)) { /* If in PBE mode, switch to PEE. PEE to PBE transition was caused by wakeup from low power mode. */
          /* MCG_C1: CLKS=0,IREFS=0 */
          MCG_C1 &= (uint8_t)~(uint8_t)((MCG_C1_CLKS(0x03) | MCG_C1_IREFS_MASK));
          while( (MCG_S & MCG_S_LOCK0_MASK) == 0x00U) { /* Wait for PLL lock */
          }
        }
      }
      break;
    case DOM_WAIT:
      /* SCB_SCR: SLEEPDEEP=0 */
      SCB_SCR &= (uint32_t)~(uint32_t)(SCB_SCR_SLEEPDEEP_MASK);
      /* SCB_SCR: SLEEPONEXIT=0 */
      SCB_SCR &= (uint32_t)~(uint32_t)(SCB_SCR_SLEEPONEXIT_MASK);
      PE_WFI();
      break;
    case DOM_SLEEP:
      /* SCB_SCR: SLEEPDEEP=1 */
      SCB_SCR |= SCB_SCR_SLEEPDEEP_MASK;
      /* SMC_PMCTRL: STOPM=0 */
      SMC_PMCTRL &= (uint8_t)~(uint8_t)(SMC_PMCTRL_STOPM(0x07));
      (void)(SMC_PMCTRL == 0U);        /* Dummy read of SMC_PMCTRL to ensure the register is written before enterring low power mode */
      /* SCB_SCR: SLEEPONEXIT=1 */
      SCB_SCR |= SCB_SCR_SLEEPONEXIT_MASK;
      PE_WFI();
      break;
    case DOM_STOP:
      break;
    default:
      return ERR_PARAM_MODE;
  }
  return ERR_OK;
}
/**
 * Update SystemCoreClock variable
 *
 * @brief  Updates the SystemCoreClock with current core Clock
 *         retrieved from CPU registers.
 */
void SystemCoreClockUpdate(void) {
   uint32_t oscerclk = OSCCLK_CLOCK;
   switch (MCG_S&MCG_S_CLKST_MASK) {
      case MCG_S_CLKST(0) : // FLL
         if ((MCG_C1&MCG_C1_IREFS_MASK) == 0) {
            SystemCoreClock = oscerclk/(1<<((MCG_C1&MCG_C1_FRDIV_MASK)>>MCG_C1_FRDIV_SHIFT));
            if ((MCG_C2&MCG_C2_RANGE0_MASK) != 0) {
               if ((MCG_C1&MCG_C1_FRDIV_M) == MCG_C1_FRDIV(6)) {
                  SystemCoreClock /= 20;
               }
               else if ((MCG_C1&MCG_C1_FRDIV_M) == MCG_C1_FRDIV(7)) {
                  SystemCoreClock /= 12;
               }
               else {
                  SystemCoreClock /= 32;
               }
            }
         }
         else {
/*!
 * @brief Update SystemCoreClock variable
 *
 * Updates the SystemCoreClock variable with current core Clock retrieved from CPU registers.
 */
void SystemCoreClockUpdate(void) {
   uint32_t oscerclk = (MCG->C7&MCG_C7_OSCSEL_MASK)?RTCCLK_CLOCK:OSCCLK0_CLOCK;
   switch (MCG->S&MCG_S_CLKST_MASK) {
      case MCG_S_CLKST(0) : // FLL
         SystemCoreClock = (MCG->C4&MCG_C4_DMX32_MASK)?732:640;
         if ((MCG->C1&MCG_C1_IREFS_MASK) == 0) {
            SystemCoreClock *= oscerclk/(1<<((MCG->C1&MCG_C1_FRDIV_MASK)>>MCG_C1_FRDIV_SHIFT));
            if (((MCG->C2&MCG_C2_RANGE0_MASK) != 0) && ((MCG->C7&MCG_C7_OSCSEL_MASK) !=  1)) {
               if ((MCG->C1&MCG_C1_FRDIV_MASK) == MCG_C1_FRDIV(6)) {
                  SystemCoreClock /= 20;
               }
               else if ((MCG->C1&MCG_C1_FRDIV_MASK) == MCG_C1_FRDIV(7)) {
                  SystemCoreClock /= 12;
               }
               else {
                  SystemCoreClock /= 32;
               }
            }
         }
         else {
Beispiel #14
0
status_t CLOCK_SetPbeMode(mcg_pll_clk_select_t pllcs, mcg_pll_config_t const *config)
{
    assert(config);

    /*
       This function is designed to change MCG to PBE mode from PEE/BLPE/FBE,
       but with this workflow, the source mode could be all modes except PEI/PBI.
     */
    MCG->C2 &= ~MCG_C2_LP_MASK; /* Disable lowpower. */

    /* Change to use external clock first. */
    MCG->C1 = ((MCG->C1 & ~(MCG_C1_CLKS_MASK | MCG_C1_IREFS_MASK)) | MCG_C1_CLKS(kMCG_ClkOutSrcExternal));

    /* Wait for CLKST clock status bits to show clock source is ext ref clk */
    while ((MCG->S & (MCG_S_IREFST_MASK | MCG_S_CLKST_MASK)) !=
           (MCG_S_IREFST(kMCG_FllSrcExternal) | MCG_S_CLKST(kMCG_ClkOutStatExt)))
    {
    }

    /* Disable PLL first, then configure PLL. */
    MCG->C6 &= ~MCG_C6_PLLS_MASK;
    while (MCG->S & MCG_S_PLLST_MASK)
    {
    }

    /* Configure the PLL. */
    {
        CLOCK_EnablePll0(config);
    }

    /* Change to PLL mode. */
    MCG->C6 |= MCG_C6_PLLS_MASK;

    /* Wait for PLL mode changed. */
    while (!(MCG->S & MCG_S_PLLST_MASK))
    {
    }

    return kStatus_Success;
}
Beispiel #15
0
/* Switch to PBE Mode */
void PBE(void)
{
	  MCG->C6 &= ~MCG_C6_CME0_MASK;

    MCG->C2 &= ~MCG_C2_LP_MASK;
    MCG->C2 |= MCG_C2_RANGE0(3) |// Very high frequency range selected for the crystal oscillator 
               MCG_C2_EREFS0_MASK;

    MCG->C5 &= ~MCG_C5_PRDIV0_MASK;
    MCG->C5 |= MCG_C5_PRDIV0(2 - 1); // External clock div 2
    
    MCG->C6 &= ~MCG_C6_VDIV0_MASK;
    MCG->C6 |= MCG_C6_VDIV0(24 - 24) | // Mul 24. 8 / 2 * 24 = 96MHz
               MCG_C6_CME0_MASK |
               MCG_C6_PLLS_MASK;

    MCG->C1 &= ~MCG_C1_CLKS_MASK;
    MCG->C1 |= MCG_C1_CLKS(2); // Output of ExTAL is selected for MCGOUTCLK
    
    while((MCG->S & MCG_S_OSCINIT0_MASK) == 0); // wait for osc init.
    while((MCG->S & MCG_S_PLLST_MASK) != MCG_S_PLLST_MASK); // wait for PLL
    while((MCG->S & MCG_S_CLKST_MASK) != MCG_S_CLKST(2)); // wait for EXTAL is selected
}
Beispiel #16
0
/**
 * @brief Initialize the FLL Bypassed Internal Mode.
 *
 * MCGOUTCLK is derived from 32kHz IRC or 4MHz IRC.
 * FLL output is not used.
 * FLL clock source is internal 32kHz IRC.
 * The FLL loop will lock the DCO frequency to the FLL-Factor.
 * Next useful mode: BLPI or FEI.
 */
static void kinetis_mcg_set_fbi(void)
{
    /* select IRC source */
    if (KINETIS_MCG_USE_FAST_IRC) {
        MCG->C2 = (uint8_t)(MCG_C2_IRCS_MASK);
    }
    else {
        MCG->C2 = (uint8_t)(0);
    }

    kinetis_mcg_set_fll_factor(KINETIS_MCG_FLL_FACTOR_FEI);
    /* enable and select slow internal reference clock */
    MCG->C1 = (uint8_t)(MCG_C1_CLKS(1) | MCG_C1_IREFS_MASK);

    /* Wait until output of IRC is selected */
    while ((MCG->S & MCG_S_CLKST_MASK) != MCG_S_CLKST(1));

    /* source of the FLL reference clock shall be internal reference clock */
    while ((MCG->S & MCG_S_IREFST_MASK) == 0);

    kinetis_mcg_disable_pll();
    current_mode = KINETIS_MCG_FBI;
}
/*! Sets up the clock out of RESET
 *!
 */
void clock_initialise(void) {

#if (CLOCK_MODE == CLOCK_MODE_RESET)
   // No clock setup
#else
   // XTAL/EXTAL Pins
   SIM_SCGC5  |= SIM_SCGC5_PORTA_MASK;
   PORTA_PCR3  = PORT_PCR_MUX(0);
   PORTA_PCR4  = PORT_PCR_MUX(0);

   // Configure the Crystal Oscillator
   OSC0_CR = OSC_CR_ERCLKEN_M|OSC_CR_EREFSTEN_M|OSC_CR_SCP_M;

   // Fast Internal Clock divider
   MCG_SC = MCG_SC_FCRDIV_M;

   // Out of reset MCG is in FEI mode
   // =============================================================

   SIM_CLKDIV1 = SIM_CLKDIV1_OUTDIV1(3) | SIM_CLKDIV1_OUTDIV2(7) | SIM_CLKDIV1_OUTDIV3(3) | SIM_CLKDIV1_OUTDIV4(7);

   // Switch from FEI -> FEI/FBI/FEE/FBE
   // =============================================================

   // Set up crystal or external clock source
   MCG_C2 =
            MCG_C2_LOCRE0_M     | // LOCRE0 = 0,1   -> Loss of clock reset
            MCG_C2_RANGE0_M     | // RANGE0 = 0,1,2 -> Oscillator low/high/very high clock range
            MCG_C2_HGO0_M       | // HGO0   = 0,1   -> Oscillator low power/high gain
            MCG_C2_EREFS0_M     | // EREFS0 = 0,1   -> Select external clock/crystal oscillator
            MCG_C2_IRCS_M;        // IRCS   = 0,1   -> Select slow/fast internal clock for internal reference

#if ((CLOCK_MODE == CLOCK_MODE_FEI) || (CLOCK_MODE == CLOCK_MODE_FBI) || (CLOCK_MODE == CLOCK_MODE_BLPI) )
   // Transition via FBI
   //=====================================
#define BYPASS (1) // CLKS value used while FLL locks
   MCG_C1 =  MCG_C1_CLKS(BYPASS)     | // CLKS     = 2     -> External reference source while PLL locks
             MCG_C1_FRDIV_M          | // FRDIV    = N     -> XTAL/2^n ~ 31.25 kHz
             MCG_C1_IREFS_M          | // IREFS    = 0,1   -> External/Slow IRC for FLL source
             MCG_C1_IRCLKEN_M        | // IRCLKEN  = 0,1   -> IRCLK disable/enable
             MCG_C1_IREFSTEN_M;        // IREFSTEN = 0,1   -> Internal reference enabled in STOP mode

   // Wait for S_IREFST to indicate FLL Reference has switched
   do {
      __asm__("nop");
   } while ((MCG_S & MCG_S_IREFST_MASK) != (MCG_C1_IREFS_V<<MCG_S_IREFST_SHIFT));

   // Wait for S_CLKST to indicating that OUTCLK has switched to bypass PLL/FLL
   do {
      __asm__("nop");
   } while ((MCG_S & MCG_S_CLKST_MASK) != MCG_S_CLKST(BYPASS));

   // Set FLL Parameters
   MCG_C4 = (MCG_C4&~(MCG_C4_DMX32_MASK|MCG_C4_DRST_DRS_MASK))|MCG_C4_DMX32_M|MCG_C4_DRST_DRS_M;
#endif

#if ((CLOCK_MODE == CLOCK_MODE_FBE) || (CLOCK_MODE == CLOCK_MODE_FEE) || (CLOCK_MODE == CLOCK_MODE_PLBE) || (CLOCK_MODE == CLOCK_MODE_PBE) || (CLOCK_MODE == CLOCK_MODE_PEE))

   // Transition via FBE
   //=====================================
#define BYPASS (2) // CLKS value used while PLL locks
   MCG_C1 =  MCG_C1_CLKS(BYPASS)     | // CLKS     = 2     -> External reference source while PLL locks
             MCG_C1_FRDIV_M          | // FRDIV    = N     -> XTAL/2^n ~ 31.25 kHz
             MCG_C1_IREFS_M          | // IREFS    = 0,1   -> External/Slow IRC for FLL source
             MCG_C1_IRCLKEN_M        | // IRCLKEN  = 0,1   -> IRCLK disable/enable
             MCG_C1_IREFSTEN_M;        // IREFSTEN = 0,1   -> Internal reference enabled in STOP mode

#if (MCG_C2_EREFS_V != 0)
   // Wait for oscillator stable (if used)
   do {
      __asm__("nop");
   } while ((MCG_S & MCG_S_OSCINIT0_MASK) == 0);
#endif

   // Wait for S_IREFST to indicate FLL Reference has switched
   do {
      __asm__("nop");
   } while ((MCG_S & MCG_S_IREFST_MASK) != (MCG_C1_IREFS_V<<MCG_S_IREFST_SHIFT));

   // Wait for S_CLKST to indicating that OUTCLK has switched to bypass PLL/FLL
   do {
      __asm__("nop");
   } while ((MCG_S & MCG_S_CLKST_MASK) != MCG_S_CLKST(BYPASS));

   // Set FLL Parameters
   MCG_C4 = (MCG_C4&~(MCG_C4_DMX32_MASK|MCG_C4_DRST_DRS_MASK))|MCG_C4_DMX32_M|MCG_C4_DRST_DRS_M;
#endif

   // Select FEI/FBI/FEE/FBE clock mode
   MCG_C1 =  MCG_C1_CLKS_M       | // CLKS     = 0,1,2 -> Select FLL/IRCSCLK/ERCLK
             MCG_C1_FRDIV_M      | // FRDIV    = N     -> XTAL/2^n ~ 31.25 kHz
             MCG_C1_IREFS_M      | // IREFS    = 0,1   -> External/Slow IRC for FLL source
             MCG_C1_IRCLKEN_M    | // IRCLKEN  = 0,1   -> IRCLK disable/enable
             MCG_C1_IREFSTEN_M;    // IREFSTEN = 0,1   -> Internal reference enabled in STOP mode

   // Wait for mode change
   do {
      __asm__("nop");
   } while ((MCG_S & MCG_S_IREFST_MASK) != (MCG_C1_IREFS_V<<MCG_S_IREFST_SHIFT));

#if defined (MCG_C6_PLLS_V) && (MCG_C1_CLKS_V == 0) // FLL or PLL
#define MCG_S_CLKST_M MCG_S_CLKST(MCG_C6_PLLS_V?3:0)
#else
   #define MCG_S_CLKST_M MCG_S_CLKST(MCG_C1_CLKS_V)
#endif

   // Wait for S_CLKST to indicating that OUTCLK has switched
   do {
      __asm__("nop");
   } while ((MCG_S & MCG_S_CLKST_MASK) != MCG_S_CLKST_M);

   // Set the SIM _CLKDIV dividers
   SIM_CLKDIV1 = SIM_CLKDIV1_OUTDIV1_M | SIM_CLKDIV1_OUTDIV2_M | SIM_CLKDIV1_OUTDIV3_M | SIM_CLKDIV1_OUTDIV4_M;

#if (CLOCK_MODE == CLOCK_MODE_BLPE) || (CLOCK_MODE == CLOCK_MODE_BLPI)
   // Select BLPE/BLPI clock mode
   MCG_C2 =
            MCG_C2_LOCRE0_M      | // LOCRE0 = 0,1   -> Loss of clock reset
            MCG_C2_RANGE0_M      | // RANGE0 = 0,1,2 -> Oscillator low/high/very high clock range
            MCG_C2_HGO0_M        | // HGO0   = 0,1   -> Oscillator low power/high gain
            MCG_C2_EREFS0_M      | // EREFS0 = 0,1   -> Select external clock/crystal oscillator
            MCG_C2_LP_M          | // LP     = 0,1   -> Select FLL enabled/disabled in bypass mode
            MCG_C2_IRCS_M;         // IRCS   = 0,1   -> Select slow/fast internal clock for internal reference

#endif // (CLOCK_MODE == CLOCK_MODE_BLPE) || (CLOCK_MODE == CLOCK_MODE_BLPI)
#endif // (CLOCK_MODE == CLOCK_MODE_RESET)

   // Basic clock multiplexing
#if defined(MCU_MK20D5) || defined(MCU_MK20D7) || defined(MCU_MK40D10) || defined(MCU_MK40DZ10)
   // Peripheral clock choice (incl. USB), USBCLK = MCGCLK
   SIM_SOPT2 |= SIM_SOPT2_PLLFLLSEL_M    | // PLL rather than FLL for peripheral clock
                SIM_SOPT2_USBSRC_MASK;     // MCGPLLCLK/2 Source as USB clock (48MHz req.)
   SIM_SOPT1 = (SIM_SOPT1&~SIM_SOPT1_OSC32KSEL_MASK)|SIM_SOPT1_OSC32KSEL_M; // ERCLK32K source
#elif defined(MCU_MK60D10) || defined(MCU_MK60DZ10)
   // Peripheral clock choice (incl. USB), USBCLK = MCGCLK
   SIM_SOPT2 |= SIM_SOPT2_PLLFLLSEL_MASK | // PLL rather than FLL for peripheral clock
                SIM_SOPT2_USBSRC_MASK;     // MCGPLLCLK/2 Source as USB clock (48MHz req.)
#elif defined(MCU_MKL24Z4) || defined(MCU_MKL25Z4) || defined(MCU_MKL26Z4) || defined(MCU_MKL46Z4)
   SIM_SOPT2 = SIM_SOPT2_UART0SRC_M      | // UART0 clock - 0,1,2,3 -> Disabled, (MCGFLLCLK, MCGPLLCLK/2),  OSCERCLK, MCGIRCLK
               SIM_SOPT2_TPMSRC_M        | // TPM clock - 0,1,2,3 -> Disabled, (MCGFLLCLK, MCGPLLCLK/2),  OSCERCLK, MCGIRCLK
               SIM_SOPT2_PLLFLLSEL_M     | // Peripheral clock - 0,1 -> MCGFLLCLK,MCGPLLCLK/2
               SIM_SOPT2_USBSRC_MASK;      // MCGPLLCLK/2 Source as USB clock (48MHz req.)
   SIM_SOPT1 = (SIM_SOPT1&~SIM_SOPT1_OSC32KSEL_MASK)|SIM_SOPT1_OSC32KSEL_M; // ERCLK32K clock - 0,1,2,3 -> OSC32KCLK, - , RTC_CLKIN, LPO (1kHz)
#elif defined(MCU_MKL14Z4) || defined(MCU_MKL15Z4) || defined(MCU_MKL16Z4) || defined(MCU_MKL34Z4) || defined(MCU_MKL36Z4)
   SIM_SOPT2 = SIM_SOPT2_UART0SRC_M      | // UART0 clock - 0,1,2,3 -> Disabled, (MCGFLLCLK, MCGPLLCLK/2),  OSCERCLK, MCGIRCLK
               SIM_SOPT2_TPMSRC_M        | // TPM clock - 0,1,2,3 -> Disabled, (MCGFLLCLK, MCGPLLCLK/2),  OSCERCLK, MCGIRCLK
               SIM_SOPT2_PLLFLLSEL_M;      // Peripheral clock - 0,1 -> MCGFLLCLK,MCGPLLCLK/2
   SIM_SOPT1 = (SIM_SOPT1&~SIM_SOPT1_OSC32KSEL_MASK)|SIM_SOPT1_OSC32KSEL_M; // ERCLK32K clock - 0,1,2,3 -> OSC32KCLK, - , RTC_CLKIN, LPO (1kHz)
#elif defined(MCU_MKL02Z4) || defined(MCU_MKL04Z4) || defined(MCU_MKL05Z4)
   SIM_SOPT2 = SIM_SOPT2_UART0SRC_M      | // UART0 clock - 0,1,2,3 -> Disabled, (MCGFLLCLK, MCGPLLCLK/2),  OSCERCLK, MCGIRCLK
               SIM_SOPT2_TPMSRC_M ;        // TPM2 source
#else
   #error "CPU not set"
#endif
   SystemCoreClockUpdate();
}
Beispiel #18
0
void ResetHandler(void)
{
    /*
     * Enable watchdog timer. Allow settings to be changed later, in case the
     * application firmware wants to adjust its settings or disable it.
     *
     * Originally I tried using the 1 kHz low-power oscillator here, but that seemed to
     * run into an issue where refreshes weren't taking effect. It seems similar to
     * this problem on the Freescale forums, which didn't really have a satisfactory
     * solution:
     *
     *  https://community.freescale.com/thread/309519
     *
     * As a workaround, I'm using the "alternate" system clock.
     */
    {
        const uint32_t watchdog_timeout = F_BUS / 100;  // 10ms

        WDOG_UNLOCK = WDOG_UNLOCK_SEQ1;
        WDOG_UNLOCK = WDOG_UNLOCK_SEQ2;
        asm volatile ("nop");
        asm volatile ("nop");
        WDOG_STCTRLH = WDOG_STCTRLH_ALLOWUPDATE | WDOG_STCTRLH_WDOGEN |
            WDOG_STCTRLH_WAITEN | WDOG_STCTRLH_STOPEN | WDOG_STCTRLH_CLKSRC;
        WDOG_PRESC = 0;
        WDOG_TOVALH = watchdog_timeout >> 16;
        WDOG_TOVALL = watchdog_timeout;
    }

    // enable clocks to always-used peripherals
    SIM_SCGC5 = 0x00043F82;     // clocks active to all GPIO
    SIM_SCGC6 = SIM_SCGC6_RTC | SIM_SCGC6_FTM0 | SIM_SCGC6_FTM1 | SIM_SCGC6_ADC0 | SIM_SCGC6_FTFL;

    // release I/O pins hold, if we woke up from VLLS mode
    if (PMC_REGSC & PMC_REGSC_ACKISO) PMC_REGSC |= PMC_REGSC_ACKISO;

    // start in FEI mode
    // enable capacitors for crystal
    OSC0_CR = OSC_SC8P | OSC_SC2P;
    // enable osc, 8-32 MHz range, low power mode
    MCG_C2 = MCG_C2_RANGE0(2) | MCG_C2_EREFS;
    // switch to crystal as clock source, FLL input = 16 MHz / 512
    MCG_C1 =  MCG_C1_CLKS(2) | MCG_C1_FRDIV(4);
    // wait for crystal oscillator to begin
    while ((MCG_S & MCG_S_OSCINIT0) == 0) ;
    // wait for FLL to use oscillator
    while ((MCG_S & MCG_S_IREFST) != 0) ;
    // wait for MCGOUT to use oscillator
    while ((MCG_S & MCG_S_CLKST_MASK) != MCG_S_CLKST(2)) ;
    // now we're in FBE mode
    // config PLL input for 16 MHz Crystal / 4 = 4 MHz
    MCG_C5 = MCG_C5_PRDIV0(3);
    // config PLL for 96 MHz output
    MCG_C6 = MCG_C6_PLLS | MCG_C6_VDIV0(0);

    // Copy things while we're waiting on the PLL
    {
        // Relocate data and text to RAM
        uint32_t *src = &_eflash;
        uint32_t *dest = &_sdtext;
        while (dest < &_edtext) *dest++ = *src++;

        // Clear BSS
        dest = &_sbss;
        while (dest < &_ebss) *dest++ = 0;

        // Copy IVT to RAM
        src = (uint32_t*) &gVectors[0];
        dest = &ramVectors[0];
        while (dest <= &ramVectors[63]) *dest++ = *src++;

        // Switch to ram IVT
        SCB_VTOR = (uint32_t) &ramVectors[0];
    }

    // wait for PLL to start using xtal as its input
    while (!(MCG_S & MCG_S_PLLST)) ;
    // wait for PLL to lock
    while (!(MCG_S & MCG_S_LOCK0)) ;
    // now we're in PBE mode

    // config divisors: 48 MHz core, 48 MHz bus, 24 MHz flash
    SIM_CLKDIV1 = SIM_CLKDIV1_OUTDIV1(1) | SIM_CLKDIV1_OUTDIV2(1) |  SIM_CLKDIV1_OUTDIV4(3);
    // switch to PLL as clock source, FLL input = 16 MHz / 512
    MCG_C1 = MCG_C1_CLKS(0) | MCG_C1_FRDIV(4);
    // wait for PLL clock to be used
    while ((MCG_S & MCG_S_CLKST_MASK) != MCG_S_CLKST(3)) ;
    // now we're in PEE mode
    // configure USB for 48 MHz clock
    SIM_CLKDIV2 = SIM_CLKDIV2_USBDIV(1); // USB = 96 MHz PLL / 2
    // USB uses PLL clock, trace is CPU clock, CLKOUT=OSCERCLK0
    SIM_SOPT2 = SIM_SOPT2_USBSRC | SIM_SOPT2_PLLFLLSEL | SIM_SOPT2_TRACECLKSEL | SIM_SOPT2_CLKOUTSEL(6);

    __enable_irq();
    main();
}
Beispiel #19
0
_mqx_uint _lpm_set_cpu_operation_mode
    (
        /* [IN] Specification of CPU core low power operation modes available */
        const LPM_CPU_OPERATION_MODE _PTR_ operation_modes,

        /* [IN] Low power operation mode identifier */
        LPM_OPERATION_MODE                 target_mode
    )
{

#ifndef PE_LDD_VERSION

    const LPM_CPU_POWER_MODE _PTR_         mode_ptr;
    _mqx_uint                              scr, flags, mcg, index;

    /* Check parameters */
    if ((NULL == operation_modes) || (LPM_OPERATION_MODES <= (_mqx_uint)target_mode))
    {
        return MQX_INVALID_PARAMETER;
    }
    index = operation_modes[target_mode].MODE_INDEX;

    if (LPM_CPU_POWER_MODES <= index)
    {
        return MQX_INVALID_CONFIGURATION;
    }
    mode_ptr = &(LPM_CPU_POWER_MODES_KINETIS[index]);
    flags = mode_ptr->FLAGS | (operation_modes[target_mode].FLAGS & LPM_CPU_POWER_MODE_FLAG_USER_MASK);

    /* Go through Kinetis Run */
    scr = (SCB_SCR & (~ (SCB_SCR_SLEEPDEEP_MASK | SCB_SCR_SLEEPONEXIT_MASK)));
    SCB_SCR = scr;
    MC_PMCTRL = LPM_CPU_POWER_MODES_KINETIS[LPM_CPU_POWER_MODE_RUN].PMCTRL;
    while (0 == (PMC_REGSC & PMC_REGSC_REGONS_MASK))
        { };

    /* Go to VLPW through VLPR */
    if (LPM_CPU_POWER_MODE_VLPW == index)
    {
        MC_PMCTRL = LPM_CPU_POWER_MODES_KINETIS[LPM_CPU_POWER_MODE_VLPR].PMCTRL;
        while (0 == (PMC_REGSC & PMC_REGSC_VLPRS_MASK))
            { };
    }

    /* Setup ARM System control register */
    if (flags & LPM_CPU_POWER_MODE_FLAG_DEEP_SLEEP)
    {
        scr |= SCB_SCR_SLEEPDEEP_MASK;
    }
    if (flags & LPM_CPU_POWER_MODE_FLAG_SLEEP_ON_EXIT)
    {
        scr |= SCB_SCR_SLEEPONEXIT_MASK;
    }
    SCB_SCR = scr;

    /* Setup wakeup unit for LLS mode */
    if (LPM_CPU_POWER_MODE_LLS == index)
    {

        LLWU_PE1 = operation_modes[target_mode].PE1;
        LLWU_PE2 = operation_modes[target_mode].PE2;
        LLWU_PE3 = operation_modes[target_mode].PE3;
        LLWU_PE4 = operation_modes[target_mode].PE4;
        LLWU_ME = operation_modes[target_mode].ME;
        LLWU_F1 = 0xFF;
        LLWU_F2 = 0xFF;
        LLWU_F3 = 0xFF;
    }
	
    /* Keep status of MCG before mode change */
    mcg = MCG_S & MCG_S_CLKST_MASK;

    /* Operation mode setup */
    MC_PMCTRL = mode_ptr->PMCTRL;

    /* Wait for proper setup of VLPR */
    if (LPM_CPU_POWER_MODE_VLPR == index)
    {

        /* K40 P2.2, K60 P2.2 and K20 P1 use different macro from previous chips */
       while (0 == (PMC_REGSC & PMC_REGSC_VLPRS_MASK))
            { };
    }

    /* Go to sleep if required */
    if (flags & LPM_CPU_POWER_MODE_FLAG_USE_WFI)
    {
        _ASM_SLEEP();
    }

    /* After stop modes, reconfigure MCG if needed */
    if ( (LPM_CPU_POWER_MODE_STOP == index)
      || (LPM_CPU_POWER_MODE_VLPS == index)
      || (LPM_CPU_POWER_MODE_LLS == index) )
    {
        if ((MCG_S_CLKST(3) == mcg) && (MCG_S_CLKST(2) == (MCG_S & MCG_S_CLKST_MASK)))
        {
            MCG_C1 &= (~ (MCG_C1_CLKS_MASK | MCG_C1_IREFS_MASK));
            while (0 == (MCG_S & MCG_S_LOCK_MASK))
                { };
        }
    }

    return MQX_OK;

#else

#ifdef Cpu_SetOperationMode_METHOD_ENABLED
    if (LPM_OPERATION_MODES <= (_mqx_uint)target_mode)
    {
        return MQX_INVALID_PARAMETER;
    }
    return Cpu_SetOperationMode (LPM_PE_OPERATION_MODE_MAP[target_mode], NULL, NULL);
#else
    #error Undefined method Cpu_SetOperationMode() in PE CPU component!
#endif

#endif

}
Beispiel #20
0
/**
 * Initialize the system
 *
 * @param  none
 * @return none
 *
 * @brief  Setup the microcontroller system.
 *         Initialize the System.
 */
void SystemInit (void) {
    // system dividers
    SIM_CLKDIV1 = SIM_CLKDIV1_OUTDIV1(0) | SIM_CLKDIV1_OUTDIV2(1) | SIM_CLKDIV1_OUTDIV3(2) | SIM_CLKDIV1_OUTDIV4(5);
    
    
    // after reset, we are in FEI mode
    
    // enable external clock source - OSC0
#if __SYS_OSC_CLK <= 8000000
    MCG_C2 = MCG_C2_LOCRE0_MASK | MCG_C2_RANGE(RANGE0_VAL) | (/*hgo_val*/0 << MCG_C2_HGO_SHIFT) | (/*erefs_val*/0 << MCG_C2_EREFS_SHIFT);
#else
    // On rev. 1.0 of silicon there is an issue where the the input bufferd are enabled when JTAG is connected.
    // This has the affect of sometimes preventing the oscillator from running. To keep the oscillator amplitude
    // low, RANGE = 2 should not be used. This should be removed when fixed silicon is available.
    MCG_C2 = MCG_C2_LOCRE_MASK | MCG_C2_RANGE(2) | (/*hgo_val*/0 << MCG_C2_HGO_SHIFT) | (/*erefs_val*/0 << MCG_C2_EREFS_SHIFT);
//    MCG_C2 = MCG_C2_LOCRE_MASK | MCG_C2_RANGE(1) | (/*hgo_val*/0 << MCG_C2_HGO_SHIFT) | (/*erefs_val*/0 << MCG_C2_EREFS_SHIFT);
#endif
    
    // select clock mode, we want FBE mode
    // CLKS = 2, FRDIV = frdiv_val, IREFS = 0, IRCLKEN = 0, IREFSTEN = 0
    MCG_C1 = MCG_C1_CLKS(2) | MCG_C1_FRDIV(FRDIV_VAL);
    
    /* wait until the MCG has moved into the proper mode */
    // if the external oscillator is used need to wait for OSCINIT to set
//      for (i = 0 ; i < 10000 ; i++)
//      {
//        if (MCG_S & MCG_S_OSCINIT_MASK) break; // jump out early if OSCINIT sets before loop finishes
//      }
//      if (!(MCG_S & MCG_S_OSCINIT_MASK)) return 0x23; // check bit is really set and return with error if not set
    
    // wait for reference clock status bit is cleared and clock source is ext ref clk
    while ((MCG_S & MCG_S_IREFST_MASK) || MCG_S_CLKST(2) != (MCG_S & MCG_S_CLKST_MASK));

    // ... FBE mode
    
    // enable clock monitor for osc0
    MCG_C6 = MCG_C6_CME_MASK;

    // PLL0
    MCG_C5 = MCG_C5_PRDIV(PRDIV_VAL - 1);       // set PLL0 ref divider, osc0 is reference

    MCG_C6 = MCG_C6_PLLS_MASK | MCG_C6_VDIV(VDIV_VAL - 16);     // set VDIV and enable PLL
        
    // wait to lock...
    while (!(MCG_S & MCG_S_PLLST_MASK));
    while (!(MCG_S & MCG_S_LOCK_MASK));
    
//    // Use actual PLL settings to calculate PLL frequency
//    prdiv = ((MCG_C5 & MCG_C5_PRDIV_MASK) + 1);
//    vdiv = ((MCG_C6 & MCG_C6_VDIV_MASK) + 16);

    // ... PBE mode
    MCG_C1 &= ~MCG_C1_CLKS_MASK;        // CLKS = 0, select PLL as MCG_OUT
    
    while (MCG_S_CLKST(3) != (MCG_S & MCG_S_CLKST_MASK));

    // ... PEE mode
    
/* ToDo: add code to initialize the system
         do not use global variables because this function is called before
         reaching pre-main. RW section maybe overwritten afterwards.          */
  SystemCoreClock = __SYSTEM_CLOCK;
}
Beispiel #21
0
_mqx_uint _lpm_set_cpu_operation_mode
    (
        /* [IN] Specification of CPU core low power operation modes available */
        const LPM_CPU_OPERATION_MODE  *operation_modes,

        /* [IN] Low power operation mode identifier */
        LPM_OPERATION_MODE                 target_mode
    )
{

#ifndef PE_LDD_VERSION

    const LPM_CPU_POWER_MODE              *mode_ptr;
    _mqx_uint                              scr, flags, mcg, index, cme;

    /* Check parameters */
    if ((NULL == operation_modes) || (LPM_OPERATION_MODES <= (_mqx_uint)target_mode))
    {
        return MQX_INVALID_PARAMETER;
    }
    index = operation_modes[target_mode].MODE_INDEX;

    if (LPM_CPU_POWER_MODES <= index)
    {
        return MQX_INVALID_CONFIGURATION;
    }
    mode_ptr = &(LPM_CPU_POWER_MODES_KINETIS[index]);
    flags = mode_ptr->FLAGS | (operation_modes[target_mode].FLAGS & LPM_CPU_POWER_MODE_FLAG_USER_MASK);

    /* Go through Kinetis Run */
    scr = (SCB_SCR & (~ (SCB_SCR_SLEEPDEEP_MASK | SCB_SCR_SLEEPONEXIT_MASK)));
    SCB_SCR = scr;
    SMC_PMCTRL = LPM_CPU_POWER_MODES_KINETIS[LPM_CPU_POWER_MODE_RUN].PMCTRL;
    while (0 == (PMC_REGSC & PMC_REGSC_REGONS_MASK))
        { };
    while (SMC_PMSTAT_PMSTAT(1) != SMC_PMSTAT)
        { };
#if MQX_ENABLE_HSRUN
    /* Go to HSRUN through RUN */
    if (LPM_CPU_POWER_MODE_HSRUN == index)
    {
        SMC_PMCTRL = LPM_CPU_POWER_MODES_KINETIS[LPM_CPU_POWER_MODE_HSRUN].PMCTRL;
        while (SMC_PMSTAT_PMSTAT(128) != SMC_PMSTAT)
            { };
    }
#endif
    /* Go to VLPW through VLPR */
    if (LPM_CPU_POWER_MODE_VLPW == index)
    {
        SMC_PMCTRL = LPM_CPU_POWER_MODES_KINETIS[LPM_CPU_POWER_MODE_VLPR].PMCTRL;
        while (SMC_PMSTAT_PMSTAT(4) != SMC_PMSTAT)
            { };
    }

    /* Setup ARM System control register */
    if (flags & LPM_CPU_POWER_MODE_FLAG_DEEP_SLEEP)
    {
        scr |= SCB_SCR_SLEEPDEEP_MASK;
    }
    if (flags & LPM_CPU_POWER_MODE_FLAG_SLEEP_ON_EXIT)
    {
        scr |= SCB_SCR_SLEEPONEXIT_MASK;
    }
    SCB_SCR = scr;

    /* Setup wakeup unit for LLS mode */
    if (LPM_CPU_POWER_MODE_LLS == index)
    {
        LLWU_PE1 = operation_modes[target_mode].PE1;
        LLWU_PE2 = operation_modes[target_mode].PE2;
        LLWU_PE3 = operation_modes[target_mode].PE3;
        LLWU_PE4 = operation_modes[target_mode].PE4;
        LLWU_ME = operation_modes[target_mode].ME;
        LLWU_F1 = 0xFF;
        LLWU_F2 = 0xFF;
        LLWU_F3 = 0xFF;
    }

    /* Setup wake up unit for VLLSx mode */
    if ((LPM_CPU_POWER_MODE_VLLS3 == index)
        || (LPM_CPU_POWER_MODE_VLLS2 == index)
        || (LPM_CPU_POWER_MODE_VLLS1 == index))
    {
        LLWU_PE1 = operation_modes[target_mode].PE1;
        LLWU_PE2 = operation_modes[target_mode].PE2;
        LLWU_PE3 = operation_modes[target_mode].PE3;
        LLWU_PE4 = operation_modes[target_mode].PE4;
        LLWU_ME = operation_modes[target_mode].ME;
        LLWU_F1 = 0xFF;
        LLWU_F2 = 0xFF;
        LLWU_F3 = 0xFF;
#if LLWU_RST_LLRSTE_MASK
        LLWU_RST |= LLWU_RST_LLRSTE_MASK;
#endif
    }

    /* Keep status of MCG before mode change */
    mcg = MCG_S & MCG_S_CLKST_MASK;

    /* Disable CME if enabled before entering changing Power mode */
    cme = MCG_C6 & MCG_C6_CME0_MASK;            /* Save CME state */
    MCG_C6 &= ~(MCG_C6_CME0_MASK);              /* Clear CME */

    /* Operation mode setup */
    SMC_PMCTRL = mode_ptr->PMCTRL;

    /* VLLSx setup */
    switch (index)
    {
#if (BSP_TWR_K22F120M || BSP_TWR_K22F120M256R || BSP_LMQ1 || BSP_K22FSH)
        case LPM_CPU_POWER_MODE_VLLS3:
            SMC_STOPCTRL = SMC_STOPCTRL_LLSM(3);
            break;
        case LPM_CPU_POWER_MODE_VLLS2:
            SMC_STOPCTRL = SMC_STOPCTRL_LLSM(2);
            break;
        case LPM_CPU_POWER_MODE_VLLS1:
            SMC_STOPCTRL = SMC_STOPCTRL_LLSM(1);
            break;
        default:
            break;
#else
        case LPM_CPU_POWER_MODE_VLLS3:
            SMC_VLLSCTRL = SMC_VLLSCTRL_VLLSM(3);
            break;
        case LPM_CPU_POWER_MODE_VLLS2:
            SMC_VLLSCTRL = SMC_VLLSCTRL_VLLSM(2);
            break;
        case LPM_CPU_POWER_MODE_VLLS1:
            SMC_VLLSCTRL = SMC_VLLSCTRL_VLLSM(1);
            break;
        default:
            break;
#endif
    }

    /* Wait for proper setup of VLPR */
    if (LPM_CPU_POWER_MODE_VLPR == index)
    {
        while (SMC_PMSTAT_PMSTAT(4) != SMC_PMSTAT)
            { };
    }

    /* Go to sleep if required */
    if (flags & LPM_CPU_POWER_MODE_FLAG_USE_WFI)
    {
/* ENGR00178898 workaround  Shut down SPI0, SPI1 pripheral. Preventing entering stop mode for some reason */
#ifdef SIM_SCGC6_SPI0_MASK
        SIM_SCGC6 &= ~SIM_SCGC6_SPI0_MASK;
#endif
#ifdef SIM_SCGC6_SPI1_MASK
        SIM_SCGC6 &= ~SIM_SCGC6_SPI1_MASK;
#endif
        _ASM_SLEEP(NULL);
#ifdef SIM_SCGC6_SPI0_MASK
        SIM_SCGC6 |= SIM_SCGC6_SPI0_MASK;
#endif
#ifdef SIM_SCGC6_SPI1_MASK
        SIM_SCGC6 |= SIM_SCGC6_SPI1_MASK;
#endif
    }

    /* After stop modes, reconfigure MCG if needed */
    if ( (LPM_CPU_POWER_MODE_STOP == index)
      || (LPM_CPU_POWER_MODE_VLPS == index)
      || (LPM_CPU_POWER_MODE_LLS == index)
      || (LPM_CPU_POWER_MODE_VLLS3 == index)
      || (LPM_CPU_POWER_MODE_VLLS2 == index)
      || (LPM_CPU_POWER_MODE_VLLS1 == index) )
    {
#ifdef BSP_CLOCK_USE_FLL
        if ((MCG_S_CLKST(0) == mcg) && (MCG_S_CLKST(1) == (MCG_S & MCG_S_CLKST_MASK)))
        {
            MCG_C1 &= (~ (MCG_C1_CLKS_MASK | MCG_C1_IREFS_MASK));
            while (0 != (MCG_S & MCG_S_CLKST(3)))
                { };
        }
#else
        if ((MCG_S_CLKST(3) == mcg) && (MCG_S_CLKST(2) == (MCG_S & MCG_S_CLKST_MASK)))
        {
            MCG_C1 &= (~ (MCG_C1_CLKS_MASK | MCG_C1_IREFS_MASK));
            while (0 == (MCG_S & MCG_S_LOCK0_MASK))
                { };
        }
#endif
    }

    /* Restore CME */
    MCG_C6 |= cme;

    return MQX_OK;

#else

#ifdef Cpu_SetOperationMode_METHOD_ENABLED
    if (LPM_OPERATION_MODES <= (_mqx_uint)target_mode)
    {
        return MQX_INVALID_PARAMETER;
    }
    return Cpu_SetOperationMode (LPM_PE_OPERATION_MODE_MAP[target_mode], NULL, NULL);
#else
    #error Undefined method Cpu_SetOperationMode() in PE CPU component!
#endif

#endif

}
/*! @brief Sets up the clock out of RESET
 *
 */
void clock_initialise(void) {

#if (CLOCK_MODE == CLOCK_MODE_NONE)
   // No clock setup
#else
   // XTAL/EXTAL Pins
   SIM->SCGC5  |= SIM_SCGC5_PORTA_MASK;
   PORTA->PCR[3]  = PORT_PCR_MUX(0);
   PORTA->PCR[4]  = PORT_PCR_MUX(0);

   // Configure the Crystal Oscillator
   RTC->CR = RTC_CR_WPE_M|RTC_CR_SUP_M|RTC_CR_UM_M|RTC_CR_OSCE_M|RTC_CR_CLKO_M|RTC_CR_SCP_M;

   // Fast Internal Clock divider
   MCG->SC = MCG_SC_FCRDIV_M;

   // Out of reset MCG is in FEI mode
   // =============================================================

   SIM->CLKDIV1 = SIM_CLKDIV1_OUTDIV1(3) | SIM_CLKDIV1_OUTDIV2(7) | SIM_CLKDIV1_OUTDIV3(3) | SIM_CLKDIV1_OUTDIV4(7);

   // Switch from FEI -> FEI/FBI/FEE/FBE
   // =============================================================

   // Set up crystal or external clock source
   MCG->C2 =
            MCG_C2_LOCRE0_M     | // LOCRE0 = 0,1   -> Loss of clock reset enable
            MCG_C2_RANGE0_M     | // RANGE0 = 0,1,2 -> Oscillator low/high/very high clock range
            MCG_C2_HGO0_M       | // HGO0   = 0,1   -> Oscillator low power/high gain
            MCG_C2_EREFS0_M     | // EREFS0 = 0,1   -> Select external clock/crystal oscillator
            MCG_C2_IRCS_M;        // IRCS   = 0,1   -> Select slow/fast internal clock for internal reference

#if ((CLOCK_MODE == CLOCK_MODE_FEI) || (CLOCK_MODE == CLOCK_MODE_FBI) || (CLOCK_MODE == CLOCK_MODE_BLPI) )
   // Transition via FBI
   //=====================================
#define BYPASS (1) // CLKS value used while FLL locks
   MCG->C1 =  MCG_C1_CLKS(BYPASS)     | // CLKS     = X     -> External reference source while PLL locks
              MCG_C1_FRDIV_M          | // FRDIV    = N     -> XTAL/2^n ~ 31.25 kHz
              MCG_C1_IREFS_M          | // IREFS    = 0,1   -> External/Slow IRC for FLL source
              MCG_C1_IRCLKEN_M        | // IRCLKEN  = 0,1   -> IRCLK disable/enable
              MCG_C1_IREFSTEN_M;        // IREFSTEN = 0,1   -> Internal reference enabled in STOP mode

   // Wait for S_IREFST to indicate FLL Reference has switched
   do {
      __asm__("nop");
   } while ((MCG->S & MCG_S_IREFST_MASK) != (MCG_C1_IREFS_V<<MCG_S_IREFST_SHIFT));

   // Wait for S_CLKST to indicating that OUTCLK has switched to bypass PLL/FLL
   do {
      __asm__("nop");
   } while ((MCG->S & MCG_S_CLKST_MASK) != MCG_S_CLKST(BYPASS));

   // Set FLL Parameters
   MCG->C4 = (MCG->C4&~(MCG_C4_DMX32_MASK|MCG_C4_DRST_DRS_MASK))|MCG_C4_DMX32_M|MCG_C4_DRST_DRS_M;
#endif

#if ((CLOCK_MODE == CLOCK_MODE_FBE) || (CLOCK_MODE == CLOCK_MODE_FEE) || (CLOCK_MODE == CLOCK_MODE_PLBE) || (CLOCK_MODE == CLOCK_MODE_PBE) || (CLOCK_MODE == CLOCK_MODE_PEE))

   // Transition via FBE
   //=====================================
#define BYPASS (2) // CLKS value used while PLL locks
   MCG->C1 =  MCG_C1_CLKS(BYPASS)     | // CLKS     = 2     -> External reference source while PLL locks
              MCG_C1_FRDIV_M          | // FRDIV    = N     -> XTAL/2^n ~ 31.25 kHz
              MCG_C1_IREFS_M          | // IREFS    = 0,1   -> External/Slow IRC for FLL source
              MCG_C1_IRCLKEN_M        | // IRCLKEN  = 0,1   -> IRCLK disable/enable
              MCG_C1_IREFSTEN_M;        // IREFSTEN = 0,1   -> Internal reference enabled in STOP mode

#if (MCG_C2_EREFS_V != 0)
   // Wait for oscillator stable (if used)
   do {
      __asm__("nop");
   } while ((MCG->S & MCG_S_OSCINIT0_MASK) == 0);
#endif

   // Wait for S_IREFST to indicate FLL Reference has switched
   do {
      __asm__("nop");
   } while ((MCG->S & MCG_S_IREFST_MASK) != (MCG_C1_IREFS_V<<MCG_S_IREFST_SHIFT));

   // Wait for S_CLKST to indicating that OUTCLK has switched to bypass PLL/FLL
   do {
      __asm__("nop");
   } while ((MCG->S & MCG_S_CLKST_MASK) != MCG_S_CLKST(BYPASS));

   // Set FLL Parameters
   MCG->C4 = (MCG->C4&~(MCG_C4_DMX32_MASK|MCG_C4_DRST_DRS_MASK))|MCG_C4_DMX32_M|MCG_C4_DRST_DRS_M;
#endif

   // Select FEI/FBI/FEE/FBE clock mode
   MCG->C1 =  MCG_C1_CLKS_M       | // CLKS     = 0,1,2 -> Select FLL/IRCSCLK/ERCLK
              MCG_C1_FRDIV_M      | // FRDIV    = N     -> XTAL/2^n ~ 31.25 kHz
              MCG_C1_IREFS_M      | // IREFS    = 0,1   -> External/Slow IRC for FLL source
              MCG_C1_IRCLKEN_M    | // IRCLKEN  = 0,1   -> IRCLK disable/enable
              MCG_C1_IREFSTEN_M;    // IREFSTEN = 0,1   -> Internal reference enabled in STOP mode

   // Wait for mode change
   do {
      __asm__("nop");
   } while ((MCG->S & MCG_S_IREFST_MASK) != (MCG_C1_IREFS_V<<MCG_S_IREFST_SHIFT));

#if defined (MCG_C6_PLLS_V) && (MCG_C1_CLKS_V == 0) // FLL or PLL
#define MCG_S_CLKST_M MCG_S_CLKST(MCG_C6_PLLS_V?3:0)
#else
   #define MCG_S_CLKST_M MCG_S_CLKST(MCG_C1_CLKS_V)
#endif

   // Wait for S_CLKST to indicating that OUTCLK has switched
   do {
      __asm__("nop");
   } while ((MCG->S & MCG_S_CLKST_MASK) != MCG_S_CLKST_M);

   // Set the SIM _CLKDIV dividers
   SIM->CLKDIV1 = SIM_CLKDIV1_OUTDIV1_M | SIM_CLKDIV1_OUTDIV2_M | SIM_CLKDIV1_OUTDIV3_M | SIM_CLKDIV1_OUTDIV4_M;

#if (CLOCK_MODE == CLOCK_MODE_BLPE) || (CLOCK_MODE == CLOCK_MODE_BLPI)
   // Select BLPE/BLPI clock mode
   MCG->C2 =
            MCG_C2_LOCRE0_M      | // LOCRE0 = 0,1   -> Loss of clock reset
            MCG_C2_RANGE0_M      | // RANGE0 = 0,1,2 -> Oscillator low/high/very high clock range
            MCG_C2_HGO0_M        | // HGO0   = 0,1   -> Oscillator low power/high gain
            MCG_C2_EREFS0_M      | // EREFS0 = 0,1   -> Select external clock/crystal oscillator
            MCG_C2_LP_M          | // LP     = 0,1   -> Select FLL enabled/disabled in bypass mode
            MCG_C2_IRCS_M;         // IRCS   = 0,1   -> Select slow/fast internal clock for internal reference

#endif // (CLOCK_MODE == CLOCK_MODE_BLPE) || (CLOCK_MODE == CLOCK_MODE_BLPI)
#endif // (CLOCK_MODE == CLOCK_MODE_NONE)


   /*!
    * SOPT1 Clock multiplexing
    */
#if defined(SIM_SOPT1_OSC32KSEL_MASK) && defined(SIM_SOPT1_OSC32KSEL_M) // ERCLK32K source
   SIM->SOPT1 = (SIM->SOPT1&~SIM_SOPT1_OSC32KSEL_MASK)|SIM_SOPT1_OSC32KSEL_M;
#endif

   /*!
    * SOPT2 Clock multiplexing
    */
#if defined(SIM_SOPT2_SDHCSRC_MASK) && defined(SIM_SOPT2_SDHCSRC_M) // SDHC clock
   SIM->SOPT2 = (SIM->SOPT2&~SIM_SOPT2_SDHCSRC_MASK)|SIM_SOPT2_SDHCSRC_M;
#endif

#if defined(SIM_SOPT2_TIMESRC_MASK) && defined(SIM_SOPT2_TIMESRC_M) // Ethernet time-stamp clock
   SIM->SOPT2 = (SIM->SOPT2&~SIM_SOPT2_TIMESRC_MASK)|SIM_SOPT2_TIMESRC_M;
#endif

#if defined(SIM_SOPT2_RMIISRC_MASK) && defined(SIM_SOPT2_RMIISRC_M) // RMII clock
   SIM->SOPT2 = (SIM->SOPT2&~SIM_SOPT2_RMIISRC_MASK)|SIM_SOPT2_RMIISRC_M;
#endif

#ifdef SIM_SCGC4_USBOTG_MASK
   // !! WARNING !! The USB interface must be disabled for clock changes to have effect !! WARNING !!
   SIM->SCGC4 &= ~SIM_SCGC4_USBOTG_MASK;
#endif

#if defined(SIM_SOPT2_USBSRC_MASK) && defined(SIM_SOPT2_USBSRC_M) // USB clock (48MHz req.)
   SIM->SOPT2 = (SIM->SOPT2&~SIM_SOPT2_USBSRC_MASK)|SIM_SOPT2_USBSRC_M;
#endif

#if defined(SIM_SOPT2_USBFSRC_MASK) && defined(SIM_SOPT2_USBFSRC_M) // USB clock (48MHz req.)
   SIM->SOPT2 = (SIM->SOPT2&~SIM_SOPT2_USBFSRC_MASK)|SIM_SOPT2_USBFSRC_M;
#endif

#if defined(SIM_SOPT2_PLLFLLSEL_MASK) && defined(SIM_SOPT2_PLLFLLSEL_M) // Peripheral clock
   SIM->SOPT2 = (SIM->SOPT2&~SIM_SOPT2_PLLFLLSEL_MASK)|SIM_SOPT2_PLLFLLSEL_M;
#endif

#if defined(SIM_SOPT2_UART0SRC_MASK) && defined(SIM_SOPT2_UART0SRC_M) // UART0 clock
   SIM->SOPT2 = (SIM->SOPT2&~SIM_SOPT2_UART0SRC_MASK)|SIM_SOPT2_UART0SRC_M;
#endif

#if defined(SIM_SOPT2_TPMSRC_MASK) && defined(SIM_SOPT2_TPMSRC_M) // TPM clock
   SIM->SOPT2 = (SIM->SOPT2&~SIM_SOPT2_TPMSRC_MASK)|SIM_SOPT2_TPMSRC_M;
#endif

#if defined(SIM_SOPT2_CLKOUTSEL_MASK) && defined(SIM_SOPT2_CLKOUTSEL_M)
   SIM->SOPT2 = (SIM->SOPT2&~SIM_SOPT2_CLKOUTSEL_MASK)|SIM_SOPT2_CLKOUTSEL_M;
#endif

#if defined(SIM_SOPT2_RTCCLKOUTSEL_MASK) && defined(SIM_SOPT2_RTCCLKOUTSEL_M)
   SIM->SOPT2 = (SIM->SOPT2&~SIM_SOPT2_RTCCLKOUTSEL_MASK)|SIM_SOPT2_RTCCLKOUTSEL_M;
#endif

#if defined(SIM_CLKDIV2_USBDIV_MASK) && defined(SIM_CLKDIV2_USBFRAC_MASK) && defined(SIM_CLKDIV2_USB_M)
   SIM->CLKDIV2 = (SIM->CLKDIV2&~(SIM_CLKDIV2_USBDIV_MASK|SIM_CLKDIV2_USBFRAC_MASK)) | SIM_CLKDIV2_USB_M;
#endif

   SystemCoreClockUpdate();
}
/*! @brief Sets up the clock out of RESET
 *
 */
void clock_initialise(void) {

#if (CLOCK_MODE == CLOCK_MODE_NONE)
   // No clock setup
#else
   // XTAL0/EXTAL0 Pins
   // Shouldn't be needed as default
//   SIM->SCGC5  |= SIM_SCGC5_PORTA_MASK;
//   PORTA->PCR[18] = PORT_PCR_MUX(0);
//   PORTA->PCR[19] = PORT_PCR_MUX(0);

   // Configure the Crystal Oscillators
   OSC0->CR    = OSC0_CR_ERCLKEN_M|OSC0_CR_EREFSTEN_M|OSC0_CR_SCP_M;

   // XTAL/EXTAL Pins
   // Shouldn't be needed as default
//   SIM->SCGC5  |= SIM_SCGC5_PORTE_MASK;
//   PORTE_PCR24 = PORT_PCR_MUX(0);
//   PORTE_PCR25 = PORT_PCR_MUX(0);

   SIM->SCGC1 |= SIM_SCGC1_OSC1_MASK;
   OSC1->CR    = OSC1_CR_ERCLKEN_M|OSC1_CR_EREFSTEN_M|OSC1_CR_SCP_M;

#if (MCG_C7_OSCSEL_V != 0)
   SIM->SCGC6 |= SIM_SCGC6_RTC_MASK;

   // Configure the RTC Crystal Oscillator
   RTC->CR = RTC_CR_SCP_M|RTC_CR_CLKO_M|RTC_CR_OSCE_M|RTC_CR_UM_M|RTC_CR_SUP_M|RTC_CR_WPE_M;
#endif

   // Select OSCCLK Source
   MCG->C7 = MCG_C7_OSCSEL_M; // OSCSEL = 0,1 -> XTAL/XTAL32

   // Fast Internal Clock divider
   MCG->SC = MCG_SC_FCRDIV_M;

   // Out of reset MCG is in FEI mode
   // =============================================================

   // Set conservative SIM clock dividers BEFORE switching to ensure the clock speed remain within specification
   SIM->CLKDIV1 = SIM_CLKDIV1_OUTDIV1(3) | SIM_CLKDIV1_OUTDIV2(7) | SIM_CLKDIV1_OUTDIV3(3) | SIM_CLKDIV1_OUTDIV4(7);

   // Switch from FEI -> FEI/FBI/FEE/FBE
   // =============================================================

   // Set up crystal or external clock source for OSC0
   MCG->C2 = 
            MCG_C2_LOCRE0_M     | // LOCRE0 = 0,1   -> Loss of clock reset enable
            MCG_C2_RANGE0_M     | // RANGE0 = 0,1,2 -> Oscillator low/high/very high clock range
            MCG_C2_HGO0_M       | // HGO0   = 0,1   -> Oscillator low power/high gain
            MCG_C2_EREFS0_M     | // EREFS0 = 0,1   -> Select external clock/crystal oscillator
            MCG_C2_IRCS_M;        // IRCS   = 0,1   -> Select slow/fast internal clock for internal reference

   // Set up crystal or external clock source for OSC1
   MCG->C10 = MCG_C10_LOCRE2_M     | // LOCRE1 = 0,1   -> Loss of clock reset enable
              MCG_C10_RANGE1_M     | // RANGE1 = 0,1,2 -> Oscillator low/high/very high clock range
              MCG_C10_HGO1_M       | // HGO1   = 0,1   -> Oscillator low power/high gain
              MCG_C10_EREFS1_M;      // EREFS1 = 0,1   -> Select external clock/crystal oscillator

   // Set up RTC clock monitor
   MCG->C8 = MCG_C8_LOCRE1_M |    // LOCRE1 = 0,1 -> Loss of Lock Reset enable
             MCG_C8_CME1_M;       // CME1   = 0,1 -> Clock monitor enable

#if ((CLOCK_MODE == CLOCK_MODE_FEI) || (CLOCK_MODE == CLOCK_MODE_FBI) || (CLOCK_MODE == CLOCK_MODE_BLPI) )
   // Transition via FBI
   //=====================================
#define BYPASS (1) // CLKS value used while FLL locks
   MCG->C1 =  MCG_C1_CLKS(BYPASS)     | // CLKS     = X     -> External reference source while PLL locks
              MCG_C1_FRDIV_M          | // FRDIV    = N     -> XTAL/2^n ~ 31.25 kHz
              MCG_C1_IREFS_M          | // IREFS    = 0,1   -> External/Slow IRC for FLL source
              MCG_C1_IRCLKEN_M        | // IRCLKEN  = 0,1   -> IRCLK disable/enable
              MCG_C1_IREFSTEN_M;        // IREFSTEN = 0,1   -> Internal reference enabled in STOP mode

   // Wait for S_IREFST to indicate FLL Reference has switched
   do {
      __asm__("nop");
   } while ((MCG->S & MCG_S_IREFST_MASK) != (MCG_C1_IREFS_V<<MCG_S_IREFST_SHIFT));

   // Wait for S_CLKST to indicating that OUTCLK has switched to bypass PLL/FLL
   do {
      __asm__("nop");
   } while ((MCG->S & MCG_S_CLKST_MASK) != MCG_S_CLKST(BYPASS));

   // Set FLL Parameters
   MCG->C4 = (MCG->C4&~(MCG_C4_DMX32_MASK|MCG_C4_DRST_DRS_MASK))|MCG_C4_DMX32_M|MCG_C4_DRST_DRS_M;
#endif

#if ((CLOCK_MODE == CLOCK_MODE_FBE) || (CLOCK_MODE == CLOCK_MODE_FEE) || (CLOCK_MODE == CLOCK_MODE_PLBE) || (CLOCK_MODE == CLOCK_MODE_PBE) || (CLOCK_MODE == CLOCK_MODE_PEE))

   // Transition via FBE
   //=====================================
#define BYPASS (2) // CLKS value used while PLL locks
   MCG->C1 =  MCG_C1_CLKS(BYPASS)     | // CLKS     = 2     -> External reference source while PLL locks
              MCG_C1_FRDIV_M          | // FRDIV    = N     -> XTAL/2^n ~ 31.25 kHz
              MCG_C1_IREFS_M          | // IREFS    = 0,1   -> External/Slow IRC for FLL source
              MCG_C1_IRCLKEN_M        | // IRCLKEN  = 0,1   -> IRCLK disable/enable
              MCG_C1_IREFSTEN_M;        // IREFSTEN = 0,1   -> Internal reference enabled in STOP mode

#if (MCG_C2_EREFS0_V != 0)
   // Wait for oscillator 0 stable (if used)
   do {
      __asm__("nop");
   } while ((MCG->S & MCG_S_OSCINIT0_MASK) == 0);
#endif

#if (MCG_C10_EREFS1_V != 0)
   // Wait for oscillator 1 stable (if used)
   do {
      __asm__("nop");
   } while ((MCG->S2 & MCG_S2_OSCINIT1_MASK) == 0);
#endif

   // Wait for S_IREFST to indicate FLL Reference has switched
   do {
      __asm__("nop");
   } while ((MCG->S & MCG_S_IREFST_MASK) != (MCG_C1_IREFS_V<<MCG_S_IREFST_SHIFT));

   // Wait for S_CLKST to indicating that OUTCLK has switched to bypass PLL/FLL
   do {
      __asm__("nop");
   } while ((MCG->S & MCG_S_CLKST_MASK) != MCG_S_CLKST(BYPASS));

   // Set FLL Parameters
   MCG->C4 = (MCG->C4&~(MCG_C4_DMX32_MASK|MCG_C4_DRST_DRS_MASK))|MCG_C4_DMX32_M|MCG_C4_DRST_DRS_M;
#endif

   // Configure PLL0 Reference Frequency
   // =============================================================
   MCG->C5 =   MCG_C5_PLLREFSEL0_M   |  // PLLREFSEL0 = 0,1 -> OSC0/OSC1 select
               MCG_C5_PLLCLKEN0_M    |  // PLLCLKEN0  = 0,1 -> PLL -/enabled (irrespective of PLLS)
               MCG_C5_PLLSTEN0_M     |  // PLLSTEN0   = 0,1 -> disabled/enabled in normal stop mode
               MCG_C5_PRDIV0_M;         // PRDIV0     = N   -> PLL divider so PLL Ref. Freq. = 8-16 MHz

   // Configure PLL1 Reference Frequency
   // =============================================================
   MCG->C11 =  MCG_C11_PLLREFSEL1_M   |  // PLLREFSEL1 = 0,1 -> OSC0/OSC1 select
               MCG_C11_PLLCLKEN1_M    |  // PLLCLKEN   = 0,1 -> PLL -/enabled (irrespective of PLLS)
               MCG_C11_PLLSTEN1_M     |  // PLLSTEN0   = 0,1 -> disabled/enabled in normal stop mode
               MCG_C11_PLLCS_M        |  // PLLCS      = 0,1 -> PLL0/PLL1 used as MCG source
               MCG_C11_PRDIV1_M;         // PRDIV0     = N   -> PLL divider so PLL Ref. Freq. = 8-16 MHz

   // Set up PLL0
   // =============================================================
   MCG->C6 = MCG_C6_LOLIE0_M    |  // LOLIE0 = 0,1 -> Loss of Lock interrupt
             MCG_C6_PLLS_M      |  // PLLS   = 0,1 -> Enable PLL
             MCG_C6_CME0_M      |  // CME0   = 0,1 -> Disable/enable clock monitor
             MCG_C6_VDIV0_M;       // VDIV0  = N   -> PLL Multiplication factor

   // Set up PLL1
   // =============================================================
   MCG->C12 = MCG_C12_LOLIE1_M    |  // LOLIE1 = 0,1 -> Loss of Lock interrupt
              MCG_C12_CME2_M      |  // CME2   = 0,1 -> Disable/enable clock monitor
              MCG_C12_VDIV1_M;       // VDIV1  = N   -> PLL Multiplication factor


#if ((CLOCK_MODE == CLOCK_MODE_PBE) || (CLOCK_MODE == CLOCK_MODE_PEE))
   // Transition via PBE
   // =============================================================

#if (MCG_C11_PLLCS_M == 0)
   // Wait for PLL0 to lock
   do {
      __asm__("nop");
   } while((MCG->S & MCG_S_LOCK0_MASK) == 0);
#else
   // Wait for PLL1 to lock
   do {
      __asm__("nop");
   } while((MCG->S2 & MCG_S2_LOCK1_MASK) == 0);
#endif
   // Wait until PLLS clock source changes to the PLL clock out
   do {
      __asm__("nop");
   } while((MCG->S & MCG_S_PLLST_MASK) == 0);
#endif

#if ((CLOCK_MODE == CLOCK_MODE_FEI) || (CLOCK_MODE == CLOCK_MODE_FEE))
   // Wait for FLL to lock
   do {
      __asm__("nop");
   } while ((MCG->C4&MCG_C4_DRST_DRS_MASK) != MCG_C4_DRST_DRS_M);
#endif

   // Select FEI/FBI/FEE/FBE/PBE/PEE clock mode
   MCG->C1 =  MCG_C1_CLKS_M       | // CLKS     = 0,1,2 -> Select FLL/IRCSCLK/ERCLK
              MCG_C1_FRDIV_M      | // FRDIV    = N     -> XTAL/2^n ~ 31.25 kHz
              MCG_C1_IREFS_M      | // IREFS    = 0,1   -> External/Slow IRC for FLL source
              MCG_C1_IRCLKEN_M    | // IRCLKEN  = 0,1   -> IRCLK disable/enable
              MCG_C1_IREFSTEN_M;    // IREFSTEN = 0,1   -> Internal reference enabled in STOP mode

   // Wait for mode change
   do {
      __asm__("nop");
   } while ((MCG->S & MCG_S_IREFST_MASK) != (MCG_C1_IREFS_V<<MCG_S_IREFST_SHIFT));

#if defined (MCG_C6_PLLS_V) && (MCG_C1_CLKS_V == 0) // FLL or PLL
#define MCG_S_CLKST_M MCG_S_CLKST(MCG_C6_PLLS_V?3:0)
#else
   #define MCG_S_CLKST_M MCG_S_CLKST(MCG_C1_CLKS_V)
#endif

   // Wait for S_CLKST to indicating that OUTCLK has switched
   do {
      __asm__("nop");
   } while ((MCG->S & MCG_S_CLKST_MASK) != MCG_S_CLKST_M);

   // Set the SIM _CLKDIV dividers
   SIM->CLKDIV1 = SIM_CLKDIV1_OUTDIV1_M | SIM_CLKDIV1_OUTDIV2_M | SIM_CLKDIV1_OUTDIV3_M | SIM_CLKDIV1_OUTDIV4_M;

#if (CLOCK_MODE == CLOCK_MODE_BLPE) || (CLOCK_MODE == CLOCK_MODE_BLPI)
   // Select BLPE/BLPI clock mode
   MCG->C2 =
            MCG_C2_LOCRE0_M      | // LOCRE0 = 0,1   -> Loss of clock reset
            MCG_C2_RANGE0_M      | // RANGE0 = 0,1,2 -> Oscillator low/high/very high clock range
            MCG_C2_HGO0_M        | // HGO0   = 0,1   -> Oscillator low power/high gain
            MCG_C2_EREFS0_M      | // EREFS0 = 0,1   -> Select external clock/crystal oscillator
            MCG_C2_LP_M          | // LP     = 0,1   -> Select FLL enabled/disabled in bypass mode
            MCG_C2_IRCS_M;         // IRCS   = 0,1   -> Select slow/fast internal clock for internal reference

#endif // (CLOCK_MODE == CLOCK_MODE_BLPE) || (CLOCK_MODE == CLOCK_MODE_BLPI)
#endif // (CLOCK_MODE == CLOCK_MODE_NONE)


   /*!
    * SOPT1 Clock multiplexing
    */
#if defined(SIM_SOPT1_OSC32KSEL_MASK) && defined(SIM_SOPT1_OSC32KSEL_M) // ERCLK32K source
   SIM->SOPT1 = (SIM->SOPT1&~SIM_SOPT1_OSC32KSEL_MASK)|SIM_SOPT1_OSC32KSEL_M;
#endif

   /*!
    * SOPT2 Clock multiplexing
    */
#if defined(SIM_SOPT2_SDHCSRC_MASK) && defined(SIM_SOPT2_SDHCSRC_M) // SDHC clock
   SIM->SOPT2 = (SIM->SOPT2&~SIM_SOPT2_SDHCSRC_MASK)|SIM_SOPT2_SDHCSRC_M;
#endif

#if defined(SIM_SOPT2_TIMESRC_MASK) && defined(SIM_SOPT2_TIMESRC_M) // Ethernet time-stamp clock
   SIM->SOPT2 = (SIM->SOPT2&~SIM_SOPT2_TIMESRC_MASK)|SIM_SOPT2_TIMESRC_M;
#endif

#if defined(SIM_SOPT2_RMIISRC_MASK) && defined(SIM_SOPT2_RMIISRC_M) // RMII clock
   SIM->SOPT2 = (SIM->SOPT2&~SIM_SOPT2_RMIISRC_MASK)|SIM_SOPT2_RMIISRC_M;
#endif

#ifdef SIM_SCGC4_USBOTG_MASK
   // !! WARNING !! The USB interface must be disabled for clock changes to have effect !! WARNING !!
   SIM->SCGC4 &= ~SIM_SCGC4_USBOTG_MASK;
#endif

#if defined(SIM_SOPT2_USBSRC_MASK) && defined(SIM_SOPT2_USBSRC_M) // USB clock (48MHz req.)
   SIM->SOPT2 = (SIM->SOPT2&~SIM_SOPT2_USBSRC_MASK)|SIM_SOPT2_USBSRC_M;
#endif

#if defined(SIM_SOPT2_USBFSRC_MASK) && defined(SIM_SOPT2_USBFSRC_M) // USB clock (48MHz req.)
   SIM->SOPT2 = (SIM->SOPT2&~SIM_SOPT2_USBFSRC_MASK)|SIM_SOPT2_USBFSRC_M;
#endif

#if defined(SIM_SOPT2_PLLFLLSEL_MASK) && defined(SIM_SOPT2_PLLFLLSEL_M) // Peripheral clock
   SIM->SOPT2 = (SIM->SOPT2&~SIM_SOPT2_PLLFLLSEL_MASK)|SIM_SOPT2_PLLFLLSEL_M;
#endif

#if defined(SIM_SOPT2_UART0SRC_MASK) && defined(SIM_SOPT2_UART0SRC_M) // UART0 clock
   SIM->SOPT2 = (SIM->SOPT2&~SIM_SOPT2_UART0SRC_MASK)|SIM_SOPT2_UART0SRC_M;
#endif

#if defined(SIM_SOPT2_TPMSRC_MASK) && defined(SIM_SOPT2_TPMSRC_M) // TPM clock
   SIM->SOPT2 = (SIM->SOPT2&~SIM_SOPT2_TPMSRC_MASK)|SIM_SOPT2_TPMSRC_M;
#endif

#if defined(SIM_SOPT2_CLKOUTSEL_MASK) && defined(SIM_SOPT2_CLKOUTSEL_M)
   SIM->SOPT2 = (SIM->SOPT2&~SIM_SOPT2_CLKOUTSEL_MASK)|SIM_SOPT2_CLKOUTSEL_M;
#endif

#if defined(SIM_SOPT2_RTCCLKOUTSEL_MASK) && defined(SIM_SOPT2_RTCCLKOUTSEL_M)
   SIM->SOPT2 = (SIM->SOPT2&~SIM_SOPT2_RTCCLKOUTSEL_MASK)|SIM_SOPT2_RTCCLKOUTSEL_M;
#endif

#if defined(SIM_CLKDIV2_USBDIV_MASK) && defined(SIM_CLKDIV2_USBFRAC_MASK) && defined(SIM_CLKDIV2_USB_M)
   SIM->CLKDIV2 = (SIM->CLKDIV2&~(SIM_CLKDIV2_USBDIV_MASK|SIM_CLKDIV2_USBFRAC_MASK)) | SIM_CLKDIV2_USB_M;
#endif

   SystemCoreClockUpdate();
}
/*! Sets up the clock out of RESET
 *!
 */
void clock_initialise(void) {
#ifdef ENABLE_CLKOUT
   showClocks();
#endif

#if (CLOCK_MODE == CLOCK_MODE_RESET)
   // No clock setup
#else
   // XTAL/EXTAL Pins
   SIM_SCGC6 |= SIM_SCGC6_PORTB_MASK;
   MXC_PTBPF1 = (MXC_PTBPF1&~MXC_PTBPF1_B6_MASK)|MXC_PTBPF1_B6(0);
   MXC_PTBPF2 = (MXC_PTBPF2&~MXC_PTBPF2_B5_MASK)|MXC_PTBPF2_B5(0);

   // Configure OSC2 (XTAL1/EXTAL1
   OSC1_CR = OSC1_CR_ERCLKEN_M|OSC1_CR_EREFSTEN_M|OSC1_CR_SCP_M;

   // Configure OSC2 (XTAL2/EXTAL2
   OSC2_CR = OSC2_CR_ERCLKEN_M|OSC2_CR_EREFSTEN_M|OSC2_CR_SCP_M;

   // Configure OSC1 (XTAL1/EXTAL1
   SIM_OSC1 = SIM_OSC1_OSC1EN_M|SIM_OSC1_OSC1RANGE_M|SIM_OSC1_OSC1HGO_M|SIM_OSC1_OSC1EREFS_M;

   // Out of reset MCG is in FEI mode
   // =============================================================

   // Switch from FEI -> FEI/FBI/FEE/FBE
   // =============================================================

   // Set up crystal or external clock source
   MCG_C2 = MCG_C2_RANGE_M     | // RANGE = 0,1,2 -> Oscillator low/high/very high clock range
            MCG_C2_HGO_M       | // HGO   = 0,1   -> Oscillator low power/high gain
            MCG_C2_EREFS_M     | // EREFS = 0,1   -> Select external clock/crystal oscillator
            MCG_C2_IRCS_M;       // IRCS  = 0,1   -> Select slow/fast internal clock for internal reference

   SIM_CLKDIV0 = SIM_CLKDIV0_OUTDIV(3);

#if ((CLOCK_MODE == CLOCK_MODE_FEI) || (CLOCK_MODE == CLOCK_MODE_FBI) || (CLOCK_MODE == CLOCK_MODE_BLPI) )
   // Transition via FBI
   //=====================================
#define BYPASS (1) // CLKS value used while FLL locks
   MCG_C1 =  MCG_C1_CLKS(BYPASS)     | // CLKS     = 1     -> Internal reference source while PLL locks
             MCG_C1_FRDIV_M          | // FRDIV    = N     -> XTAL/2^n ~ 31.25 kHz
             MCG_C1_IREFS_M          | // IREFS    = 0,1   -> External/Slow IRC for FLL source
             MCG_C1_IRCLKEN_M        | // IRCLKEN  = 0,1   -> IRCLK disable/enable
             MCG_C1_IREFSTEN_M;        // IREFSTEN = 0,1   -> Internal reference enabled in STOP mode

   // Wait for S_IREFST to indicate FLL Reference has switched
   do {
      __asm__("nop");
   } while ((MCG_S & MCG_S_IREFST_MASK) != (MCG_C1_IREFS_V<<MCG_S_IREFST_SHIFT));

   // Wait for S_CLKST to indicating that OUTCLK has switched to bypass PLL/FLL
   do {
      __asm__("nop");
   } while ((MCG_S & MCG_S_CLKST_MASK) != MCG_S_CLKST(BYPASS));

   // Set FLL Parameters
   MCG_C4 = (MCG_C4&~(MCG_C4_DMX32_MASK|MCG_C4_DRST_DRS_MASK))|MCG_C4_DMX32_M|MCG_C4_DRST_DRS_M;
#endif

#if ((CLOCK_MODE == CLOCK_MODE_FBE) || (CLOCK_MODE == CLOCK_MODE_FEE) || (CLOCK_MODE == CLOCK_MODE_PLBE) || (CLOCK_MODE == CLOCK_MODE_PBE) || (CLOCK_MODE == CLOCK_MODE_PEE))

   // Transition via FBE
   //=====================================
#define BYPASS (2) // CLKS value used while PLL locks
   MCG_C1 =  MCG_C1_CLKS(BYPASS)     | // CLKS     = 2     -> External reference source while PLL locks
             MCG_C1_FRDIV_M          | // FRDIV    = N     -> XTAL/2^n ~ 31.25 kHz
             MCG_C1_IREFS_M          | // IREFS    = 0,1   -> External/Slow IRC for FLL source
             MCG_C1_IRCLKEN_M        | // IRCLKEN  = 0,1   -> IRCLK disable/enable
             MCG_C1_IREFSTEN_M;        // IREFSTEN = 0,1   -> Internal reference enabled in STOP mode

#if (MCG_C2_EREFS_V != 0)
   // Wait for oscillator stable (if used)
   do {
      __asm__("nop");
   } while ((MCG_S & MCG_S_OSCINIT_MASK) == 0);
#endif

   // Wait for S_IREFST to indicate FLL Reference has switched
   do {
      __asm__("nop");
   } while ((MCG_S & MCG_S_IREFST_MASK) != (MCG_C1_IREFS_V<<MCG_S_IREFST_SHIFT));

   // Wait for S_CLKST to indicating that OUTCLK has switched to bypass PLL/FLL
   do {
      __asm__("nop");
   } while ((MCG_S & MCG_S_CLKST_MASK) != MCG_S_CLKST(BYPASS));

   // Set FLL Parameters
   MCG_C4 = (MCG_C4&~(MCG_C4_DMX32_MASK|MCG_C4_DRST_DRS_MASK))|MCG_C4_DMX32_M|MCG_C4_DRST_DRS_M;
#endif

#if ((CLOCK_MODE == CLOCK_MODE_PBE) || (CLOCK_MODE == CLOCK_MODE_PEE))

   // Configure PLL Reference Frequency
   // =============================================================
   MCG_C5 =  MCG_C5_PLLCLKEN_M    |  // PLLCLKEN = 0,1 -> PLL -/enabled (irrespective of PLLS)
             MCG_C5_PLLSTEN_M     |  // PLLSTEN0 = 0,1 -> disabled/enabled in normal stop mode
             MCG_C5_PRDIV_M;         // PRDIV0   = N   -> PLL divider so PLL Ref. Freq. = 2-4 MHz

   // Transition via PBE
   // =============================================================
   MCG_C6 = MCG_C6_LOLIE_M    |
            MCG_C6_PLLS_M      |  // PLLS  = 0,1 -> Enable PLL
            MCG_C6_CME_M      |  // CME0  = 0,1 -> Disable/enable clock monitor
            MCG_C6_VDIV_M;       // VDIV0 = N   -> PLL Multiplication factor

   // Wait for PLL to lock
   do {
      __asm__("nop");
   } while((MCG_S & MCG_S_LOCK_MASK) == 0);

   // Wait until PLLS clock source changes to the PLL clock out
   do {
      __asm__("nop");
   } while((MCG_S & MCG_S_PLLST_MASK) == 0);

#endif

#if ((CLOCK_MODE == CLOCK_MODE_FEI) || (CLOCK_MODE == CLOCK_MODE_FEE))
   // Wait for FLL to lock
   do {
      __asm__("nop");
   } while ((MCG_C4&MCG_C4_DRST_DRS_MASK) != MCG_C4_DRST_DRS_M);
#endif


   // Select FEI/FBI/FEE/FBE/PBE/PEE clock mode
   MCG_C1 =  MCG_C1_CLKS_M       | // CLKS     = 0,1,2 -> Select FLL/IRCSCLK/ERCLK
             MCG_C1_FRDIV_M      | // FRDIV    = N     -> XTAL/2^n ~ 31.25 kHz
             MCG_C1_IREFS_M      | // IREFS    = 0,1   -> External/Slow IRC for FLL source
             MCG_C1_IRCLKEN_M    | // IRCLKEN  = 0,1   -> IRCLK disable/enable
             MCG_C1_IREFSTEN_M;    // IREFSTEN = 0,1   -> Internal reference enabled in STOP mode

   // Wait for mode change
   do {
      __asm__("nop");
   } while ((MCG_S & MCG_S_IREFST_MASK) != (MCG_C1_IREFS_V<<MCG_S_IREFST_SHIFT));

#if defined (MCG_C6_PLLS_V) && (MCG_C1_CLKS_V == 0) // FLL or PLL
#define MCG_S_CLKST_M MCG_S_CLKST(MCG_C6_PLLS_V?3:0)
#else
   #define MCG_S_CLKST_M MCG_S_CLKST(MCG_C1_CLKS_V)
#endif

   // Wait for S_CLKST to indicating that OUTCLK has switched
   do {
      __asm__("nop");
   } while ((MCG_S & MCG_S_CLKST_MASK) != MCG_S_CLKST_M);

#if (CLOCK_MODE == CLOCK_MODE_BLPE) || (CLOCK_MODE == CLOCK_MODE_BLPI)
   // Select BLPE/BLPI clock mode
   MCG_C2 =
            MCG_C2_LOCRE_M      | // LOCRE0 = 0,1   -> Loss of clock reset
            MCG_C2_RANGE_M      | // RANGE0 = 0,1,2 -> Oscillator low/high/very high clock range
            MCG_C2_HGO_M        | // HGO0   = 0,1   -> Oscillator low power/high gain
            MCG_C2_EREFS_M      | // EREFS0 = 0,1   -> Select external clock/crystal oscillator
            MCG_C2_LP_M         | // LP     = 0,1   -> Select FLL enabled/disabled in bypass mode
            MCG_C2_IRCS_M;        // IRCS   = 0,1   -> Select slow/fast internal clock for internal reference

#endif // (CLOCK_MODE == CLOCK_MODE_BLPE) || (CLOCK_MODE == CLOCK_MODE_BLPI)
#endif // (CLOCK_MODE == CLOCK_MODE_RESET)

   // Basic clock multiplexing
#if defined(MCU_mcf51jf128)
//   SIM_SOPT2 = SIM_SOPT2_UART0SRC_M      | // UART0 clock - 0,1,2,3 -> Disabled, (MCGFLLCLK, MCGPLLCLK/2),  OSCERCLK, MCGIRCLK
//               SIM_SOPT2_TPMSRC_M ;        // TPM2 source
#else
   #error "CPU not set"
#endif

#ifdef SIM_CLKDIV1_USBFRAC_MASK
   SIM_CLKDIV1 = SIM_CLKDIV1_USBDIV_M | SIM_CLKDIV1_USBFRAC_M | SIM_CLKDIV1_USBSRC_M;
#endif

   SIM_CLKDIV0 = SIM_CLKDIV0_M;

   SystemCoreClockUpdate();
}
Beispiel #25
0
/**
 * @brief   K20x clock initialization.
 * @note    All the involved constants come from the file @p board.h.
 * @note    This function is meant to be invoked early during the system
 *          initialization, it is usually invoked from the file
 *          @p board.c.
 * @todo    This function needs to be more generic.
 *
 * @special
 */
void k20x_clock_init(void) {
#if !KINETIS_NO_INIT

  /* Disable the watchdog */
  WDOG->UNLOCK = 0xC520;
  WDOG->UNLOCK = 0xD928;
  WDOG->STCTRLH &= ~WDOG_STCTRLH_WDOGEN;

  SIM->SCGC5 |= SIM_SCGC5_PORTA |
                SIM_SCGC5_PORTB |
                SIM_SCGC5_PORTC |
                SIM_SCGC5_PORTD |
                SIM_SCGC5_PORTE;

#if KINETIS_MCG_MODE == KINETIS_MCG_MODE_FEI
  /* This is the default mode at reset. */

  /* Configure FEI mode */
  MCG->C4 = MCG_C4_DRST_DRS(KINETIS_MCG_FLL_DRS) |
            (KINETIS_MCG_FLL_DMX32 ? MCG_C4_DMX32 : 0);

  /* Set clock dividers */
  SIM->CLKDIV1 = SIM_CLKDIV1_OUTDIV1(KINETIS_CLKDIV1_OUTDIV1-1) |
                 SIM_CLKDIV1_OUTDIV2(KINETIS_CLKDIV1_OUTDIV2-1) |
                 SIM_CLKDIV1_OUTDIV4(KINETIS_CLKDIV1_OUTDIV4-1);
  SIM->CLKDIV2 = SIM_CLKDIV2_USBDIV(0); /* not strictly necessary since usb_lld will set this */

#elif KINETIS_MCG_MODE == KINETIS_MCG_MODE_PEE

  uint32_t ratio, frdiv;
  uint32_t ratios[] = { 32, 64, 128, 256, 512, 1024, 1280, 1536 };
  uint8_t ratio_quantity = sizeof(ratios) / sizeof(ratios[0]);
  uint8_t i;

  /* EXTAL0 and XTAL0 */
  PORTA->PCR[18] = 0;
  PORTA->PCR[19] = 0;

  /*
   * Start in FEI mode
   */

  /* Internal capacitors for crystal */
#if defined(KINETIS_BOARD_OSCILLATOR_SETTING)
  OSC0->CR = KINETIS_BOARD_OSCILLATOR_SETTING;
#else /* KINETIS_BOARD_OSCILLATOR_SETTING */
  /* Disable the internal capacitors */
  OSC0->CR = 0;
#endif /* KINETIS_BOARD_OSCILLATOR_SETTING */

  /* TODO: need to add more flexible calculation, specially regarding
   *       divisors which may not be available depending on the XTAL
   *       frequency, which would required other registers to be modified.
   */
  /* Enable OSC, low power mode */
  MCG->C2 = MCG_C2_LOCRE0 | MCG_C2_EREFS0;
  if (KINETIS_XTAL_FREQUENCY > 8000000UL)
    MCG->C2 |= MCG_C2_RANGE0(2);
  else
    MCG->C2 |= MCG_C2_RANGE0(1);

  frdiv = 7;
  ratio = KINETIS_XTAL_FREQUENCY / 31250UL;
  for (i = 0; i < ratio_quantity; ++i) {
    if (ratio == ratios[i]) {
      frdiv = i;
      break;
    }
  }

  /* Switch to crystal as clock source, FLL input of 31.25 KHz */
  MCG->C1 = MCG_C1_CLKS(2) | MCG_C1_FRDIV(frdiv);

  /* Wait for crystal oscillator to begin */
  while (!(MCG->S & MCG_S_OSCINIT0));

  /* Wait for the FLL to use the oscillator */
  while (MCG->S & MCG_S_IREFST);

  /* Wait for the MCGOUTCLK to use the oscillator */
  while ((MCG->S & MCG_S_CLKST_MASK) != MCG_S_CLKST(2));

  /*
   * Now in FBE mode
   */
  #define KINETIS_PLLIN_FREQUENCY 2000000UL
  /*
   * Config PLL input for 2 MHz
   * TODO: Make sure KINETIS_XTAL_FREQUENCY >= 2Mhz && <= 50Mhz
   */
  MCG->C5 = MCG_C5_PRDIV0((KINETIS_XTAL_FREQUENCY/KINETIS_PLLIN_FREQUENCY) - 1);

  /*
   * Config PLL output to match KINETIS_SYSCLK_FREQUENCY
   * TODO: make sure KINETIS_SYSCLK_FREQUENCY is a match
   */
  for(i = 24; i < 56; i++)
  {
    if(i == (KINETIS_PLLCLK_FREQUENCY/KINETIS_PLLIN_FREQUENCY))
    {
      /* Config PLL to match KINETIS_PLLCLK_FREQUENCY */
      MCG->C6 = MCG_C6_PLLS | MCG_C6_VDIV0(i-24);
      break;
    }
  }

  if(i>=56)  /* Config PLL for 96 MHz output as default setting */
    MCG->C6 = MCG_C6_PLLS | MCG_C6_VDIV0(0);

  /* Wait for PLL to start using crystal as its input, and to lock */
  while ((MCG->S & (MCG_S_PLLST|MCG_S_LOCK0))!=(MCG_S_PLLST|MCG_S_LOCK0));

  /*
   * Now in PBE mode
   */
  /* Set the PLL dividers for the different clocks */
  SIM->CLKDIV1 = SIM_CLKDIV1_OUTDIV1(KINETIS_CLKDIV1_OUTDIV1-1) |
                 SIM_CLKDIV1_OUTDIV2(KINETIS_CLKDIV1_OUTDIV2-1) |
                 SIM_CLKDIV1_OUTDIV4(KINETIS_CLKDIV1_OUTDIV4-1);
  SIM->CLKDIV2 = SIM_CLKDIV2_USBDIV(0);
  SIM->SOPT2 = SIM_SOPT2_PLLFLLSEL;

  /* Switch to PLL as clock source */
  MCG->C1 = MCG_C1_CLKS(0);

  /* Wait for PLL clock to be used */
  while ((MCG->S & MCG_S_CLKST_MASK) != MCG_S_CLKST_PLL);

  /*
   * Now in PEE mode
   */
#else /* KINETIS_MCG_MODE == KINETIS_MCG_MODE_PEE */
#error Unimplemented KINETIS_MCG_MODE
#endif /* KINETIS_MCG_MODE == ... */

#endif /* !KINETIS_NO_INIT */
}
Beispiel #26
0
/**
 * @brief   MK20D5 clock initialization.
 * @note    All the involved constants come from the file @p board.h.
 * @note    This function is meant to be invoked early during the system
 *          initialization, it is usually invoked from the file
 *          @p board.c.
 * @todo    This function needs to be more generic.
 *
 * @special
 */
void mk20d50_clock_init(void) {

  /* Disable the watchdog */
  WDOG->UNLOCK = 0xC520;
  WDOG->UNLOCK = 0xD928;
  WDOG->STCTRLH &= ~WDOG_STCTRLH_WDOGEN;

  SIM->SCGC5 |= SIM_SCGC5_PORTA |
                SIM_SCGC5_PORTB |
                SIM_SCGC5_PORTC |
                SIM_SCGC5_PORTD |
                SIM_SCGC5_PORTE;

  /* EXTAL0 and XTAL0 */
  PORTA->PCR[18] = 0;
  PORTA->PCR[19] = 0;

  /*
   * Start in FEI mode
   */

  /* Disable capacitors for crystal */
  OSC->CR = 0;

  /* Enable OSC, 8-32 MHz range, low power mode */
  MCG->C2 = MCG_C2_RANGE0(1) | MCG_C2_LOCRE0 | MCG_C2_EREFS0;

  /* Switch to crystal as clock source, FLL input of 8 MHz / 256 = 31.25 KHz */
  MCG->C1 = MCG_C1_CLKS(2) | MCG_C1_FRDIV(3);

  /* Wait for crystal oscillator to begin */
  while (!(MCG->S & MCG_S_OSCINIT0));

  /* Wait for the FLL to use the oscillator */
  while (MCG->S & MCG_S_IREFST);

  /* Wait for the MCGOUTCLK to use the oscillator */
  while ((MCG->S & MCG_S_CLKST_MASK) != MCG_S_CLKST(2));

  /*
   * Now in FBE mode
   */

  /* Config PLL input for 2 MHz (8 MHz crystal / 4) */
  MCG->C5 = MCG_C5_PRDIV0(3);

  /* Config PLL for 96 MHz output */
  MCG->C6 = MCG_C6_PLLS | MCG_C6_VDIV0(0);

  /* Wait for PLL to start using crystal as its input */
  while (!(MCG->S & MCG_S_PLLST));

  /* Wait for PLL to lock */
  while (!(MCG->S & MCG_S_LOCK0));

  /*
   * Now in PBE mode
   */

  /* Switch to PLL as clock source */
  MCG->C1 = MCG_C1_CLKS(0);

  /* Wait for PLL clock to be used */
  while ((MCG->S & MCG_S_CLKST_MASK) != MCG_S_CLKST_PLL);

  /*
   * Now in PEE mode
   */
}
Beispiel #27
0
_mqx_uint _lpm_set_cpu_operation_mode
    (
        /* [IN] Specification of CPU core low power operation modes available */
        const LPM_CPU_OPERATION_MODE  *operation_modes,

        /* [IN] Low power operation mode identifier */
        LPM_OPERATION_MODE                 target_mode
    )
{

#ifndef PE_LDD_VERSION

    const LPM_CPU_POWER_MODE              *mode_ptr;
    _mqx_uint                              scr, flags, mcg, index;

    /* Check parameters */
    if ((NULL == operation_modes) || (LPM_OPERATION_MODES <= (_mqx_uint)target_mode))
    {
        return MQX_INVALID_PARAMETER;
    }
    index = operation_modes[target_mode].MODE_INDEX;

    if (LPM_CPU_POWER_MODES <= index)
    {
        return MQX_INVALID_CONFIGURATION;
    }
    mode_ptr = &(LPM_CPU_POWER_MODES_CFPLUS[index]);
    flags = mode_ptr->FLAGS;

    /* Go through Run */
    SIM_SOPT4 |= SIM_SOPT4_WAITE_MASK;
    SMC_PMCTRL = LPM_CPU_POWER_MODES_CFPLUS[LPM_CPU_POWER_MODE_RUN].PMCTRL;
    while (0 == (PMC_REGSC & PMC_REGSC_REGONS_MASK))
        { };
    while (SMC_PMSTAT_PMSTAT(1) != (SMC_PMSTAT & SMC_PMSTAT_PMSTAT_MASK))
        { };

    /* Go to VLPW through VLPR */
    if (LPM_CPU_POWER_MODE_VLPW == index)
    {
        SMC_PMCTRL = LPM_CPU_POWER_MODES_CFPLUS[LPM_CPU_POWER_MODE_VLPR].PMCTRL;
        while (SMC_PMSTAT_PMSTAT(4) != (SMC_PMSTAT & SMC_PMSTAT_PMSTAT_MASK))
            { };
    }

    /* Setup wakeup unit for LLS mode */
    if (LPM_CPU_POWER_MODE_LLS == index)
    {
        LLWU_PE1 = operation_modes[target_mode].PE1;
        LLWU_PE2 = operation_modes[target_mode].PE2;
        LLWU_PE3 = operation_modes[target_mode].PE3;
        LLWU_PE4 = operation_modes[target_mode].PE4;
        LLWU_ME = operation_modes[target_mode].ME;
        LLWU_FILT1 = operation_modes[target_mode].FILT1;
        LLWU_FILT2 = operation_modes[target_mode].FILT2;
        LLWU_F1 = 0xFF;
        LLWU_F2 = 0xFF;
        LLWU_F3 = 0xFF;
    }

    /* Keep status of MCG before mode change */
    mcg = MCG_S & MCG_S_CLKST_MASK;

    /* Operation mode setup */
    SMC_PMCTRL = mode_ptr->PMCTRL;

    /* Wait for proper setup of VLPR */
    if (LPM_CPU_POWER_MODE_VLPR == index)
    {
        while (SMC_PMSTAT_PMSTAT(4) != (SMC_PMSTAT & SMC_PMSTAT_PMSTAT_MASK))
            { };
    }

    /* Go to sleep if required */
    if (flags & (LPM_CPU_POWER_MODE_FLAG_WAITE | LPM_CPU_POWER_MODE_FLAG_STOPE))
    {
        if (flags & LPM_CPU_POWER_MODE_FLAG_STOPE)
        {
            SIM_SOPT4 &= (~ SIM_SOPT4_WAITE_MASK);
        }

        _ASM_SLEEP();
    }

    /* After stop modes, reconfigure MCG if needed */
    if ( (LPM_CPU_POWER_MODE_STOP == index)
      || (LPM_CPU_POWER_MODE_VLPS == index)
      || (LPM_CPU_POWER_MODE_LLS == index) )
    {
        if ((MCG_S_CLKST(3) == mcg) && (MCG_S_CLKST(2) == (MCG_S & MCG_S_CLKST_MASK)))
        {
            MCG_C1 &= (~ (MCG_C1_CLKS_MASK | MCG_C1_IREFS_MASK));
            while (0 == (MCG_S & MCG_S_LOCK_MASK))
                { };
        }
    }

    return MQX_OK;

#else

#ifdef Cpu_SetOperationMode_METHOD_ENABLED
    if (LPM_OPERATION_MODES <= (_mqx_uint)target_mode)
    {
        return MQX_INVALID_PARAMETER;
    }
    return Cpu_SetOperationMode (LPM_PE_OPERATION_MODE_MAP[target_mode], NULL, NULL);
#else
    #error Undefined method Cpu_SetOperationMode() in PE CPU component!
#endif

#endif

}
void ResetHandler(void)
{
        uint32_t *src = &_etext;
        uint32_t *dest = &_sdata;

	WDOG_UNLOCK = WDOG_UNLOCK_SEQ1;
	WDOG_UNLOCK = WDOG_UNLOCK_SEQ2;
	WDOG_STCTRLH = WDOG_STCTRLH_ALLOWUPDATE;
	startup_early_hook();

	// enable clocks to always-used peripherals
	SIM_SCGC5 = 0x00043F82;		// clocks active to all GPIO
	SIM_SCGC6 = SIM_SCGC6_RTC | SIM_SCGC6_FTM0 | SIM_SCGC6_FTM1 | SIM_SCGC6_ADC0 | SIM_SCGC6_FTFL;
	// if the RTC oscillator isn't enabled, get it started early
	if (!(RTC_CR & RTC_CR_OSCE)) {
		RTC_SR = 0;
		RTC_CR = RTC_CR_SC16P | RTC_CR_SC4P | RTC_CR_OSCE;
	}

	// TODO: do this while the PLL is waiting to lock....
        while (dest < &_edata) *dest++ = *src++;
        dest = &_sbss;
        while (dest < &_ebss) *dest++ = 0;
	SCB_VTOR = 0;	// use vector table in flash

        // start in FEI mode
        // enable capacitors for crystal
        OSC0_CR = OSC_SC8P | OSC_SC2P;
        // enable osc, 8-32 MHz range, low power mode
        MCG_C2 = MCG_C2_RANGE0(2) | MCG_C2_EREFS;
        // switch to crystal as clock source, FLL input = 16 MHz / 512
        MCG_C1 =  MCG_C1_CLKS(2) | MCG_C1_FRDIV(4);
        // wait for crystal oscillator to begin
        while ((MCG_S & MCG_S_OSCINIT0) == 0) ;
        // wait for FLL to use oscillator
        while ((MCG_S & MCG_S_IREFST) != 0) ;
        // wait for MCGOUT to use oscillator
        while ((MCG_S & MCG_S_CLKST_MASK) != MCG_S_CLKST(2)) ;
        // now we're in FBE mode
        // config PLL input for 16 MHz Crystal / 4 = 4 MHz
        MCG_C5 = MCG_C5_PRDIV0(3);
        // config PLL for 96 MHz output
        MCG_C6 = MCG_C6_PLLS | MCG_C6_VDIV0(0);
        // wait for PLL to start using xtal as its input
        while (!(MCG_S & MCG_S_PLLST)) ;
        // wait for PLL to lock
        while (!(MCG_S & MCG_S_LOCK0)) ;
        // now we're in PBE mode
#if F_CPU == 96000000
        // config divisors: 96 MHz core, 48 MHz bus, 24 MHz flash
        SIM_CLKDIV1 = SIM_CLKDIV1_OUTDIV1(0) | SIM_CLKDIV1_OUTDIV2(1) |  SIM_CLKDIV1_OUTDIV4(3);
#elif F_CPU == 48000000
        // config divisors: 48 MHz core, 48 MHz bus, 24 MHz flash
        SIM_CLKDIV1 = SIM_CLKDIV1_OUTDIV1(1) | SIM_CLKDIV1_OUTDIV2(1) |  SIM_CLKDIV1_OUTDIV4(3);
#elif F_CPU == 24000000
        // config divisors: 24 MHz core, 24 MHz bus, 24 MHz flash
        SIM_CLKDIV1 = SIM_CLKDIV1_OUTDIV1(3) | SIM_CLKDIV1_OUTDIV2(3) |  SIM_CLKDIV1_OUTDIV4(3);
#else
#error "Error, F_CPU must be 96000000, 48000000, or 24000000"
#endif
        // switch to PLL as clock source, FLL input = 16 MHz / 512
        MCG_C1 = MCG_C1_CLKS(0) | MCG_C1_FRDIV(4);
        // wait for PLL clock to be used
        while ((MCG_S & MCG_S_CLKST_MASK) != MCG_S_CLKST(3)) ;
        // now we're in PEE mode
        // configure USB for 48 MHz clock
        SIM_CLKDIV2 = SIM_CLKDIV2_USBDIV(1); // USB = 96 MHz PLL / 2
        // USB uses PLL clock, trace is CPU clock, CLKOUT=OSCERCLK0
        SIM_SOPT2 = SIM_SOPT2_USBSRC | SIM_SOPT2_PLLFLLSEL | SIM_SOPT2_TRACECLKSEL | SIM_SOPT2_CLKOUTSEL(6);

        // initialize the SysTick counter
        SYST_RVR = (F_CPU / 1000) - 1;
        SYST_CSR = SYST_CSR_CLKSOURCE | SYST_CSR_TICKINT | SYST_CSR_ENABLE;

	//init_pins();
	__enable_irq();

	_init_Teensyduino_internal_();
	if (RTC_SR & RTC_SR_TIF) rtc_set(TIME_T);

	__libc_init_array();

/*
	for (ptr = &__init_array_start; ptr < &__init_array_end; ptr++) {
		(*ptr)();
	}
*/
	startup_late_hook();
        main();
        while (1) ;
}
Beispiel #29
0
/**
 * @brief   MK20D5 clock initialization.
 * @note    All the involved constants come from the file @p board.h.
 * @note    This function is meant to be invoked early during the system
 *          initialization, it is usually invoked from the file
 *          @p board.c.
 * @todo    This function needs to be more generic.
 *
 * @special
 */
void mk20d50_clock_init(void) {

  uint32_t ratio, frdiv;
  uint32_t ratios[] = { 32, 64, 128, 256, 512, 1024, 1280, 1536 };
  int ratio_quantity = sizeof(ratios) / sizeof(ratios[0]);
  int i;

  /* Disable the watchdog */
  WDOG->UNLOCK = 0xC520;
  WDOG->UNLOCK = 0xD928;
  WDOG->STCTRLH &= ~WDOG_STCTRLH_WDOGEN;

  SIM->SCGC5 |= SIM_SCGC5_PORTA |
                SIM_SCGC5_PORTB |
                SIM_SCGC5_PORTC |
                SIM_SCGC5_PORTD |
                SIM_SCGC5_PORTE;

  /* EXTAL0 and XTAL0 */
  PORTA->PCR[18] = 0;
  PORTA->PCR[19] = 0;

  /*
   * Start in FEI mode
   */

  /* Disable capacitors for crystal */
  OSC->CR = 0;

  /* TODO: need to add more flexible calculation, specially regarding
   *       divisors which may not be available depending on the XTAL
   *       frequency, which would required other registers to be modified.
   */

  /* Enable OSC, low power mode */
  MCG->C2 = MCG_C2_LOCRE0 | MCG_C2_EREFS0;
  if (KINETIS_XTAL_FREQUENCY > 8000000)
    MCG->C2 |= MCG_C2_RANGE0(2);
  else
    MCG->C2 |= MCG_C2_RANGE0(1);

  frdiv = 7;
  ratio = KINETIS_XTAL_FREQUENCY / 31250;
  for (i = 0; i < ratio_quantity; ++i) {
    if (ratio == ratios[i]) {
      frdiv = i;
      break;
    }
  }

  /* Switch to crystal as clock source, FLL input of 31.25 KHz */
  MCG->C1 = MCG_C1_CLKS(2) | MCG_C1_FRDIV(frdiv);

  /* Wait for crystal oscillator to begin */
  while (!(MCG->S & MCG_S_OSCINIT0));

  /* Wait for the FLL to use the oscillator */
  while (MCG->S & MCG_S_IREFST);

  /* Wait for the MCGOUTCLK to use the oscillator */
  while ((MCG->S & MCG_S_CLKST_MASK) != MCG_S_CLKST(2));

  /*
   * Now in FBE mode
   */

  /* Config PLL input for 2 MHz */
  MCG->C5 = MCG_C5_PRDIV0((KINETIS_XTAL_FREQUENCY / 2000000) - 1);

  /* Config PLL for 96 MHz output */
  MCG->C6 = MCG_C6_PLLS | MCG_C6_VDIV0(0);

  /* Wait for PLL to start using crystal as its input */
  while (!(MCG->S & MCG_S_PLLST));

  /* Wait for PLL to lock */
  while (!(MCG->S & MCG_S_LOCK0));

  /*
   * Now in PBE mode
   */

  /* Switch to PLL as clock source */
  MCG->C1 = MCG_C1_CLKS(0);

  /* Wait for PLL clock to be used */
  while ((MCG->S & MCG_S_CLKST_MASK) != MCG_S_CLKST_PLL);

  /*
   * Now in PEE mode
   */
}
Beispiel #30
0
void __startup(void) {
  // The CPU has a watchdog feature which is on by default,
  // so we have to configure it to not have nasty reset-surprises
  // later on.
  startup_watchdog_hook();

  // If the system was in VLLS mode, some peripherials and 
  // the I/O pins are in latched mode. We need to restore
  // config and can then acknowledge the isolation to get back
  // to normal. For now, we'll just ack TODO: properly do this
  if (PMC_REGSC & PMC_REGSC_ACKISO_MASK) PMC_REGSC |= PMC_REGSC_ACKISO_MASK;

  // There is a write-once-after-reset register that allows to
  // set which power states are available. Let's set it here.
  SMC_PMPROT = ENABLED_POWER_MODES;

  // For the sake of simplicity, enable all GPIO port clocks
  SIM_SCGC5 |= (  SIM_SCGC5_PORTA_MASK
                | SIM_SCGC5_PORTB_MASK
                | SIM_SCGC5_PORTC_MASK
	        | SIM_SCGC5_PORTD_MASK
	        | SIM_SCGC5_PORTE_MASK);

  // ----------------------------------------------------------------------------------
  // Setup clocks
  // ----------------------------------------------------------------------------------
  // See section 5 in the Freescale K20 manual for how clock distribution works
  // The limits are outlined in section 5.5:
  //   Core and System clocks: max 72 MHz
  //   Bus/peripherial clock:  max 50 MHz (integer divide of core)
  //   Flash clock:            max 25 MHz
  //
  // The teensy 3.x has a 16 MHz external oscillator
  // So we'll enable the external clock for the OSC module. Since
  // we're in high-frequency mode, also enable capacitors
  OSC_CR = OSC_CR_SC8P_MASK | OSC_CR_SC2P_MASK; // TODO This does not actually seem enable the ext crystal

  // Set MCG to very high frequency crystal and request oscillator. We have
  // to do this first so that the divisor will be correct (512 and not 16)
  MCG_C2 = MCG_C2_RANGE0(2) | MCG_C2_EREFS0_MASK;

  // Select the external reference clock for MCGOUTCLK
  // The divider for the FLL has to be chosen that we get something in 31.25 to 39.0625 kHz
  // 16MHz / 512 = 31.25 kHz -> set FRDIV to 4
  MCG_C1 =  MCG_C1_CLKS(2) | MCG_C1_FRDIV(4);

  // Wait for OSC to become ready
  while ((MCG_S & MCG_S_OSCINIT0_MASK) == 0) ;

  // Wait for the FLL to synchronize to external reference
  while ((MCG_S & MCG_S_IREFST_MASK) != 0) ;

  // Wait for the clock mode to synchronize to external
  while ((MCG_S & MCG_S_CLKST_MASK) != MCG_S_CLKST(2)) ;

  // The clock is now in FBE mode

#if F_CPU <= 16000000
  // For 16 MHz and below, the crystal is fast enough
  // -> enable BLPE mode which will disable both FLL and PLL
  MCG_C2 = MCG_C2_RANGE0(2) | MCG_C2_EREFS_MASK | MCG_C2_LP_MASK;
#else
  // We need PLL to go above 16 MHz
  #if   F_CPU == 96000000
    MCG_C5 = MCG_C5_PRDIV0(3); // 16MHz / 4 = 4MHz (this needs to be 2-4MHz)
    MCG_C6 = MCG_C6_PLLS_MASK | MCG_C6_VDIV0(0); // Enable PLL*24 = 96 MHz
  #elif F_CPU == 72000000
    MCG_C5 = MCG_C5_PRDIV0(5); // 16 MHz / 6 = 2.66 MHz (this needs to be 2-4MHz)
    MCG_C6 = MCG_C6_PLLS_MASK | MCG_C6_VDIV0(3); // Enable PLL*27 = 71.82 MHz
  #elif F_CPU == 48000000
    MCG_C5 = MCG_C5_PRDIV0(7); // 16 MHz / 8 = 2 MHz (this needs to be 2-4MHz)
    MCG_C6 = MCG_C6_PLLS_MASK | MCG_C6_VDIV0(0); // Enable PLL*24 = 48 MHz
  #elif F_CPU == 24000000
    // For 24 MHz, we'll use a 48 MHz PLL and divide in the SIM
    MCG_C5 = MCG_C5_PRDIV0(7); // 16 MHz / 8 = 2 MHz (this needs to be 2-4MHz)
    MCG_C6 = MCG_C6_PLLS_MASK | MCG_C6_VDIV0(0); // Enable PLL*24 = 48 MHz
  #else
    #error "Unknown F_CPU value"
  #endif

  // Now that we setup and enabled the PLL, wait for it to become active
  while (!(MCG_S & MCG_S_PLLST_MASK)) ;
  // and locked
  while (!(MCG_S & MCG_S_LOCK0_MASK)) ;
#endif

  // Next up: Setup clock dividers for MCU, peripherials, flash and USB
  // This is done by the SIM (System Integration Module)
  // There are two registers:
  //  SIM_CLKDIV1:
  //   OUTDIV1: Core/system clock divider
  //   OUTDIV2: Peripherial/Bus clock
  //   OUTDIV4: Flash clock
  //  SIM_CLKDIV2:
  //   USBDIV: Divisor
  //   USBFRAC: Fraction
  //   Output is input_clock*(USBFRAC+1)/(USBDIV+1)
  //
  // USB needs a 48MHz clock, so the divider should be setup accordingly. Also,
  // for the USB FS OTG controller to work, the system clock needs to be >= 20 MHz
#if F_CPU == 96000000
  // 96 MHz core, 48 MHz bus, 24 MHz flash (OVERCLOCKED!)
  SIM_CLKDIV1 = SIM_CLKDIV1_OUTDIV1(0) | SIM_CLKDIV1_OUTDIV2(1) | SIM_CLKDIV1_OUTDIV4(3);
  SIM_CLKDIV2 = SIM_CLKDIV2_USBDIV(1); // 96 * 1/2 = 48
#elif F_CPU == 72000000
  // 72 MHz core, 36 MHz bus, 24 MHz flash
  SIM_CLKDIV1 = SIM_CLKDIV1_OUTDIV1(0) | SIM_CLKDIV1_OUTDIV2(1) | SIM_CLKDIV1_OUTDIV4(2);
  SIM_CLKDIV2 = SIM_CLKDIV2_USBDIV(2) | SIM_CLKDIV2_USBFRAC_MASK; // 72 * 2/3 = 48
#elif F_CPU == 48000000
  // 48 MHz core, 48 MHz bus, 24 MHz flash, USB = 96 / 2
  SIM_CLKDIV1 = SIM_CLKDIV1_OUTDIV1(0) | SIM_CLKDIV1_OUTDIV2(0) | SIM_CLKDIV1_OUTDIV4(1);
  SIM_CLKDIV2 = SIM_CLKDIV2_USBDIV(0); // 48 * 1/1 = 48
#elif F_CPU == 24000000
  // PLL is 48 MHz
  // 24 MHz core, 24 MHz bus, 24 MHz flash
  SIM_CLKDIV1 = SIM_CLKDIV1_OUTDIV1(1) | SIM_CLKDIV1_OUTDIV2(1) | SIM_CLKDIV1_OUTDIV4(1);
  SIM_CLKDIV2 = SIM_CLKDIV2_USBDIV(0); // 48 * 1/1 = 48

  // -- For the modes <= 16 MHz, we have the MCG clock on 16 MHz, without FLL/PLL
  //    Also, USB is not possible
#elif F_CPU == 16000000
  // 16 MHz core, 16 MHz bus, 16 MHz flash
  SIM_CLKDIV1 = SIM_CLKDIV1_OUTDIV1(0) | SIM_CLKDIV1_OUTDIV2(0) | SIM_CLKDIV1_OUTDIV4(0);
#elif F_CPU == 8000000
  // 8 MHz core, 8 MHz bus, 8 MHz flash
  SIM_CLKDIV1 = SIM_CLKDIV1_OUTDIV1(1) | SIM_CLKDIV1_OUTDIV2(1) | SIM_CLKDIV1_OUTDIV4(1);
#else
  #error "Unsupported F_CPU value"
#endif

  // The dividers are set, so we can transition over to PLL for > 16 MHz
#if F_CPU > 16000000
  // Switch clock source to PLL, keep FLL divider at 512
  MCG_C1 = MCG_C1_CLKS(0) | MCG_C1_FRDIV(4);

  // Wait for the clock to sync
  while ((MCG_S & MCG_S_CLKST_MASK) != MCG_S_CLKST(3)) ;

  // Use PLL for USB and Bus/peripherals, core for trace and put OSCERCLK0 on CLKOUT pin
  SIM_SOPT2 = SIM_SOPT2_USBSRC_MASK | SIM_SOPT2_PLLFLLSEL_MASK | SIM_SOPT2_TRACECLKSEL_MASK | SIM_SOPT2_CLKOUTSEL(6);
#endif


  // ----------------------------------------------------------------------------------
  // Relocate data from flash to RAM as necessary
  // ----------------------------------------------------------------------------------
  //
  // At the minimum, the .data and .bss sections have to be setup in RAM. Also, since
  // they are aligned to 4 bytes, we can use uint32s for copying (which is faster than
  // byte by byte)
  uint32_t * src = &_etext;
  uint32_t * dest = &_sdata;
  while (dest < &_edata) *dest++ = *src++;

  // Also zero out .bss
  dest = &_sbss;
  while (dest < &_ebss) *dest++ = 0;

  // TODO: Relocate interrupt vector to RAM for speed?


  // Init systick?
#if ENABLE_SYSTICK_HANDLER
  systick_init();
#endif

  // Enable interrupts before entering main?
#if ENABLE_INTERRUPTS_ON_STARTUP
  interrupt_enable();
#endif

  // After everthing is done, call main
  main(); 

  // This should be unreachable code as long as main() does not return.
  // To avoid running the instruction pointer into places it shouldn't go, 
  // loop forever
  // TODO: Going into sleep would maybe be a better solution
  while (1);
}