cancel
Showing results for 
Search instead for 
Did you mean: 

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

jcw
Associate II

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?

23 REPLIES 23
jcw
Associate II

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

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
Associate II

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.

Thanks again. A dummy SystemInit() shaves 15 µs off the startup time (see my other comments). I've also examined the "startup_stm32l011xx.s" and "startup_stm32l031xx.s" files, which differ in a small but surprising detail: checking for flash mapping, and remapping it to address 0 (not sure why L011 and L031 differ). As I also mentioned elsewhere, the startup time I now see is 165 µs. It may be a bit extreme to try and reduce this further, but it'd be nice to at least understand where it's coming from. At 2.1 Mhz, I'd expect at least a hundred instructions to take this amount of time.

Here my results by using my method (PA0 as external wake-up pin on PA5 toggle into system_init()) but it should be the same by using iwdg reset. I will check it.

I capture 73µs @ VDD=3.3V with Fast wakeup enabled. And maybe need to take the code added into System_Init() to configure PA5 clock, and IO register. Maybe 20 cycles to remove at 2.1MHz. 9µs to substract ie 73-9 = 64µs

0690X000006CwILQA0.png

void SystemInit (void)
{ 
  /* GPIO PA5 Toogle sequence to trigger Wakeup Time measurement from Standby mode
  Sequence is coded in LL to reduce cycle number. Here 20 cycles.
  Wakeup Time is mesured by substract Wakeup Pin Rising Edge and PA5 toogle Rising Egde
  GPIOA Ports Clock Enable */
  RCC->IOPENR |= RCC_IOPENR_GPIOAEN;
  
  /* 0xEBFFFCFF is default value for GPIOA_MODER, 
  PA5 is set as Push Pull, all other GPIO Analog */ 
  GPIOA->MODER = ((0xEBFFFCFF & ~0x0C00) | 0x0400);   
  
  /* Toggle Trig GPIO PA5 */
  GPIOA->BSRR = GPIO_Pin_5;
  GPIOA->BRR = GPIO_Pin_5;
.......

Check and Clear Standby-Flag at the start of main.

I do not use STM32 libopen lib. I use CMSIS direct register access.

Let me know.

Good luck.

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
Associate II

Great to see this, many thanks. You're doing the work in "SystemInit()" which I have in "main()". I also do not use libopen, but my own code, and it also uses direct register access. The differences, as far as I can tell, should be at most a few instruction cycles - I'll investigate further. Then again, 100 µs is not much @ 2.1 MHz, so maybe the remaining 100 µs I'm chasing should just be treated as "startup overhead".

To clarify: my reason for getting the standby cycle as fast and low-power as possible, is because I want to understand how much energy is needed to power up an STM32L0. The project this is for has preciously little spare energy on startup, and needs to overcome the initial "power consumption hump" before the µC can initialise the rest of the circuit and put itself into stop mode with periodic wake-up.

jcw
Associate II

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 =)

Have you considered the use of STOP mode in place of the Standby for a compromise consumption / speed of wake ?

Current consumption less than 800nA

Wake-up less than 8μs

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.

S.Ma
Principal

"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?...