Dynamically switching clock speed/clock sources in tickless mode

amilaperera wrote on Tuesday, May 15, 2018:

Hi,

I am using FreeRTOS in tickless idle mode by using the default Sleep mode.

At running state I would like to have a system clock frequency above 48 MHz to get USB working. With this clock configuration the amount of time the RTOS is sleeping becomes very low both due to the maximum value that can be accommodated in systick reload register and the fast clock speed.

However, is it possible to switch to a different low speed clock during sleep. Can configPRE_SLEEP_PROCESSING(x) and configPOST_SLEEP_PROCESSING(x) be implemented in such a way that it switches to 2 different clock speeds or 2 different clock sources during running time and sleep time. We are relying on FreeRTOS SW timers as well. Will this clock speed/source switch affect kernel scheduler timing or FreeRTOS timers ?

Thank you in advance.
Amila.

heinbali01 wrote on Tuesday, May 15, 2018:

Hi Amila, in tickless mode (configUSE_TICKLESS_IDLE), the following function is called when the kernel wants to sleep:

    void vPortSuppressTicksAndSleep( TickType_t xExpectedIdleTime )

Now you can do anything you want, but you must guarantee three things:

  • Wake-up on any ISR which is enabled
  • Wake-up after at most xExpectedIdleTime clock ticks
  • Tell the kernel how long the sleeping took by calling vTaskStepTick(n_ticks)

Be aware that the kernel time, as provided by xTaskGetTickCount(), becomes less precise. That is because the sleeping duration won’t be a nice multiple of clock-ticks.

An example: I used “tickless idle” in an Atmel SAM4E. I decided to use a Timer-Counter (TC) as a source of time. This TC has an overflow interrupt every 30 seconds. This time sources has a resolution of 1 uS, and it is independent from the kernel tick.

It is still important to keep the kernel time as precise as possible, because many kernel delays depend in it.

Changing the system clock frequency is a bit tricky: make sure that no DMA is active. And also, if you use TC’s, their frequencies might, or might not, change as well.

In order to save energy ( batteries ), it is important to make long idle times, like e.g. 30 seconds.
I tested tickless mode in combination with FreeRTOS+TCP: that worked well. But I did disable the reception of UDP broadcasting packets, in order to increase the length of the idle periods.

USB : isn’t possible to run at a low frequency all the time, until a USB connector is plugged in? And as soon as the device is plugged-in, you increase the frequency to 48 MHz?
Once USB is connected, sleeping will be difficult because of the 1 ms USB clock-tick.

amilaperera wrote on Tuesday, May 15, 2018:

Hi Hein,

Thank you for the response.

I am a somewhat aware of vPortSuppressTicksAndSleep() and pre/post config hook functions that we can use to implement our own behaviour needed. I understand that using a low frequency clock lets the CPU to stay idle for longer periods assuring better power consumption.
Actually that’s exactly what I want to achieve with my system after enabling USB as well.

I reckon your last paragraph is highly important.

USB : isn’t possible to run at a low frequency all the time, until a USB connector is plugged in? And as soon as the device is plugged-in, you increase the frequency to 48 MHz?

This is completely possible since I just need a higher clock just to enable USB only when it is connected. Therefore I can simply detect VBUS and call a funtion that would change the clock configuration and restore it to the default clock configruration on USB disconnection.

My question is if we do in the above manner at a time when the RTOS kernel is already running, would it have bad consequences on the scheduler or SW timers the system uses ?

However, please notice that due to the tight power budget, I do need to use tickless idle mode even if we’re running at 4MHz.

Thank you.
Amila.

heinbali01 wrote on Tuesday, May 15, 2018:

Therefore I can simply detect VBUS and call a function that would change
the clock configuration and restore it to the default clock configuration
on USB disconnection.

All right, so you keep F=48 Mhz for as long as VBUS is high? I guess that should work well.
I would make sure nothing is going on while changing frequency: no interrupts, no active DMA.

if we do in the above manner at a time when the RTOS kernel is already
running, would it have bad consequences on the scheduler or SW timers
the system uses ?

Regarding time awareness, the scheduler only depends on the clock-tick. There are no other clocks involved. The clock-tick may be triggered by systick, but you may decide to use a different clock source, one which is more flexible ( be careful to choose a suitable priority ).

If you divide the CPU frequency by 12, in principle you should multiply the clock divisor by 12 to get the same clock tick rate. Or choose a different ( lower-frequency ) clock source.

However, please notice that due to the tight power budget,
I do need to use tickless idle mode even if we’re running at 4MHz.

You can look-up in a table how much current is used when running at 4MHz, maybe that is low enough to meet your requirements?

What is your configTICK_RATE_HZ? If it is 100, the sleeps will only last 10 ms.

I think that if you want to lower the power consumption, you will need tickless idle and have the CPU sleep for long periods of time, like 30 seconds.
Regards,

amilaperera wrote on Tuesday, May 15, 2018:

Hi Hein,

Thank you for the clarification.
If I understand correctly, I can run the CPU at a higher clock rate i.e. 48MHz while using a very low frequency clock to generate a tick ensuring longer idle time when running in tickless idle mode. I can think in this direction with the given requirements to come to an optimum solution.

Thanks.
Amila.