예제 #1
0
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
}
예제 #2
0
파일: low_init.c 프로젝트: liamjeal/CoOS
/** PLL initialization.
 */
static void pll_init(void) {
    // First move to FBE mode
    // Enable external oscillator, RANGE=0, HGO=, EREFS=, LP=, IRCS=
    MCG_C2 = 0;
    
    // 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);
    
    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 mode
    // Configure PLL Ref Divider, PLLCLKEN=0, PLLSTEN=0, PRDIV=0x18
    // 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(REF_CLOCK_DIV - 1);

    // Ensure MCG_C6 is at the reset default of 0. LOLIE disabled, PLL disabled, clk monitor disabled, PLL VCO divider is clear
    MCG_C6 = 0;

    // Set system options dividers
    SIM_CLKDIV1 = SIM_CLKDIV1_OUTDIV1(CORE_DIV - 1) |           // core/system clock
                  SIM_CLKDIV1_OUTDIV2(BUS_DIV - 1) |            // peripheral clock
                  SIM_CLKDIV1_OUTDIV3(FLEXBUS_DIV - 1) |        // FlexBus clock driven to the external pin (FB_CLK).
                  SIM_CLKDIV1_OUTDIV4(FLASH_DIV - 1);           // flash clock
    
    // Set the VCO divider and enable the PLL, LOLIE = 0, PLLS = 1, CME = 0, VDIV =
    MCG_C6 = MCG_C6_PLLS_MASK | MCG_C6_VDIV(PLL_CLOCK_MUL - 24);    // 2MHz * BSP_CLOCK_MUL

    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

    // ...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);

    // ...running PEE mode  
}
예제 #3
0
파일: MK60_mcg.c 프로젝트: DATIEPUZI/Test
/*!
 *  @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
예제 #4
0
/*
 * LPLD_PLL_Setup
 * 初始化内核时钟及其他系统时钟
 * 
 * 参数:
 *    core_clk_mhz--期望内核时钟频率
 *      |__PLLx--参见HAL_MCG.h中的PLL_option定义
 *
 * 输出:
 *    内核频率,单位MHz
 */
