Entering low power modes in zephyr environment

Hello everyone,

I am having trouble understanding how to enter power saving modes. I understand that once there are no tasks to run, the scheduler selects idle task which puts the mcu into system on power saving mode. However, it is not exactly clear to me how to enter this mode at command and stay in it for as long as i request. Take this completely unhinged pseudocode for example where I have two tasks running and a callback:

task1()
{
    // some code to read sensor data
    
    k_msleep(100);
}

task2()
{
    // do some calculations, transmit data somewhere
    
    k_msleep(50);
}

some_gpio_callback_function()
{
    // register interrupt, command enter to sleep mode
}

How am I supposed to enter any of the low power modes and stay in them until, say, another gpio input callback is received? Perhaps, when gpio interrupt fires, I should create a new task which would just idle forever - until another interrupt from gpio comes in, after which i would just kill the newly created idling task? Or is the a better way to do it since we already have an idle task spawned automatically by zephyr?

I hope you understand my problem, please assist. 

  • Hi,

    As you write, the idle thread will enter low power mode (essentially wait for event - WFE). It will stay there until woken up by an event/interrupt. This can be externally (like from a GPIO or similar, or from the RTC, which the Zephyr scheduler use to keep track of time).

    when gpio interrupt fires, I should create a new task which would just idle forever

    No, you do not need to create anything to enter sleep mode. As long as no tasks run, the idle thread will run, and put the device to sleep.

  • Thank you for your answer. 

    As long as no tasks run, the idle thread will run, and put the device to sleep.

    This is exactly my point. How do I make this happen - that no tasks run. I want to run tasks normally when device is in active state in such manner as I presented in pseudocode. And then, by my command, I want to stop those same tasks from running for as long as I want. Then, whenever I want, with a push of a button or some other interrupt, I want those tasks to resume working normally.

    I don't want to just sleep in between tasks, I want my system to stay idle continuously for any amount of time. I hope you understand what I mean. 

  • The default behaviour in most modules is to race to idle and wait for events. And this is how you shoud do with your tasks as well. There are many mechanisms that help you do this, which to use depend on the use case. The typical is k_sleep to wait for a defined time, or  semaphore, mutex, fifo or message queues and wait for something there (you can also use a timeout if you won't want to wait forever). You can see an example of this with a FIFO in the Basic thread manipulation sample.

Related