Difference between Suspend/Resume and Notification

Hi guys, I use FreeRTOS 9. I ask your help to understand a topic. I’ve an interrupt event (ISR) that resume a thread (with a priority above normal). The thread resumed, after doing its work, suspend itself (until the ISR resume it again.. and so on). The mechanism described above uses the vTaskSuspend and xTaskResumeFromISR() functions. What’s the difference if I use a Notification instead (the thread wait a flag given by the interrupt event and so on) ? Thank for your replies, F.B

Difference between Suspend/Resume and Notification

By using a notification, if the interrupt happens before the task suspends itself, the notification is remembered, so the task won’t stop. If that happens with suspend/resume then the resume gets ignored because the tasks isn’t suspended. Also, with notifications, you can put a timeout, so if the notification doesn’t arrive in a given time, the task resumes automatically, with a return code telling it of the timeout.

Difference between Suspend/Resume and Notification

First – what you are doing is dangerous – and that is noted in the documentation for the xTaskResumeFromISR() function API documentation. I think the xTaskResumeFromISR() API may have even been deprecated in later versions to try and stop people doing this. The problem with your technique is resuming a task is not a ‘latching’ operation – that is – there is no memory or history of it so resumes can be missed. Consider a scenario where: 1) An interrupt resumes a thread. 2) The thread starts running and executes part way through the code that needs to execute before is suspends itself again on the next iteration of its loop. 3) The interrupt executes again, and resumes the thread, but the thread was not suspended as it had not reached to call to vTaskSuspend() yet, so resuming the thread has no effect, and there is no memory of the interrupt ever calling xTaskResumeFromISR(). 4) The task continues executing and reaches the point where it suspends itself again – but it is already too late and the previous interrupt is missed. Now consider the same operation using a task notification, queue, semaphore, event group, message or stream buffer, etc. – all of which latch events…example using a task notification used as a counting semaphores: 1) An interrupt sends a notification to a task, incrementing the task’s notification value to 1. 2) The task unblocks due to the notification, decrements it notification count to 0 (that happens atomically inside the API function), and starts to execute but only gets part way through the code that needs to execute before it blocks on the notification again the next time through its loop. 3) The interrupt executes again, sends a notification to the task, incrementing the task’s notification count to 1 again even though the task was not blocked on the notification. 4) The interrupt executes again, sends a notification to the task again, incrementing the task’s notification count, this time to 2. Now the fact that two interrupts have occurred are latched in the notification count – effectively memorising that the events occurred. 5) The task continues executing and reaches the point where it blocks on the notification – but the notification count is already set to 2 so the task doesn’t block, but instead decrements the count to 1, and continues to execute the code. 6) The task continues executing and reaches the point where it blocks on the notification again – but the notification is still set to 1 so the task doesn’t block, but instead decrements the count to 0, and continues to execute. 7) The task continues executing and reaches the point where it blocks on the notification – this time the notification is 0 so the task blocks to wait for the next interrupt. In this case – no interrupts are lost.

Difference between Suspend/Resume and Notification

Dear Richard Barry and Richard Damon, Thanks for your helpful replies. I have better understood how the Resume and Suspend functions work. Now I’ve implemented the following meccanism with thread Task Notifications:
  • The thread waits a flag from interrupt handler (I use cmsis layer): ~~~ while( osSignalWait(THREADWAKEUP,osWaitForever).status != osErrorValue ) { // do something… } ~~~
  • The interrupt wake up the thread by sending the flag: if( idtask != NULL ) osSignalSet(idtask,THREAD_WAKE_UP);