Skip to main content
Visitor II
January 31, 2025
Question

STM32L011 increased current in stop mode after RTC wakeup timer interrupt

  • January 31, 2025
  • 1 reply
  • 514 views

I noticed the current draw of my STM32L011 increases after returning to stopmode from a RTC wakeup timer interrupt. The current remains higher until a reset is performed. I've narrowed it down to a minimal bit of code that reproduces the problem however I haven't found a way to avoid or fix the issue. The errata don't mention anything like this either. 

This is a trace of the current consumption, I've also attached a longer trace that includes power-on and a reset after the wakeup

rtc wakeup currentrtc wakeup current

This is with only the LSE, RTC and an input pin configured. Code to reproduce the issue:

#include "stm32l011xx.h"

constexpr uint8_t BTN_PIN = 5;
constexpr uint8_t WAKEUP_INTERVAL = 1;

int main(void)
{
 RCC->APB1ENR |= RCC_APB1ENR_PWREN;
 RCC->IOPENR |= RCC_IOPENR_GPIOAEN | RCC_IOPENR_GPIOCEN;

 // GPIO
 GPIOA->MODER = 0xffffffff & ~(3 << (BTN_PIN * 2)); // button input
 GPIOA->PUPDR |= (1 << (BTN_PIN * 2)); // pullup enabled

 PWR->CR |= PWR_CR_DBP | PWR_CR_LPRUN | PWR_CR_LPSDSR; // also enable LPRUN mode
 wait_for_flag_set(PWR->CR, PWR_CR_DBP);

 // enable LSE, configure RTC clock source and enable RTC
 RCC->CSR &= ~(RCC_CSR_LSEDRV_1 | RCC_CSR_LSEDRV_0 | RCC_CSR_LSION);
 RCC->CSR |= RCC_CSR_RTCSEL_LSE | RCC_CSR_LSEON | RCC_CSR_RTCEN;
 wait_for_flag_set(RCC->CSR, RCC_CSR_LSERDY);

 // RTC
 RTC->WPR = 0xca;
 RTC->WPR = 0x53;
 RTC->ISR |= RTC_ISR_INIT;
 wait_for_flag_set(RTC->ISR, RTC_ISR_INITF);

 RTC->CR &= ~RTC_CR_WUTE;
 wait_for_flag_set(RTC->ISR, RTC_ISR_WUTWF);

 RTC->CR |= RTC_CR_WUTIE | RTC_CR_WUCKSEL_2;
 RTC->WUTR = WAKEUP_INTERVAL;

 RTC->TR = 2113575;
 RTC->DR = 2441505;
 // exit init and lock
 RTC->ISR &= ~RTC_ISR_INIT;
 RTC->WPR = 0xff;
 wait_for_flag_set(RTC->ISR, RTC_ISR_RSF);

 // wakeup event is on EXTI line 20
 EXTI->IMR |= EXTI_IMR_IM20;
 EXTI->RTSR |= EXTI_RTSR_RT20;

 NVIC_SetPriority(RTC_IRQn, 1);
 NVIC_EnableIRQ(RTC_IRQn);

 // button interrupt falling edge
 EXTI->IMR |= (1 << BTN_PIN);
 EXTI->FTSR |= (1 << BTN_PIN);
 NVIC_SetPriority(EXTI4_15_IRQn, 1);
 NVIC_EnableIRQ(EXTI4_15_IRQn);

 // configure stop mode
 PWR->CR |= PWR_CR_FWU | PWR_CR_ULP | PWR_CR_LPDS | PWR_CR_LPSDSR | PWR_CR_LPRUN;
 SCB->SCR |= SCB_SCR_SLEEPDEEP_Msk;

 while(1)
 {
 __WFI(); // do nothing
 }
}

extern "C" void RTC_IRQHandler(void)
{
 EXTI->PR = EXTI_PR_PIF20;
 RTC->ISR &= ~(RTC_ISR_WUTF);

 // disable wakeup timer
 RTC->WPR = 0xca;
 RTC->WPR = 0x53;

 RTC->CR &= ~RTC_CR_WUTE;
 wait_for_flag_set(RTC->ISR, RTC_ISR_WUTWF);

 RTC->WPR = 0xff;

 // enable button
 EXTI->IMR |= (1 << BTN_PIN);
 GPIOA->MODER &= ~(3 << (BTN_PIN * 2));
}

extern "C" void EXTI4_15_IRQHandler(void)
{
 EXTI->PR |= (1 << BTN_PIN);
 // set button to hi-z and disable interrupt
 EXTI->IMR &= ~(1 << BTN_PIN);
 GPIOA->MODER |= (3 << (BTN_PIN * 2));

 // enable wakeup timer
 RTC->WPR = 0xca;
 RTC->WPR = 0x53;

 RTC->CR |= RTC_CR_WUTE;

 RTC->WPR = 0xff;
}

static bool wait_for_flag_set(volatile uint32_t& reg, const uint32_t flag, uint32_t timeout = 1000)
{
 while(timeout --)
 {
 if(reg & flag)
 {
 return true;
 }
 }
 return false;
}

static bool wait_for_flag_clear(volatile uint32_t& reg, const uint32_t flag, uint32_t timeout = 1000)
{
 while(timeout--)
 {
 if(!(reg & flag))
 {
 return true;
 }
 }
 return false;
}

 

    This topic has been closed for replies.

    1 reply

    ST Employee
    February 3, 2025

    Hello @Luke_

    Inside the RTC_IRQHandler, try reconfiguring the clocks and power settings: 

    RCC->APB1ENR |= RCC_APB1ENR_PWREN;
    PWR->CR |= PWR_CR_DBP | PWR_CR_LPRUN | PWR_CR_LPSDSR;