cancel
Showing results for 
Search instead for 
Did you mean: 

Inaccurate tick period when enabling USE_TICKLESS_IDLE

chirpy
Associate

Hello,

I am using STM32U575RGT6 with CubeMX 6.17 and the bundled X-CUBE-FREERTOS v1.4.0. After enabling USE_TICKLESS_IDLE, I observed that the tick period becomes inaccurate.

Specifically, the delay appears to be consistently shortened to about 0.875× of the expected value.

void StartDefaultTask(void const *argument) {
    while (1) {
        HAL_GPIO_TogglePin(LED_RED_GPIO_Port, LED_RED_Pin);
        vTaskDelay(400);
    }
}

With USE_TICKLESS_IDLE disabled, the delay is approximately 400 ms as expected.
ScreenImg.png

After enabling it, the delay is reduced to about 350 ms.

I have created a minimal project to reproduce the issue, and it shows the same behavior consistently. The project is attached.

Could anyone help explain the cause or suggest a fix?

Thank you.

1 ACCEPTED SOLUTION

Accepted Solutions
FBL
ST Employee

Hello  @chirpy 

Thank you for your feedback!

When configUSE_TICKLESS_IDLE = 1 with CubeMX:

FreeRTOS uses the standard vPortSuppressTicksAndSleep() in port.c. It:

  • Reprograms SysTick to cover several ticks at once.
  • Calls configPRE_SLEEP_PROCESSING() and then executes WFI.
  • After wakeup, computes how many ticks elapsed and calls vTaskStepTick(), then restores SysTick to 1‑tick.

So the tick timing is changed even if you never enter STOP. That explains your 350 ms vs 400 ms observation when only the built in tickless is enabled.

The code generated does not:

  • Select STOP modes, or
  • Configure wakeup sources RTC/LPTIM/EXTI, or
  • Save nd restore RCC PWR and voltage scaling after STOP...

Those are expected to be implemented by the application in: configPRE_SLEEP_PROCESSING and configPOST_SLEEP_PROCESSING. CubeMX only generates empty hooks.

I found this article useful. How to use STM32U5 with FreeRTOS™ in tickless mode. Enjoy reading.

To give better visibility on the answered topics, please click on Accept as Solution on the reply which solved your issue or answered your question.




Best regards,
FBL

View solution in original post

3 REPLIES 3
FBL
ST Employee

Hi @chirpy 

Your HAL timebase is using TIM7.

Low power hook macros configPRE_SLEEP_PROCESSING / configPOST_SLEEP_PROCESSING are defined, but your PreSleepProcessing() PostSleepProcessing() functions are empty, so they do not yet control the STOP mode entry/exit.

To check whether the issue is really inside the tickless logic itself and not related to STOP or clock reconfiguration, could you run these two simple tests:

  1. Test 1: Tickless enabled, and no low power / STOP

    • In FreeRTOSConfig.h: #define configUSE_TICKLESS_IDLE 1
    • In app_freertos.c:
      void PreSleepProcessing(uint32_t ulExpectedIdleTime)
      {
          (void)ulExpectedIdleTime; // do nothing, no STOP or clock change
      }
    • Measure osDelay 400 again.
    • If it is already around 350ms, the problem is in the tickless algorithm/compensation itself.
  2. Test 2 : Tickless enabled with STOP / low power

    • Implement your intended STOP or low power entry in PreSleepProcessing() and restore the clock configuration on wakeup
    • Measure osDelay 400 again.

If test 1 is correct and test 2 is wrong, the issue is linked to STOP/clock reconfiguration, not to the tickless logic.

To give better visibility on the answered topics, please click on Accept as Solution on the reply which solved your issue or answered your question.




Best regards,
FBL

Hi @FBL ,

Thank you for the detailed response and for breaking it down into two tests — it really helped me think through the problem more carefully.

I have to be upfront: I was initially under the impression that simply enabling USE_TICKLESS_IDLE in CubeMX with "Built-in Functionality" would handle everything automatically, including proper low-power entry. I've since realized (with some help from an AI assistant) that this is not quite the case.

From what I now understand:

- Test 1 is essentially my current state — the built-in tickless implementation only issues a WFI instruction, without actually entering STOP or switching clocks. This would explain why my power consumption barely improves with tickless enabled. Is my understanding correct that "Built-in Functionality Enabled" only provides the tick suppression framework, and that actually entering a low-power mode like STOP1 is left entirely to the user?

- For Test 2, my understanding is that I need to: switch to a clock source that remains active in STOP mode (e.g. LSI or LSE driving LPTIM), enter STOP in PreSleepProcessing(), and then restore the system clock in PostSleepProcessing() after wakeup. However, I'm honestly not very familiar with this area, and I'm worried about getting it wrong — for example, would the MCU just hang indefinitely if no wakeup source is configured before entering STOP? Could you point me to a reference example, or help me understand the minimal correct implementation for Test 2?

As an additional data point: I tried replacing the tick source with LPTIM driven by LSI, using jefftenney's LPTIM-Tick-U5 (https://github.com/jefftenney/LPTIM-Tick-U5). With this in place, the tick period is back to normal with no noticeable error, and power consumption drops noticeably as well. I've attached the working minimal project based on this approach.

Given these findings, I'd like to understand what exactly happens under the hood when USE_TICKLESS_IDLE is enabled with the built-in implementation, and what is expected from the user side to make it work properly.

Thanks again for your patience and guidance.

FBL
ST Employee

Hello  @chirpy 

Thank you for your feedback!

When configUSE_TICKLESS_IDLE = 1 with CubeMX:

FreeRTOS uses the standard vPortSuppressTicksAndSleep() in port.c. It:

  • Reprograms SysTick to cover several ticks at once.
  • Calls configPRE_SLEEP_PROCESSING() and then executes WFI.
  • After wakeup, computes how many ticks elapsed and calls vTaskStepTick(), then restores SysTick to 1‑tick.

So the tick timing is changed even if you never enter STOP. That explains your 350 ms vs 400 ms observation when only the built in tickless is enabled.

The code generated does not:

  • Select STOP modes, or
  • Configure wakeup sources RTC/LPTIM/EXTI, or
  • Save nd restore RCC PWR and voltage scaling after STOP...

Those are expected to be implemented by the application in: configPRE_SLEEP_PROCESSING and configPOST_SLEEP_PROCESSING. CubeMX only generates empty hooks.

I found this article useful. How to use STM32U5 with FreeRTOS™ in tickless mode. Enjoy reading.

To give better visibility on the answered topics, please click on Accept as Solution on the reply which solved your issue or answered your question.




Best regards,
FBL