How low (power) can you go?

In my last post, “Arm Cortex-M low-power mode fundamentals”, we explored the fundamentals of low power modes that can be found on every Arm Cortex-M processor and how we could leverage the WFI and WFE instructions to put a processor to sleep. The question that really remains though is how are these low power modes implemented on a real microcontroller and how do those modes affect our embedded system? In this post, we will explore in more detail how we can put a microcontroller to sleep and see how much energy that buys us.

Low Power Mode Experimentation

The best way to explore low power modes is to select a microcontroller and actually run the processor in various low power modes. For this post, I decided to dust off my tried and true NXP Kinetis-L Freedom board which I have not only experimented with but have used in many products, applications and courses. I also decided, right or wrong, to measure not just the amount of energy that the microcontroller was drawing but the entire development board. The MCU is usually one of the most power-hungry devices on a board, but I’ve often found that measuring the entire system current reminds me that it’s not the only energy consumer on the board. Optimizing the microcontroller can take you a long way but it’s not always the only device that might require energy optimization.  

Start with a baseline measurement

Whenever I’m working on optimizing the energy consumption of a product, I first start by taking a baseline energy measurement. This is normally done by profiling the current draw of the device over several seconds or minutes to understand where we are starting at. For my development board experiment, I left the Kinetis-L in run mode with no sleep implemented, all peripherals on and set the board to toggle an LED periodically. Using IAR Embedded Workbench with an I-Jet debugger and the I-Scope, I was able to profile a simple baseline for my board ~16.9 mA when the LED was off and ~18.0 mA when the LED was on which can be seen below in Figure 1. As you can see, it’s important to note where you take your measurement from or else you can be off significantly in your analysis.

click for larger image

Figure 1. A current measurement of the development board with an LED toggling once per second. (Source: Author)

Optimizing Energy with Wait and Deep Sleep Modes

The quickest way to see some energy savings is to implement the wait or the deep sleep mode. An examination of the datasheet for the Kinetis-L processors shows that the wait mode draws between 3.7 and 5.0 mA at 3 volts. In this mode, the CPU and peripheral clocks are disabled but the flash is in a doze mode which allows the processor to still wake up within an interrupt time frame (12 – 15 clock cycles). Wait mode is easy to implement, the code to enter wait mode can be seen below:

void Sleep_Wait(void)
{
      SCB_SCR &=~ SCB_SCR_SLEEPDEEP_MASK;
      asm(“WFI”);
}

Scroll or drag the corner of the box to expand as needed.

With just those two lines of code, the current consumption of the development board drops from 18.0 mA to 15.9 mA. That’s an 11.6% decrease in current consumption! If the board was being powered by a 680 mA battery, the battery life for the device would have gone from 37.8 hours to 42.8 hours! A five hour increase from just two lines of code!

What’s great about these high-level power modes is that we can easily take this another step further. Instead of putting the processor into wait mode, we can move it into a deep sleep wait mode using the following code:

void Sleep_Deep(void)
{
      SCB_SCR |= SCB_SCR_SLEEPDEEP_MASK;
      asm(“WFI”);
}

Scroll or drag the corner of the box to expand as needed.

All we did was adjust a single bit in the SCB_SCR register and we now have gone from an original 18 mA current draw to 14.8 mA. That’s a 17.8% decrease in current consumption! Again, assuming the board was powered by a 680 mA battery, the battery life would now have gone from 37.8 hours to 46 hours! These are some big savings for just a couple lines of code and it’s only the tip of the iceberg!

Leveraging Stop and VLLS modes for uA current draw

Using stop mode has the potential to further drop the MCU current draw by up to another two milliamps by disabling the core and system clocks. What you will find is that the lower the power mode, the more code it takes to implement it and the more complex the code becomes to wake the system back up. The code to enter stop mode on the Kinetis-L can be seen below:

void Sleep_Stop(void)
{
      volatile unsigned int dummyread = 0;
      SMC_PMCTRL &=~ SMC_PMCTRL_STOPM_MASK;
      SMC_PMCTRL |= SMC_PMCTRL_STOPM(0);
      dummyread = SMC_PMCTRL;
      Sleep_Deep();
}

Scroll or drag the corner of the box to expand as needed.

Notice that stop mode is controlled through a power management control register and once the state is set, the Sleep_Deep function is called to finish setting the power mode and executing WFI.

Up to this point, we’ve been talking about the MCU drawing 1 – 2 mA. A modern microcontroller will have power modes that can draw microamps or even nanoamps! The Kinetis-L processor debuted back around 2013, and its Very Low Leakage Stop (VLLS) mode draws only 135 to 496 microamps! The code to initialize this power mode can be seen below:

void Sleep_VLLS1(void)
{
      volatile unsigned int dummyread = 0;
      SMC_PMCTRL &=~ SMC_PMCTRL_STOPM_MASK;
      SMC_PMCTRL |= SMC_PMCTRL_STOPM(0x4);
      SMC_VLLSTRL = SMC_VLLSCTRL_LLSM(1);
      dummyread = VLLS_CTRL;
      Sleep_Deep();
}

Scroll or drag the corner of the box to expand as needed.

At this point, the microcontroller would be drawing nearly no energy at all!

The effect of low power modes on wake-up latency

As we have seen so far, moving the processor into lower and lower power modes is a great way to save energy but that savings does come at a cost. The lower the energy state of the processor, the more time that is required for the processor to wake up and do useful work. For example, if I were to use the standard stop mode, it would take 2 us plus interrupt latency for the processor to wake up and start executing code again. Not too bad. However, if I were to use one of the VLLS modes on the Kinetis-L, I would have a wake-up latency of booting the processor plus another 53 to 115 microseconds! This may not be acceptable depending on the application. Figure 2 shows additional transitions from low power modes to the run state on the Kinetis-L.

click for larger image

Figure 2. Transition times from low power modes to various modes on the Kinetis-L. (Source: Kinetis-L datasheet)

Conclusion

Arm microcontrollers will all have the standard low power modes, but every silicon vendor customizes the low power modes that are available to developers. As we have seen, silicon vendors often offer several modes that act as low hanging fruit that have minimal effect on wake-up latency. They also provide several very low power modes that nearly turn the processor off and draw only a few hundred microamps or less! Developers often need to balance the amount of energy they want to draw with how quickly they need their system to wake up and respond to events. The trade-offs are definitely application specific so don’t expect to be able to run the lowest power mode on every product and application.


Jacob Beningo is an embedded software consultant, advisor and educator who currently works with clients in more than a dozen countries to dramatically transform their software, systems and processes. Feel free to contact him at jacob@beningo.com, at his website www.beningo.com, and sign-up for his monthly Embedded Bytes Newsletter.

1 thought on “How low (power) can you go?

  1. “I remember laughin aloud a decade ago when ARM9 device manufacturers used the 'low-power' adjective and I saw the numbers.nToday, one can get lower (and I mean _lower_) numbers with specially designed arm processors like TI's MSP432 or even before those,

    Log in to Reply

Leave a Reply

This site uses Akismet to reduce spam. Learn how your comment data is processed.