FreeRTOS and sleep mode (battery saving)

jerry1111 wrote on Sunday, November 02, 2008:


I have several threads which are required to run every 5 seconds. I also have an RTC (AVR32) which can be used to wake the micro up from sleep mode. The question is: how do I know that after wake-up all the tasks have completed everything and are ready to go to sleep for 5 seconds?

I don’t like the idea of using idle task hook to go to sleep, because that’s going to happen with every timer tick. I want to put the micro safely (means all the tasks are doing nothing) to sleep.

Is there a way to do it other than having a lot of semaphores? Those semaphores would then signal to the ‘monitoring’ task that everything’s finished and we can go to sleep.



kolodko1 wrote on Sunday, November 02, 2008:

If idle task get processor time that means that all task over idle task priority finished, right? it is time to disable IRQ tick if you know what you are doing.

You can use counting semaphore as well.

richard_damon wrote on Sunday, November 02, 2008:

Actually, I could see a case where the idle task might get a bit of time will some task is delaying for some I/O to finish. I would use the idle hook, and have it check flags that the other tasks set while busy. You don’t need the expense of a semaphore, because having the idle task polling these flags isnt ging to be a waste of time, as by definition nothing else is able to run at that point.

edwards3 wrote on Sunday, November 02, 2008:

> Actually, I could see a case where the idle task might get a
> bit of time will some task is delaying for some I/O to
> finish.

If the IO causes an interrupt that will take the micro out of sleep mode then it does not matter if the idle task causes sleep mode to be entered while the task waits for the IO. Even if the task sleeps to wait for polled IO it still does not matter as the task will wake from the sleep during a tick interrupt which will also take the micro out of sleep mode.

richard_damon wrote on Sunday, November 02, 2008:

Depending on the processor, this might not be true. In some processors, their is a deep sleep mode that does things like turn off the crystal oscillator, and switches to a low frequency clock. Waking up from this type of sleep can take significant time (on computer scales) and might cause some peripherals to not work right (if they need the high speed clock). You may well want to make sure that you are done with certain activities before hitting this sort of sleep.

Your comment is true for an idle mode that just stops the CPU until something happens (like an interrupt) and the CPU can pick up immediately. There is generally no reason not to put this form of sleep in the idle loop.

jerry1111 wrote on Sunday, November 02, 2008:

Because I want to put the processor to sleep for several seconds (might be any number between 1 and 60), then I’m planning to use deep-sleep mode. In this mode all the peripherals except 32kHz clock will be powered down. The processor will not wake up by an interrupt, because with all peripherals disabled there will be no interrupts.The only working thing will be RTC, and that can wake the processor up.

Because waking up might take some time (haven’t checked yet - based on datasheet) then I don’t want to do it in idle task - it won’t be power-efficient (time to switch off everything and then switch it back on again 100x a second is probably not a good idea). However I will consider using just sleep mode (cpu off, timers working) in idle task with hope that it will help to reduce energy consumption by additional 10-20%. I can see that being useful when waiting for all peripherals to finish. But the highest priority is to put this thing to sleep for several seconds.

The idea of idle task polling a set of flags (static variables presumably) to check if every thread has finished seems like the only sensible idea (without adding semaphores).

Thanks for advice - really helpful. But please don’t look at this as a closed issue! Someone might come up with another interesting idea!

I’ll try to implement it this week - will tell how it behaves :wink:

Oh, and one more thing: the idle task is just a normal task, but it’s not allowed to use blocking OS calls? And when it’s doing something and it gets interrupted in the middle, then it will resume at the same point when everything’s finished?
Or is it behaving in a different way?

richard_damon wrote on Sunday, November 02, 2008:

Idle task is just like any other task. Like you say, it shouldn’t block as then there is nothing to run and the schedule may crash.

You actually don’t need a number of flags, but could use just a single flag with the number of actions still to finish. Using a bunch of flags is a bit simpler on the other tasks, as they can assume they have exclusive write access to them so don’t need critical sections to change it. Using a common count would require placing the increment and decrement in a critical section (and take less memory if that is an issue).

The idle task hook routine could be something like this (pseudo code)

void vApplicationIdleHook() {
    if(all done) { // all done either (runcount == 0) or (task1run + task2run + task3run … == 0)
        go into deep sleep
        kick start operations (and set there run flags)
    } else {
        go into idle sleep (if available, this being a stop processor till next interrupt, and restart immediately)

Depending on what is needed to restart the operations, you may want to kick by signaling a high priority task that starts everything up then waits to be kicked again. This would be needed if starting up the periodic tasks will cause the idle task to be preempted before it can start all of the desired tasks, making the kick start take too long.