2025-04-10 7:03 PM
Took me a little while to work this one out so though i'd share.
My goal was to use the RTC wake up interrupt as the time source to periodically flash a LED.
STM32CubeMx Configuration:
To configure the RTC, I used the code from the cube L0 firmware example RTC_ExitStandbyWithWakeUpTimer for STM32L073RZ_NUCLEO to get started. The RTC configuration:
LL_RTC_DisableWriteProtection(RTC);
LL_RTC_WAKEUP_Disable(RTC);
while(LL_RTC_IsActiveFlag_WUTW(RTC)==0) {}
LL_RTC_WAKEUP_SetAutoReload(RTC,200); //RTC_WUTR_WUT value can be written only when WUTWF is set to 1 in RTC_ISR
LL_RTC_WAKEUP_SetClock(RTC, LL_RTC_WAKEUPCLOCK_DIV_16); //RTC_CR_WUCKSEL reg is write-protected. Bit can be written only when RTC_CR WUTE bit = 0 and RTC_ISR WUTWF bit = 1
LL_RTC_WAKEUP_Enable(RTC); //WUTE flag = Wakeup Timer Enable. WUTE Bit is write protected.
LL_RTC_ClearFlag_WUT(RTC);
LL_RTC_EnableIT_WUT(RTC); //RTC_CR_WUTIE Bit is write-protected.
LL_RTC_EnableWriteProtection(RTC);
uint32_t getClock,getAutoReload,getIsEnabledIT_WUT,getRTC_WAKEUP_IsEnabled;
getClock=LL_RTC_WAKEUP_GetClock(RTC);
getAutoReload=LL_RTC_WAKEUP_GetAutoReload(RTC);
getIsEnabledIT_WUT=LL_RTC_IsEnabledIT_WUT(RTC);
getRTC_WAKEUP_IsEnabled=LL_RTC_WAKEUP_IsEnabled(RTC);
What I noticed was the interrupt never fired.
uint32_t myRTC_IRQHandler;
void RTC_IRQHandler(void)
{
/* USER CODE BEGIN RTC_IRQn 0 */
myRTC_IRQHandler++;
LL_RTC_ClearFlag_WUT(RTC);
MyCallback();
/* USER CODE END RTC_IRQn 0 */
/* USER CODE BEGIN RTC_IRQn 1 */
/* USER CODE END RTC_IRQn 1 */
}
There is a subtle difference in waking up from stop mode compared to standby mode. The reference manual page 159:
To wake up from the Stop mode with an RTC Wakeup event, it is necessary to:
a) Configure the EXTI Line 20 to be sensitive to rising edges (Interrupt or Event
modes)
b) Enable the RTC Wakeup Interrupt in the RTC_CR register
c) Configure the RTC to generate the RTC Wakeup event
To wake up from the Standby mode with an RTC Wakeup event, it is necessary to:
a) Enable the RTC Wakeup Interrupt in the RTC_CR register
b) Configure the RTC to generate the RTC Wakeup event
After adding the following code, the interrupt then triggered once.
LL_EXTI_InitTypeDef eitd;
//configure the EXTI
eitd.Line_0_31 = LL_EXTI_LINE_20;
eitd.LineCommand = ENABLE;
eitd.Mode = LL_EXTI_MODE_IT;
eitd.Trigger = LL_EXTI_TRIGGER_RISING;
LL_EXTI_Init(&eitd);
LL_EXTI_ClearFlag_0_31(LL_EXTI_LINE_20);
LL_EXTI_EnableIT_0_31(LL_EXTI_LINE_20);
Since the wake up interrupt has an auto reload, to re-arm the interrupt the following was added to the ISR.
uint32t myRTC_IRQHandler,myEXTI20ActiveFlag;
void RTC_IRQHandler(void)
{
/* USER CODE BEGIN RTC_IRQn 0 */
myRTC_IRQHandler++;
if(LL_EXTI_IsActiveFlag_0_31(LL_EXTI_LINE_20))
{
myEXTI20ActiveFlag++;
}
LL_EXTI_ClearFlag_0_31(LL_EXTI_LINE_20);
LL_RTC_ClearFlag_WUT(RTC);
LL_EXTI_EnableIT_0_31(LL_EXTI_LINE_20);
MyCallback();
/* USER CODE END RTC_IRQn 0 */
/* USER CODE BEGIN RTC_IRQn 1 */
/* USER CODE END RTC_IRQn 1 */
}
2025-04-10 9:13 PM
Looking through the HAL libraries, this configures the EXTI interrupt for you in
file - stm32l0xx_hal_rtc_ex.c
function - HAL_RTCEx_SetWakeUpTimer_IT
/* Enable and configure the EXTI line associated to the RTC Wakeup Timer interrupt */
__HAL_RTC_WAKEUPTIMER_EXTI_ENABLE_IT();
__HAL_RTC_WAKEUPTIMER_EXTI_ENABLE_RISING_EDGE();