Skip to main content
Associate III
April 24, 2026
Question

STM32U545 Low-Power Mode with FreeRTOS

  • April 24, 2026
  • 1 reply
  • 85 views

Hello, I am currently using the NUCLEO-U545RE-Q and trying to set low-power modes with FreeRTOS. I have already seen videos from official ST channel and read documentation but I cannot get to set this functioning when using FreeRTOS and RTC. My goal is to blink an LED every 5 seconds and in the reamaining time go to STOP mode for low power consumption. This are my functions:

void StartDefaultTask(void *argument)
{
 /* USER CODE BEGIN defaultTask */
 /* Infinite loop */
 while(1)
 {
	 osSemaphoreAcquire(BinarySemaphoreHandle, osWaitForever);
	 printf("Toggle Led\n");
	 BSP_LED_Toggle(LED_GREEN);
 }
 /* USER CODE END defaultTask */
}

/* Private application code --------------------------------------------------*/
/* USER CODE BEGIN Application */

void HAL_RTCEx_WakeUpTimerEventCallback(RTC_HandleTypeDef *hrtc)
{
	printf("RTC Callback\n");
	osSemaphoreRelease(BinarySemaphoreHandle);
}

void PreSleepProcessing(uint32_t ulExpectedIdleTime)
{
	HAL_SuspendTick();

	/* Start low power timer */
	if (HAL_RTCEx_SetWakeUpTimer_IT(&hrtc, 2000, RTC_WAKEUPCLOCK_RTCCLK_DIV16, 0) != HAL_OK)
	{
		Error_Handler();
	}

	/* Enter STOP2 */
	HAL_PWREx_EnterSTOP2Mode(PWR_STOPENTRY_WFI);
}

void PostSleepProcessing(uint32_t ulExpectedIdleTime)
{
	HAL_RTCEx_DeactivateWakeUpTimer(&hrtc);
	SystemClock_Config();
	/* Resume HAL timebase */
	HAL_ResumeTick();
}

When I add the code inside PreSleep and PostSleep the LED simply does not blink. From printing debug, the application is always going to PreSleep and PostSleep non-stop and the RTC callback does not get fired. Can someone help me with this?

Best regards.

1 reply

ST Employee
April 27, 2026

Hello @JPortilha ,

I think the key issue is that PostSleepProcessing() can run after any wakeup, not only after the RTC wakeup you intended.

In the FreeRTOS tickless flow, the sequence is roughly:

  1. The system goes idle.
  2. PreSleepProcessing() runs and arms the wake source.
  3. The MCU enters STOP mode.
  4. Any enabled interrupt can wake the core.
  5. PostSleepProcessing() runs.

So, if there is another interrupt source waking the MCU before the RTC expires, PostSleepProcessing() will still run, and if you call HAL_RTCEx_DeactivateWakeUpTimer() there, you may be disabling the RTC wakeup before it ever gets a chance to fire and release the semaphore. That would match what you are seeing: the code keeps cycling through pre-sleep and post-sleep, but the RTC callback never executes.

I would suggest checking two things:

  • Make sure there is no other periodic wakeup source active.
  • Do not deactivate the RTC wakeup timer unconditionally in PostSleepProcessing().That function is too early to assume the RTC was the wake source. A safer pattern is to leave PostSleepProcessing() only for clock restoration and tick resume, and stop/deactivate the RTC wakeup timer only from the RTC wakeup path itself.

Please let me know how it works out for you, 

Kind regards,

DHIF Khaled 

"Please mark my answer as best by clicking on the “Accept as solution"" button if it fully answered your question. This will help other users find this solution faster.​"
JPortilhaAuthor
Associate III
April 27, 2026

Hello, I have changed the code a little bit. I now have this:

/* USER CODE BEGIN PREPOSTSLEEP */
void PreSleepProcessing(uint32_t ulExpectedIdleTime)
{
/* place for user code */
	HAL_PWREx_EnableUltraLowPowerMode();
	HAL_SuspendTick();
/* Start RTC */
 if (HAL_RTCEx_SetWakeUpTimer_IT(&hrtc, 20000, RTC_WAKEUPCLOCK_RTCCLK_DIV16, 0) != HAL_OK)
 {
	 Error_Handler();
 }
 /* Enter Stop2 mode, wake up on interrupt */
 HAL_PWREx_EnterSTOP2Mode(PWR_STOPENTRY_WFI);
}

void PostSleepProcessing(uint32_t ulExpectedIdleTime)
{
/* place for user code */
	/* Restore Clock settings */
	SystemClock_Config();
	/* Resume HAL timebase */
	HAL_ResumeTick();
}

void StartDefaultTask(void *argument)
{
 /* USER CODE BEGIN defaultTask */
 /* Infinite loop */
	for(;;osSemaphoreAcquire(appBinarySemHandle, osWaitForever))
	//while(1)
	{
		HAL_GPIO_TogglePin(GPIOA, GPIO_PIN_5);
	}
 /* USER CODE END defaultTask */
}

/* Private application code --------------------------------------------------*/
/* USER CODE BEGIN Application */
void HAL_RTCEx_WakeUpTimerEventCallback(RTC_HandleTypeDef *hrtc)
{
	osSemaphoreRelease(appBinarySemHandle);
}

Seems to be working, but my current consumption is around 30uA, when the datasheet says it should be around 3 or 4uA. Do you know what can be causing such high consumption?

BR.