8 years, 4 months ago.

How to wake up from standby mode in Nucleo L053R8?

I need to use the standby mode because in this way I can achieve the lowest power consumption of the board. This can be done by calling the function HAL_PWR_EnterSTANDBYMode().

I read that you can wake up from the standby mode with a RTC alarm:

(+) RTC auto-wakeup (AWU) from the Standby mode
        (++) To wake up from the Standby mode with an RTC alarm event, it is necessary to:
             (+++) Enable the RTC Alarm Interrupt using the RTC_ITConfig() function.
             (+++) Configure the RTC to generate the RTC alarm using the RTC_SetAlarm() 
                   and RTC_AlarmCmd() functions.

However, I couldn't find any of these function. Instead, I found these:

/* RTC Alarm functions ********************************************************/
HAL_StatusTypeDef HAL_RTC_SetAlarm(RTC_HandleTypeDef *hrtc, RTC_AlarmTypeDef *sAlarm, uint32_t Format);
HAL_StatusTypeDef HAL_RTC_SetAlarm_IT(RTC_HandleTypeDef *hrtc, RTC_AlarmTypeDef *sAlarm, uint32_t Format);
HAL_StatusTypeDef HAL_RTC_DeactivateAlarm(RTC_HandleTypeDef *hrtc, uint32_t Alarm);
HAL_StatusTypeDef HAL_RTC_GetAlarm(RTC_HandleTypeDef *hrtc, RTC_AlarmTypeDef *sAlarm, uint32_t Alarm, uint32_t Format);
void              HAL_RTC_AlarmIRQHandler(RTC_HandleTypeDef *hrtc);
HAL_StatusTypeDef HAL_RTC_PollForAlarmAEvent(RTC_HandleTypeDef *hrtc, uint32_t Timeout);
void              HAL_RTC_AlarmAEventCallback(RTC_HandleTypeDef *hrtc);

I tried to use the first one, but it didn't work. I don't know what I'm doing wrong. Here is my code:

#include "rtc_api.h"
#include "WakeUp.h"

void programAlarm(){
    /* (1) Write access for RTC registers */
    /* (2) Disable alarm A to modify it */
    /* (3) Wait until it is allow to modify alarm A value */
    /* (4) Modify alarm A mask to have an interrupt each 1Hz */
    /* (5) Enable alarm A and alarm A interrupt */
    /* (6) Disable write access */
    RTC->WPR = 0xCA; /* (1) */
    RTC->WPR = 0x53; /* (1) */
    RTC->CR &=~ RTC_CR_ALRAE; /* (2) */
    while((RTC->ISR & RTC_ISR_ALRAWF) != RTC_ISR_ALRAWF) /* (3) */
    {
    /* add time out here for a robust application */
    }
    RTC->ALRMAR = RTC_ALRMAR_MSK4 | RTC_ALRMAR_MSK3 | RTC_ALRMAR_MSK2 |
    RTC_ALRMAR_MSK1; /* (4) */
    RTC->CR = RTC_CR_ALRAIE | RTC_CR_ALRAE; /* (5) */
    RTC->WPR = 0xFE; /* (6) */
    RTC->WPR = 0x64; /* (6) */
}

void programAlarmA(uint32_t seconds){
    static RTC_HandleTypeDef RtcHandle;
    RtcHandle.Instance = RTC;
    
    RTC_AlarmTypeDef sAlarm;
    
    time_t time = rtc_read();
    time += seconds;
    struct tm *timeinfo = localtime(&time);
    
    /* Enable the Alarm A */
    sAlarm.AlarmTime.Hours = timeinfo->tm_hour;
    sAlarm.AlarmTime.Minutes = timeinfo->tm_min;
    sAlarm.AlarmTime.Seconds = timeinfo->tm_sec;
    sAlarm.AlarmTime.SubSeconds = 0;
    sAlarm.AlarmTime.TimeFormat = RTC_HOURFORMAT12_AM;
    sAlarm.AlarmTime.DayLightSaving = RTC_DAYLIGHTSAVING_NONE;
    sAlarm.AlarmTime.StoreOperation = RTC_STOREOPERATION_RESET;
    sAlarm.AlarmMask = RTC_ALARMMASK_NONE;
    sAlarm.AlarmSubSecondMask = RTC_ALARMSUBSECONDMASK_ALL;
    sAlarm.AlarmDateWeekDaySel = RTC_ALARMDATEWEEKDAYSEL_DATE;
    sAlarm.AlarmDateWeekDay = timeinfo->tm_mday;
    sAlarm.Alarm = RTC_ALARM_A;
    HAL_RTC_SetAlarm(&RtcHandle, &sAlarm, FORMAT_BIN);        
}

int main() {    
    //programAlarm();
    programAlarmA(5);
    //WakeUp::set(5);
    
    printf("Starting Standby mode...\r\n");
    HAL_PWR_EnterSTANDBYMode();
}

The first function I wrote is exactly the same that an example in the reference manual of the microcontroller, but it does not work either.

My last option was this library: https://developer.mbed.org/users/Sissors/code/WakeUp/ It works, but the problem is that it only works the first time. After that, the microcontroller is not entering in Standby mode.

Can anybody help me?

2 Answers

8 years, 4 months ago.

Hi,

In the case of use the function WakeUP only need add this line "PWR->CR |= PWR_CR_CWUF;" before you call the function "HAL_PWR_EnterSTANDBYMode();"

Accepted Answer

Thanks for your answer, it works.

However, there is another problem: After a reset, a protection is activated and you can't write the RTC registers, which means the Wakeup doesn't work. You can solve it by enabling the access with the DBP bit in the Power Control Register.

posted by Viviana Marcela Quirama Cañaveral 29 Aug 2016
8 years, 4 months ago.

From my experience with STM32 HAL (Haven't used RTC, though), the alarm calls for HAL_RTC_AlarmIRQHandler when triggered. That function should clear the interrupt flags and calls for HAL_RTC_AlarmXEventCallback, where X is the alarm channel (Your case, A).

HAL_RTC_AlarmAEventCallback is defined as weak in stm32xxxx_hal_rtc.c, which means you need to define it in your code. So, copy this into your code and implement the callback. That should help.

void HAL_RTC_AlarmAEventCallback(RTC_HandleTypeDef *hrtc)
{
 //Code to wake from low power state
}

Hello all, Have tried it with my L476RG nucleo with no luck... There should be an easy way of understand this :) As far I can understand there are alot of HAL options but do not know how to implement it properly as the documentation is not so clear to me. In my setup I had a cr2032 to keep the RTC working, does it is working based on LSI or LSE how to change it? The clock is working well and can change time with out no problem it also keep it while the usb is disconnected. But the alarm could not figured it out. When I check the HAL_RTCEx_GetWakeUpTimer(&RtcHandle) does it should be always the same number or it should decrements? Can someone explain me the steps? Thanks. All the best, Tim

posted by Timóteo Mendes 27 Jan 2019