How to set main core frequency of FRDM-K22F to 100MHz?

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

How to set main core frequency of FRDM-K22F to 100MHz?

7,881 Views
zoranm
Contributor III

Hello all. I am working on this ARM Cortex M4 board and as you can see the MCU runs at 120 MHz. I would like to bring that down to 100 MHz because I am trying to implement a Timer init function and interrupt handler. A basic 1ms heartbeat timer is needed for much of the testing I need to do regarding this board. I found this reference manual for the specific MCU on this board. I've been told I could alter the clock going into the systick or alter the PLL configuration but I am new to this and I am not too sure how to approach this. By the way, I am using Kinetis Design Studio and KSDK. Any and all help is greatly appreciated.

Labels (1)
55 Replies

2,427 Views
mjbcswitzerland
Specialist V

Hello Zoran

See the following:

- µTasker MCG Configuration Support

- µTasker Kinetis FRDM-K22F support

The FRDM-K22F has an 8MHz crystal or can use the internal IRC48M as PLL source.

Your configuration will be PEE (PLL Engaged External) with a PLL factor of x30 (4MHz PLL input x 30 = 120MHz).

This means that you simply need to modify the multipiction factor used during initialisation from x30 to x25 to achieve 100MHz instead.

The Flash clock will be 120/5 = 24MHz and so can be changed from /5 to /4 to get the optimum speed of 25MHz.

The bus clock divider can be left at 2 to achieve 50MHz.

Regards

Mark

Kinetis: µTasker Kinetis support

K22: µTasker Kinetis FRDM-K22F support  / µTasker Kinetis TWR-K22F120M support

For the complete "out-of-the-box" Kinetis experience and faster time to market

2,427 Views
zoranm
Contributor III

Hi Mark. Thank you for that valuable information. I am using Kinetis Design Studio and KSDK; how can I go about doing that using this IDE and SDK?

0 Kudos

2,427 Views
mjbcswitzerland
Specialist V

Hello Zoran

The code involved has nothing to do with the IDE and I don't know how KSDK does it - but if you show me the initialisation code that you have I can probably show you which line(s) to change.

As reference - the uTasker project does it with this configuration:

#define OSC_LOW_GAIN_MODE

#define CRYSTAL_FREQUENCY    8000000  // 8 MHz crystal

#define _EXTERNAL_CLOCK      CRYSTAL_FREQUENCY

#define CLOCK_DIV            2 // input must be divided to 2MHz..4MHz range (/1 to /24)

#define CLOCK_MUL            25 // the PLL multiplication factor to achieve operating frequency of 100MHz (x24 to x55 possible)

#define FLEX_CLOCK_DIVIDE    2 // 100/2 to give 50MHz

#define FLASH_CLOCK_DIVIDE   4 // 100/4 to give 25MHz

Which results in this code for the K22:

MCG_C2 = (MCG_C2_RANGE_1M_8M | MCG_C2_GAIN_MODE | MCG_C2_EREFS | MCG_C2_LOCRE0); // select crystal oscillator and select a suitable range

MCG_C1 = (MCG_C1_CLKS_EXTERN_CLK | MCG_C1_FRDIV_256); // switch to external source (the FLL input clock is set to as close to its input range as possible, although this is not absolutely necessary if the FLL will not be used)

while ((MCG_S & MCG_S_OSCINIT) == 0) {} // loop until the crystal source has been selected

while ((MCG_S & MCG_S_IREFST) != 0) {} // loop until the FLL source is no longer the internal reference clock

while ((MCG_S & MCG_S_CLKST_MASK) != MCG_S_CLKST_EXTERN_CLK) {} // loop until the external reference clock source is valid

MCG_C5 = ((CLOCK_DIV - 1) | MCG_C5_PLLSTEN0); // now move from state FEE to state PBE (or FBE) PLL remains enabled in normal stop modes

MCG_C6 = ((CLOCK_MUL - MCG_C6_VDIV0_LOWEST) | MCG_C6_PLLS);

while ((MCG_S & MCG_S_PLLST) == 0) {} // loop until the PLLS clock source becomes valid

