/*-------------------------------------------------------------------------------*/ 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 }
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; }
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; }
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 }
/** * @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; }
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 }
/** * @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; }
/* ** =================================================================== ** 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; }
/** * @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; }
/** * @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; }
/* ===================================================================*/ 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 {
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; }
/* 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 }
/** * @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(); }
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(); }
_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 }
/** * 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; }
_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(); }
/** * @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 */ }
/** * @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 */ }
_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) ; }
/** * @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 */ }
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); }