8 years, 10 months ago.

Problem after waking up from STOP mode with the goto_standby function

Hi

I asked a question about powerconsumption in deepsleep on the Nucleo L152RE and was told to take a look at the below function in the SetRTC library.

I have tried different modifications of the code below, but with the code from line 3-27 my program doesn't execute code properly after a WakeUp interrupt from stop mode. The power consumption is lower than by using regular deepsleep.

So my question is if you could shed some light on what the code iin these lines does with a few words?

void goto_standby(void)
{
    RCC->AHBENR |= (RCC_AHBENR_GPIOAEN | RCC_AHBENR_GPIOBEN | RCC_AHBENR_GPIOCEN |
                    RCC_AHBENR_GPIODEN | RCC_AHBENR_GPIOHEN);
#if 0
    GPIO_InitTypeDef GPIO_InitStruct;
    // All other ports are analog input mode
    GPIO_InitStruct.Pin = GPIO_PIN_All;
    GPIO_InitStruct.Mode = GPIO_MODE_ANALOG;
    GPIO_InitStruct.Pull = GPIO_NOPULL;
    GPIO_InitStruct.Speed = GPIO_SPEED_LOW;
    HAL_GPIO_Init(GPIOA, &GPIO_InitStruct);
    HAL_GPIO_Init(GPIOB, &GPIO_InitStruct);
    HAL_GPIO_Init(GPIOC, &GPIO_InitStruct);
    HAL_GPIO_Init(GPIOD, &GPIO_InitStruct);
    HAL_GPIO_Init(GPIOE, &GPIO_InitStruct);
    HAL_GPIO_Init(GPIOH, &GPIO_InitStruct);
#else
    GPIOA->MODER = 0xffffffff;
    GPIOB->MODER = 0xffffffff;
    GPIOC->MODER = 0xffffffff;
    GPIOD->MODER = 0xffffffff;
    GPIOE->MODER = 0xffffffff;
    GPIOH->MODER = 0xffffffff;
#endif
    RCC->AHBENR &= ~(RCC_AHBENR_GPIOAEN | RCC_AHBENR_GPIOBEN |RCC_AHBENR_GPIOCEN |
                     RCC_AHBENR_GPIODEN | RCC_AHBENR_GPIOHEN);
    while(1) {
#if 0
        HAL_PWR_EnterSTOPMode(PWR_LOWPOWERREGULATOR_ON, PWR_STOPENTRY_WFI);
#else
        HAL_PWR_EnterSTANDBYMode();
#endif
    }
}

Question relating to:

In the past, you need modify rtc_api.c in mbed-dev source code. From this revision, you can just use RTC function all of conditions (Normal, Reset, Stand-by, Power OFF). Nucleo, power on/off, reset, RTC, stm32, VBAT

2 Answers

8 years, 10 months ago.

Hi Hakon,
The code line 3 to 27 intends to reduce I/O leak current reduction.
if MODER sets 0xff..., port is analog input mode and this mode is best performance for leakage.
If you would like to wake-up by interrupt, please carefully check your configuration.
If you set interrupt by input port level change, this setting will case a problem.
SetRTC lib. is only concern a wake-up from reset condition
. Kenji

Hi again Kenji. I tried modifying as below, by measuring the current it seems I am able to wake the system back up with an interrupt, but I am not able to do a printf. The current is down to about 10uA

Is this because all GPIO pins will be set to analog mode after wake up? Can I add something to reconfigure GPIO pins back to normal?

I am really out of my knowledge here so I am sorry if my question might be a bit off...

Håkon

void goto_standby(void)
{
    RCC->AHBENR |= (RCC_AHBENR_GPIOAEN | RCC_AHBENR_GPIOBEN | RCC_AHBENR_GPIOCEN |
                    RCC_AHBENR_GPIODEN | RCC_AHBENR_GPIOHEN);

    GPIO_InitTypeDef GPIO_InitStruct;
    
    // All other ports are analog input mode
    GPIO_InitStruct.Pin = GPIO_PIN_All;
    GPIO_InitStruct.Mode = GPIO_MODE_ANALOG;
    GPIO_InitStruct.Pull = GPIO_NOPULL;
    GPIO_InitStruct.Speed = GPIO_SPEED_LOW;
    HAL_GPIO_Init(GPIOA, &GPIO_InitStruct);
    HAL_GPIO_Init(GPIOB, &GPIO_InitStruct);
    HAL_GPIO_Init(GPIOC, &GPIO_InitStruct);
    HAL_GPIO_Init(GPIOD, &GPIO_InitStruct);
    HAL_GPIO_Init(GPIOE, &GPIO_InitStruct);
    HAL_GPIO_Init(GPIOH, &GPIO_InitStruct);
    
    RCC->AHBENR &= ~(RCC_AHBENR_GPIOAEN | RCC_AHBENR_GPIOBEN |RCC_AHBENR_GPIOCEN |
                     RCC_AHBENR_GPIODEN | RCC_AHBENR_GPIOHEN);
  
    HAL_PWR_EnterSTOPMode(PWR_LOWPOWERREGULATOR_ON, PWR_STOPENTRY_WFI);
                     
    SetSysClock();
}

posted by Håkon Bryn 10 May 2015

With amount of spam new questions/answers are hard to notice.

But yes that code puts all pins into AnalogIn mode, so that includes your Serial connection. Easiest option is to re-initialize Serial: After wake up add: Serial pc(USBTX, USBRX), and it should put the pins in correct state again.