while ((MCG_S & MCG_S_LOCK) == 0) {} // loop until PLL locks

SIM_CLKDIV1 = (((SYSTEM_CLOCK_DIVIDE - 1) << 28) | ((BUS_CLOCK_DIVIDE - 1) << 24) | ((FLEX_CLOCK_DIVIDE - 1) << 20) | ((FLASH_CLOCK_DIVIDE - 1) << 16)); // prepare bus clock divides

MCG_C1 = (MCG_C1_CLKS_PLL_FLL | MCG_C1_FRDIV_1024); // finally move from PBE to PEE mode - switch to PLL clock

while ((MCG_S & MCG_S_CLKST_MASK) != MCG_S_CLKST_PLL) {} // loop until the PLL clock is selected

So essentially, just the values of the defines need to be changed at the corresponding code locations in your initialisation.

The uTasker simulator verifies that all is in range and shows the values obtained when run:

pastedImage_0.png

Regards

Mark

Kinetis: µTasker Kinetis support

K22: µTasker Kinetis FRDM-K22F support  / µTasker Kinetis TWR-K22F120M support

For the complete "out-of-the-box" Kinetis experience and faster time to market

0 Kudos

2,427 Views
zoranm
Contributor III

Hi Mark. I have nothing so far. I am still deciding which IDE and SDK to use to program this board. So you used uTasker which is another IDE to program this board, correct? So what you did is plug in the FRDM-K22F and just upload the code you showed me above, correct? But since uTasker is not free I am using Kinetis Design Studio and KSDK. So I am trying to figure out how to do that code you just showed me and upload it to the board using Kinetis Design Studio and KSDK.

0 Kudos

2,427 Views
mjbcswitzerland
Specialist V

Hi Zoran

uTasker is free for non-commerical work so you don't need to be frightened if you are learning or a hobbist.

If you are doing commerical work it does cost a little but comes with 3 or 12 months personal email and telephone support and industrial quality software equivalent to several years of project development, so is in fact virtually free for commercial use too - and likely to slash many thousands of dollars off project budgets since it greatly accelerates real work, especially its complete project simulation.

Just load some of the projects to your board from µTasker Kinetis FRDM-K22F support to get an idea of what it can do.

It is not an IDE but can be used with any of the following IDEs - and supports your board and almost all other Freescale one with no porting needed when moving between processors or boards - it will run on all by adapting itself automatically.

If you choose KDS as your IDE you can open the project in it and have your board up and running (with UARTs, accelerometer, USB, file systems etc.) after checking or adjusting half a dozen  settings: µTasker Kinetis Compiler Information . You would have the code above running the chip at 100MHz with a couple of additional clicks.

I understand you will then need HW timers, which are built in according to http://www.utasker.com/docs/uTasker/uTaskerHWTimers.PDF

Regards

Mark

Kinetis: µTasker Kinetis support

K22: µTasker Kinetis FRDM-K22F support  / µTasker Kinetis TWR-K22F120M support

For the complete "out-of-the-box" Kinetis experience and faster time to market

0 Kudos

2,427 Views
zoranm
Contributor III

Hi Mark. I will continue using Kinetis Design Studio. So all that I have to do to make my board run at 100MHz is simply copy and paste that code above into Kinetis Design Studio, then upload it to my FRDM-K22F board, correct?

0 Kudos

2,427 Views
mjbcswitzerland
Specialist V

Hi Zoran

In KDS you will need to create a project based on whatever code source you choose. It the code source allows you to set 100MHz you can do it immediately. If it doesn't (eg. it has only a 120MHz reference configuration) you will then need to edit it.

You can't use the code above directly unless your code base uses the same register defines. It may do, and if not, it is easy to see what needs to be (slightly) modified.

The code above will not run by itself since there is a lot needed in addition to get the processor to start (reset vectors, flash configuration, start-up code with watchdog configuration and variable initialisation and interrupts (if used)).

Regards

Mark

Kinetis: µTasker Kinetis support

K22: µTasker Kinetis FRDM-K22F support  / µTasker Kinetis TWR-K22F120M support

For the complete "out-of-the-box" Kinetis experience and faster time to market

0 Kudos

