Before the project start, average power consumption of the K70-SOM running uClinux was around 140 mA. This is without any attempts at power saving at all.
The primary contributor to this effort so far has been Robert Brehm and his team in the University of Southern Denmark.
Here is how Robert describes their work on this project:
Our route was to start off with the static manual suspend-to-ram mode and then move on to the dynamic mode. The manual/static suspend-to-ram mode is supported using the standard Linux power management core – we just had to implement the "struct platform_suspend_ops" callbacks.
The system can be suspended to RAM with the "echo mem > /sys/power/state/" command. Then, it can be woken up through the console (serial port) by a keystroke on the keyboard, or by an external interrupt.
We have implemented the supporting framework code for the Linux power management framework to switch the Kinetis K70 into a low power mode and also started to implement the necessary suspend functions for device drivers, mainly in the FEC to power down the Ethernet interface and.
Also we have started to implement the on-chip RTC using the kernels RTC framework as a wakeup (interrupt) source when suspended.
As far as numbers go, our first result was getting down to about 29mA in the suspend-to-ram mode from around 140mA on a running system. This was higher than we had hoped and expected.
Our suspicion was that the LPDRAM was not entering the self-refresh mode and thereby being responsible for a big portion of these remaining 29mA.
I did some dissolved measurements to verify whether I would see 100Hz wake-ups when suspended. That would indicate that the internal Linux timer was waking the system up. The measurements with a scope demonstrated that not to be the case, the current drawn was absolutely static at around 29mA. But when in normal operational mode I could nicely see those current peaks at 100Hz.
We were kind of stuck for some time at that point and then we decided to temporarily step away from Linux and implement control of the RAM modes from straight sequential code in CodeWarrior in order to determine if the RAM would enter different running states at all. The same for the Ethernet PHY and the NAND flash.
That approach yielded good results: we got the power consumption down to ~2.0xx mA... in very-low-power stop mode ... the 2mA in front of the comma must be mainly the Ethernet PHY chip (KSZ8051) responsibility which we set into its lowest power state where it still takes about 2mA (which is a bit of a pity).
The Ethernet PHY also turned out to be the main problem of our initial attempts: we never really went into its power saving mode, and that is why we never got below those 29mA. There were some "simple" issues with the timing and control for the Ethernet PHY. Once we had gotten past that issue, the power consumption dropped to 2mA levels.
Anyway, that's a big step ... so we will now try to incorporate all that into the Linux kernel (resp. the respective driver) to be able to statically suspend the system and get it back to life using the real-time clock or an external interrupt.
One of the challenges is that the kernel is executed from the LPDRAM which we need to suspend in order to reach a comparable low power consumption of less than 2mA in static sleep mode. The idea here is to hardcode the last instructions to suspend the LPDRAM into the internal processors flash and execute the last few instructions before deep sleep from the flash memory.
Emcraft plans to integrate Robert’s low-power patches into the main Linux Cortex-M kernel tree and then move on to optimizing the power consumption of a running system. We will try switching the Kinetis core and on-board peripherals to low-power sleep mode when the operating system is idle, possibly using the "tickless kernel" Linux feature, as well as utilizing the ARM DS5 debugger and the associated Energy Probe to analyze and optimize the power profile of a running system.