Preemption of Idle Task Hook (vApplicationIdleHook())

Hello Community, I have a “what happens if…” type question related to using the Idle Task Hook (configUSEIDLEHOOK is set to 1 in FreeRTOSConfig.h). Background: The Idle Task runs at the lowest priority (tskIDLE_PRIORITY) and therefore only runs when there is no higher priority task(s) to run. Furthermore the hook, vApplicationIdleHook(), is called from the Idle Task so it, too, runs at the lowest priority. This means vApplicationIdleHook() can be preempted if a higher priority task becomes scheduled to run (becomes in the Ready state) during execution of vApplicationIdleHook(). Scenario: In my FreeRTOS v9.0.0 project I use vApplicationIdleHook() for periodic (say, once per minute) low prioirty application “maintenance” — say updating some runtime statistics/counters. Once vApplicationIdleHook() returns the application typically enters low-power tickless idle mode (portSUPPRESSTICKSAND_SLEEP()) shortly thereafter. However, *during* vApplicationIdleHook() an interrupt could occur, ultimately making a high priority task state become Ready. What happens if that interrupt were to occur? My understanding is that when the interrupt handler returns execution will jump immediately to the high priority task instead of returning to vApplicationIdleHook(). Let’s suppose the high priority task keeps busy for a long time… After a while the high priority task has nothing to do and becomes Blocked, and (I expect) vApplicationIdleHook() resumes from whereever it was at the time of the original interrupt…and as in the typical case, enters low-power tickless idle mode. Is my understanding correct? I am concerned of vApplicationIdleHook() being interrupted (as above) if it has something critical to do and which is expected to complete, like write application data to non-volatile FLASH memory (which would be bad if interrupted). What is the right way to ensure code executing at even lowest prioity (like vApplicationIdleTask()) will complete without context switch until the critical code has finished? Is the solution just to wrap the critical bit of vApplicationIdleHook() around taskENTERCRITICAL() and taskEXITCRITICAL()? Lastly, its mentioned here that vApplicationIdleHook() mustn’t call any API function that can block. Presumably this includes xSemaphoreTake(…, (TickTypet) portMAXDELAY) and xQueueSendToBack(…, …, ( TickTypet ) portMAXDELAY). So, how does one add to task queues (if occasionally needed) without these blocking API calls? Is it better (or best) practice to avoid inserting anything to task queues from vApplicationIdleHook()? (After all, the application is supposed to be idle?!) Thanks for reading this far — hope I explained clearly 🙂 Best, Bryce

Preemption of Idle Task Hook (vApplicationIdleHook())

Sounds mostly correct. The interrupt wll go into the interrupt handler, which might wake up a higher priority task. A critical section should normally be very short, as it disables interrupts, so a flash memory write may not take longer than you want for this. (but if writing to the flash shouldn’t be interrupted, it might be the rigth thing to do). Another alternative is to suspend the scheduler, which will still allow interrupt to occur, but not let it activate the higher priority task until the action is done. A third option would be that it sounds like this small section really should be considered a high priority operation, so perhaps the idle task could at that point signal a higher priority task to do the flash write. This would allow you to set its priority to allow perhaps a few very high prioity operations to interrupt you, but not lower (but still above idle) operations. An alternative here would be to have the IdleHook function raise the task priority for that section and then lower it again when done.

Preemption of Idle Task Hook (vApplicationIdleHook())

Thanks, Richard! That’s a quick response 🙂 I think I can try easily the first and second options and see how it goes…and if needed move to the third option…it seems more complicate; is it more “correct” way of doing things? I had edited my original post before noticing your reply…I added this paragraph at the end: Lastly, its mentioned here that vApplicationIdleHook() mustn’t call any API function that can block. Presumably this includes xSemaphoreTake(…, (TickTypet) portMAXDELAY) and xQueueSendToBack(…, …, ( TickTypet ) portMAXDELAY). So, how does one add to task queues (if occasionally needed) without these blocking API calls? Is it better (or best) practice to avoid inserting anything to task queues from vApplicationIdleHook()? (After all, the application is supposed to be idle?!) Could you comment on this aspect? Thanks much 🙂

Preemption of Idle Task Hook (vApplicationIdleHook())

You can send to a queue, you just can’t block, so the block time must be set to 0.

Preemption of Idle Task Hook (vApplicationIdleHook())

https://www.youtube.com/watch?v=mtjcoL-sGEM&t=82s

Preemption of Idle Task Hook (vApplicationIdleHook())

Thanks for confirming!

Preemption of Idle Task Hook (vApplicationIdleHook())

Excellent — thanks! Wow — released just a few hours ago! Great to see new content on YouTube covering RTOS! 🙂