Beispiel #1
0
void Common_Init(void)
{
  /* Common initialization of registers which initialization is required 
     for proper functionality of components in the project but initialization
     component which would be configuring these registers is missing 
     in the project. 
     Add associated initialization component to the project to avoid 
     initialization of registers in the Common_Init().
     Also, after reset value optimization property affects initialization of 
     registers in this method (see active generator configuration 
     Optimizations\Utilize after reset values property or enabled processor 
     component Common settings\Utilize after reset values property) */
  /* SIM_CLKDIV2: USBDIV=4,USBFRAC=1 */
  SIM_CLKDIV2 = (uint32_t)((SIM_CLKDIV2 & (uint32_t)~(uint32_t)(
                 SIM_CLKDIV2_USBDIV(0x03)
                )) | (uint32_t)(
                 SIM_CLKDIV2_USBDIV(0x04) |
                 SIM_CLKDIV2_USBFRAC_MASK
                ));
  /* SIM_SCGC4: VREF=1,USBOTG=1 */
  SIM_SCGC4 |= (SIM_SCGC4_VREF_MASK | SIM_SCGC4_USBOTG_MASK);
  /* SIM_SOPT2: USBSRC=1 */
  SIM_SOPT2 |= SIM_SOPT2_USBSRC_MASK;
  /* NVICIP53: PRI53=0 */
  NVICIP53 = NVIC_IP_PRI53(0x00);
}
Beispiel #2
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
}
Beispiel #3
0
bool CLOCK_EnableUsbfs0Clock(clock_usb_src_t src, uint32_t freq)
{
    bool ret = true;

    CLOCK_DisableClock(kCLOCK_Usbfs0);

    if (kCLOCK_UsbSrcExt == src)
    {
        SIM->SOPT2 &= ~SIM_SOPT2_USBSRC_MASK;
    }
    else
    {
        switch (freq)
        {
            case 120000000U:
                SIM->CLKDIV2 = SIM_CLKDIV2_USBDIV(4) | SIM_CLKDIV2_USBFRAC(1);
                break;
            case 96000000U:
                SIM->CLKDIV2 = SIM_CLKDIV2_USBDIV(1) | SIM_CLKDIV2_USBFRAC(0);
                break;
            case 72000000U:
                SIM->CLKDIV2 = SIM_CLKDIV2_USBDIV(2) | SIM_CLKDIV2_USBFRAC(1);
                break;
            case 48000000U:
                SIM->CLKDIV2 = SIM_CLKDIV2_USBDIV(0) | SIM_CLKDIV2_USBFRAC(0);
                break;
            default:
                ret = false;
                break;
        }

        SIM->SOPT2 = ((SIM->SOPT2 & ~(SIM_SOPT2_PLLFLLSEL_MASK | SIM_SOPT2_USBSRC_MASK)) | (uint32_t)src);
    }

    CLOCK_EnableClock(kCLOCK_Usbfs0);

    if (kCLOCK_UsbSrcIrc48M == src)
    {
        USB0->CLK_RECOVER_IRC_EN = 0x03U;
        USB0->CLK_RECOVER_CTRL |= USB_CLK_RECOVER_CTRL_CLOCK_RECOVER_EN_MASK;
    }
    return ret;
}
Beispiel #4
0
void _bsp_platform_init(void)
{
	/* Point the VTOR to the new copy of the vector table */
	SCB_VTOR = (uint_32)___VECTOR_RAM;
		
	NVICICPR2 = (1 << 9);                     // Clear any pending interrupts on USB
	NVICISER2 = (1 << 9);                     // Enable interrupts from USB module
	
    // Clear ACKISO
	if (PMC_REGSC &  PMC_REGSC_ACKISO_MASK)
    	PMC_REGSC |= PMC_REGSC_ACKISO_MASK;
	
	/* init pll */
	pll_init();
              
	#ifdef MCGOUTCLK_72_MHZ
		// USB Freq. Divider (Out. clk. = In. clk * (2/3))
		SIM_CLKDIV2 = SIM_CLKDIV2_USBDIV(2) | SIM_CLKDIV2_USBFRAC_MASK;		
	#else
    	// USB Freq. Divider (Out. clk. = In. clk * (1/1))
    	SIM_CLKDIV2 = SIM_CLKDIV2_USBDIV(0);     
	#endif 
    
    // MCGPLLCLK clock selected as CLK source    	
    SIM_SOPT2 |= SIM_SOPT2_USBSRC_MASK | SIM_SOPT2_PLLFLLSEL_MASK;
	
    // USB Clock Gating 
	SIM_SCGC4 |= (SIM_SCGC4_USBOTG_MASK);    
    
	#if(USE_MICRO_USB == TRUE)
		/** USB 5V enable */
		SIM_SCGC5 |=  SIM_SCGC5_PORTC_MASK;              // Turn on PTC clocks 
		PORTC_PCR9 = (0 | PORT_PCR_MUX(1));              // Configure PTC9 pin as GPIO
		
		GPIOC_PDDR |=(1<<9);                             // Set as output
		GPIOC_PSOR =(1<<9);
	#endif   
    
    // Weak pull-downs
    USB0_USBCTRL = USB_USBCTRL_PDE_MASK;
}
Beispiel #5
0
static int32_t bsp_usb_dev_io_init
(
    int32_t i
)
{
    if (i == USB_CONTROLLER_KHCI_0)
    {
#if BSPCFG_USB_USE_IRC48M

        /*
        * Configure SIM_CLKDIV2: USBDIV = 0, USBFRAC = 0
        */
        SIM_CLKDIV2 = (uint32_t)0x0UL; /* Update USB clock prescalers */

        /* Configure USB to be clocked from IRC 48MHz */
        SIM_SOPT2_REG(SIM_BASE_PTR)  |= SIM_SOPT2_USBSRC_MASK | SIM_SOPT2_IRC48MSEL_MASK;

        /* Enable USB-OTG IP clocking */
        SIM_SCGC4_REG(SIM_BASE_PTR) |= SIM_SCGC4_USBOTG_MASK;
        /* Enable IRC 48MHz for USB module */
        USB_CLK_RECOVER_IRC_EN = 0x03;
#else
        /* Configure USB to be clocked from PLL0 */
        SIM_SOPT2_REG(SIM_BASE_PTR) |= SIM_SOPT2_USBSRC_MASK;
        /* Configure USB divider to be 120MHz * 2 / 5 = 48 MHz */
        SIM_CLKDIV2_REG(SIM_BASE_PTR) = SIM_CLKDIV2_USBDIV(4) | SIM_CLKDIV2_USBFRAC_MASK;

        /* Enable USB-OTG IP clocking */
        SIM_SCGC4_REG(SIM_BASE_PTR) |= SIM_SCGC4_USBOTG_MASK;
#endif
    }
    else
    {
        return -1; //unknow controller
    }

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

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

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

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

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

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

	//init_pins();
	__enable_irq();

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

	__libc_init_array();

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

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

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

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

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

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

#elif KINETIS_MCG_MODE == KINETIS_MCG_MODE_PEE

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

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

  /*
   * Start in FEI mode
   */

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

#endif /* !KINETIS_NO_INIT */
}
Beispiel #8
0
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. !!! ***/
}
Beispiel #9
0
/*
** ===================================================================
**     Method      :  Cpu_SetClockConfiguration (component MK22FN512VDC12)
**
**     Description :
**         Calling of this method will cause the clock configuration
**         change and reconfiguration of all components according to
**         the requested clock configuration setting.
**     Parameters  :
**         NAME            - DESCRIPTION
**         ModeID          - Clock configuration identifier
**     Returns     :
**         ---             - ERR_OK - OK.
**                           ERR_RANGE - Mode parameter out of range
** ===================================================================
*/
LDD_TError Cpu_SetClockConfiguration(LDD_TClockConfiguration ModeID)
{
  if (ModeID > 0x03U) {
    return ERR_RANGE;                  /* Undefined clock configuration requested requested */
  }

  if (0x03U == ClockConfigurationID) {
    if ((CPU_CLOCK_CONFIG_1 == ModeID) || ( CPU_CLOCK_CONFIG_2 == ModeID))
        return ERR_FAILED;
    Cpu_SetMCGClockInModePEE(ModeID);
  }

  if (0x03U == ModeID) {
    if ((CPU_CLOCK_CONFIG_1 == ClockConfigurationID) || ( CPU_CLOCK_CONFIG_2 == ClockConfigurationID))
        return ERR_FAILED;
    Cpu_SetMCGClockInModePEE(ModeID); 
  }

  switch (ModeID) {
    case CPU_CLOCK_CONFIG_0:
      if (ClockConfigurationID == 2U) {
        /* Clock configuration 0 and clock configuration 2 use different clock configuration */
	/* SIM_CLKDIV1: OUTDIV1=0,OUTDIV2=1,OUTDIV3=4,OUTDIV4=4,??=0,??=0,??=0,??=0,??=0,??=0,??=0,??=0,??=0,??=0,??=0,*/
	SIM_CLKDIV1 = SIM_CLKDIV1_OUTDIV1(0x00) |
	              SIM_CLKDIV1_OUTDIV2(0x01) |
		      SIM_CLKDIV1_OUTDIV3(0x04) |
		      SIM_CLKDIV1_OUTDIV4(0x04); /* Set the system prescalers to safe value */
        Cpu_SetMCG(0U);                /* Update clock source setting */
      }
      /* 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(0x03) |
                    SIM_CLKDIV1_OUTDIV4(0x02); /* Update system prescalers */
#if (BSPCFG_USB_CLK_FROM_IRC48M)
        SIM_CLKDIV2  =  0;
        SIM_SOPT2   |=  SIM_SOPT2_PLLFLLSEL(0x03);
        SIM_SCGC4   |= (SIM_SCGC4_USBOTG_MASK);
        /* Enable IRC 48MHz for USB module */
        USB_CLK_RECOVER_IRC_EN = 0x03;
#else
      /* SIM_CLKDIV2: USBDIV=4,USBFRAC=1 */
      SIM_CLKDIV2 = SIM_CLKDIV2_USBDIV(0x4) | SIM_CLKDIV2_USBFRAC_MASK; /* Update USB clock prescalers */
      /* SIM_SOPT2: PLLFLLSEL=0x01 */
      SIM_SOPT2 |= SIM_SOPT2_PLLFLLSEL(0x01); /* Select PLL as a clock source for various peripherals */
      /* SIM_SOPT1: OSC32KSEL=0 */
#endif
      SIM_SOPT1 &= (uint32_t)~(uint32_t)(SIM_SOPT1_OSC32KSEL(0x03)); /* System oscillator drives 32 kHz clock for various peripherals */
      break;
    case CPU_CLOCK_CONFIG_1:
      if (ClockConfigurationID == 2U) {
        /* Clock configuration 1 and clock configuration 2 use different clock configuration */
        /* SIM_CLKDIV1: OUTDIV1=0,OUTDIV2=1,OUTDIV3=4,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(0x04) |
		      SIM_CLKDIV1_OUTDIV4(0x04); /* Set the system prescalers to safe value */
        Cpu_SetMCG(0U);                /* Update clock source setting */
      }
      /* SIM_CLKDIV1: OUTDIV1=9,OUTDIV2=9,OUTDIV3=9,OUTDIV4=9,??=0,??=0,??=0,??=0,??=0,??=0,??=0,??=0,??=0,??=0,??=0,??=0,??=0,??=0,??=0,??=0 */
      SIM_CLKDIV1 = SIM_CLKDIV1_OUTDIV1(0x09) |
                    SIM_CLKDIV1_OUTDIV2(0x09) |
                    SIM_CLKDIV1_OUTDIV3(0x09) |
                    SIM_CLKDIV1_OUTDIV4(0x09); /* Update system prescalers */
      /* SIM_CLKDIV2: USBDIV=4,USBFRAC=1 */
        SIM_CLKDIV2 = SIM_CLKDIV2_USBDIV(0x4) | SIM_CLKDIV2_USBFRAC_MASK;
      /* SIM_SOPT2: PLLFLLSEL=0x01 */
      SIM_SOPT2 |= SIM_SOPT2_PLLFLLSEL(0x01);
      /* SIM_SOPT1: OSC32KSEL=0 */
      SIM_SOPT1 &= (uint32_t)~(uint32_t)(SIM_SOPT1_OSC32KSEL(0x03)); /* System oscillator drives 32 kHz clock for various peripherals */
      break;
    case CPU_CLOCK_CONFIG_2:
     /* SIM_CLKDIV1: OUTDIV1=0,OUTDIV2=1,OUTDIV3=4,OUTDIV4=4,??=0,??=0,??=0,??=0,??=0,??=0,??=0,??=0,??=0,??=0,??=0,??*/
     SIM_CLKDIV1 = SIM_CLKDIV1_OUTDIV1(0x00) |
                   SIM_CLKDIV1_OUTDIV2(0x01) |
	           SIM_CLKDIV1_OUTDIV3(0x04) |
	           SIM_CLKDIV1_OUTDIV4(0x04); /* Set the system prescalers to safe value */
     if ((MCG_C2 & MCG_C2_IRCS_MASK) == 0x00U) {
       /* MCG_SC: FCRDIV=1 */
         MCG_SC = (uint8_t)((MCG_SC & (uint8_t)~(uint8_t)(
	           MCG_SC_FCRDIV(0x06)
		  )) | (uint8_t)(
		   MCG_SC_FCRDIV(0x01)
		  ));
      } else {
        /* MCG_C2: IRCS=0 */
        MCG_C2 &= (uint8_t)~(uint8_t)(MCG_C2_IRCS_MASK);
	while((MCG_S & MCG_S_IRCST_MASK) != 0x00U) { /* Check that the source internal reference clock is slow clock. */
	}
        /* MCG_SC: FCRDIV=1 */
        MCG_SC = (uint8_t)((MCG_SC & (uint8_t)~(uint8_t)(
                  MCG_SC_FCRDIV(0x06)
		 )) | (uint8_t)(
		  MCG_SC_FCRDIV(0x01)
		 ));
	/* MCG_C2: IRCS=1 */
        MCG_C2 |= MCG_C2_IRCS_MASK;
	while((MCG_S & MCG_S_IRCST_MASK) == 0x00U) { /* Check that the source internal reference clock is fast clock. */
	}
      }
      Cpu_SetMCG(1U);                  /* Update clock source setting */
      /* SIM_CLKDIV1: OUTDIV1=0,OUTDIV2=0,OUTDIV3=0,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(0x00) |
                    SIM_CLKDIV1_OUTDIV3(0x00) |
                    SIM_CLKDIV1_OUTDIV4(0x03); /* Update system prescalers */
      /* SIM_CLKDIV2: USBDIV=4,USBFRAC=1 */
        SIM_CLKDIV2 = SIM_CLKDIV2_USBDIV(0x4) | SIM_CLKDIV2_USBFRAC_MASK;
      /* 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 */
      break;
	case CPU_CLOCK_CONFIG_3:
      /* SIM_CLKDIV1: OUTDIV1=0,OUTDIV2=1,OUTDIV3=4,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(0x04) |
                    SIM_CLKDIV1_OUTDIV4(0x04); /* Update system prescalers */

#if (BSPCFG_USB_CLK_FROM_IRC48M)
        SIM_CLKDIV2  =  0;
        SIM_SOPT2   |=  SIM_SOPT2_PLLFLLSEL(0x03);
        SIM_SCGC4   |= (SIM_SCGC4_USBOTG_MASK);
        /* Enable IRC 48MHz for USB module */
        USB_CLK_RECOVER_IRC_EN = 0x03;
#else
      /* SIM_CLKDIV2: USBDIV=4,USBFRAC=1 */
      SIM_CLKDIV2 = SIM_CLKDIV2_USBDIV(0x4) | SIM_CLKDIV2_USBFRAC_MASK;
      /* SIM_SOPT2: PLLFLLSEL=1 */
      SIM_SOPT2 |= SIM_SOPT2_PLLFLLSEL(0x01); /* Select PLL as a clock source for various peripherals */
#endif


	   /* SIM_SOPT1: OSC32KSEL=0 */
      SIM_SOPT1 &= (uint32_t)~(uint32_t)(SIM_SOPT1_OSC32KSEL(0x03)); /* System oscillator drives 32 kHz clock for various peripherals */
	  break;
    default:
      break;
  }
  LDD_SetClockConfiguration(ModeID);   /* Call all LDD components to update the clock configuration */
  ClockConfigurationID = ModeID;       /* Store clock configuration identifier */
  return ERR_OK;
}
Beispiel #10
0
void __startup(void) {
  // The CPU has a watchdog feature which is on by default,
  // so we have to configure it to not have nasty reset-surprises
  // later on.
  startup_watchdog_hook();

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

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

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

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

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

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

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

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

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

  // The clock is now in FBE mode

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

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

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

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

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

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

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


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

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

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


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

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

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

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

}
Beispiel #12
0
void ResetHandler(void)
{
    /*
     * Enable watchdog timer. Allow settings to be changed later, in case the
     * application firmware wants to adjust its settings or disable it.
     *
     * Originally I tried using the 1 kHz low-power oscillator here, but that seemed to
     * run into an issue where refreshes weren't taking effect. It seems similar to
     * this problem on the Freescale forums, which didn't really have a satisfactory
     * solution:
     *
     *  https://community.freescale.com/thread/309519
     *
     * As a workaround, I'm using the "alternate" system clock.
     */
    {
        const uint32_t watchdog_timeout = F_BUS / 100;  // 10ms

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

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

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

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

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

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

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

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

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

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

    __enable_irq();
    main();
}
Beispiel #13
0
void USB0_Init(void)
{
  /* SIM_CLKDIV2: USBDIV=0,USBFRAC=0 */
  SIM_CLKDIV2 &= (uint32_t)~(uint32_t)(
                  SIM_CLKDIV2_USBDIV(0x07) |
                  SIM_CLKDIV2_USBFRAC_MASK
                 );
  /* SIM_SOPT2: USBSRC=1 */
  SIM_SOPT2 |= SIM_SOPT2_USBSRC_MASK;
  /* SIM_SCGC4: USBOTG=1 */
  SIM_SCGC4 |= SIM_SCGC4_USBOTG_MASK;
  /* USB0_CTL: ODDRST=1 */
  USB0_CTL |= USB_CTL_ODDRST_MASK;
  /* USB0_USBCTRL: SUSP=1,PDE=1,??=0,??=0,??=0,??=0,??=0,??=0 */
  USB0_USBCTRL = (USB_USBCTRL_SUSP_MASK | USB_USBCTRL_PDE_MASK);
  /* USB0_OTGISTAT: IDCHG=1,ONEMSEC=1,LINE_STATE_CHG=1,??=1,SESSVLDCHG=1,B_SESS_CHG=1,??=1,AVBUSCHG=1 */
  USB0_OTGISTAT = USB_OTGISTAT_IDCHG_MASK |
                  USB_OTGISTAT_ONEMSEC_MASK |
                  USB_OTGISTAT_LINE_STATE_CHG_MASK |
                  USB_OTGISTAT_SESSVLDCHG_MASK |
                  USB_OTGISTAT_B_SESS_CHG_MASK |
                  USB_OTGISTAT_AVBUSCHG_MASK |
                  0x12U;
  /* USB0_ISTAT: STALL=1,ATTACH=1,RESUME=1,SLEEP=1,TOKDNE=1,SOFTOK=1,ERROR=1,USBRST=1 */
  USB0_ISTAT = USB_ISTAT_STALL_MASK |
               USB_ISTAT_ATTACH_MASK |
               USB_ISTAT_RESUME_MASK |
               USB_ISTAT_SLEEP_MASK |
               USB_ISTAT_TOKDNE_MASK |
               USB_ISTAT_SOFTOK_MASK |
               USB_ISTAT_ERROR_MASK |
               USB_ISTAT_USBRST_MASK;
  /* USB0_ERRSTAT: BTSERR=1,??=1,DMAERR=1,BTOERR=1,DFN8=1,CRC16=1,CRC5EOF=1,PIDERR=1 */
  USB0_ERRSTAT = USB_ERRSTAT_BTSERR_MASK |
                 USB_ERRSTAT_DMAERR_MASK |
                 USB_ERRSTAT_BTOERR_MASK |
                 USB_ERRSTAT_DFN8_MASK |
                 USB_ERRSTAT_CRC16_MASK |
                 USB_ERRSTAT_CRC5EOF_MASK |
                 USB_ERRSTAT_PIDERR_MASK |
                 0x40U;
  /* USB0_INTEN: STALLEN=1,ATTACHEN=1,RESUMEEN=1,SLEEPEN=1,TOKDNEEN=1,SOFTOKEN=1,ERROREN=1,USBRSTEN=1 */
  USB0_INTEN = USB_INTEN_STALLEN_MASK |
               USB_INTEN_ATTACHEN_MASK |
               USB_INTEN_RESUMEEN_MASK |
               USB_INTEN_SLEEPEN_MASK |
               USB_INTEN_TOKDNEEN_MASK |
               USB_INTEN_SOFTOKEN_MASK |
               USB_INTEN_ERROREN_MASK |
               USB_INTEN_USBRSTEN_MASK;
  /* USB0_ERREN: BTSERREN=0,??=0,DMAERREN=0,BTOERREN=0,DFN8EN=0,CRC16EN=0,CRC5EOFEN=0,PIDERREN=0 */
  USB0_ERREN = 0x00U;
  /* USB0_USBTRC0: USBRESET=0,??=1,USBRESMEN=1,??=0,??=0,??=0,SYNC_DET=0,USB_RESUME_INT=0 */
  USB0_USBTRC0 = (USB_USBTRC0_USBRESMEN_MASK | 0x40U);
  /* USB0_OTGICR: IDEN=0,ONEMSECEN=0,LINESTATEEN=0,??=0,SESSVLDEN=0,BSESSEN=0,??=0,AVBUSEN=0 */
  USB0_OTGICR = 0x00U;
  /* USB0_ADDR: LSEN=0,ADDR=0 */
  USB0_ADDR = USB_ADDR_ADDR(0x00);
  /* USB0_ENDPT0: HOSTWOHUB=0,RETRYDIS=0,??=0,EPCTLDIS=0,EPRXEN=0,EPTXEN=0,EPSTALL=0,EPHSHK=0 */
  USB0_ENDPT0 = 0x00U;
  /* USB0_ENDPT1: HOSTWOHUB=0,RETRYDIS=0,??=0,EPCTLDIS=0,EPRXEN=0,EPTXEN=0,EPSTALL=0,EPHSHK=0 */
  USB0_ENDPT1 = 0x00U;
  /* USB0_ENDPT2: HOSTWOHUB=0,RETRYDIS=0,??=0,EPCTLDIS=0,EPRXEN=0,EPTXEN=0,EPSTALL=0,EPHSHK=0 */
  USB0_ENDPT2 = 0x00U;
  /* USB0_ENDPT3: HOSTWOHUB=0,RETRYDIS=0,??=0,EPCTLDIS=0,EPRXEN=0,EPTXEN=0,EPSTALL=0,EPHSHK=0 */
  USB0_ENDPT3 = 0x00U;
  /* USB0_ENDPT4: HOSTWOHUB=0,RETRYDIS=0,??=0,EPCTLDIS=0,EPRXEN=0,EPTXEN=0,EPSTALL=0,EPHSHK=0 */
  USB0_ENDPT4 = 0x00U;
  /* USB0_ENDPT5: HOSTWOHUB=0,RETRYDIS=0,??=0,EPCTLDIS=0,EPRXEN=0,EPTXEN=0,EPSTALL=0,EPHSHK=0 */
  USB0_ENDPT5 = 0x00U;
  /* USB0_ENDPT6: HOSTWOHUB=0,RETRYDIS=0,??=0,EPCTLDIS=0,EPRXEN=0,EPTXEN=0,EPSTALL=0,EPHSHK=0 */
  USB0_ENDPT6 = 0x00U;
  /* USB0_ENDPT7: HOSTWOHUB=0,RETRYDIS=0,??=0,EPCTLDIS=0,EPRXEN=0,EPTXEN=0,EPSTALL=0,EPHSHK=0 */
  USB0_ENDPT7 = 0x00U;
  /* USB0_ENDPT8: HOSTWOHUB=0,RETRYDIS=0,??=0,EPCTLDIS=0,EPRXEN=0,EPTXEN=0,EPSTALL=0,EPHSHK=0 */
  USB0_ENDPT8 = 0x00U;
  /* USB0_ENDPT9: HOSTWOHUB=0,RETRYDIS=0,??=0,EPCTLDIS=0,EPRXEN=0,EPTXEN=0,EPSTALL=0,EPHSHK=0 */
  USB0_ENDPT9 = 0x00U;
  /* USB0_ENDPT10: HOSTWOHUB=0,RETRYDIS=0,??=0,EPCTLDIS=0,EPRXEN=0,EPTXEN=0,EPSTALL=0,EPHSHK=0 */
  USB0_ENDPT10 = 0x00U;
  /* USB0_ENDPT11: HOSTWOHUB=0,RETRYDIS=0,??=0,EPCTLDIS=0,EPRXEN=0,EPTXEN=0,EPSTALL=0,EPHSHK=0 */
  USB0_ENDPT11 = 0x00U;
  /* USB0_ENDPT12: HOSTWOHUB=0,RETRYDIS=0,??=0,EPCTLDIS=0,EPRXEN=0,EPTXEN=0,EPSTALL=0,EPHSHK=0 */
  USB0_ENDPT12 = 0x00U;
  /* USB0_ENDPT13: HOSTWOHUB=0,RETRYDIS=0,??=0,EPCTLDIS=0,EPRXEN=0,EPTXEN=0,EPSTALL=0,EPHSHK=0 */
  USB0_ENDPT13 = 0x00U;
  /* USB0_ENDPT14: HOSTWOHUB=0,RETRYDIS=0,??=0,EPCTLDIS=0,EPRXEN=0,EPTXEN=0,EPSTALL=0,EPHSHK=0 */
  USB0_ENDPT14 = 0x00U;
  /* USB0_ENDPT15: HOSTWOHUB=0,RETRYDIS=0,??=0,EPCTLDIS=0,EPRXEN=0,EPTXEN=0,EPSTALL=0,EPHSHK=0 */
  USB0_ENDPT15 = 0x00U;
  USB0_BDTPAGE1 = (uint8_t)((((uint32_t)((uint32)&g_Mem[0])) >> 0x08) & 0xFEU);
  USB0_BDTPAGE2 = (uint8_t)((((uint32_t)((uint32)&g_Mem[0])) >> 0x10) & 0xFFU);
  USB0_BDTPAGE3 = (uint8_t)((((uint32_t)((uint32)&g_Mem[0])) >> 0x18) & 0xFFU);
  /* USB0_SOFTHLD: CNT=0 */
  USB0_SOFTHLD = USB_SOFTHLD_CNT(0x00);
  /* USB0_OTGCTL: DPHIGH=0,??=0,DPLOW=0,DMLOW=0,??=0,OTGEN=0,??=0,??=0 */
  USB0_OTGCTL = 0x00U;
  /* USB0_CONTROL: ??=0,??=0,??=0,DPPULLUPNONOTG=0,??=0,??=0,??=0,??=0 */
  USB0_CONTROL = 0x00U;
  /* USB0_CTL: TXSUSPENDTOKENBUSY=0,HOSTMODEEN=0,ODDRST=0,USBENSOFEN=1 */
  USB0_CTL = (uint8_t)((USB0_CTL & (uint8_t)~(uint8_t)(
              USB_CTL_TXSUSPENDTOKENBUSY_MASK |
              USB_CTL_HOSTMODEEN_MASK |
              USB_CTL_ODDRST_MASK
             )) | (uint8_t)(
              USB_CTL_USBENSOFEN_MASK
             ));
}
/*! Sets up the clock for USB operation (out of RESET)
 *!
 *! MCGOUTCLK = 48MHz
 *! core/platform/system clock = PLL (48MHz), 
 *! bus clock = PLL (48MHz),
 *! flash clock = PLL/2 (24MHz)
 *!
 *! Assumes 8 MHz external crystal
 *!
 *! Modes: FEI [FLL engaged internal] -> 
 *!        FBE [FLL bypassed external] ->
 *!        PBE [PLL bypassed external] ->
 *!        PEE [PLL engaged external]
 *!
 *! Refer 24.5.3.1 of K20 Family reference
 */
void initClock(void) {
   MCG_C7 = 0; // OSCSEL = 0 => Crystal Osc
   
   // Out of reset MCG is in FEI mode
   // Configure the Crystal Oscillator
   OSC0_CR = OSC_CR_SC16P_MASK;
   
   // 1. Switch from FEI (FLL engaged internal) to FBE (FLL bypassed external)
   
   // 1 a) Set up crystal 
   MCG_C2 =                         // oscillator in low power mode (w/o Rf)
            MCG_C2_EREFS0_MASK |    // because crystal is being used
            MCG_C2_RANGE0(1)   |    // 4 or 8 MHz is in high frequency range
            MCG_C2_IRCS_MASK;
 
   // 1 b) Select clock mode
   MCG_C1 =  MCG_C1_CLKS(2)            |  // CLKS = 10   -> External reference clock
             MCG_C1_FRDIV(FRDIV_VALUE) |  // FRDIV = 2,3   -> 8MHz,4MHz/256 = 31.25 kHz
             MCG_C1_IRCLKEN_MASK;         // IRCLKEN = 1 -> MCGIRCLK active
   
   // Make sure - reset default
   MCG_C4 &= ~(MCG_C4_DMX32_MASK|MCG_C4_DRST_DRS_MASK);
   
   // 1 c) Wait for crystal to start up        
   while ((MCG_S & MCG_S_OSCINIT0_MASK) == 0) {
   }
   // 1 d) Wait for mode change
   while ((MCG_S & MCG_S_IREFST_MASK) != 0) {
   }
   // 1 e) Wait for MCGOUT indicating that the external reference to be fed to MCGOUT
   while ((MCG_S & MCG_S_CLKST_MASK) != MCG_S_CLKST(2)) {
   }
   
   // 2. Configure PLL Ref. Freq.
   
   // 2 a) Set PRDIV for correct range
   MCG_C5 =  MCG_C5_PLLCLKEN0_MASK |
             MCG_C5_PRDIV0(PRDIV_VALUE);    // PRDIV=3,1, PLL Ref Freq. = 8MHz,4MHz/4 => 2 MHz

   MCG_C6 = 0;
   
   // 3. FBE => BLPE => PBE
   // 3 a) BLPE
   MCG_C2 =                         // oscillator in low power mode (w/o external Rf)
            MCG_C2_EREFS0_MASK |    // because crystal is being used
            MCG_C2_RANGE0(1)   |    // 4 or 8 MHz is in high frequency range
            MCG_C2_IRCS_MASK ;
   // 3 b) BLPE/PBE
   MCG_C6 = MCG_C6_PLLS_MASK|MCG_C6_VDIV0(0); // 2MHz x 24 = 96MHz
   // 3 c) BPE
   MCG_C2 =                         // oscillator in low power mode (w/o Rf)
            MCG_C2_EREFS0_MASK |    // because crystal is being used
            MCG_C2_RANGE0(1)   |    // 4 or 8 MHz is in high frequency range
            MCG_C2_IRCS_MASK;
   // 3 d) Wait until PLLS clock source changes to the PLL
   while((MCG_S & MCG_S_PLLST_MASK) == 0) {
   }
   // 3 e)  Wait for PLL to acquired lock
   while((MCG_S & MCG_S_LOCK0_MASK) == 0) {
   }
   // Set up the SIM clock dividers BEFORE switching to the PLL to ensure the
   // system clock speeds are in spec.
#if 1 || (CPU == MK20D5)
   {
   // Disable Flash pre-fetch while changing flash divider
   uint32_t temp = FMC_PFAPR;
   FMC_PFAPR |= FMC_PFAPR_M3AP_MASK|FMC_PFAPR_M2AP_MASK|FMC_PFAPR_M1AP_MASK|FMC_PFAPR_M0AP_MASK;
   // core/platform/system clock = PLL (48MHz), bus clock = PLL (48MHz), flash clock = PLL/2 (24MHz)
   SIM_CLKDIV1 = SIM_CLKDIV1_OUTDIV1(0) | SIM_CLKDIV1_OUTDIV2(0) | SIM_CLKDIV1_OUTDIV4(1);
   FMC_PFAPR = temp;
   }
#elif CPU == MKL25Z4
   {
   // Disable Flash pre-fetch while changing flash divider
   uint32_t temp = FMC_PFAPR;
   FMC_PFAPR |= FMC_PFAPR_M3AP_MASK|FMC_PFAPR_M2AP_MASK|FMC_PFAPR_M1AP_MASK|FMC_PFAPR_M0AP_MASK;
   // core/platform/system clock = PLL/2 (48MHz), bus clock/flash clock = PLL/2/2 (24MHz)
   SIM_CLKDIV1 = SIM_CLKDIV1_OUTDIV1(1) | SIM_CLKDIV1_OUTDIV4(1);
   FMC_PFAPR = temp;
   }
#endif
   
   // 4. PBE mode transitions into PEE mode:
   // 4 a) Select clock mode
   MCG_C1 = MCG_C1_CLKS(0)  |    // CLKS  = 0 -> FLL or PLL is selected
            MCG_C1_FRDIV(FRDIV_VALUE) |  // FRDIV = 2,3   -> 8MHz,4MHz/256 = 31.25 kHz
            MCG_C1_IRCLKEN_MASK;
   
   // 4 b)  Wait for clock stable
   while ((MCG_S & MCG_S_CLKST_MASK) != (3<<MCG_S_CLKST_SHIFT)) {
   }
   // Now MCGOUTCLK=MCGPLLCLK=[(2 MHz / 1) * 24] = 48 MHz
   
   // Basic clock selection
#if 1 || (CPU == MK20D5)
   // 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 Source as USB clock (48MHz req.)
   
   // USB Clock = Divider input clock x [(USBFRAC+1)/(USBDIV+1)] 
   // USBDIV 0-7, USBFRAC 0-1
//   SIM_CLKDIV2 = SIM_CLKDIV2_USBDIV(1);
   SIM_CLKDIV2 = SIM_CLKDIV2_USBDIV(0);

#elif CPU == MKL25Z4 
   SIM_SOPT2 = SIM_SOPT2_UART0SRC(1)     | // MCGPLLCLK/2 as UART0 clock
		         SIM_SOPT2_TPMSRC(1)       | // MCGPLLCLK/2 as TPM clock
			      SIM_SOPT2_PLLFLLSEL_MASK  | // PLL rather than FLL for peripheral clock 
               SIM_SOPT2_USBSRC_MASK;      // MCGPLLCLK/2 Source as USB clock (48MHz req.)
#else
   #error "CPU not set"
#endif
}