cancel
Showing results for 
Search instead for 
Did you mean: 

STM32L011 increased current in stop mode after RTC wakeup timer interrupt

Luke_
Associate

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;
}

 

1 REPLY 1
Sarra.S
ST Employee

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.