The example for tickless idle documented here: https://www.keil.com/pack/doc/CMSIS/RTOS2/html/theory_of_operation.html#TickLess is missing an important check.
If RTX doesn't actually need to wake back up "after some time", osKernelSuspend returns osWaitForever (0xFFFFFFFF). In that case you should NOT use the RTC to wake the system up. Instead letting other interrupts do that job.
The documented example is for MSP32, which is not my platform, but for STM32L4 it looks something like this:
__NO_RETURN void osRtxIdleThread (void *argument) { (void)argument; uint32_t expectedIdleTime; uint32_t actualIdleTime = 0; for (;;) { expectedIdleTime = osKernelSuspend(); if (expectedIdleTime > 0) { // Enter the low power state actualIdleTime = 0; HAL_SuspendTick(); // If the kernel needs to wake up "after some time", use the RTC to do that if (expectedIdleTime != osWaitForever) { HAL_RTCEx_SetWakeUpTimer_IT(&rtcHandle, expectedIdleTime<<1, RTC_WAKEUPCLOCK_RTCCLK_DIV16); } HAL_PWREx_EnterSTOP2Mode(PWR_STOPENTRY_WFI); if (expectedIdleTime != osWaitForever) { actualIdleTime = HAL_RTCEx_GetWakeUpTimer(&rtcHandle)>>1; HAL_RTCEx_DeactivateWakeUpTimer(&rtcHandle); expectedIdleTime = actualIdleTime; } HAL_ResumeTick(); } // Adjust the kernel ticks with the amount of ticks slept osKernelResume (expectedIdleTime); } } void RTC_WKUP_IRQHandler(void) { HAL_RTCEx_WakeUpTimerIRQHandler(&rtcHandle); }
If you look at the code you can see the answer. I'm not saying you don't need the RTC at all. You just don't need to set its alarm when the expectedIdleTime is osWaitForever. When it's something else, you need to set the RTC alarm to expectedIdleTime.
Hmm, I still think there is a problem with the code as presented. If osKernelSuspend() does return osWaitForever, then that same value is passed back to osKernelResume(). Shouldn't the latter call be passed the actual idle time? Surely the intent is to inform the kernel of how many ticks were actually lost in the low power mode?
I am a bit confused by the variable naming too. Isn't expectedIdleTime an INPUT to the rtc plus low power logic, and then actualIdleTime is its OUTPUT? Wouldn't you then use actualIdleTime as is to pass back to osKernelResume? I'm not sure why you are assigning what I view as the output back to what I view as the input, in your assignment of line 23.