TAKE A NAP!
Most embedded systems spend a lot of time waiting for something to happen. It could for example be waiting for user input, a peripheral unit, or just for some time to pass. While waiting, the microcontroller will consume power as long as the CPU is executing instructions, even if it is doing nothing.
Fortunately, modern low power microcontrollers provide a plethora of low power modes in which the application can take refuge while waiting, saving a little bit of energy. The different power modes provide different combinations of power consumption, functionality, and wake up time.
As a general rule of thumb, when the application is waiting for the device status to change it should use a low power mode and make sure it will be woken by either a timer or an interrupt. One common mistake is to ignore this rule and use a poll loop instead.
In the example below, we are waiting for a USB device to finish configuring and become ready for communication. The code construct executes without interruption until the status value changes into the expected state.
while (USBD_GetState() < USBD_STATE_CONFIGURED); For a system with an unlimited power budget, this is a straightforward construct, but when there are power constraints it will waste unnecessary power because the CPU and all on-chip systems are active. A better idea would be to enter a low power mode that keeps the USB powered but at least turns off the CPU while waiting, and set up an interrupt to trigger once the USB device is done. Another way to do it, in particular in cases where timing is not of vital importance, is to set a hardware timer to periodically trigger an interrupt. The timer approach will normally consume a little more power depending on how often you need to wake up and check device status. In a multitasking system, the situation might be a little different as the scheduler might be executing other tasks while waiting for the USB device to finish. But the principle is the same. The application should not spend clock cycles in active mode while waiting. If the USB task uses an interrupt instead, the scheduler can put the device to sleep. The interrupt will put the CPU back in active mode and the ISR can be completed before the device goes back to sleep. Another related situation where the application is waiting while doing nothing is when a time delay is implemented as a for or a while loop, like in the following example: i = 10000; // SW Delay do i–; while (i != 0); This piece of code keeps the CPU very busy executing instructions that do nothing except make the time go by. Time delays are much better implemented using a hardware timer unless they are meant to last only just a few clock cycles. In both these situations and many others not exemplified here, the code could be changed to minimize power consumption. If you remember the power debugging features described in previous articles, do this and can help you identify where in the application power is unnecessarily consumed and will allow you to find the spots where any power optimization efforts should be focused. In event-driven systems, you can display both events (interrupts) and power consumption on a common timeline, allowing you to visually monitor how various events affect the power consumption.