yielding from ISR questions

eyalasko1 wrote on Friday, March 08, 2019:

Hi,

I’ve seen some past questions about this issue but would like to further clarify it.

assume the following pseudo code:

void someHelperFuncCalledFromISR(void*arg)
{
    // do stuff

        BaseType_t xHigherPriorityTaskWoken = false;
        xSemaphoreGiveFromISR(GlobalMutexHandle, &xHigherPriorityTaskWoken);
        portYIELD_FROM_ISR( xHigherPriorityTaskWoken );  // <<==  Can this be called here or returned to calling ISR
}

void ISR_Handler(void)
{
        BaseType_t xHigherPriorityTaskWoken1 = false;
        xSemaphoreGiveFromISR(MutexHandle, &xHigherPriorityTaskWoken);
        portYIELD_FROM_ISR( xHigherPriorityTaskWoken );  //<<== Can this be called here or only before returning ?
        
          BaseType_t xHigherPriorityTaskWoken2 = false;
        xQueueSendFromISR(QueueHandle, data, &xHigherPriorityTaskWoken2);
        portYIELD_FROM_ISR( xHigherPriorityTaskWoken2 );  // <<== Does freeRTOS 'merge' this yield with previous yield or should the app take care (OR-ing?) of it?
}

Thanks

richarddamon wrote on Friday, March 08, 2019:

How portYIELD_FORM_ISR works is dependant on the port. On a lot (maybe all) of the ports that allow nesting of interrupt, the Yield is done by using an interrupt, which the portYIELD_FROM_ISR will trigger, but that trigger won’t happen until the ISR ends, so it doesn’t matter where the call actually is, so your example will be safe.

Other ports, some which don’t allow for nesting, the portYIELD_FROM_ISR actually calles the scheduler, and right at the point of the call you switch to the new task, and the rest of the ISR (like the final return from interrupt) doesn’t occur until the task that was running is switched back to. One example of this sort of machine (at least was when I last looked at them) was the Pic24 family. For those processors, the portYIELD_FROM_ISR needs to be the very last effective line of the ISR, so your example wouldn’t work.

My preference, unless I KNOW that the code will only be used on machines that it would work is to call the portYIELD_FROM_ISR only at the end of the ISR, which means that any helper functions that make FreeRTOS calls need to take a pointer to the waswoken flag, which has a side affect of making it clear which funtions are part of the isr and which can’t be.

eyalasko1 wrote on Friday, March 08, 2019:

Thanks.

The port is for Arm cortex M4F (Nordic nRF52) which has nested interrupt model.

What about calling _fromISR() api few times inside an ISR - Should the SAME wasWoken pointer be transferred as an argument , including ‘chaining’ this pointer to helper functions ?

Thanks again for your prompt reply.

richarddamon wrote on Friday, March 08, 2019:

Arm Corex M processors all use the pending interrupt method, so multiple calls are safe. In a technical sense it doesn’t matter if each call uses its own flag or they share. The system is designed to allow an ISR to use a single flag, with a call at the end, that that is probably incrementally more efficient (there will be just a single test of the flag and set the pend interrtupt in the function as opposed to multiple).

I personally still put the portYIELD_FROM_ISR at the end of the isr and use a single flag in the isr.

It does say that a helper function could be passed a pointer to the flag, or do it inside itself and have things work. My personal preferance is to pass the pointer, but having an extra portYIELD_FROM_ISR does work.