Response Time of xTaskResumeFromISR()

cstrahm wrote on Friday, May 08, 2009:

Perhaps I do not understand something about the way FreeRTOS works, but I am surprised about the time it takes the scheduler to respond to xTaskResumeFromISR().  I also tried using Semaphores, but result was the same.  I am running FreeRTOS-5.2 with PREEMPTION enabled, also configIDLE_SHOULD_YIELD, Mutex,Coroutines,Sem off.  MCU is ARM7 LPC2468 (72MHz).  My tick time is 10mSec.  The CPU spends 98% of time in the IDLE task.

I have 3 tasks besides IDLE, and two have prioity 1 and the other has priority 4.  There is a wrapped ISR.  The PRI-4 task waits suspended.  At the end of this ISR I call xTaskResumeFromISR() to release the PRI-4 task.  I expected that as soon as the ISR returns the scheduler would instantly do a switch to the PRI-4 task. It does the switch fine, but it appears to be taking a lot of time.

I placed uSec performance time markers at the end of the ISR and right after vTaskSuspend()in the PRI-4 task.  It appears that the scheduler is taking between 3-7 mSec to switch to the PRI-4 task.  This I do not understand.  I expected something on the order of 10’s or 100’s of uSec. 

I expected that the scheduler should leave the IDLE task immediately and jump into PRI-4.  But it seems like it is waiting until the end of the tick time slice before it switches.  That’s the only explanation I can see for the big delay.  Is this correct?

Regards,  Chris.

edwards3 wrote on Friday, May 08, 2009:

Can you post your ISR code? Which compiler are you using?

cstrahm wrote on Friday, May 08, 2009:

// FreeRTOS Wrapper for ISR
// -------------------------------------------------------
void __attribute__ ((naked)) vEMAC_ISR_Wrapper( void ) {   
    portSAVE_CONTEXT();    // Save the context of the current task.
    EthService();        // Actual ISR
    portRESTORE_CONTEXT();    // Restore the context of the current task -
}                                // which may be different to the task that was interrupted.

// ISR handler
void EthService(void) {
  unsigned long   IntFlags;
  unsigned long   currentRxProduceIndex;
  unsigned long   wakeTask;
  unsigned char   loop;
  VICVectAddr=0;    / Acknowledge Interrupt in VIC
  loop =0;

  if (wakeTask) {
} // EthService

richard_damon wrote on Saturday, May 09, 2009:

Note that when you call xTaskResumeFromISR(), the scheduler will start up what ever is now the highest priority ready task. Execution to the rest of the ISR will not happen until the task that was interrupted get scheduled to run again, which is why the xTaskResumeFromISR() is supposed to be the very last piece of your ISR,

davedoors wrote on Saturday, May 09, 2009:

You are never requesting a context switch, which is why the context switch does not happen until the next tick. You need to request a context switch before you leave EthService. As the code is you are just restoring the context of the task that was originally interrupted.

The syntax needed to ask for a context switch is dependent on the compiler you are using. Look at the "interrupt service routines" section of the html page that describes the port you are using. Also you can look at the examples in the download.

cstrahm wrote on Saturday, May 09, 2009:

Yes correct, I figured out what the problem was, I was not calling the portYIELD_FROM_ISR().  The tail end of the ISR should look like this:

if (wakeTask) {
    if(pdTRUE ==xTaskResumeFromISR(ethdev.hHttpTask))

Now the switch time to PRI-4 task is 18 uSec.  That’s what I expected.  I checked the Semaphore setup as well, and it performed virtually the same speed. 

Interestingly, turning ON both the StackChecking & Trace barely changed the switch context time.  Only went from 18 to 19 uSec. Not much of a penalty at all.

Everything looks good now.

Thanks, Chris.

rtel wrote on Saturday, May 09, 2009:

It is normally preferable to use a semaphore to unblock a task rather than using the suspend/resume mechanism.  This is because semaphores will effectively latch events that are occurring too quickly for them to be reacted too, whereas simply suspending and resuming a task can cause these events to be simply missed.