Skip to main content
jcw
Associate
December 30, 2018
Question

Trying to make an L031 wake up in 65 µs - how?

  • December 30, 2018
  • 23 replies
  • 3399 views

I've been trying to get an STM32L031 to periodically wakeup with minimal power consumption. The specs say it can standby at under 0.5 µA, which I can confirm, but also that it can wake up within 65 µs, which I cannot reproduce. I'm seeing a 1.6 ms delay with 300..400 µA current consumption. This seems to indicate that the µC is waiting for Vrefint to stabilise, even though I have the FWU bit set. Below is a minimal example which still does not wake up in 65 µs:

#include <jee.h>
 
int main() {
 MMIO32(Periph::iwdg+0x00) = 0x5555; // unlock PR
 MMIO32(Periph::iwdg+0x04) = 1; // max timeout is 800ms
 MMIO32(Periph::iwdg+0x00) = 0xCCCC; // start watchdog
 
 constexpr uint32_t scr = 0xE000ED10;
 MMIO32(scr) |= (1<<2); // set SLEEPDEEP
 
 MMIO32(Periph::rcc+0x38) |= (1<<28); // PWREN
 MMIO32(Periph::pwr) |= (1<<10) | (1<<9) | (1<<1); // FWU, ULP, PDDS
 
 __asm("wfi");
}

I changed the option byte to disable BOR, but it did not make a difference. My write-up about this issue can be found here: https://jeelabs.org/2018/low-power-l031/

What am I missing?

This topic has been closed for replies.

23 replies

S.Ma
Principal
December 30, 2018

Not a speclalist in low power mode, however, if the clock is stopped, How is the clock generated? If it comes from PLL it probably needs time to stabilize before the SW can actually continue running? There should be some low power modes application note somewhere.

jcw
jcwAuthor
Associate
December 30, 2018

The L031 starts up with the MSI @ 2.1 MHz, which takes only a few cycles, I think.

Tesla DeLorean
Guru
December 30, 2018

What tools?

Sure you don't have code in SystemInit() running prior to main(). Review code executing in startup.s

Tips, Buy me a coffee, or three.. PayPal Venmo (See Profile) Up vote any posts that you find helpful, it shows what's working..
jcw
jcwAuthor
Associate
December 30, 2018

Aha, thanks! Will investigate. Using PlatformIO w/ gcc, stm32cube as runtime.

RomainR.
ST Employee
December 30, 2018

Hi jcw

Could you explain your method for wake up measurement ?

Are you sure FWU is enabed ?

usually, when mcu is in low power mode, we trigger (with oscilloscope) the duration between rising edge on Wakeup-Pin and a GPIO toggle written into CMSIS System_init() function or into Reset_Handler (in assembly)

Important Note: You must check the Reset Flag status if the reset cause is from a hard reset or from Standby return. And clear it properly. Do that early in your code.

BR

To give better visibility on the answered topics, please click on Accept as Solution on the reply which solved your issue or answered your question.
jcw
jcwAuthor
Associate
December 30, 2018

Method: I measure current, and trigger on its leading flank.

FWU: yes, see code snippet above.

There's no external wakeup, I'm using the independent watchdog.

jcw
jcwAuthor
Associate
December 30, 2018

New results, and frankly, I'm not sure how to interpret them - I now get more like 180 µs delay, much closer to the expected 65 µs, and a good deal better than the 1.6 ms reported earlier.

Here is the new code, with an LED attached to PA1, so I can see when the main code starts:

int main() {
 PinA<1> led;
 led.mode(Pinmode::out);
 
 MMIO32(Periph::iwdg+0x00) = 0x5555; // unlock PR
 MMIO32(Periph::iwdg+0x04) = 1; // max timeout is 800ms
 MMIO32(Periph::iwdg+0x00) = 0xCCCC; // start watchdog
 
 constexpr uint32_t scr = 0xE000ED10;
 MMIO32(scr) |= (1<<2); // set SLEEPDEEP
 
 MMIO32(Periph::rcc+0x38) |= (1<<28); // PWREN
 
 MMIO32(Periph::pwr) |= (1<<10) | (1<<9) | (1<<1); // FWU, ULP, PDDS
 
 __asm("wfi");
}

jcw
jcwAuthor
Associate
December 30, 2018

And here's the matching scope shot with the current consumption readings:

0690X000006CwBZQA0.png

jcw
jcwAuthor
Associate
December 30, 2018

Another small step, I've added an empty "SystemInit()" definition, and can see that it overrides the default since the resulting code is smaller. And the wakeup delay goes to 165 µs. Baby steps ...

UPDATE - code size is as follows now:

 text	 data	 bss	 dec	 hex	filename
 664	 8	 1564	 2236	 8bc	.pioenvs/l031/firmware.elf

The BSS size matches the default 512+1024 bytes min heap and stack. So one way to explain the remaining 100 µs startup overhead, is that the C runtime is clearing ≈ 1500 bytes of memory.

Although I don't understand why those areas would need be cleared on power-up.

S.Ma
Principal
December 30, 2018

Is it possible to start with HSI (16MHz?) instead of MSI (and switch later)

MSI has to probably calibrate and lock from LSI/LSE...

jcw
jcwAuthor
Associate
December 30, 2018

MSI takes 5 µs to start up, and 2 µs to stabilise (I don't have an LSE, and AFAIK, LSI is not accurate enough to assist MSI). HSI startup time is 3.7 µs. All values are "typical", not max.

jcw
jcwAuthor
Associate
December 31, 2018

Ok, I''ve got the startup time to toggling an I/O pin in main down to 85 µs. Did this by removing most of the code in the startup.s file for L031, not calling SystemInit, and not even initialising BSS (just as a test). My demo is cycling nicely at 0.8s, with standby and the IWDG waking it up again.

My conclusion is that the remaining 20 µs are down purely to the few remaining instructions needed to set up the stack and I/O pin (and some variation in that 65 µs spec). So all is well - this is indeed the amount of time it takes to get an L031 out of standby. All conform to specs.

My sincere thanks to everyone who offered tips, comments, sample code, and screen shots. All of these became little nudges to keep going and figure this all out. What a nice way to end 2018 =)

S.Ma
Principal
December 31, 2018

"The specs say it can standby at under 0.5 µA, which I can confirm, but also that it can wake up within 65 µs, which I cannot reproduce. " ==> This 65 us in the spec is based on 2.1MHz MSI?

If start time is more important than consumption, HSI will run the instructions in shorter time?...

jcw
jcwAuthor
Associate
December 31, 2018

Yes, 2.1 MHz MSI is the default startup clock. Yes, HSI will run faster, but also draw more current. In the end, most energy consumption in a µC is dynamic, i.e. based on number of logic transitions, and whether you deal with them quickly or slowly is less important.

As I mentioned in another reply (bit spread out over this thread, sorry), my main goal is neither current (amps), nor time (seconds), but the product of those (Coulombs), i.e. getting to application code while having consumed the minimum amount of energy.