Hi
We've recently added FreeRTOS to the firmware of an existing product (primarily to pre-empt big chunks of 3rd-party code over which we have no control and execute them in a well-timed fashion). The goal is to achieve almost the same low-power properties as before adding FreeRTOS.
We're using the SDK 14.0.0 and SoftDevice S132 v5 (I know, old project).
The firmware is not really FreeRTOS-aware and communicates from the interrupts to the main context by setting flag variables.
In order to achieve the low power mode in FreeRTOS, we did
1 suspending (vTaskSuspend) the main task instead of calling
2 configUSE_TICKLESS_IDLE 1 and configUSE_IDLE_HOOK 0
3 defined configPOST_SLEEP_PROCESSING to be a function
if (NVIC->ISPR[0] | NVIC->ISPR[1] | NVIC->ISPR[2]) { vTaskResume(m_main_task_handle); }
This seems to work, the system remains responsive and the power consumption measurements are as low as we want them.
However, I was thinking about theoretical correctness of the code so that the system neither sleeps too little nor too much. This does not seem to be easy to achieve.
My thoughts are:
The first call to ssd_app_evt_wait after switching to the idle task from the main task always returns immediately because software interrupts are used in task switching and ssd_app_evt_wait does not sleep if an interrupt happend since it was last called.
Hence, if I remove the check for pended interrupts in the configPOST_SLEEP_PROCESSING handler, the system basically never sleeps.
Interrupts that happen during sleep are pended since the ssd_app_evt_wait inside port_cmsis_systick.c is called in a critical section and allows for subsequent inspection of the NVIC->ISPR register.
With this configuration, my code catches all the reasons to unsuspend the main task that happen during the second call to ssd_app_evt_wait. But if an interrupt happens before the first call to ssd_app_evt_wait, for example, we cannot know since it returns immediately and clears the event register.
In other words, the race condition that is not present in ssd_app_evt_wait (or in the sequence WFE, SEV, WFE) is present in my way of calling vTaskSuspend and vTaskResume. The system will not sleep too little, but it might sleep too much.
Is there some other condition that I can check and base resumption of the main task on?
Thanks