From a software perspective, there are some less obvious tricks to reduce power consumption. As stated in a previous post, the best way to conserve power is to stay in the lowest power state for as long as possible. Since run mode with the CPU actively executing instructions is never the lowest power state, we want to minimize the amount of work the CPU must perform. This allows the CPU to complete tasks faster and allows the MCU to return to a low power mode. So, here are some tips for reducing the CPU execution time.
Data types
Match the default data type to the CPU. When writing C code, it is easy to forget that the common integer is usually defined as 16 or 32 bit number, even on compilers for 8-bit MCUs. For 8-bit devices, always default to using the 8-bit char type unless a larger size is really necessary. Even then, you may be able to reduce code size by breaking a 16-bit or 32-bit number into 8-bit slices and only concatenate at the end of the data manipulation.
Conversely, a 32-bit CPU can typically manipulate and move 32-bit data more efficiently than manipulating or moving four 8-bit values. However, if the data really only needs 8-bits, it would be more efficient to use an 8-bit char instead of an integer.
Avoid short loops and small functions
Avoid using short loops or subroutine calls if you can afford the extra memory to use in-line code. Every loop and subroutine uses additional CPU cycles to either determine if the loop is complete or to stack and unstack the program counter. If you know a short loop will always be executed four times, just write the same code four times in a row rather than using a for-next or while loop. If a subroutine only has 10 or 20 bytes of code, consider in-lining it instead of keeping it a subroutine. This will eliminate a fair amount of CPU overhead for simple tasks.
Pre-calculate values
Pre-calculate values when appropriate. For example, assume a wireless link uses two baud rates depending on what the application is talking to. When writing C code it may be tempting to pass the actual baud rate to the serial interface setup routine rather than the actual prescaler value the serial interface requires. After all, this makes the code more readable. However, this also forces the serial interface routine to calculate the prescaler value from the baud rate every time the baud rate is changed. Calculating the prescaler values beforehand and passing these to the serial setup routine will save CPU cycles and code space.
An extension of the pre-calculating concept is using look-up tables rather than complex calculations. Many MCUs have very efficient instructions and address modes for accessing tabled data. Depending on the complexity of the calculation, this can save quite a bit of CPU effort. If calculations are still required, always check for early exits before starting the routine. A simple example is looking for multiplication by ‘1’ or ‘0’.
-Scott





