Waking from standby mode with RTC alarms
Posted: Sat Feb 12, 2022 1:46 am
I've been using standby mode for several years with some sub uA data loggers. The basic life cycle is
0. Wake from standby
1. Initialize the system
2. Determine wake up cause
3. Log some data
4. Go to standby
The data loggers have two wake up sources, an external sensor and an internal alarm. Recently I noticed some gaps in the data -- a few blocks out of thousands over many months. Fortunately, there's enough redundant information that no harm was done. Of course the first thing that comes to mind is a race condition -- the external sensor and the alarm are asynchronous to each other. In digging a bit, I have a clue as to what is going on. I had assumed that it was necessary to enable the alarm interrupts to wake from standby. The problem with this is that there is a window between waking from standby and initializing all the necessary interrupt configuration during which an alarm can be missed. It turns out that (as usual) standby is special :
Here are a couple of key bits of information from the stm32l432 reference manual (5.3.11)
"To wakeup from Standby mode, there is no need to configure the EXTI 18"
"To wakeup from Standby mode, there is no need to configure the EXTI Line 20."
So rather than doing what the hal RTC drivers do, which is initialize the alarm and the alarm interrupt
rtcp->rtc->CR |= RTC_CR_ALRAE;
rtcp->rtc->CR |= RTC_CR_ALRAIE;
the right course of action is just to initialize the alarm and not the interrupt:
rtcp->rtc->CR |= RTC_CR_ALRAE;
In my application, I poll the RTC isr register and it's relatively easy to clear only the bits that you "know" have been set. In this way no alarms will be missed.
It'd be nice if the hal didn't automatically enable interrupts when setting RTC alarms (and wakeup timer), but I can work around that by pulling the key bits directly into my application.
Standby mode is tricky and the documentation is literally scattered throughout the various STM reference documents.
0. Wake from standby
1. Initialize the system
2. Determine wake up cause
3. Log some data
4. Go to standby
The data loggers have two wake up sources, an external sensor and an internal alarm. Recently I noticed some gaps in the data -- a few blocks out of thousands over many months. Fortunately, there's enough redundant information that no harm was done. Of course the first thing that comes to mind is a race condition -- the external sensor and the alarm are asynchronous to each other. In digging a bit, I have a clue as to what is going on. I had assumed that it was necessary to enable the alarm interrupts to wake from standby. The problem with this is that there is a window between waking from standby and initializing all the necessary interrupt configuration during which an alarm can be missed. It turns out that (as usual) standby is special :
Here are a couple of key bits of information from the stm32l432 reference manual (5.3.11)
"To wakeup from Standby mode, there is no need to configure the EXTI 18"
"To wakeup from Standby mode, there is no need to configure the EXTI Line 20."
So rather than doing what the hal RTC drivers do, which is initialize the alarm and the alarm interrupt
rtcp->rtc->CR |= RTC_CR_ALRAE;
rtcp->rtc->CR |= RTC_CR_ALRAIE;
the right course of action is just to initialize the alarm and not the interrupt:
rtcp->rtc->CR |= RTC_CR_ALRAE;
In my application, I poll the RTC isr register and it's relatively easy to clear only the bits that you "know" have been set. In this way no alarms will be missed.
It'd be nice if the hal didn't automatically enable interrupts when setting RTC alarms (and wakeup timer), but I can work around that by pulling the key bits directly into my application.
Standby mode is tricky and the documentation is literally scattered throughout the various STM reference documents.