2025-01-30 07:30 PM
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
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;
}
2025-02-03 09:02 AM
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;
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.