Skip to main content
Graduate II
July 25, 2025
Question

STM32L433 - RTC alarm whilst also using a periodic wake

  • July 25, 2025
  • 5 replies
  • 1064 views

I am trying to get the RTC alarm working whilst also using a periodic wake, I can get each working independently but not both together.

If I DON'T shutdown for RTC wakeup, the RTC alarm DOES work.

If I DO shutdown for RTC wakeup, the RTC alarm DOES NOT work.

To summarize:

  • I am trying to use RTC Alarm for a shutdown in 1 minute
  • But I've also configured an RTC Wakeup Timer to wake every 5 seconds
  • After shutdown, RTC Wakeup Timer works — but RTC Alarm doesn't
  • When I re-call MX_RTC_Init(), the Alarm is lost

Below is the function I call to shutdown the mcu for 5 seconds, before waking up again...

void shutdownRun (void){
	/* The Following Wakeup sequence is highly recommended prior to each Standby mode entry
	 mainly when using more than one wakeup source this is to not miss any wakeup event.
	 - Disable all used wakeup sources,
	 - Clear all related wakeup flags,
	 - Re-enable all used wakeup sources,
	 - Enter the shutdown mode.
	 */

	// Save pressure before shutdwon
	HAL_RTCEx_BKUPWrite(&hrtc, RTC_BKP_DR0, *(uint32_t*)&pressure_bak);

	/* Disable all used wakeup sources*/
	HAL_RTCEx_DeactivateWakeUpTimer(&hrtc);
	HAL_RTCEx_SetWakeUpTimer_IT(&hrtc, 5, RTC_WAKEUPCLOCK_CK_SPRE_16BITS);

	/* Clear all related wakeup flags */
	__HAL_PWR_CLEAR_FLAG(PWR_FLAG_WU);

	ampPowerDown();

	/* Enter the shutdown mode */
	HAL_PWREx_EnterSHUTDOWNMode();
}

 

Below is the RTC initialization (note I have commented where hours/minutes/seconds is set to zero, otherwise it would be reset each time the RTC wakes the mcu and would never trigger the alarm)...

 

static void MX_RTC_Init(void)
{

 /* USER CODE BEGIN RTC_Init 0 */

 /* USER CODE END RTC_Init 0 */

 RTC_TimeTypeDef sTime = {0};
 RTC_DateTypeDef sDate = {0};
 RTC_AlarmTypeDef sAlarm = {0};

 /* USER CODE BEGIN RTC_Init 1 */

 /* USER CODE END RTC_Init 1 */

 /** Initialize RTC Only
 */
 hrtc.Instance = RTC;
 hrtc.Init.HourFormat = RTC_HOURFORMAT_24;
 hrtc.Init.AsynchPrediv = 127;
 hrtc.Init.SynchPrediv = 255;
 hrtc.Init.OutPut = RTC_OUTPUT_DISABLE;
 hrtc.Init.OutPutRemap = RTC_OUTPUT_REMAP_NONE;
 hrtc.Init.OutPutPolarity = RTC_OUTPUT_POLARITY_HIGH;
 hrtc.Init.OutPutType = RTC_OUTPUT_TYPE_OPENDRAIN;
 if (HAL_RTC_Init(&hrtc) != HAL_OK)
 {
 Error_Handler();
 }

 /* USER CODE BEGIN Check_RTC_BKUP */

 /* USER CODE END Check_RTC_BKUP */

 /** Initialize RTC and set the Time and Date
 */
 // sTime.Hours = 0x0;
 // sTime.Minutes = 0x0;
 // sTime.Seconds = 0x0;
 sTime.DayLightSaving = RTC_DAYLIGHTSAVING_NONE;
 sTime.StoreOperation = RTC_STOREOPERATION_RESET;
 if (HAL_RTC_SetTime(&hrtc, &sTime, RTC_FORMAT_BCD) != HAL_OK)
 {
 Error_Handler();
 }
 sDate.WeekDay = RTC_WEEKDAY_MONDAY;
 sDate.Month = RTC_MONTH_JANUARY;
 sDate.Date = 0x1;
 sDate.Year = 0x0;

 if (HAL_RTC_SetDate(&hrtc, &sDate, RTC_FORMAT_BCD) != HAL_OK)
 {
 Error_Handler();
 }

 /** Enable the Alarm A
 */
 sAlarm.AlarmTime.Hours = 0x0;
 sAlarm.AlarmTime.Minutes = 0x1;
 sAlarm.AlarmTime.Seconds = 0x0;
 sAlarm.AlarmTime.SubSeconds = 0x0;
 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 = 0x1;
 sAlarm.Alarm = RTC_ALARM_A;
 if (HAL_RTC_SetAlarm_IT(&hrtc, &sAlarm, RTC_FORMAT_BCD) != HAL_OK)
 {
 Error_Handler();
 }
 /* USER CODE BEGIN RTC_Init 2 */

 /* USER CODE END RTC_Init 2 */

}

 Below is my alarm interrupt, which is only triggered if I never call the 'shutdownRun' function ...

