Post navigation

Starting Point for Kinetis Low Power LLS Mode

In “IoT: FreeRTOS Down to the Micro Amps” I’m using an application with FreeRTOS to get down in micro amps low power mode. Well, nearly all or my applications are using FreeRTOS because it makes the application scalable and extensible. Still, for anyone not used to an RTOS, that might be a hard start. So here we go: how to get into the Kinetis Low Power LLS Mode *without* an RTOS.

Power Measurement

Outline

In this project I create a very simple bare-metal application for the Freescale FRDM-KL25Z board. All what it does is to blink an LED from the Low Power wake-up interrupt to show that the application is running. Right after the wake-up interrupt, it enters again the LLS low power mode. So I enter LLS low power mode, and the timer interrupt will wake me up every second. As in LLS mode only a few timer and wake-up sources are available, I’m going to use the 1 kHz Low Power clock source.

The project and all the settings is available on GitHub at the link provided at the end of this article.

Processor Expert Components

In this project, I’m using the following components:

3 LED components (RGB)

TimerInt with TimerUnit_LDD for the low power wake-up timer

WAIT component to flash different LED’s after power-up with a delay.

Processor Expert Components

Timer

As timer I use the LPTMR with a period of one second:

Low Power 1 Second Timer

Inside the period settings, I configure it to use the LPO 1 kHz timer as clock source, as this clock still will run in LLS mode:

LPO 1 kHz Source

CPU Component

First, we need to configure the CPU component to be ready for low power mode. I enable the methods SetOperationMode() and GetLLSWakupFlags() (so the black x is removed):

Enabled SetOperationMode and GetLLSWakeupFlags

In the CPU properties, I enable all low power modes, configure LPTMR0 as wake-up source, and enable the INT_LLW wake-up interrupt:

Enabled Low Power Modes

Then I configure the WAIT, SLEEP and STOP modes (these are the three different low power modes in Processor Expert):

WAIT, SLEEP and STOP modes

Source Files

Time to write the application code. I’m using Application.h and Application.c:

Summary

This application shows how to set up an application for Low Power LLS mode, in a bare-metal mode. So it should be useful for you if you want to have a starting point for your own project without an RTOS.

About Erich Styger

38 thoughts on “Starting Point for Kinetis Low Power LLS Mode”

Thanks for this timely project. I am also working on getting low power operation on a FRDM-KL25Z so it is interesting to compare my results with yours.

My own code does pretty much the same thing as yours, and I can get about 1.2uA current on the FRSM-KL25Z (Rev D) in LLS mode, and 1.9uA on a modified version where I change the crystal to a 32kHz crystal.

I have run your LowPower_LLS project on my FRDM-KL25Z and get a current of about 1.7uA (measured on two different boards). There is a spike every second when the timer wakes up.

So I am interested to know why you seem to measure higher currents than I do. Is it the PCB revision – are you using a Rev E? Do you have the debugger interface active? I am measuring the current by cutting the JP4 link and bridging it with a 10 ohm resistor and measuring the voltage with a volt meter.

The KL25Z is not perfectly isolated from the rest of the circuit: it is not impossible that the debug interface and the accelerometer interface (powered on the USB side of JP4) could be influencing our readings. I am normally meticulous about ensuring that GPIO pins are in the right state – e.g. not floating. Mis-configured pins can have a big effect on sleep current. The Kinetis family seems to have a novel feature where if the PORTx_PCRn register MUX bits are set to disabled, you can overlook how the pins are terminated. (I think…)

FYI: I changed the toggling LED in your app with code that clears PTB8 in APP_OnLLSWakeUpInterrupt() and sets it in APP_TimerInterrupt(). This makes no different to the power consumption (since the LEDs draw their current on the USB side of JP4) but allows me (monitoring PTB8 on a scope) to see that there is about 10us between these two events.

I will now return to FreeRTOS – so far I have not managed to get it into a low current state. For me your Freedom_LowPower project draws 610uA. (Would you care to revisit this?)

I used in that post an older RevD board. I know these boards make it hard to measure things as there are other components drawinig current. I have re-run that LLS mode application on a KL25Z RevE board, with R73. R81 and R74 removed (with jumper headers installed). Now I measure the current flow thorugh J4 with a multimeter, and I get 2.05 uA (with the spike you report during timer wake-up).

