2
votes

I’m writing a low power application for the STM32F407VG. It goes into standby mode and can wake up in two ways:

  • Periodically, using the RTC wakeup timer;
  • By pressing a push-button connected to the PA0-WKUP pin.

Depending on whether the application was woken up by the RTC or the push-button, I need to perform two different tasks. Therefore, when the firmware resets after waking up from standby mode, I must figure out the wakeup reason (RTC or push-button).

I’ve made the necessary configurations to wake up from Standby mode from either source, and they’re working — the processor does wake up periodically, or when I hit the push-button. The issue is with figuring out the wakeup reason.

The documentation for the RTC_ISR register’s WUTF states the following:

Bit 10 WUTF: Wakeup timer flag

This flag is set by hardware when the wakeup auto-reload counter reaches 0.

This flag is cleared by software by writing 0.

This flag must be cleared by software at least 1.5 RTCCLK periods before WUTF is set to 1 again.

This seems perfect to me — if the flag is set, it must be because the wakeup timer reached 0 and woke up the processor.

I inserted some code at the beginning of my firmware to read WUTF and set an LED according to it, and then clear the flag immediately after that. Unfortunately, this flag is always set, not only when waking up from Standby mode due to the RTC, but also when waking up due to the push-button, and even when powering on the circuit for the first time.

I checked the errata sheet for this MCU and found no mention of this issue.

I do realize a workaround would be to read the status of the push-button, and if it corresponds to the pressed state, assume the wakeup reason is due to the push-button being pressed. However, my firmware runs for only a couple of microseconds in Run mode before going back into Standby mode, and due to bouncing issues with the push-button, this kind of detection is not reliable unless I stretch out the Run mode time to several microseconds. This in turn impacts the average power consumption of my application (and therefore battery life). While adding a capacitor might help, I’d like to implement a software-only solution if possible.

1
I'm sorry that I don't know this platform, but this is a fascinating question. Is your firmware entirely in control of the platform, or is there a runtime that might be getting in the way by treating a wakeup as more of a reset than you want?Steve Friedl
This is a bare-metal platform. While I am using FreeRTOS, it’s more of a library than an underlying platform. I don’t run any FreeRTOS code prior to querying the flag. In fact the only code that runs prior to the query is the reset handler, and I don’t think it could be responsible for this. I’ll try to add a breakpoint to the start of the reset handler to make sure the flag is checked before absolutely any code is run.swineone
Reading the STM docs, it seems clear this should work as you want it to, it wouldn't really make any sense otherwise. How often is the programmed wakeup?Steve Friedl
I’m using LSI for the clock source and ask for a wakeup every two seconds. In practice, because the LSI is very inaccurate, I measured the wakeup period at about 3.5 seconds.swineone

1 Answers

2
votes

It was entirely my bad. I was reading the flag through the following HAL macro:

 __HAL_RTC_WAKEUPTIMER_GET_FLAG(&hRTC, RTC_FLAG_WUTF);

It turns out I was using it before initializing hRTC.Instance, so rather than accessing the RTC's registers, it was just reading some random memory (probably address 0). After fixing it, the flag appears to work reliably.