Problems Resuming a Task from an ISR

simpsonseric wrote on Saturday, September 06, 2008:

I’m currently using FreeRTOS on Atmel’s AVR32 UC3 Serieas and am trying to resume a task from an ISR. Here is my ISR:

__attribute__ ((naked))
static void dataready_int_handler(void)
   portBASE_TYPE xYieldRequired = pdFALSE;

   //Tell the processing task to start
   xYieldRequired = xTaskResumeFromISR( xQuantumHandle );


This code gets to the switch context once, and then on every subsequent call of xTaskResumeFromISR, it says no context switch is necessary because prvIsTaskSuspended says xQuantumHandle is not suspended (but I’m quite sure it’s not running, and there is always one item in the xSuspendedTaskList).

The suspicious code is in prvIsTaskSuspended:

      /* Is the task we are attempting to resume actually in the
      suspended list? */
      if( listIS_CONTAINED_WITHIN( &xSuspendedTaskList, &( pxTCB->xGenericListItem ) ) != pdFALSE )
         /* Has the task already been resumed from within an ISR? */
         if( listIS_CONTAINED_WITHIN( &xPendingReadyList, &( pxTCB->xEventListItem ) ) != pdTRUE )

It gets past the first check that the task is in the suspended list, but after this pxTCB changes to 0x00. Any thoughts on what might cause this or something I could be doing wrong?


davedoors wrote on Saturday, September 06, 2008:

First thing is, is it valid to call ENTER_CRITICAL() EXIT_CRITICAL() in an interrupt on an AVR32. I don’t know anything about the port so maybe it is but this would not be normal for most port.

Second, if you are using the task suspension mechanism to control an event handler task by unsuspending the task in the interrupt then having the task suspend itself, I would recommend switching to use a semaphore instead. The task suspension mechanism will not work because interrupt occurring before the task has suspended itself will simply be lost because the interrupt is trying to unsuspend a task that is not yet suspended. When the task next suspends itself it will not be unsuspended until the following interrupt. 

From the documentation "vTaskResumeFromISR() should not be used to synchronise a task with an interrupt if there is a chance that the interrupt could arrive prior to the task being suspended - as this can lead to interrupts being missed. Use of a semaphore as a synchronisation mechanism would avoid this eventuality."

Look at the example on this page instead You might even want to use a counting semaphore depending on the characteristics of you application.

simpsonseric wrote on Monday, September 08, 2008:

You’re right, I don’t know that it is valid to call ENTER_CRITICAL() EXIT_CRITICAL() in an interrupt, but on second thought  other interrupts are automatically masked anyways in an ISR here.

I was thinking about using a semaphore, but I was concerned that it would be much slower. This application has a periodic interrupt to tell it to read data from another chip. The window to read data is very small (and missing a read occasionally is tolerable) so I thought this may be a bit faster. Other than missing some interrupts, is there any fundamental reason that this mechanism doesn’t work?