AnsweredAssumed Answered

Help with oscilator problem on Kinetis K40

Question asked by Luis Filipe Rossi on Oct 19, 2011
Latest reply on Oct 19, 2011 by Luis Filipe Rossi

Hi i am working on a custom design with a PK40N512. I want to run my core at 100Mhz., however i got a weird problem. The circuit i am using at the crystal is attached for reference. My crystal is a 4MHz one (ATS040SM) and the R1 resistor is 1M Ohm.

The problem is the following. If i place a 0R resistor at R2, for some reason the Kinetis run at half of the frequency (from the flash and from the RAM). I am measuring it using the PIT module. However, if i place a 390R resistor, the circuit run at the right frequency (100Mhz) when running from the RAM, but hangs at the external referencen initialization when running from the flash. 

 

My initialization code is the following:

 

#pragma section CopyToRAM beginvoid clock_init(void){// 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)  OSC_CR = (uint8_t)0xA0U;  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(4);// 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)  SIM_SOPT2 &= (uint8_t)~(uint8_t)0x01U;  MCG_C5 = MCG_C5_PRDIV(0); // 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 | MCG_C6_VDIV(1);// 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    SIM_SCGC5 |= (uint32_t)0x0200UL;     /* Enable clock gate for ports to enable pin routing */    SIM_SOPT2 &= (uint8_t)~(uint8_t)0x01U;}#pragma section CopyToRAM end

 My linker got the following lines added from the basic one: 

 

_ROMCodeToCopy = ___ROM_AT + SIZEOF(.app_data);
.copyToRAM: AT(_ROMCodeToCopy) {
. = ALIGN (0x4);
__START_COPYTORAM = .;
*(CopyToRAM)
__END_COPYTORAM = .;
} >> m_data

 

The problem is at the line with the following code: 

  while (((MCG_S & MCG_S_CLKST_MASK) >> MCG_S_CLKST_SHIFT) != 0x2){}

 

Any idea of what is the problem?

 

Thank you!

Outcomes