Use Sleep Mode for All It’s Worth to Cut Power Consumption

One way to cut power and energy consumption in processor-based systems is to put the processor to sleep. No work gets done when the processor is asleep so you need to wake it up once in a while so it can look around, check to see if anything needs service, and then put it to sleep. That’s what you need to do if some tasks are based on periodic service requirements. Things are easier if all tasks are interrupt-driven. Then all you need to do is let the interrupt-service routine (ISR) awaken the processor.

But let’s consider the case of a periodic time waking the processor for time-based task processing. Actually, let’s consider the case when there are several periodic tasks with different service periods. Often, the approach taken is to analyze the various service periods and then develop an interrupt clock tick that’s the smallest common interval of the various periods. This approach needlessly wastes power because many of the ISR activations will awaken the processor only to find no tasks to execute. Let’s look at why.

The problem arises when tasks do not have periods that are integer multiples of each other or when one or more tasks has multiple modes with different periods. For example, say that one task has a required periodicity of 30 msec and another task has a periodicity of 100 msec. The only way to handle both periods is to set the interrupt time to 10 msec. Then the first task can be executed on every third interrupt and the second task can be executed every 10 interrupts as shown in this sequence:

Interrupt 0: Service 30- and 100-msec task

Interrupt 1: No service

Interrupt 2: No service

Interrupt 3: Service 30-msec task

Interrupt 4: No service

Interrupt 5: No service

Interrupt 6: Service 30-msec task

Interrupt 7: No service

Interrupt 8: No service

Interrupt 9: Service 30-msec task

Interrupt 10: Service 100-msec task

Interrupt 11: No service

Interrupt 12: Service 30-msec task

Interrupt 13: No service

Interrupt 14: No service

Interrupt 15: Service 30-msec task

Interrupt 16: No service

Interrupt 17: No service

Interrupt 18: Service 30-msec task

Interrupt 19: No service

Interrupt 20: service 100-msec task

However, as you can see, out of every 10 timer interrupts, an average of more than five interrupts will result in no servicing because neither the 30-msec nor the 100-msec task needs to be executed. In other words, half of the interrupts that awaken the processor will result in a return to sleep mode with no useful work done but with excess energy consumed.

There’s a way to eliminate these unnecessary interrupts and to save the wasted power consumed by the unneeded ISRs using a little smarter code. Instead of using a fixed-period ISR timer, write the timer code to keep track of the time to the next needed interrupt by tracking the amount of time since each pending task was last executed in a software-updated register or memory counter.

For the above example, the main code would first service both the 30- and 100-msec tasks. Then, it would set the interrupt-timer interval for 30 msec (minus the amount of time needed to execute the 30-msec task). When the interrupt timer goes off, the code executes the 30-msec ISR and then reprograms the timer interrupt for another 30-msec period because that’s the next periodic task scheduled to be executed. The timer code must also deduct 30 msec from the period value it’s tracking for the 100-msec task, reducing that value to 70 msec.

At the next timer interrupt, the timer code again schedules a 30-msec period and deducts another 30 msec from the 100-msec counter, leaving 40 msec. After another 30-msec interval, there’s 10 msec left before the 100-msec task needs to be executed, so the timer code sets the next timer-interrupt interval to 10 msec (minus the time needed to execute the 30-msec ISR). Finally, 10 msec later, the processor awakes, executes the 100-msec task, and subtracts 10 msec from the 30-msec task’s counter leaving 20 msec. So the timer code sets the next interrupt for 20 msec (the time remaining until the 30-msec task should be executed). And so the process continues.

Using this scheme and a simple set of tracking counters for the various tasks to be executed, a real-time kernal can minimize periodic interrupts to just those that are actually required and can thus keep the processor asleep more of the time. For battery-powered applications, this technique can provide substantial power savings and a resultant improvement in battery life.

This blog entry is based on the article “Improving energy efficiency in ultra-low power devices” written by Raúl Martín Rello.

This entry was posted in Design, Low-Power and tagged , , , , , . Bookmark the permalink.

Leave a Reply