2,427 Views
zoranm
Contributor III

Hi Mark. Can you help me write this code? Where do I get this code source you speak of so that I can modify it to run my MCU at 100MHz? Should it come with the FRDM-K22F source code library provided by Kinetis?

0 Kudos

2,427 Views
mjbcswitzerland
Specialist V

Hello Zoran

You can get a complete solution at the links that I gave in case your priorities are to learn and complete fast - you can have a working project within 20 minutes or so for your board or any other Freescale boards. You can use KDS for this as IDE. Simply register at µTasker - Registration formular - this can be supported here or at the uTasker Kinetis forum: FreescaleTM 522XX and KINETIS

If you need to write it yourself you will need to study the tools and data sheets because it will involve a learning curve of a few weeks or months.

If you need to use KDS and KSDK you can get the source from the KSDK package: Software Development Kit for Kinetis MCUs|Freescale  You will need to read the KSDK documents and do some experimenting and learn the details of the code that it uses, after which you can start modifying it. You will then need to ask any questions in Kinetis Software Development Kit

Regards

Mark

Kinetis: µTasker Kinetis support

K22: µTasker Kinetis FRDM-K22F support  / µTasker Kinetis TWR-K22F120M support

For the complete "out-of-the-box" Kinetis experience and faster time to market

0 Kudos

2,427 Views
zoranm
Contributor III

Hi Mark. One more question for you. How would I implement a 1ms heartbeat timer. On page 61 here I found some information on setting up the interrupt handler, but I am stuck as to how to proceed setting the interrupt handler. How should I go about doing so?

0 Kudos

2,428 Views
mjbcswitzerland
Specialist V

Zoran

There are many ways to implement a timer.

1. Use the SysTick in the Cortex Core

2. In peripheral HW using PITs, FlexTimer, low power timer or (in some cases) RTC.

3. In HW using a serial peripheral such as SPI or UART (useful when no more HW timers are available)

4. In SW using a SW timer (which will ultimately be based on a HW tmer but shared for multiple SW usage)

Software timers: http://www.utasker.com/docs/uTasker/uTaskerTimers.PDF

Hardware Timers: http://www.utasker.com/docs/uTasker/uTaskerHWTimers.PDF

Interrupt and interrupt handling are automated if you use the methods described - otherwise you need to either configure an interrupt vector table in Flash or in RAM, configure the timer, configure and enable the interrupt in the peripheral (and in NVIC and enable at the core) and then correctly handle the interrupt to clear its source when it fires.

Attached is PIT code as reference.

Regards

Mark

Kinetis: µTasker Kinetis support

K22: µTasker Kinetis FRDM-K22F support  / µTasker Kinetis TWR-K22F120M support

For the complete "out-of-the-box" Kinetis experience and faster time to market

0 Kudos

2,428 Views
zoranm
Contributor III

Hi Mark. So I found this code where they show how to implement the SysTick Timer in C. How could I modify the code to give me a basic 1ms heartbeat timer?

0 Kudos

2,428 Views
mjbcswitzerland
Specialist V

Hi Zoran

The code that you have found is not interrupt code but just waits until the SysTick counts to a specified value.

It It will only be accurate if you have 80MHz system clock, otherwise you will need to manually modify it accordingly.

I wouldn't use such code since it is non-portable and of little use in anything but the simplest circumstances.

The following is interrupt based SysTick initialisation with handling of generated 1ms interrupts:

#define TICK_RESOLUTION 1

// Routine to initialise the tick interrupt (uses Cortex M4/M0+ SysTick timer)

//

extern void fnStartTick(void)