uint8 LPLD_PLL_Setup(PllOptionEnum_Type core_clk_mhz)
{
  uint8 pll_freq;
  uint8 prdiv, vdiv;
  uint8 core_div, bus_div, flexbus_div, flash_div;
  
/*
 *************************************************
  【LPLD注解】MCG关键系数
  prdiv(PLL分频系数): 0~31(1~32)
  vdiv(PLL倍频系数): 0~31(24~55)
  PLL参考时钟范围: 2MHz~4MHz
  PLL参考时钟 = 外部参考时钟(CPU_XTAL_CLK_HZ)/prdiv
  CoreClk = PLL参考时钟 x PLL倍频系数 /OUTDIV1
 *************************************************
 */
  
  // 对于MK60DZ10来说,core_clk_mhz建议不要超过100,这里限制为最高200
  core_clk_mhz = (PllOptionEnum_Type)(core_clk_mhz>200u?200u:core_clk_mhz);
  
  // 根据期望主频选择分频和倍频系数
  switch(core_clk_mhz)
  {
  case PLL_48:
    prdiv = 24u;
    vdiv = 0u;
    break;
  case PLL_50:
    prdiv = 24u;
    vdiv = 1u;
    break;
  case PLL_96:
    prdiv = 24u;
    vdiv = 24u;
    break;
  case PLL_100:
    prdiv = 24u;
    vdiv = 26u;
    break;
  case PLL_120:
    prdiv = 19u;
    vdiv = 24u;
    break;
  case PLL_150:
    prdiv = 15u;
    vdiv = 24u;
    break;
  case PLL_180:
    prdiv = 14u;
    vdiv = 30u;
    break;
  case PLL_200:
    prdiv = 12u;
    vdiv = 28u;
    break;
  default:
    return LPLD_PLL_Setup(PLL_96);
  }
  
  pll_freq = core_clk_mhz * 1;
  core_div = 0;
  if((bus_div = (uint8)(core_clk_mhz/BUS_CLK_MHZ - 1u)) == (uint8)-1)
  {
    bus_div = 0;
  }
  else if(core_clk_mhz/(bus_div+1) > BUS_CLK_MHZ)
  {
    bus_div += 1;
  }
  if((flexbus_div = (core_clk_mhz/FLEXBUS_CLK_MHZ - 1u)) == (uint8)-1)
  {
    flexbus_div = 0;
  }
  else if(core_clk_mhz/(flexbus_div+1) > FLEXBUS_CLK_MHZ)
  {
    flexbus_div += 1;
  }
  if((flash_div = (core_clk_mhz/FLASH_CLK_MHZ - 1u)) == (uint8)-1)
  {
    flash_div = 0;
  }
  else if(core_clk_mhz/(flash_div+1) > FLASH_CLK_MHZ)
  {
    flash_div += 1;
  }
  
  // 这里假设复位后 MCG 模块默认为 FEI 模式
  
  // 首先移动到 FBE 模式
  MCG->C2 = 0;
  
  // 振荡器初始化完成后,释放锁存状态下的 oscillator 和 GPIO 
  SIM->SCGC4 |= SIM_SCGC4_LLWU_MASK;
  LLWU->CS |= LLWU_CS_ACKISO_MASK;
  
  // 选择外部 oscilator 、参考分频器 and 清零 IREFS 启动外部osc
  // CLKS=2, FRDIV=3, IREFS=0, IRCLKEN=0, IREFSTEN=0
  MCG->C1 = MCG_C1_CLKS(2) | MCG_C1_FRDIV(3);  
  
  while (MCG->S & MCG_S_IREFST_MASK){}; // 等待参考时钟清零
  
  while (((MCG->S & MCG_S_CLKST_MASK) >> MCG_S_CLKST_SHIFT) != 0x2){}; // 等待时钟状态显示为外部参考时钟(ext ref clk)
  
  // 进入FBE模式
  // 配置 PLL 参考分频器, PLLCLKEN=0, PLLSTEN=0, PRDIV=5
  // 用晶振频率来选择 PRDIV 值. 仅在有频率晶振的时候支持
  // 产生 2MHz 的参考时钟给 PLL.
  MCG->C5 = MCG_C5_PRDIV(prdiv); // 设置 PLL 匹配晶振的参考分频数 
  
  // 确保MCG_C6处于复位状态,禁止LOLIE、PLL、和时钟控制器,清PLL VCO分频器
  MCG->C6 = 0x0;
  
  //设置系统时钟分频系数
  LPLD_Set_SYS_DIV(core_div, bus_div, flexbus_div, flash_div);  
  
  //设置倍频系数
  MCG->C6 = MCG_C6_PLLS_MASK | MCG_C6_VDIV(vdiv); 
  
  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;
} 
예제 #5
0
void kinetis_pllconfig(void)
{
  uint32_t regval32;
  uint8_t regval8;

  /* Transition to FLL Bypassed External (FBE) mode */

#ifdef BOARD_EXTCLOCK
  /*   IRCS  = 0 (Internal Reference Clock Select)
   *   LP    = 0 (Low Power Select)
   *   EREFS = 0 (External Reference Select)
   *   HGO   = 0 (High Gain Oscillator Select)
   *   RANGE = 0 (Oscillator of 32 kHz to 40 kHz)
   */

  putreg8(0, KINETIS_MCG_C2);
#else
  /* Enable external oscillator:
   *
   *   IRCS  = 0 (Internal Reference Clock Select)
   *   LP    = 0 (Low Power Select)
   *   EREFS = 1 (External Reference Select)
   *   HGO   = 1 (High Gain Oscillator Select)
   *   RANGE = 2 (Oscillator of 8 MHz to 32 MHz)
   */

  putreg8(MCG_C2_EREFS | MCG_C2_HGO | MCG_C2_RANGE_VHIGH, KINETIS_MCG_C2);
#endif

  /* Released latched state of oscillator and GPIO */

  regval32 = getreg32(KINETIS_SIM_SCGC4);
  regval32 |= SIM_SCGC4_LLWU;
  putreg32(regval32, KINETIS_SIM_SCGC4);

  regval8 = getreg8(KINETIS_LLWU_CS);
  regval8 |= LLWU_CS_ACKISO;
  putreg8(regval8, KINETIS_LLWU_CS);

  /* Select external oscillator and Reference Divider and clear IREFS to
   * start the external oscillator.
   *
   *   IREFSTEN = 0 (Internal Reference Stop Enable)
   *   IRCLKEN  = 0 (Internal Reference Clock Enable)
   *   IREFS    = 0 (Internal Reference Select)
   *   FRDIV    = 3 (FLL External Reference Divider, RANGE!=0 divider=256)
   *   CLKS     = 2 (Clock Source Select, External reference clock)
   */

  putreg8(MCG_C1_FRDIV_DIV256 | MCG_C1_CLKS_EXTREF, KINETIS_MCG_C1);

  /* If we aren't using an oscillator input we don't need to wait for the
   * oscillator to initialize
   */

#ifndef BOARD_EXTCLOCK
  while ((getreg8(KINETIS_MCG_S) & MCG_S_OSCINIT) == 0);
#endif

  /* Wait for Reference clock Status bit to clear */

  while ((getreg8(KINETIS_MCG_S) & MCG_S_IREFST) != 0);

  /* Wait for clock status bits to show that the clock source is the
   * external reference clock.
   */

  while ((getreg8(KINETIS_MCG_S) & MCG_S_CLKST_MASK) != MCG_S_CLKST_EXTREF);

  /* We are now in  FLL Bypassed External (FBE) mode. Configure PLL
   * reference clock divider:
   *
   *   PLLCLKEN = 0
   *   PLLSTEN  = 0
   *   PRDIV    = Determined by PLL reference clock frequency
   *
   * Either the external clock or crystal frequency is used to select the
   * PRDIV value. Only reference clock frequencies are supported that will
   * produce a 2MHz reference clock to the PLL.
   */

  putreg8(MCG_C5_PRDIV(BOARD_PRDIV), KINETIS_MCG_C5);

  /* Ensure that MCG_C6 is at the reset default of 0: LOLIE disabled, PLL
   * disabled, clk monitor disabled, PLL VCO divider cleared.
   */

  putreg8(0, KINETIS_MCG_C6);

  /* Set system options dividers based on settings from the board.h file.
   *
   * MCG         = PLL
   * Core        = MCG / BOARD_OUTDIV1
   * bus         = MCG / BOARD_OUTDIV2
   * FlexBus     = MCG / BOARD_OUTDIV3
   * Flash clock = MCG / BOARD_OUTDIV4
   */

  kinesis_setdividers(BOARD_OUTDIV1, BOARD_OUTDIV2, BOARD_OUTDIV3, BOARD_OUTDIV4); 
 
  /* Set the VCO divider, VDIV, is defined in the board.h file.  VDIV
   * selects the amount to divide the VCO output of the PLL. The VDIV bits
   * establish the multiplication factor applied to the reference clock
   * frequency.  Also set
   *
   * LOLIE       = 0 (Loss of Lock Interrrupt Enable)
   * PLLS        = 1 (PLL Select)
   * CME         = 0 (Clock Monitor Enable)
   */

  putreg8(MCG_C6_PLLS | MCG_C6_VDIV(BOARD_VDIV), KINETIS_MCG_C6);

  /* Wait for the PLL status bit to set */

  while ((getreg8(KINETIS_MCG_S) & MCG_S_PLLST) == 0);

  /* Wait for the PLL LOCK bit to set */

  while ((getreg8(KINETIS_MCG_S) & MCG_S_LOCK) == 0);

  /* We are now running in PLL Bypassed External (PBE) mode.  Transition to
   * PLL Engaged External (PEE) mode by setting CLKS to 0
   */

  regval8 = getreg8(KINETIS_MCG_C1);
  regval8 &= ~MCG_C1_CLKS_MASK;
  putreg8(regval8, KINETIS_MCG_C1);

  /* Wait for clock status bits to update */

  while ((getreg8(KINETIS_MCG_S) & MCG_S_CLKST_MASK) != MCG_S_CLKST_PLL);

  /* We are now running in PLL Engaged External (PEE) mode. */
}
예제 #6
0
/************************************************************************************************ 
* 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){};
} 
/*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. !!! ***/

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

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

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

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

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

    // ... PEE mode
    