Plan B is to use a bit less of a brute force approach, and see if you can figure out which pins are exactly responsible for the leakage current.

posted by Erik - 10 May 2015

Yes the spam is really annoying...

Plan B would be the best option, but the code below works for now, I am down to 4uA in deepsleep :)

Thanks for helping me out!

Haakon

while(1)
    {
         wait(0.1);
         RCC->AHBENR |= (RCC_AHBENR_GPIOAEN | RCC_AHBENR_GPIOBEN | RCC_AHBENR_GPIOCEN |
                    RCC_AHBENR_GPIODEN | RCC_AHBENR_GPIOHEN);
                    
         GPIO_InitTypeDef GPIO_InitStruct;
         // All other ports are analog input mode
         GPIO_InitStruct.Pin = GPIO_PIN_All;
         GPIO_InitStruct.Mode = GPIO_MODE_ANALOG;
         GPIO_InitStruct.Pull = GPIO_NOPULL;
         GPIO_InitStruct.Speed = GPIO_SPEED_LOW;
         HAL_GPIO_Init(GPIOA, &GPIO_InitStruct);
         HAL_GPIO_Init(GPIOB, &GPIO_InitStruct);
         HAL_GPIO_Init(GPIOC, &GPIO_InitStruct);
         HAL_GPIO_Init(GPIOD, &GPIO_InitStruct);
         HAL_GPIO_Init(GPIOE, &GPIO_InitStruct);
         HAL_GPIO_Init(GPIOH, &GPIO_InitStruct);
    
         RCC->AHBENR &= ~(RCC_AHBENR_GPIOAEN | RCC_AHBENR_GPIOBEN |RCC_AHBENR_GPIOCEN |
                    RCC_AHBENR_GPIODEN | RCC_AHBENR_GPIOHEN);
        
        WakeUp::set(measure_rate);
        wait(0.1);
        deepsleep();
        Serial pc(PC_10, PC_11);
        put_data();
        
    }

posted by Håkon Bryn 10 May 2015
8 years, 2 months ago.

In case anyone lands here,

Now I have finally got my board to wake up on the external crystal, I have used the above example but run the low power configuration first before defining the pins. This appears to do the trick and deepsleep's @ just under 3uA.

But use the L476 bigger, faster and no need to run the low power configuration code.

L152 deepsleep @ 3uA

#include "mbed.h"
#include "WakeUp.h"

void LowPowerConfiguration(void);

int main() { 

    LowPowerConfiguration();

    InterruptIn sw1(PC_13);
    DigitalOut led(LED1);
    Serial pc(PC_10, PC_11);


    while(1) {
        
        led=1;        
        wait_ms(1000);
        WakeUp::set_ms(4000);
        led=0;       
        deepsleep();
    }
}

void LowPowerConfiguration(void)
{
RCC->AHBENR |= (RCC_AHBENR_GPIOAEN | RCC_AHBENR_GPIOBEN | RCC_AHBENR_GPIOCEN |
                    RCC_AHBENR_GPIODEN | RCC_AHBENR_GPIOHEN);
                    
         GPIO_InitTypeDef GPIO_InitStruct;
         // All other ports are analog input mode
         GPIO_InitStruct.Pin = GPIO_PIN_All;
         GPIO_InitStruct.Mode = GPIO_MODE_ANALOG;
         GPIO_InitStruct.Pull = GPIO_NOPULL;
         GPIO_InitStruct.Speed = GPIO_SPEED_LOW;
         HAL_GPIO_Init(GPIOA, &GPIO_InitStruct);
         HAL_GPIO_Init(GPIOB, &GPIO_InitStruct);
         HAL_GPIO_Init(GPIOC, &GPIO_InitStruct);
         HAL_GPIO_Init(GPIOD, &GPIO_InitStruct);
         HAL_GPIO_Init(GPIOE, &GPIO_InitStruct);
         HAL_GPIO_Init(GPIOH, &GPIO_InitStruct);
    
         RCC->AHBENR &= ~(RCC_AHBENR_GPIOAEN | RCC_AHBENR_GPIOBEN |RCC_AHBENR_GPIOCEN |
                    RCC_AHBENR_GPIODEN | RCC_AHBENR_GPIOHEN);
}

Hi Paul, maybe you can help me with an issue. I have a custom board based on NUCLEO-F446ZE with both crystals, where WakeUp library has no effect on deepsleep(). deepsleep() can only be awaken with an external interrupt if the file system_stm32f4xx.c is modified to :

lines 141...143

#define USE_PLL_HSE_EXTC (0) /* Use external clock */
#define USE_PLL_HSE_XTAL (1) /* Use external xtal */
#define DEBUG_MCO        (0) // Output the MCO1/MCO2 on PA8/PC9 for debugging (0=OFF, 1=ON)

Any ideas on how to make WakeUp library compatible with custom boards with external crystal? I tried your code, but in my case it did not make a difference.

posted by Guillermo García 23 Feb 2017

I would check with Erik, some of the ST MCU's have trouble waking up, it depends on the RTC configuration as this is used for the wakeup timer. I know it works well on the L476, I have several custom boards working correctly. Check and compare the RTC code with your MCU.

https://developer.mbed.org/users/Sissors/code/WakeUp/

posted by Paul Staron 23 Feb 2017