vTaskResume in an ISR

nobody wrote on Saturday, July 23, 2005:

I’m playing with the LPC2106 + GCC … it seems that vTaskResume has an issue (causes a pabort when it starts going through taskEXIT_CRITICAL()) when it’s executed from the ISR. I was just wondering if this is normal before I start poking the port files…I have a timerISR that should resume the suspended task… I guess I could use the vTaskDelay but the timer provides me with exact timing which is kind of important in this case… 

rtel wrote on Saturday, July 23, 2005:

vTaskResume() can cause portYIELD() to be called.  This will happen if the task being resumed has a priority higher than the calling task  or in your case if the task being resumed has a priority higher than the task that was interrupted.

Generally care must be taken using portYIELD() from within an ISR.  How it works is port dependent.  In general, it should only ever be used at the end of an ISR.

If your application needs to do this then I suggest creating a xTaskResumeFromISR() function.  This would return whether or not a context switch is required or not, rather than actually perform the context switch.  This would be easy to do  take a look at the function xTaskResume().  You will see the variable xYieldRequired  this should be returned and the call to portYIELD() removed.

This is then the equivalent to the xQueueSend() and xQueueSendFromISR() functions.  You cant take a look at these two functions to see what I mean, and take a look at the FreeRTOS\Demo\ARM7_LPC2106_GCC\serial\serialISR.c file to see how they are used.  In serialISR.c the function vUART_ISR() uses xQueueReceiveFromISR() and xQueueSendFromISR().  The idea is that rather than have these function perform a context switch (which you dont want from the middle of the ISR), they return whether or not a switch is required.  Then at the end of the ISR  when everything is cleaned up and the interrupt serviced and reset  you can perform the context switch if required by calling portEXIT_SWITCHING_ISR().  Note also that you require portENTER_SWITCHING_ISR() at the top of the ISR.

An exact timing can be created for a task using vTaskDelayUntil()  providing the tick frequency is an exact multiple of the period you require.