{

    #define REQUIRED_MS ((1000/TICK_RESOLUTION)) // the TICK frequency we require in kHz

    #define TICK_DIVIDE (((CORE_CLOCK + REQUIRED_MS/2)/REQUIRED_MS) - 1) // the divide ratio required (for systick)

    #if TICK_DIVIDE > 0x00ffffff

        #error "TICK value cannot be achieved with SYSTICK at this core frequency!!"

    #endif

    #if !defined INTERRUPT_VECTORS_IN_FLASH

    VECTOR_TABLE *ptrVect;

    ptrVect = (VECTOR_TABLE *)(RAM_START_ADDRESS);

    ptrVect->ptrSysTick = _RealTimeInterrupt; // enter interrupt handler

    #endif

    SYSTICK_RELOAD = TICK_DIVIDE; // set reload value to determine the period

    SYSTEM_HANDLER_12_15_PRIORITY_REGISTER |= (SYSTICK_PRIORITY << 24); // enter the SYSTICK priority

    SYSTICK_CSR = (SYSTICK_CORE_CLOCK | SYSTICK_ENABLE | SYSTICK_TICKINT); // enable timer and its interrupt

}

static __interrupt void _RealTimeInterrupt(void)

{

    INT_CONT_STATE_REG = PENDSTCLR; // reset interrupt

}

Regards

Mark

Kinetis: µTasker Kinetis support

K22: µTasker Kinetis FRDM-K22F support  / µTasker Kinetis TWR-K22F120M support

For the complete "out-of-the-box" Kinetis experience and faster time to market

0 Kudos

2,428 Views
zoranm
Contributor III

Hi Mark. So SysTick would be the way to go when implementing a timer in these Cortex MCUs, correct? So as we can see from your code

1.) the basic 1ms heartbeat timer is implemented,

2.) and it is triggering an interrupt every heartbeat.

If SysTick couldn't satisfy these two conditions, then we would have to go the old route of configuring a basic multipurpose 16-bit timer, correct?

0 Kudos

2,428 Views
mjbcswitzerland
Specialist V

Zoran

The SysTick is suitable for a periodic interrupt (that is what it is intended for).

The Kinetis has various other timers - 16 and 32 bits - for additional independent timers or more advanced usage.

Regards

Mark

Kinetis: µTasker Kinetis support

K22: µTasker Kinetis FRDM-K22F support  / µTasker Kinetis TWR-K22F120M support

For the complete "out-of-the-box" Kinetis experience and faster time to market

0 Kudos

2,428 Views
zoranm
Contributor III

Hi Mark. So when I go ahead and build the project in Keil I get this error. Here is a screenshot of the code in Keil.

0 Kudos

2,428 Views
mjbcswitzerland
Specialist V

Zoran

The header files used by Keil are not compatible with the code. You must find the equivalent defines used by Keil and then re-write the lines that are failing.

Alternatively you could take the Keil project from the uTasker package and simply build it. It depends on what you are trying to achieve and whether your time is an issue or not.

Regards

Mark

Kinetis: µTasker Kinetis support

K22: µTasker Kinetis FRDM-K22F support  / µTasker Kinetis TWR-K22F120M support

For the complete "out-of-the-box" Kinetis experience and faster time to market

0 Kudos

2,428 Views
zoranm
Contributor III

Hi Mark. I figured this was the case. What IDE are you using? Even in Kinetis I get the same errors which you can see here. Can you help me rewrite the code to use equivalent headers found in Kinetis Design Studio?

0 Kudos

2,428 Views
mjbcswitzerland
Specialist V

Hi Zoran

The code has nothing to do with IDEs apart from the fact that if you are using an example supplied with an IDE as base it will use its own header files and then may not work with other code frameworks.

If you work through each line at a time you will be able to find out what it does and then find an equivalent in the hardware header that you are using.

Note that you could also use PE, MQX Lite or KSDK to do this if you would find it easier - they also generate or include much the same code.

If you download the uTasker code it will also work with zero effort in all of these IDEs.

Regards

Mark

Kinetis: µTasker Kinetis support

K22: µTasker Kinetis FRDM-K22F support  / µTasker Kinetis TWR-K22F120M support

For the complete "out-of-the-box" Kinetis experience and faster time to market

0 Kudos

2,424 Views
zoranm
Contributor III

Hi Mark. So I am using Kinetis Design Studio with KSDK. What I did was simply file>new kinetis project and pasted your code into main.c, but I get those errors. So what you are saying is that the header files that are automatically created by Kinetis when I start the new kinetis project are not compatible with the header files in your code. How can I reference the Kinetis hardware header to find equivalent to your code and then just modify the code?

0 Kudos