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.