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); }
I agree with you that in the case of 'infinite expected idle time', the RTC doesn't have to produce an interrupt to wake the system from low power mode. But that does not mean that you don't need an RTC to run while in low power mode at all. I can't tell from your post if you are implying that the RTC itself isn't needed, or only that the RTC interrupt isn't needed.
I think an RTC timer is needed regardless since it has to measure the passage of time from the osKernelSuspend call to the moment the interrupt (gpio, uart, etc) fired. How else can you compute a 'lost ticks' value to pass to osKernelResume?
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.