Switching main CPU clock frequency after starting up FreeRTOS

Hi all

I have an application running on custom HW; sometime after startup I will have to switch between a fast but inaccurate CPU clock to a slower but accurate one.

We are currently using the faster clock and FreeRTOS with a 1mSec tick. I’ve had a quick look at the source and it seems it would be relatively easy to switch from one clock rate to another; by redefining configCPU_CLK_HZ in some way and having a version of prvSetupTimerInterrupt() to stop the clock and restart using the new divisor.

Is this right? Has anyone else done anything like this?

I will be trying to make sure that the system is as ‘quiescent’ as possible when making the switch.

Thanks for any thoughts, Jon N

Is it possible to switch the clock source during init before starting the scheduler (and the SysTick) ?
Then I think you could build your app with the final configCPU_CLK_HZ and don’t need to worry about it.

Hi Hartmut

We are looking at this approach, but I think it is likely that freeRTOS will have some minimal role to play before switching the clock - hence the question.

Thanks, Jon N

If you change the CPU clock rate, then yes, if that affects the counter that is generating the tick, you need to adjust its divider, and be ready to handle any transition issues due to that.

What can work better, depending on the processor, is to use timer on the processor that isn’t tied to the processor clock to generate the tick, and thus don’t need to reprogram it as you change processor speeds.

On many processors there is a low frequency “Real Time” clock that can give you this sort of counter, which I find useful to use.

Since in this sort of setup, you will likely need to replace prvSetupTimerInterrupt(), the value of configCPU_CLK_HZ isn’t important unless you use it somewhere else in your code.

Hi Richard - thanks for the idea, but there is no timer that is not tied to the processor clock. We do have a (currently spare) second processor timer; I suppose we could set up the two timers with the respective divisors, and then switch between the two timers, rather than have two divisors for the same timer. However that sounds like rather more trouble for the same result to me…

The second timer could help, but isn’t needed. What I do when I need to change timers that have their clock rate change is

  • Stop the timer
  • Change the Clock Rate.
  • Save Old Divider
  • Save Counter
  • Compute new Divider and load
  • Compute a new Counter scaled by the ratio of the dividers
  • Restart the timer.

You will lose a bit of time due to the stopping and starting of the timer, but that should be small enough to not really matter. You can figure out how much time that is and add an adjustment to the counter when you reload it if you need a more accurate time base.

If there is no timer not based on the processor, my guess is MANY devices in the system need to be reinitialized with new timing values at this point too.

Hi Richard
Thanks, that’s pretty much what I had in mind. Computing a new Counter may or may not be necessary, I haven’t worked that bit out yet.

If there is no timer not based on the processor, my guess is MANY devices in the system need to be reinitialized with new timing values at this point too.

You are not wrong…

Note when a task enters the Blocked state it is placed on a list in wake time order - that means most of the time you only need to look at the head of the list in a tick interrupt to know if the new tick value should unblock a task. As a consequence, the list item stores a time as a tick count. If the frequency of the tick changes then that time will be wrong.

Thanks Richard, that’s just the sort of information I was hoping to learn. As I say, I am hoping to arrange things to become as ‘quiescent’ as possible when making the switch. I am not yet 100% sure what that will mean…

Jon

One thing to watch out about not updating the counter. If it is an up counter that triggers on EQUAL, then the counter may be past the time of the trigger, you you will need to wait for a counter overflow to trigger.

If it is a down counter, the counter value may be bigger than the current divider, and the next tick will be over long, the possible amount being a function of the ration of processor speeds.

Therefore, when you change the counter period you need to at least check for bad values and force a reload in those cases.

Thanks Richard, all good points to consider. I think I have enough to get on with this now…

Regards, Jon N