Low Power Challenges for NXP's ARM Cortex-M3 based Microcontrollers

My name is Johnny Sun.  I'm a systems engineer here at DMC and I'm back to demonstrate some low-power operating modes for the LPC1788 microcontroller. I have a demo board here that's a barebones board where it just has the microcontroller without any peripherals attached to it so we can get a good power consumption readings for just the processor.  

I've taken out the linear regulator that's attached to it and I swapped in the switching regulator that has a high efficiency, so the power consumption numbers will pretty clearly reflect what the processor is drawing.  I have it set up where I'm giving 3.7 volts to the regulator to pretend that it's a lithium ion battery and the regulator set is down to 3.3 volts, and I'm just measuring the current on this multi meter here.

The project that we've been working on, it requires a very high performance microcontroller during normal operation where the product is connected to AC power.  It will have an LCD touch screen and it will do a lot of Ethernet or Wi-Fi communications.  But at the same time, there's a requirement for it where if it loses AC power, it needs to continue running its core periodic data acquisition tasks for a set amount of time on just battery power.  Not only does the microcontroller need to be very powerful and the LCD needs to go into a very low power state for the occasions when power is lost. 

The LPC1788 has four low power modes.  The first of which is just a normal sleep mode.  This is the low power mode that draws the highest amount of power and when it goes into the regular sleep mode, any interrupt can wake it up.  So it's also the most flexible because only the power to the core is stopped and all the peripherals are going to keep running.  

After that we have deep sleep mode. Here the processor is turned off and the flash memory is also disabled.  So we use less power, but the disadvantage is we can only wake up from deep sleep under a limited number of interrupts that are NMI (non-maskable interrupts) external interrupts, GPIO interrupts, and we're going to be using the RTC interrupts.  

After deep sleep, there's a power-down mode that's also very similar to deep sleep, but it uses a little bit less power.  The only downside is it takes longer to resume operation after waking up because the flash memory is completely turned off.  

The lowest power state is deep power-down mode and in that state, the entire chip is turned off, and only an RTC or reset signal can wake it up after which the program needs to resume at the beginning again.

The low-power states that we want to use for our project is sleep and power-down and that's because under normal operation, we'll just use sleep when no tasks are running and I need the FreeRTOS taken are up to be able to wake it up.  So we'll save a little bit of power under AC power while when we're in power saving mode.  Where there is no AC power we'll be going into power-down mode and occasionally wake up using the RTC interrupt to take a daily sample, store it, and then go right back down to sleep.

Let me show you the power consumption that the chip uses when it's running at 120 megahertz.  My sample program adjusts, sets some pins up to, it sets all of its GPIO to a pretty low power states, and basically increments a counter infinitely.  As you can see, in this mode it's drawing around 113 milliamps run at 120 megahertz and not doing too much else if we enable the sleep mode on the processor, and we'll build that.  
Now we went into sleep mode, and any low power modes, you want to after you program it, you need to remove the debugger and do a reset on the chip to get it to go into the, to give us an accurate power rating because otherwise it won't sleep properly when the debuggers connected.  Now it, once again it sets the pins, turns off the pull-ups to all the pins and sets them all to outputs, and here it's drawing around 30, 33 milliamps that's about an 80 milliamp savings just by going into sleep mode.

Next we'll run through deep sleep mode real quick.  Once you've programmed the processor to go into sleep mode, you have to boot it up in ISP mode before flashing.  Now we're at deep sleep mode, so we have a drastic power improvement.  We're only using around 612 micro amps and now we can only wake up using RTC.  We can't use any system timers or any of the regular interrupt sources.

So let's do deep power-down and this time we see around 338, 337 micro amps, so it cut the power consumption in half from deep sleep.  The only difference between power-down and deep sleep is that the flash memory is completely disabled, so waking up from this mode takes longer than from deep sleep.  But since we're only waking up very infrequently, this is the best power mode for us to go into when we're running on battery power.  

Just for completeness, demonstrate how much power deep power-down mode consumes.  Here we go.  So now we're only at about 240 micro amps.  This is about as good of power consumption as you can get with this chip and it's not too much better than power-down and the disadvantage is when you wake up from this mode, you go into a full reset and start from the beginning of the program again, so it doesn't store what state it was running at.  

The library I've been using to go into sleep states wasn't the most straightforward.  It's provided by NXP.  It's called the NXP Common Driver Library and here you can see the functions to bring the chip into sleep, deep sleep, power-down, and deep power-down.  A problem I've found with these functions is in regards to using both a deep sleep or power-down state and sleep in the same program.  One thing is the original sleep function does not reset the deep sleep bit, the sleep deep bit and the status control register whenever you call sleep.  

So if you've originally called deep sleep or power-down and then now you want to call sleep, instead of doing a normal sleep, it will go into deep sleep.  Here's the sleep deep bit that I'm talking about.  That's a minor problem, but another problem that I haven't really been able to fix, I've only been able to work around is in these original functions, the deep sleep and power-down commands disable the brownout detect functionality of this chip and what that does for us.

So this is the bit that it sets when originally it wanted to go to deep sleep or power-down.  The problem is, if you set this and next time, and after you wake up want to do a regular sleep, what I've found is after you've called power-down and you've woken up again and you go to sleep, the original sleep function re-enables the brownout detect functionality and as soon as we execute this line that I've commented out right now.  As soon as we execute that, the processor would reset and since I cannot debug when I'm testing any sleep modes, I don't know what it’s doing.  

But the workaround is I now always disable the brownout detects and the brownout resets.  So I enable both this bit and this bit which disables the brownout circuit and the brownout reset functionality.  On each sleep mode, I always have those two bits set to make sure that we don't run into problems going between different levels of sleep but if you have those set right, you'll be able to go into any of the sleep states and mix and match different sleep states for different program operating modes.

Finally, how all of this ties together with FreeRTOS.  The real-time operating system we're using is, even though there is an option for in for a tickless idle on FreeRTOS, it just means that the operating system tick is suppressed and it won't wake up so often to service the tick interrupts.  

We needed something more drastic than this because even if the ticks were suppressed we still can only go into the regular sleep mode because any timer interrupts can only wake the processor up from regular sleep, and it would have been complicated to switch the tick interrupt onto the RTC when we're in power-down because the RTC can only generate ticks at most every second.  So instead, since we don't really care about the tick timer keeping time when we're at a low power mode we kind of put all of our tasks into a suspended state, so it's safe to completely shut down the operating system and go to sleep.  The only thing keeping time for us is the RTC timer, and that's the thing that enforces our periodic data collection.

With all of this we're able to get less than 500 micro amps power consumption average in low power mode and with even a small 500 milliamp hour lithium ion battery we're able to get around a thousand hours of operation out of that.

To recap, we went over running the ARM Cortex M-3 port of FreeRTOS on our LPC1788 microcontroller.  We also discussed how to do dynamic core clock speed switching without affecting the tick rate of FreeRTOS, and finally we went over some various sleep states for the LPC1788 and how to correctly use them in conjunction with FreeRTOS.  I hope you found some of these topics useful, and thanks for watching