2

In order to make a function I am writing able to be used both inside and outside ISRs, is it safe to just use the ISR-safe version of the FreeRTOS API calls?

// NOT ISR-safe
uint32_t messages_waiting(void)
{
    return uxQueueMessagesWaiting(queue);
}

// ISR-safe
// - maybe just use this function ALL THE TIME??--both inside and outside ISRs?
uint32_t messages_waiting(void)
{
    return uxQueueMessagesWaitingFromISR(queue);
}

FreeRTOS API reference: https://www.freertos.org/a00018.html#ucQueueMessagesWaitingFromISR

Here are the FreeRTOS implementations for each of these functions, from queue.c:

UBaseType_t uxQueueMessagesWaiting( const QueueHandle_t xQueue )
{
UBaseType_t uxReturn;

    configASSERT( xQueue );

    taskENTER_CRITICAL();
    {
        uxReturn = ( ( Queue_t * ) xQueue )->uxMessagesWaiting;
    }
    taskEXIT_CRITICAL();

    return uxReturn;
} /*lint !e818 Pointer cannot be declared const as xQueue is a typedef not pointer. */

UBaseType_t uxQueueMessagesWaitingFromISR( const QueueHandle_t xQueue )
{
UBaseType_t uxReturn;

    configASSERT( xQueue );

    uxReturn = ( ( Queue_t * ) xQueue )->uxMessagesWaiting;

    return uxReturn;
} /*lint !e818 Pointer cannot be declared const as xQueue is a typedef not pointer. */

Follow-up: I can see that the non-ISR-safe version adds access guards:

taskENTER_CRITICAL();
taskEXIT_CRITICAL();

Maybe I could add the ISR-safe versions of these too, as follows? Now, can this function be used both inside and outside ISRs?

uint32_t messages_waiting(void)
{
    UBaseType_t saved_interrupt_status = taskENTER_CRITICAL_FROM_ISR();
    uint32_t num_msgs_waiting = uxQueueMessagesWaitingFromISR(queue);
    taskEXIT_CRITICAL_FROM_ISR(saved_interrupt_status);

    return num_msgs_waiting;
}

Reference & example usage of taskENTER_CRITICAL_FROM_ISR(): https://www.freertos.org/taskENTER_CRITICAL_FROM_ISR_taskEXIT_CRITICAL_FROM_ISR.html

Gabriel Staples
  • 36,492
  • 15
  • 194
  • 265

1 Answers1

3

In this specific context, technically it is safe to use the fromISR variant of the function. I wouldn't recommend it though, as this may change any time and detecting this error after you decide to upgrade FreeRTOS to newer version will be a pain.

The reason they provide separate non-ISR and from-ISR variants of the functions operating on queues/mutexes/semaphores is to provide consistent API, even for cases when technically the functions do exactly the same thing as in this case. This is done to allow your application to continue to work throughout FreeRTOS upgrades, even though the underlying implementation may change drastically. As long as you use the API properly, it should contiue to function as before.

PS. As a sidenote for everyone else reading this post - it is generally very much NOT safe to mix non-ISR and from-ISR variants of the functions. For example, most non-ISR functions perform critical sections enter/exit and - depending on circumstances - task preemption, while the from-ISR variants do not. If you mix those two, you're asking for trouble.

J_S
  • 2,985
  • 3
  • 15
  • 38