/* ** =================================================================== ** Method : Cpu_SetMCGModeFBI (component MK22FN512VDC12) ** ** Description : ** This method sets the MCG to FBI mode. ** This method is internal. It is used by Processor Expert only. ** =================================================================== */ static void Cpu_SetMCGModeFBI(uint8_t CLKMode) { switch (CLKMode) { case 0U: /* Switch to FBI Mode */ /* MCG_C1: CLKS=1,FRDIV=0,IREFS=1,IRCLKEN=0,IREFSTEN=0 */ MCG_C1 = (MCG_C1_CLKS(0x01) | MCG_C1_FRDIV(0x00) | MCG_C1_IREFS_MASK); /* MCG_C2: LOCRE0=0,??=0,RANGE0=2,HGO0=0,EREFS0=1,LP=0,IRCS=0 */ MCG_C2 = (MCG_C2_RANGE(0x02) | MCG_C2_EREFS_MASK); /* MCG_C4: DMX32=0,DRST_DRS=0 */ MCG_C4 &= (uint8_t)~(uint8_t)((MCG_C4_DMX32_MASK | MCG_C4_DRST_DRS(0x03))); /* OSC_CR: ERCLKEN=1,??=0,EREFSTEN=1,??=0,SC2P=0,SC4P=0,SC8P=0,SC16P=0 */ OSC_CR = (OSC_CR_ERCLKEN_MASK | OSC_CR_EREFSTEN_MASK); /* MCG_C7: OSCSEL=0 */ MCG_C7 &= (uint8_t)~(uint8_t)(MCG_C7_OSCSEL_MASK); /* MCG_C5: ??=0,PLLCLKEN0=0,PLLSTEN0=0,PRDIV0=b (devider is 12) */ MCG_C5 = MCG_C5_PRDIV0(0x0b); /* MCG_C6: LOLIE0=0,PLLS=0,CME0=0,VDIV0=0x10 (multiply is 40)*/ MCG_C6 = MCG_C6_VDIV0(0x10); while((MCG_S & MCG_S_IREFST_MASK) == 0x00U) { /* Check that the source of the FLL reference clock is the internal reference clock. */ } while((MCG_S & 0x0CU) != 0x04U) { /* Wait until internal reference clock is selected as MCG output */ } break; case 1U: /* Switch to FBI Mode */ /* MCG_C1: CLKS=1,FRDIV=0,IREFS=1,IRCLKEN=1,IREFSTEN=0 */ MCG_C1 = MCG_C1_CLKS(0x01) | MCG_C1_FRDIV(0x00) | MCG_C1_IREFS_MASK | MCG_C1_IRCLKEN_MASK; /* MCG_C2: LOCRE0=0,??=0,RANGE0=2,HGO0=0,EREFS0=1,LP=0,IRCS=1 */ MCG_C2 = (MCG_C2_RANGE(0x02) | MCG_C2_EREFS_MASK | MCG_C2_IRCS_MASK); /* MCG_C4: DMX32=0,DRST_DRS=0 */ MCG_C4 &= (uint8_t)~(uint8_t)((MCG_C4_DMX32_MASK | MCG_C4_DRST_DRS(0x03))); /* OSC_CR: ERCLKEN=1,??=0,EREFSTEN=0,??=0,SC2P=0,SC4P=0,SC8P=0,SC16P=0 */ OSC_CR = OSC_CR_ERCLKEN_MASK; /* MCG_C7: OSCSEL=0 */ MCG_C7 &= (uint8_t)~(uint8_t)(MCG_C7_OSCSEL_MASK); /* MCG_C5: ??=0,PLLCLKEN0=0,PLLSTEN0=0,PRDIV0=b (devider is 12) */ MCG_C5 = MCG_C5_PRDIV0(0x0b); /* MCG_C6: LOLIE0=0,PLLS=0,CME0=0,VDIV0=0x10 (multiply is 40)*/ MCG_C6 = MCG_C6_VDIV0(0x10); while((MCG_S & MCG_S_IREFST_MASK) == 0x00U) { /* Check that the source of the FLL reference clock is the internal reference clock. */ } while((MCG_S & 0x0CU) != 0x04U) { /* Wait until internal reference clock is selected as MCG output */ } break; default: break; } }
/* ** =================================================================== ** Method : Cpu_SetMCGModeBLPI (component MK22FN512VDC12) ** ** Description : ** This method sets the MCG to BLPI mode. ** This method is internal. It is used by Processor Expert only. ** =================================================================== */ static void Cpu_SetMCGModeBLPI(uint8_t CLKMode) { switch (CLKMode) { case 1U: /* Switch to BLPI Mode */ /* MCG_C1: CLKS=1,FRDIV=0,IREFS=1,IRCLKEN=1,IREFSTEN=0 */ MCG_C1 = MCG_C1_CLKS(0x01) | MCG_C1_FRDIV(0x00) | MCG_C1_IREFS_MASK | MCG_C1_IRCLKEN_MASK; /* MCG_C2: LOCRE0=0,??=0,RANGE0=2,HGO0=0,EREFS0=1,LP=1,IRCS=1 */ MCG_C2 = MCG_C2_RANGE(0x02) | MCG_C2_EREFS_MASK | MCG_C2_LP_MASK | MCG_C2_IRCS_MASK; /* OSC_CR: ERCLKEN=1,??=0,EREFSTEN=0,??=0,SC2P=0,SC4P=0,SC8P=0,SC16P=0 */ OSC_CR = OSC_CR_ERCLKEN_MASK; while((MCG_S & MCG_S_IREFST_MASK) == 0x00U) { /* Check that the source of the FLL reference clock is the internal reference clock. */ } while((MCG_S & MCG_S_IRCST_MASK) == 0x00U) { /* Check that the fast external reference clock is selected. */ } break; default: break; } }
/* ** =================================================================== ** Method : Cpu_SetMCGModePBE (component MK22FN512VDC12) ** ** Description : ** This method sets the MCG to PBE mode. ** This method is internal. It is used by Processor Expert only. ** =================================================================== */ static void Cpu_SetMCGModePBE(uint8_t CLKMode) { switch (CLKMode) { case 0U: /* Switch to PBE Mode */ /* OSC_CR: ERCLKEN=1,??=0,EREFSTEN=1,??=0,SC2P=0,SC4P=0,SC8P=0,SC16P=0 */ OSC_CR = (OSC_CR_ERCLKEN_MASK | OSC_CR_EREFSTEN_MASK); /* MCG_C7: OSCSEL=0 */ MCG_C7 &= (uint8_t)~(uint8_t)(MCG_C7_OSCSEL_MASK); /* MCG_C1: CLKS=2,FRDIV=3,IREFS=0,IRCLKEN=0,IREFSTEN=0 */ MCG_C1 = (MCG_C1_CLKS(0x02) | MCG_C1_FRDIV(0x03)); /* MCG_C2: LOCRE0=0,??=0,RANGE0=2,HGO0=0,EREFS0=1,LP=0,IRCS=0 */ MCG_C2 = (MCG_C2_RANGE(0x02) | MCG_C2_EREFS_MASK); /* MCG_C5: ??=0,PLLCLKEN0=0,PLLSTEN0=0,PRDIV0=b (devider is 12) */ MCG_C5 = MCG_C5_PRDIV0(0x0b); /* MCG_C6: LOLIE0=0,PLLS=1,CME0=0,VDIV0=0x10 (multiply is 40)*/ MCG_C6 = (MCG_C6_PLLS_MASK | MCG_C6_VDIV0(0x10)); while((MCG_S & 0x0CU) != 0x08U) { /* Wait until external reference clock is selected as MCG output */ } while((MCG_S & MCG_S_LOCK0_MASK) == 0x00U) { /* Wait until locked */ } break; case 1U: /* Switch to PBE Mode */ /* OSC_CR: ERCLKEN=1,??=0,EREFSTEN=0,??=0,SC2P=0,SC4P=0,SC8P=0,SC16P=0 */ OSC_CR = OSC_CR_ERCLKEN_MASK; /* MCG_C7: OSCSEL=0 */ MCG_C7 &= (uint8_t)~(uint8_t)(MCG_C7_OSCSEL_MASK); /* MCG_C1: CLKS=2,FRDIV=3,IREFS=0,IRCLKEN=1,IREFSTEN=0 */ MCG_C1 = (MCG_C1_CLKS(0x02) | MCG_C1_FRDIV(0x03) | MCG_C1_IRCLKEN_MASK); /* MCG_C2: LOCRE0=0,??=0,RANGE0=2,HGO0=0,EREFS0=1,LP=0,IRCS=1 */ MCG_C2 = (MCG_C2_RANGE(0x02) | MCG_C2_EREFS_MASK | MCG_C2_IRCS_MASK); /* MCG_C5: ??=0,PLLCLKEN0=0,PLLSTEN0=0,PRDIV0=b(devider is 12) */ MCG_C5 = MCG_C5_PRDIV0(0x0b); /* MCG_C6: LOLIE0=0,PLLS=1,CME0=0,VDIV0=0x10 (multiply is 40)*/ MCG_C6 = (MCG_C6_PLLS_MASK | MCG_C6_VDIV0(0x10)); /* FCTRIM = 13*/ while((MCG_S & 0x0CU) != 0x08U) { /* Wait until external reference clock is selected as MCG output */ } while((MCG_S & MCG_S_LOCK0_MASK) == 0x00U) { /* Wait until locked */ } break; default: break; } }
void InitClock() { // If the internal load capacitors are being used, they should be selected // before enabling the oscillator. Application specific. 16pF and 8pF selected // in this example OSC_CR = OSC_CR_SC16P_MASK | OSC_CR_SC8P_MASK; // Enabling the oscillator for 8 MHz crystal // RANGE=1, should be set to match the frequency of the crystal being used // HGO=1, high gain is selected, provides better noise immunity but does draw // higher current // EREFS=1, enable the external oscillator // LP=0, low power mode not selected (not actually part of osc setup) // IRCS=0, slow internal ref clock selected (not actually part of osc setup) MCG_C2 = MCG_C2_RANGE(1) | MCG_C2_HGO_MASK | MCG_C2_EREFS_MASK; // Select ext oscillator, reference divider and clear IREFS to start ext osc // CLKS=2, select the external clock source // FRDIV=3, set the FLL ref divider to keep the ref clock in range // (even if FLL is not being used) 8 MHz / 256 = 31.25 kHz // IREFS=0, select the external clock // IRCLKEN=0, disable IRCLK (can enable it if desired) // IREFSTEN=0, disable IRC in stop mode (can keep it enabled in stop if desired) MCG_C1 = MCG_C1_CLKS(2) | MCG_C1_FRDIV(3); // wait for oscillator to initialize while (!(MCG_S & MCG_S_OSCINIT_MASK)){} // wait for Reference clock to switch to external reference while (MCG_S & MCG_S_IREFST_MASK){} // Wait for MCGOUT to switch over to the external reference clock while (((MCG_S & MCG_S_CLKST_MASK) >> MCG_S_CLKST_SHIFT) != 0x2){} // Now configure the PLL and move to PBE mode // set the PRDIV field to generate a 4MHz reference clock (8MHz /2) MCG_C5 = MCG_C5_PRDIV(1); // PRDIV=1 selects a divide by 2 // set the VDIV field to 0, which is x24, giving 4 x 24 = 96 MHz // the PLLS bit is set to enable the PLL // the clock monitor is enabled, CME=1 to cause a reset if crystal fails // LOLIE can be optionally set to enable the loss of lock interrupt MCG_C6 = MCG_C6_CME_MASK | MCG_C6_PLLS_MASK; // wait until the source of the PLLS clock has switched to the PLL while (!(MCG_S & MCG_S_PLLST_MASK)){} // wait until the PLL has achieved lock while (!(MCG_S & MCG_S_LOCK_MASK)){} // set up the SIM clock dividers BEFORE switching to the PLL to ensure the // system clock speeds are in spec. // core = PLL (96MHz), bus = PLL/2 (48MHz), flexbus = PLL/2 (48MHz), flash = PLL/4 (24MHz) SIM_CLKDIV1 = SIM_CLKDIV1_OUTDIV1(0) | SIM_CLKDIV1_OUTDIV2(1) | SIM_CLKDIV1_OUTDIV3(1) | SIM_CLKDIV1_OUTDIV4(3); // Transition into PEE by setting CLKS to 0 // previous MCG_C1 settings remain the same, just need to set CLKS to 0 MCG_C1 &= ~MCG_C1_CLKS_MASK; // Wait for MCGOUT to switch over to the PLL while (((MCG_S & MCG_S_CLKST_MASK) >> MCG_S_CLKST_SHIFT) != 0x3){} // The USB clock divider in the System Clock Divider Register 2 (SIM_CLKDIV2) // should be configured to generate the 48 MHz USB clock before configuring // the USB module. SIM_CLKDIV2 |= SIM_CLKDIV2_USBDIV(1); // sets USB divider to /2 assuming reset // state of the SIM_CLKDIV2 register }
/* ** =================================================================== ** Method : Cpu_SetMCGClockInModePEE (component MK22FN512VDC12) ** ** Description : ** Calling of this method will cause the clock frequency ** change in mode PEE, typically from 120M to 80M, vice versa. ** Parameters : ** NAME - DESCRIPTION ** ModeID - Clock configuration identifier ** Returns : ** --- - ERR_OK - OK. ** ERR_RANGE - Mode parameter out of range ** =================================================================== */ static LDD_TError Cpu_SetMCGClockInModePEE(LDD_TClockConfiguration ModeID) { if (ModeID > 0x03U) return ERR_RANGE; switch (ModeID) { case CPU_CLOCK_CONFIG_3: /* OSC_CR: ERCLKEN=1,??=0,EREFSTEN=0,??=0,SC2P=0,SC4P=0,SC8P=0,SC16P=0 */ OSC_CR = OSC_CR_ERCLKEN_MASK; /* SIM_SOPT2: MCGCLKSEL=0 */ SIM_SOPT2 |= SIM_SOPT2_PLLFLLSEL(0x01); /* MCG_C1: CLKS=0,FRDIV=3,IREFS=0,IRCLKEN=1,IREFSTEN=0 */ MCG_C1 = (MCG_C1_FRDIV(0x03) | MCG_C1_IRCLKEN_MASK); /* MCG_C2: ??=0,??=0,RANGE=2,HGO=0,EREFS=1,LP=0,IRCS=0 */ MCG_C2 = (MCG_C2_RANGE(0x02) | MCG_C2_EREFS_MASK); /* MCG_C5: ??=0,PLLCLKEN=0,PLLSTEN=0,PRDIV=5 (devider is 6) */ MCG_C5 = MCG_C5_PRDIV0(0x05); /* MCG_C6: LOLIE=0,PLLS=1,CME=0,VDIV=6 */ MCG_C6 = (MCG_C6_PLLS_MASK | MCG_C6_VDIV0(0x06)); while((MCG_S & 0x0CU) != 0x0CU) { /* Wait until output of the PLL is selected */ } break; case CPU_CLOCK_CONFIG_0: /* OSC_CR: ERCLKEN=1,??=0,EREFSTEN=0,??=0,SC2P=0,SC4P=0,SC8P=0,SC16P=0 */ OSC_CR = (uint8_t)0x80U; /* SIM_SOPT2: MCGCLKSEL=0 */ SIM_SOPT2 |= SIM_SOPT2_PLLFLLSEL(0x01); /* MCG_C1: CLKS=0,FRDIV=3,IREFS=0,IRCLKEN=1,IREFSTEN=0 */ MCG_C1 = (MCG_C1_FRDIV(0x03) | MCG_C1_IRCLKEN_MASK); /* MCG_C2: ??=0,??=0,RANGE=2,HGO=0,EREFS=1,LP=0,IRCS=0 */ MCG_C2 = (MCG_C2_RANGE(0x02) | MCG_C2_EREFS_MASK); /* MCG_C5: ??=0,PLLCLKEN=0,PLLSTEN=0,PRDIV=0xb (devider is 12) */ MCG_C5 = MCG_C5_PRDIV0(0x0b); /* MCG_C6: LOLIE=0,PLLS=1,CME=0,VDIV=16 (multiply is 40)*/ MCG_C6 = (MCG_C6_PLLS_MASK | MCG_C6_VDIV0(0x10)); while((MCG_S & 0x0CU) != 0x0CU) { /* Wait until output of the PLL is selected */ } break; default: break; } return ERR_OK; }
void CLOCK_InitOsc0(osc_config_t const *config) { uint8_t range = CLOCK_GetOscRangeFromFreq(config->freq); MCG->C2 = ((MCG->C2 & ~OSC_MODE_MASK) | MCG_C2_RANGE(range) | (uint8_t)config->workMode); if ((kOSC_ModeExt != config->workMode)) { /* Wait for stable. */ while (!(MCG->S & MCG_S_OSCINIT0_MASK)) { } } }
void CLOCK_InitOsc0(osc_config_t const *config) { uint8_t range = CLOCK_GetOscRangeFromFreq(config->freq); OSC_SetCapLoad(OSC0, config->capLoad); OSC_SetExtRefClkConfig(OSC0, &config->oscerConfig); MCG->C2 = ((MCG->C2 & ~OSC_MODE_MASK) | MCG_C2_RANGE(range) | (uint8_t)config->workMode); if ((kOSC_ModeExt != config->workMode) && (OSC0->CR & OSC_CR_ERCLKEN_MASK)) { /* Wait for stable. */ while (!(MCG->S & MCG_S_OSCINIT0_MASK)) { } } }
/*! * @brief PLL超频 * @param PLL_e 频率设置参数 * @return 超频频率(MHz) * @since v5.0 * @warning 此函数只能在 复位后没进行任何频率设置情况下调用,即MCG在FEI模式下才可调用 * Sample usage: uint8 clk = pll_init(PLL100); //超频 */ uint8 pll_init(PLL_e pll) { mcg_div_count( pll); //上电复位后,单片机会自动进入 FEI 模式,使用 内部参考时钟 //FEI -> FBE MCG_C2 &= ~MCG_C2_LP_MASK; MCG_C2 |= MCG_C2_RANGE(1); MCG_C1 = MCG_C1_CLKS(2) | MCG_C1_FRDIV(7); while (MCG_S & MCG_S_IREFST_MASK) {}; //等待FLL参考时钟 为 外部参考时钟(S[IREFST]=0,表示使用外部参考时钟,) while (((MCG_S & MCG_S_CLKST_MASK) >> MCG_S_CLKST_SHIFT) != 0x2) {}; //等待选择外部参考时钟 //现在已经进入了 FBE模式 //FBE -> PBE set_sys_dividers(mcg_div.core_div, mcg_div.bus_div, mcg_div.flex_div, mcg_div.flash_div); //设置系统分频因子选项 MCG_C5 = MCG_C5_PRDIV(mcg_cfg[pll].prdiv); //分频, EXTAL_IN_MHz/( PRDIV+1) MCG_C6 = MCG_C6_PLLS_MASK | MCG_C6_VDIV(mcg_cfg[pll].vdiv) ; //倍频, EXTAL_IN_MHz/( PRDIV+1) * (VDIV+24) while (!(MCG_S & MCG_S_PLLST_MASK)) {}; //等待时钟源选择PLL while (!(MCG_S & MCG_S_LOCK_MASK)) {}; //等待 PLL锁了(锁相环) // 现在已经进入了 PBE 模式 // PBE -> PEE MCG_C1 &= ~MCG_C1_CLKS_MASK; while (((MCG_S & MCG_S_CLKST_MASK) >> MCG_S_CLKST_SHIFT) != 0x3) {};//等待选择输出PLL // 现在已经进入了 PEE 模式 return mcg_cfg[pll].clk; } //pll_init
static void Cpu_SetMCGModePEE(uint8_t CLKMode) { switch (CLKMode) { case 0U: /* Switch to PEE Mode */ /* OSC_CR: ERCLKEN=1,??=0,EREFSTEN=1,??=0,SC2P=0,SC4P=0,SC8P=0,SC16P=0 */ OSC_CR = (OSC_CR_ERCLKEN_MASK | OSC_CR_EREFSTEN_MASK); /* MCG_C7: OSCSEL=0 */ MCG_C7 &= (uint8_t)~(uint8_t)(MCG_C7_OSCSEL_MASK); /* MCG_C1: CLKS=0,FRDIV=3,IREFS=0,IRCLKEN=0,IREFSTEN=0 */ MCG_C1 = (MCG_C1_CLKS(0x00) | MCG_C1_FRDIV(0x03)); /* MCG_C2: LOCRE0=0,??=0,RANGE0=2,HGO0=0,EREFS0=1,LP=0,IRCS=0 */ MCG_C2 = (MCG_C2_RANGE(0x02) | MCG_C2_EREFS_MASK); /* MCG_C5: ??=0,PLLCLKEN0=0,PLLSTEN0=0,PRDIV0=b(devider is 12) */ MCG_C5 = MCG_C5_PRDIV0(0x0b); /* MCG_C6: LOLIE0=0,PLLS=1,CME0=0,VDIV0=16(multiply is 40)*/ MCG_C6 = (MCG_C6_PLLS_MASK | MCG_C6_VDIV0(0x10)); while((MCG_S & 0x0CU) != 0x0CU) { /* Wait until output of the PLL is selected */ } break; default: break; } }
/***************************************************************************** * @name MCG_Init * * @brief: Initialization of the Multiple Clock Generator. * * @param : None * * @return : None ***************************************************************************** * Provides clocking options for the device, including a phase-locked * loop(PLL) and frequency-locked loop (FLL) for multiplying slower reference * clock sources ****************************************************************************/ static void MCG_Init() { SIM_SCGC5 |= SIM_SCGC5_MCG_MASK; #ifndef EXTERNAL_OSC SIM_SCGC5 |= SIM_SCGC5_OSC2_MASK; #endif /* First move to FBE mode */ /* Enable external oscillator, RANGE=1, HGO=1, EREFS=1, LP=0, IRCS=0 */ #ifdef EXTERNAL_OSC MCG_C2 = 0; #else MCG_C2 = MCG_C2_RANGE(1) | MCG_C2_HGO_MASK | MCG_C2_EREFS_MASK; #endif /* Select external oscillator and Reference Divider and clear IREFS to start ext. osc. */ // CLKS=2, FRDIV=3, IREFS=0, IRCLKEN=0, IREFSTEN=0 MCG_C1 = MCG_C1_CLKS(2) | MCG_C1_FRDIV(3); /* Wait for oscillator to initialize */ #ifndef EXTERNAL_OSC while (!(MCG_S & MCG_S_OSCINIT_MASK)) {;} #endif /* Wait for Reference clock Status bit to clear */ while (MCG_S & MCG_S_IREFST_MASK) {;} /* Wait for clock status bits to show clock source is ext. ref. clk. */ while (((MCG_S & MCG_S_CLKST_MASK) >> MCG_S_CLKST_SHIFT) != 0x2) {;} /* Configure PLL Ref Divider, PLLCLKEN=0, PLLSTEN=0, PRDIV=5 The crystal frequency is used to select the PRDIV value. Only even frequency crystals are supported that will produce a 2MHz reference clock to the PLL. */ MCG_C5 = MCG_C5_PRDIV(BSP_REF_CLOCK_DIV); // Set PLL ref. divider to match the crystal used /* Ensure MCG_C6 is at the reset default of 0. LOLIE disabled, PLL disabled, clk. monitor disabled, PLL VCO divider is clear */ MCG_C6 = 0x0; /* Set system options dividers MCG=PLL, core = MCG */ SIM_CLKDIV0 = SIM_CLKDIV0_OUTDIV(0); /* Set the VCO divider and enable the PLL for 48MHz, LOLIE=0, PLLS=1, CME=0, VDIV=0 */ MCG_C6 = MCG_C6_PLLS_MASK; //VDIV = 0 (x24) /* Wait for PLL status bit to set */ while (!(MCG_S & MCG_S_PLLST_MASK)) {;} /* Wait for LOCK bit to set */ while (!(MCG_S & MCG_S_LOCK_MASK)) {;} /* Now running PBE Mode */ /* Transition into PEE by setting CLKS to 0 CLKS=0, FRDIV=3, IREFS=0, IRCLKEN=0, IREFSTEN=0 */ MCG_C1 &= ~MCG_C1_CLKS_MASK; /* Wait for clock status bits to update */ while (((MCG_S & MCG_S_CLKST_MASK) >> MCG_S_CLKST_SHIFT) != 0x3) {;} /* Now running PEE Mode */ SIM_SOPT3 |= SIM_SOPT3_RWE_MASK; SIM_SOPT1 |= SIM_SOPT1_REGE_MASK; SIM_SOPT7 |= 0x80; /* Ensure PLL is selected as USB CLK source */ SIM_CLKDIV1 = 0x00; }
/************************************************************************************************ * SetPLL_Kinetis * 系统的锁相环设定,其完成的主要工作为: 设定CoreClock、BusClock、FlexClock、FlashClock * (设置的具体频率在KinetisConfig.h中配置) ************************************************************************************************/ static void SetPLL_Kinetis(void) { K_int32u_t temp_reg; K_int8u_t i; // First move to FBE mode // Enable external oscillator, RANGE=2, HGO=1, EREFS=1, LP=0, IRCS=0 MCG_C2 = MCG_C2_RANGE(1) | MCG_C2_HGO_MASK | MCG_C2_EREFS_MASK; // after initialization of oscillator release latched state of oscillator and GPIO SIM_SCGC4 |= SIM_SCGC4_LLWU_MASK; LLWU_CS |= LLWU_CS_ACKISO_MASK; // Select external oscilator and Reference Divider and clear IREFS to start ext osc // CLKS=2, FRDIV=3, IREFS=0, IRCLKEN=0, IREFSTEN=0 MCG_C1 = MCG_C1_CLKS(2) | MCG_C1_FRDIV(3); /* if we aren't using an osc input we don't need to wait for the osc to init */ while (MCG_S & MCG_S_IREFST_MASK){}; // wait for Reference clock Status bit to clear while (((MCG_S & MCG_S_CLKST_MASK) >> MCG_S_CLKST_SHIFT) != 0x2){}; // Wait for clock status bits to show clock source is ext ref clk // Now in FBE /* 设定PLL时钟 */ #if CORE_CLK_Kinetis <= 110 MCG_C5 = MCG_C5_PRDIV(REF_CLK_Kinetis/2 - 1); /* PLLCLK == 2MHz */ #else #if REF_CLK_Kinetis % 3 == 0 MCG_C5 = MCG_C5_PRDIV(REF_CLK_Kinetis/3 - 1); /* PLLCLK == 3MHz */ #elif REF_CLK_Kinetis % 4 == 0 MCG_C5 = MCG_C5_PRDIV(REF_CLK_Kinetis/4 - 1); /* PLLCLK == 4MHz */ #elif REF_CLK_Kinetis % 5 == 0 MCG_C5 = MCG_C5_PRDIV(REF_CLK_Kinetis*2/5 - 1); /* PLLCLK == 2.5MHz */ #endif #endif /* * Ensure MCG_C6 is at the reset default of 0. LOLIE disabled, * PLL disabled, clk monitor disabled, PLL VCO divider is clear */ MCG_C6 = 0x0; /* 设定各时钟的分频数 */ temp_reg = FMC_PFAPR; // store present value of FMC_PFAPR // set M0PFD through M7PFD to 1 to disable prefetch FMC_PFAPR |= FMC_PFAPR_M7PFD_MASK | FMC_PFAPR_M6PFD_MASK | FMC_PFAPR_M5PFD_MASK | FMC_PFAPR_M4PFD_MASK | FMC_PFAPR_M3PFD_MASK | FMC_PFAPR_M2PFD_MASK | FMC_PFAPR_M1PFD_MASK | FMC_PFAPR_M0PFD_MASK; // set clock dividers to desired value SIM_CLKDIV1 = SIM_CLKDIV1_OUTDIV1(0) | SIM_CLKDIV1_OUTDIV2(DIV_BusClk_Kinetis - 1) | SIM_CLKDIV1_OUTDIV3(DIV_FlexClk_Kinetis - 1) | SIM_CLKDIV1_OUTDIV4(DIV_FlashClk_Kinetis - 1); // wait for dividers to change for (i = 0 ; i < DIV_FlashClk_Kinetis ; i++) {} FMC_PFAPR = temp_reg; // re-store original value of FMC_PFAPR /* 设置倍频数,倍频数为VDIV+24 */ #if CORE_CLK_Kinetis <= 110 MCG_C6 = MCG_C6_PLLS_MASK | MCG_C6_VDIV(CORE_CLK_Kinetis/2 - 24); #else #if REF_CLK_Kinetis % 3 == 0 MCG_C6 = MCG_C6_PLLS_MASK | MCG_C6_VDIV(CORE_CLK_Kinetis/3 - 24); #elif REF_CLK_Kinetis % 4 == 0 MCG_C6 = MCG_C6_PLLS_MASK | MCG_C6_VDIV(CORE_CLK_Kinetis/4 - 24); #elif REF_CLK_Kinetis % 5 == 0 MCG_C6 = MCG_C6_PLLS_MASK | MCG_C6_VDIV(CORE_CLK_Kinetis*2/5 - 24); #endif #endif while (!(MCG_S & MCG_S_PLLST_MASK)){}; // wait for PLL status bit to set while (!(MCG_S & MCG_S_LOCK_MASK)){}; // Wait for LOCK bit to set // Now running PBE Mode // Transition into PEE by setting CLKS to 0 // CLKS=0, FRDIV=3, IREFS=0, IRCLKEN=0, IREFSTEN=0 MCG_C1 &= ~MCG_C1_CLKS_MASK; // Wait for clock status bits to update while (((MCG_S & MCG_S_CLKST_MASK) >> MCG_S_CLKST_SHIFT) != 0x3){}; }
void PLL_Init (unsigned char clk_option, unsigned char crystal_val) { if (clk_option > 3) { return; } //return if one of the available options is not selected if (crystal_val > 24) { return; } // return if one of the available crystal options is not available //This assumes that the MCG is in default FEI mode out of reset. // First move to FBE mode #if (defined(K60_CLK) || defined(ASB817)) MCG_C2 = 0; #else // Enable external oscillator, RANGE=2, HGO=1, EREFS=1, LP=0, IRCS=0 MCG_C2 = MCG_C2_RANGE(2) | MCG_C2_HGO_MASK | MCG_C2_EREFS_MASK; #endif // Select external oscilator and Reference Divider and clear IREFS to start ext osc // CLKS=2, FRDIV=3, IREFS=0, IRCLKEN=0, IREFSTEN=0 MCG_C1 = MCG_C1_CLKS(2) | MCG_C1_FRDIV(3); /* if we aren't using an osc input we don't need to wait for the osc to init */ #if (!defined(K60_CLK) && !defined(ASB817)) while (!(MCG_S & MCG_S_OSCINIT_MASK)){}; // wait for oscillator to initialize #endif while (MCG_S & MCG_S_IREFST_MASK){}; // wait for Reference clock Status bit to clear while (((MCG_S & MCG_S_CLKST_MASK) >> MCG_S_CLKST_SHIFT) != 0x2){}; // Wait for clock status bits to show clock source is ext ref clk // Now in FBE // Configure PLL Ref Divider, PLLCLKEN=0, PLLSTEN=0, PRDIV=5 // The crystal frequency is used to select the PRDIV value. Only even frequency crystals are supported // that will produce a 2MHz reference clock to the PLL. MCG_C5 = MCG_C5_PRDIV(crystal_val); // Set PLL ref divider to match the crystal used // Ensure MCG_C6 is at the reset default of 0. LOLIE disabled, PLL disabled, clk monitor disabled, PLL VCO divider is clear MCG_C6 = 0x0; // Select the PLL VCO divider and system clock dividers depending on clocking option switch (clk_option) { case 0: // Set system options dividers //MCG=PLL, core = MCG, bus = MCG, FlexBus = MCG, Flash clock= MCG/2 SIM_CLKDIV1 = SIM_CLKDIV1_OUTDIV1(0) | SIM_CLKDIV1_OUTDIV2(0) | SIM_CLKDIV1_OUTDIV3(0) | SIM_CLKDIV1_OUTDIV4(1); // Set the VCO divider and enable the PLL for 50MHz, LOLIE=0, PLLS=1, CME=0, VDIV=1 MCG_C6 = MCG_C6_PLLS_MASK | MCG_C6_VDIV(1); //VDIV = 1 (x25) break; case 1: // Set system options dividers //MCG=PLL, core = MCG, bus = MCG/2, FlexBus = MCG/2, Flash clock= MCG/4 SIM_CLKDIV1 = SIM_CLKDIV1_OUTDIV1(0) | SIM_CLKDIV1_OUTDIV2(1) | SIM_CLKDIV1_OUTDIV3(1) | SIM_CLKDIV1_OUTDIV4(3); // Set the VCO divider and enable the PLL for 100MHz, LOLIE=0, PLLS=1, CME=0, VDIV=26 MCG_C6 = MCG_C6_PLLS_MASK | MCG_C6_VDIV(26); //VDIV = 26 (x50) break; case 2: // Set system options dividers //MCG=PLL, core = MCG, bus = MCG/2, FlexBus = MCG/2, Flash clock= MCG/4 SIM_CLKDIV1 = SIM_CLKDIV1_OUTDIV1(0) | SIM_CLKDIV1_OUTDIV2(1) | SIM_CLKDIV1_OUTDIV3(1) | SIM_CLKDIV1_OUTDIV4(3); // Set the VCO divider and enable the PLL for 96MHz, LOLIE=0, PLLS=1, CME=0, VDIV=24 MCG_C6 = MCG_C6_PLLS_MASK | MCG_C6_VDIV(24); //VDIV = 24 (x48) break; case 3: // Set system options dividers //MCG=PLL, core = MCG, bus = MCG, FlexBus = MCG, Flash clock= MCG/2 SIM_CLKDIV1 = SIM_CLKDIV1_OUTDIV1(0) | SIM_CLKDIV1_OUTDIV2(0) | SIM_CLKDIV1_OUTDIV3(0) | SIM_CLKDIV1_OUTDIV4(1); // Set the VCO divider and enable the PLL for 48MHz, LOLIE=0, PLLS=1, CME=0, VDIV=0 MCG_C6 = MCG_C6_PLLS_MASK; //VDIV = 0 (x24) break; } while (!(MCG_S & MCG_S_PLLST_MASK)){}; // wait for PLL status bit to set while (!(MCG_S & MCG_S_LOCK_MASK)){}; // Wait for LOCK bit to set // Now running PBE Mode // Transition into PEE by setting CLKS to 0 // CLKS=0, FRDIV=3, IREFS=0, IRCLKEN=0, IREFSTEN=0 MCG_C1 &= ~MCG_C1_CLKS_MASK; // Wait for clock status bits to update while (((MCG_S & MCG_S_CLKST_MASK) >> MCG_S_CLKST_SHIFT) != 0x3){}; // Now running PEE Mode } //pll_init
void __pe_initialize_hardware(void) { /*** !!! Here you can place your own code before PE initialization using property "User code before PE initialization" on the build options tab. !!! ***/ /*** ### MK22FN512VDC12 "Cpu" init code ... ***/ /*** PE initialization code after reset ***/ /* Disable the WDOG module */ /* WDOG_UNLOCK: WDOGUNLOCK=0xC520 */ WDOG_UNLOCK = WDOG_UNLOCK_WDOGUNLOCK(0xC520); /* Key 1 */ /* WDOG_UNLOCK: WDOGUNLOCK=0xD928 */ WDOG_UNLOCK = WDOG_UNLOCK_WDOGUNLOCK(0xD928); /* Key 2 */ /* WDOG_STCTRLH: ??=0,DISTESTWDOG=0,BYTESEL=0,TESTSEL=0,TESTWDOG=0,??=0,??=1,WAITEN=1,STOPEN=1,DBGEN=0,ALLOWUPDATE=1,WINEN=0,IRQRSTEN=0,CLKSRC=1,WDOGEN=0 */ WDOG_STCTRLH = WDOG_STCTRLH_BYTESEL(0x00) | WDOG_STCTRLH_WAITEN_MASK | WDOG_STCTRLH_STOPEN_MASK | WDOG_STCTRLH_ALLOWUPDATE_MASK | WDOG_STCTRLH_CLKSRC_MASK | 0x0100U; #if 0 /* SIM_SCGC6: RTC=1 */ SIM_SCGC6 |= SIM_SCGC6_RTC_MASK; if ((RTC_CR & RTC_CR_OSCE_MASK) == 0u) { /* Only if the OSCILLATOR is not already enabled */ /* RTC_CR: SC2P=0,SC4P=0,SC8P=0,SC16P=0 */ RTC_CR &= (uint32_t)~(uint32_t)( RTC_CR_SC2P_MASK | RTC_CR_SC4P_MASK | RTC_CR_SC8P_MASK | RTC_CR_SC16P_MASK ); /* RTC_CR: OSCE=1 */ RTC_CR |= RTC_CR_OSCE_MASK; /* RTC_CR: CLKO=0 */ RTC_CR &= (uint32_t)~(uint32_t)(RTC_CR_CLKO_MASK); } #endif /* System clock initialization */ /* SIM_CLKDIV1: OUTDIV1=0,OUTDIV2=1,OUTDIV3=3,OUTDIV4=3,??=0,??=0,??=0,??=0,??=0,??=0,??=0,??=0,??=0,??=0,??=0,??=0,??=0,??=0,??=0,??=0 */ SIM_CLKDIV1 = SIM_CLKDIV1_OUTDIV1(0x00) | SIM_CLKDIV1_OUTDIV2(0x01) | SIM_CLKDIV1_OUTDIV3(0x03) | SIM_CLKDIV1_OUTDIV4(0x03); /* Set the system prescalers to safe value */ /* SIM_SCGC5: PORTD=1,PORTC=1,PORTA=1 */ SIM_SCGC5 |= SIM_SCGC5_PORTD_MASK | SIM_SCGC5_PORTC_MASK | SIM_SCGC5_PORTA_MASK; /* Enable clock gate for ports to enable pin routing */ if ((PMC_REGSC & PMC_REGSC_ACKISO_MASK) != 0x0U) { /* PMC_REGSC: ACKISO=1 */ PMC_REGSC |= PMC_REGSC_ACKISO_MASK; /* Release IO pads after wakeup from VLLS mode. */ } /* SIM_CLKDIV1: OUTDIV1=0,OUTDIV2=1,OUTDIV3=2,OUTDIV4=4,??=0,??=0,??=0,??=0,??=0,??=0,??=0,??=0,??=0,??=0,??=0,??=0,??=0,??=0,??=0,??=0 */ SIM_CLKDIV1 = SIM_CLKDIV1_OUTDIV1(0x00) | SIM_CLKDIV1_OUTDIV2(0x01) | SIM_CLKDIV1_OUTDIV3(0x02) | SIM_CLKDIV1_OUTDIV4(0x04); /* Update system prescalers */ /* SIM_CLKDIV2: USBDIV=4,USBFRAC=1 */ SIM_CLKDIV2 = SIM_CLKDIV2_USBDIV(0x4) | SIM_CLKDIV2_USBFRAC_MASK; /* Update USB clock prescalers */ /* SIM_SOPT2: PLLFLLSEL=1 */ SIM_SOPT2 |= SIM_SOPT2_PLLFLLSEL(0x01); /* Select PLL as a clock source for various peripherals */ /* SIM_SOPT1: OSC32KSEL=0 */ SIM_SOPT1 &= (uint32_t)~(uint32_t)(SIM_SOPT1_OSC32KSEL(0x03)); /* System oscillator drives 32 kHz clock for various peripherals */ /* PORTA_PCR18: ISF=0,MUX=0 */ PORTA_PCR18 &= (uint32_t)~(uint32_t)((PORT_PCR_ISF_MASK | PORT_PCR_MUX(0x07))); /* PORTA_PCR19: ISF=0,MUX=0 */ PORTA_PCR19 &= (uint32_t)~(uint32_t)((PORT_PCR_ISF_MASK | PORT_PCR_MUX(0x07))); /* Switch to FBE Mode */ /* MCG_C2: LOCRE0=0,??=0,RANGE0=2,HGO0=0,EREFS0=1,LP=0,IRCS=0 */ MCG_C2 = (MCG_C2_RANGE(0x02) | MCG_C2_EREFS_MASK); /* OSC_CR: ERCLKEN=1,??=0,EREFSTEN=1,??=0,SC2P=0,SC4P=0,SC8P=0,SC16P=0 */ OSC_CR = (OSC_CR_ERCLKEN_MASK | OSC_CR_EREFSTEN_MASK); /* MCG_C7: OSCSEL=0 */ MCG_C7 &= (uint8_t)~(uint8_t)(MCG_C7_OSCSEL_MASK); /* MCG_C1: CLKS=2,FRDIV=3,IREFS=0,IRCLKEN=0,IREFSTEN=0 */ MCG_C1 = (MCG_C1_CLKS(0x02) | MCG_C1_FRDIV(0x03)); /* MCG_C4: DMX32=0,DRST_DRS=0 */ MCG_C4 &= (uint8_t)~(uint8_t)((MCG_C4_DMX32_MASK | MCG_C4_DRST_DRS(0x03))); /* MCG_C5: ??=0,PLLCLKEN0=0,PLLSTEN0=0,PRDIV0=b(devider is 12) */ MCG_C5 = MCG_C5_PRDIV0(0x0b); /* MCG_C6: LOLIE0=0,PLLS=0,CME0=0,VDIV0=16(multiply is 40) */ MCG_C6 = MCG_C6_VDIV0(0x10); while((MCG_S & MCG_S_OSCINIT0_MASK) == 0x00U) { /* Check that the oscillator is running */ } while((MCG_S & MCG_S_IREFST_MASK) != 0x00U) { /* Check that the source of the FLL reference clock is the external reference clock. */ } while((MCG_S & 0x0CU) != 0x08U) { /* Wait until external reference clock is selected as MCG output */ } /* Switch to PBE Mode */ /* MCG_C6: LOLIE0=0,PLLS=1,CME0=0,VDIV0=16(multiply is 40) */ MCG_C6 = (MCG_C6_PLLS_MASK | MCG_C6_VDIV0(0x10)); while((MCG_S & 0x0CU) != 0x08U) { /* Wait until external reference clock is selected as MCG output */ } while((MCG_S & MCG_S_LOCK0_MASK) == 0x00U) { /* Wait until locked */ } /* Switch to PEE Mode */ /* MCG_C1: CLKS=0,FRDIV=3,IREFS=0,IRCLKEN=0,IREFSTEN=0 */ MCG_C1 = (MCG_C1_CLKS(0x00) | MCG_C1_FRDIV(0x03)); ClockConfigurationID = CPU_CLOCK_CONFIG_3; while((MCG_S & 0x0CU) != 0x0CU) { /* Wait until output of the PLL is selected */ } /*** End of PE initialization code after reset ***/ /*** !!! Here you can place your own code after PE initialization using property "User code after PE initialization" on the build options tab. !!! ***/ }
/************************************************************************* * 野火嵌入式开发工作室 * * 函数名称:pll_init * 功能说明:锁相环函数,用于设定频率。 * 参数说明:crystal_val 晶体选项,这里没用到 * 函数返回:无 * 修改时间:2012-1-20 * 备 注:根据 全局变量 mcg_div 保存的分频因子来分频 *************************************************************************/ unsigned char pll_init(clk_option opt) { unsigned char pll_freq; if(opt != PLLUSR ) //自定义模式,直接加载全局变量mcg_div的值 { //设置MCG时钟 switch(opt) { case PLL48: mcg_div.prdiv = 24; mcg_div.vdiv = 0; break; case PLL50: mcg_div.prdiv = 24; mcg_div.vdiv = 1; break; case PLL96: mcg_div.prdiv = 24; mcg_div.vdiv = 24; break; case PLL100: mcg_div.prdiv = 24; mcg_div.vdiv = 26; break; case PLL110: mcg_div.prdiv = 24; mcg_div.vdiv = 31; break; case PLL120: mcg_div.prdiv = 19; mcg_div.vdiv = 24; break; case PLL125: mcg_div.prdiv = 19; mcg_div.vdiv = 26; break; case PLL130: mcg_div.prdiv = 19; mcg_div.vdiv = 28; break; case PLL140: mcg_div.prdiv = 14; mcg_div.vdiv = 18; break; case PLL150: mcg_div.prdiv = 14; mcg_div.vdiv = 21; break; case PLL160: mcg_div.prdiv = 14; mcg_div.vdiv = 24; break; case PLL170: mcg_div.prdiv = 14; mcg_div.vdiv = 27; break; case PLL180: mcg_div.prdiv = 14; mcg_div.vdiv = 30; break; case PLL200: mcg_div.prdiv = 12; mcg_div.vdiv = 28; break; case PLL225: mcg_div.prdiv = 11; mcg_div.vdiv = 30; break; case PLL250: mcg_div.prdiv = 10; mcg_div.vdiv = 31; break; default: return pll_init(PLL100); //这情况不会发生。 } //设置分频 mcg_div.core_div = 0; // core = MCG /* 这里提示警告,但是安全的,是为了安全才故意添加进去 */ if (opt <= 1 * MAX_BUS_CLK) mcg_div.bus_div = 0; // bus = MCG else if(opt <= 2 * MAX_BUS_CLK) mcg_div.bus_div = 1; // bus = MCG/2 else if(opt <= 3 * MAX_BUS_CLK) mcg_div.bus_div = 2; // bus = MCG/3 else if(opt <= 4 * MAX_BUS_CLK) mcg_div.bus_div = 3; // bus = MCG/4 这里提示警告,不过没关系 else mcg_div.bus_div = 15; // bus = MCG/16 mcg_div.flex_div = mcg_div.bus_div; // flex = bus /* 这里提示警告,但是安全的,是为了安全才故意添加进去 */ if (opt <= 1 * MAX_FLASH_CLK) mcg_div.flash_div = 0; // flash = MCG else if(opt <= 2 * MAX_FLASH_CLK) mcg_div.flash_div = 1; // flash = MCG/2 else if(opt <= 3 * MAX_FLASH_CLK) mcg_div.flash_div = 2; // flash = MCG/3 else if(opt <= 4 * MAX_FLASH_CLK) mcg_div.flash_div = 3; // flash = MCG/4 else if(opt <= 5 * MAX_FLASH_CLK) mcg_div.flash_div = 4; // flash = MCG/5 else if(opt <= 6 * MAX_FLASH_CLK) mcg_div.flash_div = 5; // flash = MCG/6 else if(opt <= 7 * MAX_FLASH_CLK) mcg_div.flash_div = 6; // flash = MCG/7 else if(opt <= 8 * MAX_FLASH_CLK) mcg_div.flash_div = 7; // flash = MCG/8 else if(opt <= 9 * MAX_FLASH_CLK) mcg_div.flash_div = 8; // flash = MCG/9 这里提示警告,不过没关系 else if(opt <= 10 * MAX_FLASH_CLK) mcg_div.flash_div = 9; // flash = MCG/10 else mcg_div.flash_div = 15; // flash = MCG/16 } pll_freq = (u8)(( (u16)50 * (u16)( mcg_div.vdiv + 24 )) / (u16)( mcg_div.prdiv + 1 ) ); // 50/ ( prdiv +1 ) * ( mcg_div.vdiv + 24 ) //上电复位后,单片机会自动进入 FEI 模式,使用 内部参考时钟 //为了使用外部时钟参考源,我们要先进入 FBE 模式: #if (defined(K60_CLK) || defined(ASB817)) MCG_C2 = 0; #else // Enable external oscillator, RANGE=2, HGO=1, EREFS=1, LP=0, IRCS=0 MCG_C2 = MCG_C2_RANGE(2) | MCG_C2_HGO_MASK | MCG_C2_EREFS_MASK; #endif //初始化晶振后释放锁定状态的振荡器和GPIO SIM_SCGC4 |= SIM_SCGC4_LLWU_MASK; LLWU_CS |= LLWU_CS_ACKISO_MASK; // Select external oscilator and Reference Divider and clear IREFS to start ext osc // CLKS=2, FRDIV=3, IREFS=0, IRCLKEN=0, IREFSTEN=0 MCG_C1 = MCG_C1_CLKS(2) | MCG_C1_FRDIV(3); /* if we aren't using an osc input we don't need to wait for the osc to init */ #if (!defined(K60_CLK) && !defined(ASB817)) while (!(MCG_S & MCG_S_OSCINIT_MASK)) {}; //等待晶振稳定 #endif while (MCG_S & MCG_S_IREFST_MASK) {}; // wait for Reference clock Status bit to clear while (((MCG_S & MCG_S_CLKST_MASK) >> MCG_S_CLKST_SHIFT) != 0x2) {}; // Wait for clock status bits to show clock source is ext ref clk //进入FBE模式 分频后结果必须在 :2 MHz ~ 4 MHz. // n (n+1)分频 50M/(n+1) n为12~24之间 MCG_C5 = MCG_C5_PRDIV(mcg_div.prdiv); // prdiv +1 分频 :2M MCG_C6 = 0x0; // Ensure MCG_C6 is at the reset default of 0. LOLIE disabled, PLL disabled, clk monitor disabled, PLL VCO divider is clear // 设置系统分频因子选项 //MCG=PLL, core = MCG/(mcg_div.core_div + 1), bus = MCG/(mcg_div.bus_div + 1), //FlexBus = MCG/(mcg_div.flex_div + 1), Flash clock= MCG/(mcg_div.flash_div + 1) set_sys_dividers(mcg_div.core_div, mcg_div.bus_div, mcg_div.flex_div, mcg_div.flash_div); // Set the VCO divider and enable the PLL for 48MHz, LOLIE=0, PLLS=1, CME=0, VDIV=0 // n (n+24)倍频 n为0~31之间 MCG_C6 = MCG_C6_PLLS_MASK | MCG_C6_VDIV(mcg_div.vdiv) ; // mcg_div.vdiv + 1 倍频 while (!(MCG_S & MCG_S_PLLST_MASK)) {}; // wait for PLL status bit to set while (!(MCG_S & MCG_S_LOCK_MASK)) {}; // Wait for LOCK bit to set // 现在已经进入了 PBE 模式 // Transition into PEE by setting CLKS to 0 // CLKS=0, FRDIV=3, IREFS=0, IRCLKEN=0, IREFSTEN=0 MCG_C1 &= ~MCG_C1_CLKS_MASK; // Wait for clock status bits to update while (((MCG_S & MCG_S_CLKST_MASK) >> MCG_S_CLKST_SHIFT) != 0x3) {}; // 现在已经进入了 PEE 模式 return pll_freq; } //pll_init
/** * 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; }
/*lint -esym(765,Cpu_Interrupt) Disable MISRA rule (8.10) checking for symbols (Cpu_Interrupt). */ void __init_hardware(void) { /*** !!! Here you can place your own code before PE initialization using property "User code before PE initialization" on the build options tab. !!! ***/ /*** ### MK60DN512ZVLQ10 "Cpu" init code ... ***/ /*** PE initialization code after reset ***/ SCB_VTOR = (uint32_t)(&__vect_table); /* Set the interrupt vector table position */ /* Disable the WDOG module */ /* WDOG_UNLOCK: WDOGUNLOCK=0xC520 */ WDOG_UNLOCK = WDOG_UNLOCK_WDOGUNLOCK(0xC520); /* Key 1 */ /* WDOG_UNLOCK: WDOGUNLOCK=0xD928 */ WDOG_UNLOCK = WDOG_UNLOCK_WDOGUNLOCK(0xD928); /* Key 2 */ /* WDOG_STCTRLH: ??=0,DISTESTWDOG=0,BYTESEL=0,TESTSEL=0,TESTWDOG=0,??=0,STNDBYEN=1,WAITEN=1,STOPEN=1,DBGEN=0,ALLOWUPDATE=1,WINEN=0,IRQRSTEN=0,CLKSRC=1,WDOGEN=0 */ WDOG_STCTRLH = WDOG_STCTRLH_BYTESEL(0x00) | WDOG_STCTRLH_STNDBYEN_MASK | WDOG_STCTRLH_WAITEN_MASK | WDOG_STCTRLH_STOPEN_MASK | WDOG_STCTRLH_ALLOWUPDATE_MASK | WDOG_STCTRLH_CLKSRC_MASK; /* System clock initialization */ /* SIM_CLKDIV1: OUTDIV1=0,OUTDIV2=1,OUTDIV3=3,OUTDIV4=3,??=0,??=0,??=0,??=0,??=0,??=0,??=0,??=0,??=0,??=0,??=0,??=0,??=0,??=0,??=0,??=0 */ SIM_CLKDIV1 = SIM_CLKDIV1_OUTDIV1(0x00) | SIM_CLKDIV1_OUTDIV2(0x01) | SIM_CLKDIV1_OUTDIV3(0x03) | SIM_CLKDIV1_OUTDIV4(0x03); /* Set the system prescalers to safe value */ /* SIM_SCGC5: PORTC=1,PORTA=1 */ SIM_SCGC5 |= (SIM_SCGC5_PORTC_MASK | SIM_SCGC5_PORTA_MASK); /* Enable clock gate for ports to enable pin routing */ /* SIM_CLKDIV1: OUTDIV1=0,OUTDIV2=0,OUTDIV3=1,OUTDIV4=1,??=0,??=0,??=0,??=0,??=0,??=0,??=0,??=0,??=0,??=0,??=0,??=0,??=0,??=0,??=0,??=0 */ SIM_CLKDIV1 = SIM_CLKDIV1_OUTDIV1(0x00) | SIM_CLKDIV1_OUTDIV2(0x00) | SIM_CLKDIV1_OUTDIV3(0x01) | SIM_CLKDIV1_OUTDIV4(0x01); /* Update system prescalers */ /* SIM_CLKDIV2: USBDIV=0,USBFRAC=1 */ SIM_CLKDIV2 = (uint32_t)((SIM_CLKDIV2 & (uint32_t)~(uint32_t)( SIM_CLKDIV2_USBDIV(0x07) )) | (uint32_t)( SIM_CLKDIV2_USBFRAC_MASK )); /* Update USB clock prescalers */ /* SIM_SOPT2: PLLFLLSEL=0 */ SIM_SOPT2 &= (uint32_t)~(uint32_t)(SIM_SOPT2_PLLFLLSEL_MASK); /* Select FLL as a clock source for various peripherals */ /* SIM_SOPT1: OSC32KSEL=0 */ SIM_SOPT1 &= (uint32_t)~(uint32_t)(SIM_SOPT1_OSC32KSEL_MASK); /* System oscillator drives 32 kHz clock for various peripherals */ /* Switch to FEI Mode */ /* MCG_C1: CLKS=0,FRDIV=0,IREFS=1,IRCLKEN=1,IREFSTEN=0 */ MCG_C1 = MCG_C1_CLKS(0x00) | MCG_C1_FRDIV(0x00) | MCG_C1_IREFS_MASK | MCG_C1_IRCLKEN_MASK; /* MCG_C2: ??=0,??=0,RANGE=0,HGO=0,EREFS=0,LP=0,IRCS=0 */ MCG_C2 = MCG_C2_RANGE(0x00); /* MCG_C4: DMX32=0,DRST_DRS=0 */ MCG_C4 &= (uint8_t)~(uint8_t)((MCG_C4_DMX32_MASK | MCG_C4_DRST_DRS(0x03))); /* OSC_CR: ERCLKEN=1,??=0,EREFSTEN=0,??=0,SC2P=0,SC4P=0,SC8P=0,SC16P=0 */ OSC_CR = OSC_CR_ERCLKEN_MASK; /* SIM_SOPT2: MCGCLKSEL=0 */ SIM_SOPT2 &= (uint32_t)~(uint32_t)(SIM_SOPT2_MCGCLKSEL_MASK); /* MCG_C5: ??=0,PLLCLKEN=0,PLLSTEN=0,PRDIV=0 */ MCG_C5 = MCG_C5_PRDIV(0x00); /* MCG_C6: LOLIE=0,PLLS=0,CME=0,VDIV=0 */ MCG_C6 = MCG_C6_VDIV(0x00); while((MCG_S & MCG_S_IREFST_MASK) == 0x00U) { /* Check that the source of the FLL reference clock is the internal reference clock. */ } while((MCG_S & 0x0CU) != 0x00U) { /* Wait until output of the FLL is selected */ } /*** End of PE initialization code after reset ***/ /*** !!! Here you can place your own code after PE initialization using property "User code after PE initialization" on the build options tab. !!! ***/ }
static unsigned char pll_init(void) { void (*fcn_ram_call)(uint_32); uint_32 fcn_thumb_flag; uint_32 fcn_rom_addr; uint_32 fcn_ram_addr; /* * Allocate stack space for set_sys_dividers() function copy * The sizeof(set_sys_dividers_ram_copy) must be enough to * fit whole set_sys_dividers() function. */ uint_32 fcn_ram_copy[64]; uint_32 SIM_CLKDIV1_COPY; /* * Copy set_sys_dividers() function to stack @ function_copy address * Because Thumb-2 instruction mode is used its necessary to set * bit[0] correctly to represent the opcode type of the branch target. * For details see: * http://infocenter.arm.com/help/index.jsp?topic=/com.arm.doc.faqs/ka12545.html */ fcn_thumb_flag = (uint_32)set_sys_dividers & 0x01; fcn_rom_addr = (uint_32)set_sys_dividers & ~(uint_32)0x01; fcn_ram_addr = (uint_32)fcn_ram_copy | (fcn_rom_addr & 0x02); _mem_copy ((pointer)fcn_rom_addr, (pointer)fcn_ram_addr, sizeof(fcn_ram_copy)-3); /* Get pointer of set_sys_dividers function to run_in_ram_fcn */ fcn_ram_call = (void (*)(uint_32))(fcn_ram_addr | fcn_thumb_flag); /* * First move to FBE mode * Enable external oscillator, RANGE=2, HGO=1, EREFS=1, LP=0, IRCS=0 */ MCG_C2 = MCG_C2_RANGE(2) | MCG_C2_HGO_MASK | MCG_C2_EREFS_MASK | MCG_C2_IRCS_MASK; /* Select external oscillator and Reference Divider and clear IREFS * to start external oscillator * CLKS = 2, FRDIV = 3, IREFS = 0, IRCLKEN = 0, IREFSTEN = 0 */ MCG_C1 = MCG_C1_CLKS(2) | MCG_C1_FRDIV(3); /* Wait for oscillator to initialize */ while (!(MCG_S & MCG_S_OSCINIT_MASK)){}; /* Wait for Reference Clock Status bit to clear */ while (MCG_S & MCG_S_IREFST_MASK) {}; /* Wait for clock status bits to show clock source * is external reference clock */ while (((MCG_S & MCG_S_CLKST_MASK) >> MCG_S_CLKST_SHIFT) != 0x2) {}; /* Now in FBE * Configure PLL Reference Divider, PLLCLKEN=1, PLLSTEN=0, PRDIV=8 * The crystal frequency is used to select the PRDIV value. * Only even frequency crystals are supported * that will produce a 2MHz reference clock to the PLL. */ MCG_C5 = MCG_C5_PRDIV(BSP_REF_CLOCK_DIV - 1) | MCG_C5_PLLCLKEN_MASK; /* Ensure MCG_C6 is at the reset default of 0. LOLIE disabled, * PLL disabled, clock monitor disabled, PLL VCO divider is clear */ MCG_C6 = 0; /* Calculate mask for System Clock Divider Register 1 SIM_CLKDIV1 */ SIM_CLKDIV1_COPY = SIM_CLKDIV1_OUTDIV1(BSP_CORE_DIV - 1) | SIM_CLKDIV1_OUTDIV2(BSP_BUS_DIV - 1) | SIM_CLKDIV1_OUTDIV3(BSP_FLEXBUS_DIV - 1) | SIM_CLKDIV1_OUTDIV4(BSP_FLASH_DIV - 1); /* * Set system clock dividers by function running from RAM * This routine must be placed in RAM. It is a workaround for errata e2448. */ fcn_ram_call(SIM_CLKDIV1_COPY); /* Set the VCO divider and enable the PLL, * LOLIE = 0, PLLS = 1, CME = 0, VDIV = 2MHz * BSP_CLOCK_MUL */ MCG_C6 = MCG_C6_PLLS_MASK | MCG_C6_VDIV(BSP_CLOCK_MUL - 24); /* wait for PLL status bit to set */ while (!(MCG_S & MCG_S_PLLST_MASK)) {}; /* Wait for LOCK bit to set */ while (!(MCG_S & MCG_S_LOCK_MASK)) {}; /* Now running PBE Mode */ /* Transition into PEE by setting CLKS to 0 * CLKS=0, FRDIV=3, IREFS=0, IRCLKEN=0, IREFSTEN=0 */ MCG_C1 &= ~MCG_C1_CLKS_MASK; /* Wait for clock status bits to update */ while (((MCG_S & MCG_S_CLKST_MASK) >> MCG_S_CLKST_SHIFT) != 0x3) {}; /* Now running PEE Mode */ return MQX_OK; }