Many embedded applications spend most of their time waiting for something to happen, such as receiving data on a serial port, watching for an I/O pin to state change, or waiting for a time delay to expire. The way in which the MCU's software handles these and other routine tasks can make a huge difference in the power a device consumes.
Many microcontrollers have a number of low-power modes in which different parts of the microcontroller can be turned off when they aren't needed. Placing MCUs in a low-power mode during idle times can significantly reduce power consumption and extend battery life by orders of magnitude. But software is what defines which parts of the MCU are idle and so determines your ability to utilize these low-power modes to maximum advantage.
Common software mistakes that cause unnecessary power consumption include:
- Using a polling loop to wait for a status change, such as in a peripheral register flag, instead of using an interrupt
- Implementing a time delay with a software loop instead of a hardware timer
- Moving data between peripherals and memory using software copy loops instead of a DMA channel
In all of these cases the CPU should be put in a low-power mode and then awakened using an interrupt when the peripheral completes its operations.
An even more costly operation in terms of power consumption that a designer can control from a software perspective is accessing memory. Starting from the bottom of the memory hierarchy, the first thing designers should do is move software functions and subroutines from Flash into RAM, so that every access would consume less power. Given the often small RAM sizes available in some microcontrollers it can be quite difficult to run an entire program from RAM. But there is significant power to save if the CPU executes from RAM at least the most frequently executed functions, provided, of course, they have a small enough footprint.
The next step is to be sure that functions handle memory-stored data efficiently as possible. Optimizing memory access is one of the most effective software methods of reducing current consumption in an embedded system, because memory accesses themselves consume a lot of energy. It also takes time to read and write data, so optimizing memory accesses not only reduces power consumption, it speeds execution time. There are many techniques to optimize data management, such as grouping accesses to the same variable, specifying that the CPU put some particular variables in CPU registers, and so on.
The operating system is another potential power waster. In a task-oriented design the idle task is the perfect place to switch from active mode to low-power modes, but the use of a standard RTOS in a low-power design can raise some problems related to the scheduling algorithm. The common system to switch between ready tasks in an RTOS is to use an interrupt generated at a fixed period, typically on the order of milliseconds. This fixed period typically imposes an active duty cycle greater than necessary, especially if there is no task ready to execute.
One solution is to adopt a totally tick-less kernel. A totally tick-less kernel, despite being configured to generate an interrupt at a predetermined tick rate, will generate a new tick only when a task is ready to be processed. This approach allows the kernel to wake up the microcontroller only when it needs to be awake, not every time period. The approach guarantees best-performance scheduling of tasks with a lower time resolution and never interrupts the execution of a task. The tick-less scheduler does add an additional overhead in order to compute the events the CPU will need to perform in the near future, but experimental results show that this approach is still better than using a tick-based scheduler.
Some new RTOSes designed for remote sensor monitoring, like TinyOS and Contiki, follow such an event-driven approach, but they provide a reduced set of features compared with normal RTOSes. The TiROS from Sandia National Laboratories and Q-Kernel from Quasarsoft are two recent examples of totally tick-less RTOS that introduce also some interesting features to support power management.
In the simplest applications you could replace a tick-less scheduler with a dynamic tick scheduler that works like a normal scheduler during active mode and disables the scheduler during standby modes. This approach leaves to the designer the choice of how to wake up the microcontroller. Choices include several interrupts coming from I/O and specialized timers.
There are efforts underway today to push the tick-less feature into the times when the microcontroller is busy running tasks, in order to minimize the periodic tick as much as possible. The goal is reducing the critical sections that induce latencies, which will also reduce power consumption.
Comments and questions are welcome.
Related posts: