[En-Nut-Discussion] tickless idle mode
Andras Szemzo
szemzo.andras at gmail.com
Mon Dec 3 09:19:07 CET 2018
Hi,
I try to implement tickless idle operation for NutOS. I’m using a stripped down NutOS (just the kernel, without vfs, net, configurator,c runtime etc) on Microchip/Atmel SAMD21 Cortex-m0+.
What I do is in the IDLE thread, I added a call to a function which have to calculate the next event from the timer list:
uint32_t NutIdleEventNext(void)
{
NUTTIMERINFO *tn = nutTimerList;
uint32_t ticks_sleep = UINT32_MAX;
while (tn != NULL) {
if ( tn->tn_ticks_left < ticks_sleep)
ticks_sleep = tn->tn_ticks_left;
tn = tn->tn_next;
}
return ticks_sleep;
}
It is possible to further tuning this function, to do not sleep if ticks_sleep < XXX, or something like that, but now it’s that simple.
The idle thread:
for (;;) {
/* Check if other threads became ready to run. */
NutThreadYield();
/* Remove terminated threads. */
NutThreadDestroy();
#ifdef NUT_TICKLESS_IDLE
vPortSuppressTicksAndSleep(NutIdleEventNext());
#endif
}
The vPortSuppressTicksAndSleep is the timer setup function for sleep mode (yes, the name is from FreeRTOS).
I use the SAMD21’s timer4/5 in 32bit mode, and I use that for system tick (instead of Cortex's SYSTICK), and for the sleep counter with a ultra low power internal OSC.
After wakeup, I calculate the time we slept and fast-forward NutOS time with a function:
static void vTaskStepTick(uint32_t idle_time)
{
nut_ticks += idle_time;
}
In the function vPortSuppressTicksAndSleep() after I stop the system tick timer, I disable the interrupts before sleep, and make a last check,
if any interrupt is fired (and any thread has to wake up with call NutEventPostFromIrq(xxx) ), something like that:
/* Enter critical section */
asm volatile( "cpsid i" ::: "memory" );
asm volatile( "dsb" );
asm volatile( "isb" );
if (total_pending != 0) {
system_tick_resume(); /* resume NutOS system tick timer */
/* Leave critical section */
asm volatile( "cpsie i" ::: "memory" );
asm volatile( "dsb" );
asm volatile( "isb" );
NutThreadResume(); /* allow woken up thread to schedule */
return;
}
With this setup my power consumption is a few uA with NutOS at sleep.
Am I missing something? Is there any other implementation of tickeless mode for NutOS?
Regards,
Andras
More information about the En-Nut-Discussion
mailing list