Sorry for reply too late.
I used this example. And I used interrupt period 1ms in run status. But I want to change the interrupt period to 300ms in sleep status to wake up the device, and then change back to 1ms after wake up. How could I do?

If you are using my latest FreeRTOS component, then it has two additional hooks: vOnPreSleepProcessing() and vOnPostSleepProcessing(): you can use the hooks to do whatever you want, including changing the clock frequency.

I have successfully used LLS mode on the KL25Z. Now I was trying out the same on the FRDM-K64F Board, but ran into the following problem:
In Processor Expert –> CPU component Properties –> Low Power mode settings
…there are only two categories: “Allowed Power modes” and “Operation mode settings”. Where is the “LLWU settings” category?

Without that category it seems difficult to select a “wake-up source”, etc…

Hi Erik,
thanks! But I have not used low power modes for the K64F yet. Simply because the boards I have used with it did not need in low power mode (always connected to power). But looking at the CPU component, it looks it now only supports the Kinetis SDK :-(. Which means a completely different way and method has to be used. I would need to wrap my head around this first (speaking in pictures)….

Hi Mr Styger
I am currently trying to use the CMP module in LLS mode. The CMP should wake up the MCU on rising and falling edge. As soon as the LLS is entered, the CMP module throws numerous interrupts (with a delay of 49us between the interrupts) through NVIC, altought there is no edge in the analog signal. The LLWU interrupt is only sporadically called by CMP, not on every edge as it should.
What i have already checked:
– voltage reference of CMP
– LLS works in combination with low power timer. If I add the CMP module, the LTPM does not work reliable any more.
– Resetting the interrupt flags of CMP (similar to LPTM) in LLWU interrupt routine.
– I considered the errata sheet, which contains two entrys of CMP and LLS => Recommended solutions do not solve the problem.

Hi Mathais
I have not used the comparator, but here are a few extra things you could check:
– As you leave and enter low power mode the processor current will change and this may lead to changes in supply voltage. Could this be causing the comparator to trigger?
– Do you have plenty of power decoupling capacitance, and decoupling on your analog inputs?
– Have you enabled the comparator output function, so you can monitor the comparator’s output on a pin? Then you could be certain whether the interrupts you see coincide with real comparator transitions or some other reason.
– Explore settings for filtering and hysteresis. The KL15 data sheet says “The window and filter functions are not available in LLS”. Are you relying on some feature that vanishes when you sleep?
– Are you comparing two external voltages or one voltage and the internal DAC? What voltages do you expect these to be?

Hi
– Supply voltage looks smooth
– Decoupling capacitors are similar to TWRK21-Evalboard
– CMP works correctly => The problem must on NVIC or LLWU
– No filter or window functions are enabled. Hysteresis is set to 30mV.
– I compare an external votlage with the internal reference. I already changed it to comparing two external voltages, internal bandgap,.. with no effect.

I tested some more cases:
– If the CMP event is disabled in Processor Expert, it no longer throws interrupts through NVIC (makes sense). But the LLWU does not work too, respectively only throws ISR’s randomly.
– If the CMP event is disabled and it triggers only on rising edges, everything is functioning.
– IF the CMP event is enabled and it triggers only on rising edges, the LLWU functions and the NVIC only throws interrupts if the voltage at the CMP has a high level.
– If all events of Processor Expert are disabled and two CMP’s should trigger independently at either falling or rising edge, the LLWU stops working again. I’m really confused.

It seems that there are two problems:
1. NVIC interrupt throwing during LLS. Maybe a problem of priority..
2. LLWU fails, if two wakeup sources are active.

Hi Erich,
I am working with Freescale KL-15 processor and PE version (Version: 10.4.0
Build: b140319). Initially I am trying to use your FRDM KL-25Z LLS example, when I import the project in PE 10.4.0, I do not see the following three Methods under the CPU (SetClockConfiguration, GetClockConfiguration and SetOPerationMode). Any suggestions or ideas why these methods are not appearing under the CPU?

I would like to use the sleep mode (STOP) in KL25Z128 but to wake up use the different interrupts (ExtInt) that I have, Is this possible? Do you have some example? I have to use another sleep mode? I was checking the manual an it says “Normal stop mode (STOP): Asynchronous Wakeup Interrupt Controller (AWIC) is used to wake from interruptions.”

I’m having an issue here. I used a delay to blink a LED when the MCU wakes up. Firts time (before the first sleep), its blinks normal. But when the MCU sleeps, and wakes up after I send something on my UART port, the blink function takes a long time. I’m using the WAIT component with a 250ms delay. Seems like there’s an issue with my clock (after the sleep). It’s taking much more than 250ms to blink the LED.

Thanks for the reply Erich! I’m using Cortex-M4 (MK20). I fixed the issue half an hour after I posted here. Inside APP_OnLLSWakeUpInterrupt(), I called Cpu_SetOperationMode() with DOM_RUN, and seems to work normal now.
Cpu_SetOperationMode(DOM_RUN,NULL,NULL);

I know this thread is very old but I am having issues finding a solution to my problem.
I am using the K10 series and would like to use the 4MHz internal clock while awake and the 32.768kHz internal clock while asleep.

I cannot comment on the K10 as I have not used it in my designs, but I would think that if you use Processor Expert, things should be pretty much possible. You would need to go through the clock gear shifting. Processor Expert has the option to allow multiple different clock settings, and it generates the correct code to shift between them. Otherwise you might look a the MCUXpresso SDK (if it does support your device) if there are examples for this?

Hi, Thanks, I am trying to repeat what you have done as a practice but I find several tiny issues with CodeWarrior that is slowing me down. I know this might not be directed to your post but your answer can be very valuable to me. I cannot find some of the components in my CodeWarrior. For example, I cannot find the WAIT or LED. I have read some of your pages about missing components. I refreshed the pages and also my software is updated. Do you have any suggestions?

Thanks alot, it was useful. I managed to add the components. I repeated your work but with a different FRDM board (KL-46Z256). In this case the current consumption is 18mA at 3V before the LED blinks and it is 23mA at 3V when the LED blinks. I think it is not gone to the low power mode. I am not expert and probably I have done something wrong but the only thing I changed compare to your code is the LEDs pin numbers (Since it is different for KL-46Z256). I can see on the board the LED is blinking, that means interrupt has happened. Do you have any example for KL-46Z256 or how to debug with CodeWarrior to find if the system is really gone to low power sleep or not? I used this application.c code (changed your code slightly) :
/*
* Application.c
*
* Created on: Mar 16, 2014
* Author: Erich Styger
*/

Thanks, I looked at the problem in details. I am sure my current reading is correct as I have done it several times in the past, with other MCU as well and I read a correct value.
I have saved 2 videos and photos here:

I share a video with you which shows that the current consumption changes slightly when an interrupt happen (when the yellow LED is on). This is shown in the “FirstVideo” and the code is in a png file as “CodeForFirstVideo.png”. Then secondly I put and LED2_Neg(); /* RED LED */ inside the for(;;) loop and run the code. In the “SecondVideo” you can see the RED LED is blinking. I also put the code “CodeForSecondVideo.png”.
So I guess I am in the for loop and also the interrupt happens but something is wrong then.

My question is: APP_OnLLSWakeUpInterrupt() function is responsible for interupt or APP_TimerInterrupt()? In my case APP_OnLLSWakeUpInterrupt() is not sending an interupt.

Hi,
APP_TimerInterrupt() is only used to toggle the RED LED to show the system is running. It gets called by the T1 (LPTMR_CMR) interrupt which wakes up from LLS mode.
In case the CPU wakes up from LLS, it calls Cpu_OnLLSWakeUpINT() which then calls APP_OnLLSWakeUpInterrupt(). If APP_OnLLSWakeUpInterrupt() does not happen, your system is not waking up from LLS.

Do you know if there is anyway to look at the peripherals in CodeWarior and see that low power mode has happened? I am looking for a method that shows we are in low power without measuring the current every time. I have done your work but it seems Cpu_SetOperationMode(DOM_STOP, NULL, NULL); /* next interrupt will wake us up */
does not do anything and I am not in low power stop mode, even if I go to the function I do not know what to check or look for to find the problem.

To my understanding, there is no such information on the device itself. What I did is measuring the current to check if it really enters low power mode. Keep in mind that you should disconnect the debugging cable (and not debugging it while in low power mode).
I hope this helps,
Erich