How fast is the clock running on the TWRK21F120M?

cancel
Showing results for 
Show  only  | Search instead for 
Did you mean: 

How fast is the clock running on the TWRK21F120M?

1,177 Views
ARQuattr
Contributor IV

I am using the TWRK21F120M BSP on a board that has the K22F120M MCU and I'm not sure at what speed the clock is running.  It appears from the BSP that it uses the 'config 0' settings which look to be 120MHz, but I'm concerned the execution is running slowly.  For example, toggling a GPIO bit using direct register access only runs at about 4.5MHz.

Am I mistaken about what default frequency the BSP is set to run, or is there something specifically I need to do to set the clock rate?  Is it because I'm using a slightly different MCU?  I noticed a note in the twr21f120m.h header (ln 134) that indicates 48MHz, which doesn't seem to match the values in bsp_cm.h so I'm not sure if it's a typo or I'm just confused.

Thanks,

Angelo

Labels (1)
Tags (3)
0 Kudos
Reply
2 Replies

867 Views
daweiyou
NXP Employee
NXP Employee

Hello:

The real clock setting code is located at bsp_cm.c: __pe_initialize_hardware()

Which could be replaced by PE generated code.

By checking the code, which should be 120M core clock, 60M bus clock;

You could output the internal clock from CLKOUT pin to check also;

PLS see

CLKOUTSEL CLKOUT select

SIM_SOPT2 field descriptions (continued)

Field Description

Selects the clock to output on the CLKOUT pin.

000 FlexBus CLKOUT

001 Reserved

010 Flash clock

011 LPO clock (1 kHz)

100 MCGIRCLK

101 RTC 32.768kHz clock

110 OSCERCLK0

111 Reserved

/*

    • ===================================================================

    • Method : __pe_initialize_hardware (component MK21FN1M0MC12)

**

    • Description :

    • Initializes the whole system like timing, external bus, etc.

    • This method is internal. It is used by Processor Expert only.

    • ===================================================================

*/

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. !!! ***/

/*** ### MK21FN1M0VMC12 "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 MQX_ENABLE_LOW_POWER

/* Reset from LLWU wake up source */

if (_lpm_get_reset_source() == MQX_RESET_SOURCE_LLWU)

{

PMC_REGSC |= PMC_REGSC_ACKISO_MASK;

}

#endif

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

}

/* 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 */

/* 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=0,USBFRAC=0 */

SIM_CLKDIV2 = (uint32_t)0x09UL; /* Update USB clock prescalers */

/* SIM_SOPT2: PLLFLLSEL=1 */

SIM_SOPT2 |= SIM_SOPT2_PLLFLLSEL_MASK; /* 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_RANGE0(0x02) | MCG_C2_EREFS0_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=1 */

MCG_C5 = MCG_C5_PRDIV0(0x01);

/* MCG_C6: LOLIE0=0,PLLS=0,CME0=0,VDIV0=6 */

MCG_C6 = MCG_C6_VDIV0(0x06);

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=6 */

MCG_C6 = (MCG_C6_PLLS_MASK | MCG_C6_VDIV0(0x06));

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

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. !!! ***/

}

Dawei You(尤大为)

Mobile: +86 13675169919

0 Kudos
Reply

867 Views
ARQuattr
Contributor IV

In bsp_cm.c, I changed this line in __pe_initialize_hardware() to output the OSCERCLK signal:

  SIM_SOPT2 |= SIM_SOPT2_PLLFLLSEL_MASK | SIM_SOPT2_CLKOUTSEL(6); /* Select PLL as a clock source for various peripherals */

And I set the PCR as follows (it looks like the K22FN1M0VLL120 has CLKOUT on PTC3):

    PORTC_PCR3 = (PORTC_PCR3 & ~PORT_PCR_MUX_MASK) | PORT_PCR_MUX(5);    //set PTC3 as clkout pin

After this I see the 8MHz signal at the CLKOUT pin, but I'm not sure this proves anything.  Based on fig26-1 of the reference manual, I believe OSCERCLK should match the crystal frequency, correct?  I changed the CLKOUTSEL to the LPO clock and see 1kHz.  So I think the clock is OK, but the processing seems slow.

With the MCF52259, when I call _time_delay(5) I get a reliable 5ms delay.  I think 5ms is the minimum tick period for the default TWR52259 BSP.  But when I call this with the TWRK21 BSP this gives me a 10ms delay.  I ran some tests with different delay values and got these results:

_time_delay(x) gives a delay of y (ms)

x = 1 to 5 -> y = 10

x = 6 to 10 -> y = 15

x = 11 to 15 -> y = 20

x = 16 to 20 -> y = 25

and this pattern continues at least up to x = 99

So it seems the tick resolution is 5ms as expected and the general clock setup is right, but maybe the number of ticks calculated when using _time_delay is not right (there is an extra tick)?

I looked into time.c in the psp and found this where it indicates it is adding another tick, although it appears it's actually adding 2.

/* Convert milliseconds to ticks, truncated */
PSP_MILLISECONDS_TO_TICKS_QUICK(milliseconds, &td_ptr->TIMEOUT);
/* Resolve truncation by adding one tick. Add another tick to accomplish the requested amount of time. */
PSP_ADD_TICKS_TO_TICK_STRUCT(&td_ptr->TIMEOUT, 2, &td_ptr->TIMEOUT);

After seeing how much processing is done just to convert milliseconds to ticks, I'm probably going to change all my delays to use ticks, at least in time-critical areas.

I tried the above test using _time_delay_ticks, and I get the expected delay periods (5ms per tick).

I'm not sure if this delay error is because of changing to a Kinetis PSP, or upgrading from MQX 3.6 (which I was testing the TWR52259 PSP in) to MQX 4.1.

0 Kudos
Reply