More ...FromISR() and portYIELD_FROM_ISR() confusion

The API documentation for xQueueSendFromISR() says, “From FreeRTOS V7.3.0 pxHigherPriorityTaskWoken is an optional parameter and can be set to NULL.”

That’s all well and good but what then should be passed to the (required) portYIELD_FROM_ISR()?

Thanks,
Dave

If you need to know if a higher priority task was woken then don’t pass pxHigherPriorityTaskWoken as NULL. You could opt to pass it as NULL if you are always going to take the same action regardless. For example, if you were always going to force a yield anyway.

So a portYIELD_FROM_ISR( pdTRUE ) at the end of the ISR will always have the scheduler check for (and handle) a higher-priority task being awakened by the xQueueSendFromISR( …, …, NULL ), right?

Not quite, it will make the current running task yield, and then select the highest priority task. That might be itself, but if a task of the same priority is ready, then because it yielded an moved to the back of the line, the other task will be switched to. If you used the wasWoken flag, that case would not have had that switch.

Here is a short example:

void HAL_ETH_RxCpltCallback( ETH_HandleTypeDef * xEMACTaskHandle )
{
    BaseType_t xHigherPriorityTaskWoken = pdFALSE;
    xTaskNotifyFromISR( xEMACTaskHandle,
                        EMAC_IF_RX_EVENT,
                        eSetBits,
                        &( xHigherPriorityTaskWoken ) );
    portYIELD_FROM_ISR( xHigherPriorityTaskWoken );
}

I could leave out the variable xHigherPriorityTaskWoken, and call portYIELD_FROM_ISR( pdTRUE ). But that would be less efficient, you could see a unnecessary yield.

If I put portYIELD_FROM_ISR( pdFALSE ), no yield will be done, and it might take a while before the waiting task will be woken up.

Thanks for the clarification. This topic has (and apparently, continues to be) a sticking point for not just me.

So at the end of the day it’s actually not an option to pass NULL to …FromISR(), not really, if one expects “normal” scheduling behavior.

I’d be nice if the API documentation actually explained things properly and completely.

Depends on the “normal” you are expecting. Probably the biggest case you would use that option would be in a program using cooperative multi-tasking to simplify the details of variable sharing, as you don’t need to worry about pre-emptive switches. Such a program doesn’t need to have the wasWoken flag, as you don’t intend to use interrupt pre-emption.

1 Like

And just to add, this is exactly what I am using the NULL option for in the moment. If you have preemption disabled, using portYIELD_FROM_ISR is most of the time NOT what you want to do, because it DOES actually lead to preemption even if it is disabled in the FreeRTOS config.
The other way around you can also use it to get preemption in case of specific interrupts, even though you don’t want to have preemption due to timer ticks.