void HAL_RTC_AlarmAEventCallback(RTC_HandleTypeDef *hrtc) {
	shutdownFull();
}

 

    This topic has been closed for replies.

    5 replies

    Super User
    July 25, 2025

    Don't shut down within the RTC interrupt. It will not pre-empt itself.

    Instead, set a flag within the interrupt and shut down within the main thread itself.

    freeflyerAuthor
    Graduate II
    July 25, 2025

    I changed the interrupt and main as you suggested but its still not working.

    Interrupt is now....

    void HAL_RTC_AlarmAEventCallback(RTC_HandleTypeDef *hrtc) {
    	flgReqShudownFull = 1;
    }

    And main is now...

    	while (1) {
    		if (flgReqShudownFull){
    			shutdownFull();
    		}
    }

     

    Going into shutdown and using the RTC to wake after 5 seconds prevents the alarm interrupt from working, but I cant find the issue 

    If I dont go into shutdown and wake every 5 seconds, the alarm interrupt works.

     

    Super User
    July 25, 2025

    Can you show the full code? Doesn't seem to be any issues with the code you've presented.

    freeflyerAuthor
    Graduate II
    July 27, 2025

    Is the problem caused because sAlarm.AlarmTime.Seconds is reset when shutdown ? 

    For test purposes, I am using the following settings:

    • RTC Wakeup Timer set to 5 seconds
    • RTC Alarm set to 30 seconds

    The MCU runs for 10 seconds, then shuts down for 5 seconds using the functions:

    • HAL_RTCEx_SetWakeUpTimer_IT(&hrtc, 5, RTC_WAKEUPCLOCK_CK_SPRE_16BITS);
    • HAL_PWREx_EnterSHUTDOWNMode)

    When the MCU wakes, sAlarm.AlarmTime.Seconds is zero, so I have to set it back to 0x30 (should it be 0x30 or decimal 30, I'm not sure because its BCD ?).

    The diagram below explains what I think might be happening, it should fully shut down and not wake again when the alarm is reached (30 seconds).  But maybe it doesn't because sAlarm.AlarmTime.Seconds is reset when shutdown. ?

     

    Picture 1.jpg

     

     

    The application is battery powered and once manually switched on, it is supposed to read a pressure sensor every few minutes then shutdown between each measurement.

    After 12 hours of being switched on, it is supposed to permanently shutdown and not wake again until switched manually on again.

    I am using shorter times for test purposed, the 5 second shutdown and wake for 10 seconds works.

    But the permanent shutdown (set by sAlarm.AlarmTime) is not working.

    I have either implemted this wrong or it is not possible ?

     

    Super User
    July 27, 2025

    I suspect it's because, on startup, you're initializing RTC regardless of its current state. You should check to see if it's already initialized and, if so, don't touch it.

    Implement code in the first user block within MX_RTC_Init that checks to see if it's initialized already.

    freeflyerAuthor
    Graduate II
    July 28, 2025

    I only initialize the RTC once, because I check if the MCU was woken by the RTC as follows...

    	if (__HAL_PWR_GET_FLAG(PWR_FLAG_SB)) {
    		// Woke from standby
    		__HAL_PWR_CLEAR_FLAG(PWR_FLAG_SB);
    	}
    	else
    	{
    		 MX_RTC_Init();
    	}

     

    I set a breakpoint on the line MX_RTC_Init() and the breakpoint is only hit on the first startup.  When the RTC wakes the MCU, the breakpoint is not hit.

    The diagram below shows the behavior I expect...

    Picture1.jpg

    The diagram below shows what is actually happening, with the following observations made...

    • shutdownRun called at 25 seconds, but it does not shutdown and continues running
    • shutdownFull is not called at 30 seconds (sAlarm.AlarmTime.Seconds was set to 0x30)
    • sAlarm.AlarmTime.Seconds is reset when woken by the RTC
      • is this not to be expected as when the MCU is shutdown all variables are lost, so how is this supposed to be handled ?

    Picture2.jpg

    The diagram below shows the alarm works if I don't shutdown with RTC wake...

    Picture3.jpg

     

    Below is the main code...

     

    int main(void)
    {
    
     /* USER CODE BEGIN 1 */
    
     /* USER CODE END 1 */
    
     /* MCU Configuration--------------------------------------------------------*/
    
     /* Reset of all peripherals, Initializes the Flash interface and the Systick. */
     HAL_Init();
    
     /* USER CODE BEGIN Init */
    
     /* USER CODE END Init */
    
     /* Configure the system clock */
     SystemClock_Config();
    
     /* USER CODE BEGIN SysInit */
    
     /* USER CODE END SysInit */
    
     /* Initialize all configured peripherals */
     MX_GPIO_Init();
     MX_DMA_Init();
     MX_DAC1_Init();
     MX_TIM6_Init();
     MX_SPI2_Init();
     MX_LPUART1_UART_Init();
     MX_SPI1_Init();
     MX_I2C1_Init();
     MX_USART3_UART_Init();
     MX_ADC1_Init();
     MX_TIM7_Init();
     /* USER CODE BEGIN 2 */
    
     /* USER CODE END 2 */
    
     /* Infinite loop */
     /* USER CODE BEGIN WHILE */
    
    	if (__HAL_PWR_GET_FLAG(PWR_FLAG_SB)) {
    		// Woke from shutdown
    		__HAL_PWR_CLEAR_FLAG(PWR_FLAG_SB);
    	}
    	else
    	{
    		 MX_RTC_Init();
    	}
    
    
    	Enable_PC13_EXTI();	// enable power switch wake up
    	HAL_RTCEx_SetWakeUpTimer_IT(&hrtc, 5, RTC_WAKEUPCLOCK_CK_SPRE_16BITS); // enable RTC wake up
    
    	while (1) {
    		HAL_Delay(10000);
    		shutdownRun();
    		
    		if (flgReqShudownFull){
    			shutdownFull();
    		}
     /* USER CODE END WHILE */
    
     /* USER CODE BEGIN 3 */
    
    	}
     /* USER CODE END 3 */
    }

     

    Below is the RTC init function (only called once)...

    static void MX_RTC_Init(void)
    {
    
     /* USER CODE BEGIN RTC_Init 0 */
    
     /* USER CODE END RTC_Init 0 */
    
    
     /* USER CODE BEGIN RTC_Init 1 */
    
     /* USER CODE END RTC_Init 1 */
    
     /** Initialize RTC Only
     */
     hrtc.Instance = RTC;
     hrtc.Init.HourFormat = RTC_HOURFORMAT_24;
     hrtc.Init.AsynchPrediv = 127;
     hrtc.Init.SynchPrediv = 255;
     hrtc.Init.OutPut = RTC_OUTPUT_DISABLE;
     hrtc.Init.OutPutRemap = RTC_OUTPUT_REMAP_NONE;
     hrtc.Init.OutPutPolarity = RTC_OUTPUT_POLARITY_HIGH;
     hrtc.Init.OutPutType = RTC_OUTPUT_TYPE_OPENDRAIN;
     if (HAL_RTC_Init(&hrtc) != HAL_OK)
     {
     Error_Handler();
     }
    
     /* USER CODE BEGIN Check_RTC_BKUP */
    
     /* USER CODE END Check_RTC_BKUP */
    
     /** Initialize RTC and set the Time and Date
     */
     sTime.Hours = 0x0;
     sTime.Minutes = 0x0;
     sTime.Seconds = 0x0;
     sTime.DayLightSaving = RTC_DAYLIGHTSAVING_NONE;
     sTime.StoreOperation = RTC_STOREOPERATION_RESET;
     if (HAL_RTC_SetTime(&hrtc, &sTime, RTC_FORMAT_BCD) != HAL_OK)
     {
     Error_Handler();
     }
     sDate.WeekDay = RTC_WEEKDAY_MONDAY;
     sDate.Month = RTC_MONTH_JANUARY;
     sDate.Date = 0x1;
     sDate.Year = 0x0;
    
     if (HAL_RTC_SetDate(&hrtc, &sDate, RTC_FORMAT_BCD) != HAL_OK)
     {
     Error_Handler();
     }
    
     /** Enable the Alarm A
     */
     sAlarm.AlarmTime.Hours = 0x0;
     sAlarm.AlarmTime.Minutes = 0x0;
     sAlarm.AlarmTime.Seconds = 0x30;
     sAlarm.AlarmTime.SubSeconds = 0x0;
     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 = 0x1;
     sAlarm.Alarm = RTC_ALARM_A;
     if (HAL_RTC_SetAlarm(&hrtc, &sAlarm, RTC_FORMAT_BCD) != HAL_OK)
     {
     Error_Handler();
     }
     /* USER CODE BEGIN RTC_Init 2 */
    
     /* USER CODE END RTC_Init 2 */
    
    }

     

    Below is the shutdownRun function...

    void shutdownRun (void){
    	/* Disable all used wakeup sources*/
    	HAL_RTCEx_DeactivateWakeUpTimer(&hrtc);
    	HAL_RTCEx_SetWakeUpTimer_IT(&hrtc, 5, RTC_WAKEUPCLOCK_CK_SPRE_16BITS);
    
    	/* Clear all related wakeup flags */
    	__HAL_PWR_CLEAR_FLAG(PWR_FLAG_WU);
    
    	/* Enter the shutdown mode */
    	HAL_PWREx_EnterSHUTDOWNMode();
    }

     

    Below is the shutdownFull function...

     

    void shutdownFull (void){
    	HAL_RTCEx_DeactivateWakeUpTimer(&hrtc); // disable RTC wakeup
    	Enable_PC13_Wakeup();
    	HAL_PWREx_EnterSHUTDOWNMode();
    }

     

    Below is the RTC alarm interrupt, I set a breakpoint here but it never hits...

    void HAL_RTC_AlarmAEventCallback(RTC_HandleTypeDef *hrtc) {
    	flgReqShudownFull = 1;
    }

     

    freeflyerAuthor
    Graduate II
    July 28, 2025

    I am going around in circles with this issue, so I had to resort to ChatGPT.

    If ChatGPT is correct, then it is not possible to implement the functionality I require and I need to use a different approach.

    ChatGPT said...

    Summary of Key Concepts

     
    Wake SourceEXTI Line Wake from ShutdownWake from Standby Notes
    RTC Wakeup TimerEXTI Line 22YesYes16-bit counter, limited max duration
    RTC Alarm AEXTI Line 17YesYesOne-shot alarm, precise
     

    The problem is you cannot use both at the same time for wakeup from Shutdown or Standby without reconfiguring the EXTI line.


    Why Your Alarm Doesn’t Work After Wakeup Timer

    When you set HAL_RTCEx_SetWakeUpTimer_IT, it configures EXTI line 22.

    Then, if you later configure HAL_RTC_SetAlarm_IT, it sets EXTI line 17.
    But the STM32 only supports one EXTI wakeup at a time in Shutdown.
    So the last one you configure takes precedence, and the other is ignored.

     

    The suggested fix is

    1. On Initial Power-Up:

    • Read current RTC time

    • Store the UNIX timestamp or RTC_TimeTypeDef + RTC_DateTypeDef in RTC_BKP_DRx0

    RTC_TimeTypeDef time;
    RTC_DateTypeDef date;
    HAL_RTC_GetTime(&hrtc, &time, RTC_FORMAT_BIN);
    HAL_RTC_GetDate(&hrtc, &date, RTC_FORMAT_BIN);
    
    uint32_t startSeconds = RTC_to_unix(&time, &date);
    HAL_RTCEx_BKUPWrite(&hrtc, RTC_BKP_DR1, (startSeconds >> 16) & 0xFFFF);
    HAL_RTCEx_BKUPWrite(&hrtc, RTC_BKP_DR2, startSeconds & 0xFFFF);

    On Every Wake-Up (or after active mode exits):

    • Read current time and compute elapsed seconds:

    HAL_RTC_GetTime(&hrtc, &time, RTC_FORMAT_BIN);
    HAL_RTC_GetDate(&hrtc, &date, RTC_FORMAT_BIN);
    uint32_t currentSeconds = RTC_to_unix(&time, &date);
    
    uint32_t startHigh = HAL_RTCEx_BKUPRead(&hrtc, RTC_BKP_DR1);
    uint32_t startLow = HAL_RTCEx_BKUPRead(&hrtc, RTC_BKP_DR2);
    uint32_t startSeconds = (startHigh << 16) | startLow;
    
    if ((currentSeconds - startSeconds) >= (14UL * 60 * 60)) {
     HAL_RTCEx_DeactivateWakeUpTimer(&hrtc);
     HAL_PWREx_EnterSHUTDOWNMode();
    }

     

    Graduate
    July 29, 2025

    Hey there! Can you send your HAL_RTC_MspInit ? Just want to check you have NVIC  lines properly enabled. Just to calm you down, the setup you intend is perfectly doable irl, i have multiple projects where i used that rtc management. 

    Also beforehand for acquiring good practises i recommend you always clear flags before setting interrupts, example:

    HAL_NVIC_DisableIRQ(RTC_WKUP_IRQn);
    
    HAL_RTCEx_DeactivateWakeUpTimer(&hrtc);
    
    __HAL_RTC_WAKEUPTIMER_CLEAR_FLAG(hrtc, RTC_FLAG_WUTF);
    
    NVIC_ClearPendingIRQ(RTC_WKUP_IRQn);
    
    HAL_NVIC_EnableIRQ(RTC_WKUP_IRQn);
    
    HAL_RTCEx_SetWakeUpTimer_IT(&hrtc, 599, RTC_WAKEUPCLOCK_CK_SPRE_16BITS, 0);


    Although from your graphic i guess the first wakeup from wakuptimer is happening, isn't it? Make sure the wakup flag is getting cleared properly, usually generated automatically in stm32xx_it.c file. Can you sum up the current issue in 3 lines max clearly please? 

    freeflyerAuthor
    Graduate II
    July 30, 2025

    Thanks Martí

    I gave up and used the method ChatGPT suggested.

    Its not as accurate, but I dont need it to be that accurate as its only to shutdown the device after a long period (e.g. 12 hours) to preserve battery power.

    Its working in debug and run mode, but not after a cold restart (power loss then reconnected)

    I have just written this post, it includes the code and a flow chart diagram to explain how it works...

    https://community.st.com/t5/stm32-mcus-products/shutdown-and-wake-rtc-wkup-work-in-debug-run-but-not-in/m-p/827185#M283558