/* ToDo: add code to initialize the system
         do not use global variables because this function is called before
         reaching pre-main. RW section maybe overwritten afterwards.          */
  SystemCoreClock = __SYSTEM_CLOCK;
}
예제 #9
0
//锁相环频率为60M测试函数
void pllinit60M(void)
{
	uint32_t temp_reg;
        //使能IO端口时钟    
    SIM_SCGC5 |= (SIM_SCGC5_PORTA_MASK
                              | SIM_SCGC5_PORTB_MASK
                              | SIM_SCGC5_PORTC_MASK
                              | SIM_SCGC5_PORTD_MASK
                              | SIM_SCGC5_PORTE_MASK );
    //这里处在默认的FEI模式
    //首先移动到FBE模式
    MCG_C2 = 0;  
    //MCG_C2 = MCG_C2_RANGE(2) | MCG_C2_HGO_MASK | MCG_C2_EREFS_MASK;
    //初始化晶振后释放锁定状态的振荡器和GPIO
    SIM_SCGC4 |= SIM_SCGC4_LLWU_MASK;
    LLWU_CS |= LLWU_CS_ACKISO_MASK;
    
    //选择外部晶振,参考分频器,清IREFS来启动外部晶振
    //011 If RANGE = 0, Divide Factor is 8; for all other RANGE values, Divide Factor is 256.
    MCG_C1 = MCG_C1_CLKS(2) | MCG_C1_FRDIV(3);
    
    //等待晶振稳定	    
    //while (!(MCG_S & MCG_S_OSCINIT_MASK)){}              //等待锁相环初始化结束
    while (MCG_S & MCG_S_IREFST_MASK){}                  //等待时钟切换到外部参考时钟
    while (((MCG_S & MCG_S_CLKST_MASK) >> MCG_S_CLKST_SHIFT) != 0x2){}
    
    //进入FBE模式,
    //0x18==25分频=2M,
    //0x11==18分频=2.7778M 
    //0x12==19分频=2.63M,
    //0x13==20分频=2.5M    
    MCG_C5 = MCG_C5_PRDIV(0x18);                
    
    //确保MCG_C6处于复位状态,禁止LOLIE、PLL、和时钟控制器,清PLL VCO分频器
    MCG_C6 = 0x0;
    
    //保存FMC_PFAPR当前的值
    temp_reg = FMC_PFAPR;
    
    //通过M&PFD置位M0PFD来禁止预取功能
    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;    
    ///设置系统分频器
    //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);       
    
    //从新存FMC_PFAPR的原始值
    FMC_PFAPR = temp_reg; 
    
    //设置VCO分频器,使能PLL为100MHz, LOLIE=0, PLLS=1, CME=0, VDIV=26
    MCG_C6 = MCG_C6_PLLS_MASK | MCG_C6_VDIV(6);  //VDIV = 31 (x55)
                                                  //VDIV = 26 (x50)
												  //VDIV = 6 (x30)
    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模式    
    //通过清零CLKS位来进入PEE模式
    // CLKS=0, FRDIV=3, IREFS=0, IRCLKEN=0, IREFSTEN=0
    MCG_C1 &= ~MCG_C1_CLKS_MASK;
    
    //等待时钟状态位更新
    while (((MCG_S & MCG_S_CLKST_MASK) >> MCG_S_CLKST_SHIFT) != 0x3){};
    //SIM_CLKDIV2 |= SIM_CLKDIV2_USBDIV(1);  
    
        //设置跟踪时钟为内核时钟
    SIM_SOPT2 |= SIM_SOPT2_TRACECLKSEL_MASK;	
    //在PTA6引脚上使能TRACE_CLKOU功能
    PORTA_PCR6 = ( PORT_PCR_MUX(0x7));  
    //使能FlexBus模块时钟
    SIM_SCGC7 |= SIM_SCGC7_FLEXBUS_MASK;
    //在PTA6引脚上使能FB_CLKOUT功能
    PORTC_PCR3 = ( PORT_PCR_MUX(0x5));
}
예제 #10
0
/*************************************************************************
*                             野火嵌入式开发工作室
*
*  函数名称: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
예제 #11
0
파일: mcg.c 프로젝트: Gargy007/eGUI
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
예제 #12
0
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;
}
/*****************************************************************************
 * @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;            
}