[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