Why can't FreeRTOS software timer callback use blocking API
Asked Answered
B

1

6

Quoting the documentation (emphasis theirs)

Timer callback functions execute in the context of the timer service task. It is therefore essential that timer callback functions never attempt to block. For example, a timer callback function must not call vTaskDelay(), vTaskDelayUntil(), or specify a non zero block time when accessing a queue or a semaphore.

The FreeRTOS reference book elaborates a little more, abut again without a clear explanation

It is ok to call functions such as xQueueReceive(), but only if the function’s xTicksToWait parameter (which specifies the function’s block time) is set to 0. It is not ok to call functions such as vTaskDelay(), as calling vTaskDelay() will always place the calling task into the Blocked state.

My question is: why is this such a problem? I'm waiting for a semaphore, that's set by an interrupt, in the timer callback, and it has worked fine so far. (It's used for sending long packets using a USB bulk endpoint.)

Is the only issue possibly delaying other waiting timers?

Bacteriostasis answered 3/2, 2018 at 7:56 Comment(2)
I think that the sentence: "Timer callback functions execute in the context of the timer service task." is the clue. If you will block on a timer callback execution the time restrictions for other callbacks could not be fulfilled as all callbacks are invoked within same thread.Shadowgraph
@K.Koovalsky : I appreciate that you may not have been using SO for long, but you should avoid answering questions in the comments section. Post an answer.Woodworker
W
9

The statement:

Timer callback functions execute in the context of the timer service task.

is the key. If your callback, blocks, you are blocking the timer service task, which if it were allowed to happen would delay other timer actions, and the RTOS scheduling guarantees could not be fulfilled.

The timer service task will perform the timer actions for all timers that have expired in that tick in a loop. If your timer callback were to perform a delay or blocking action, that would delay all timer actions not yet invoked but which were scheduled for the same tick, and would delay all actions in subsequent ticks if they came due while the service task were blocked.

If the action to be performed requires blocking (or even just takes a significant amount of time), the correct action would be to have your callback signal an independent task to perform the action. Timer callbacks should be treated like interrupt service routines - run to completion as quickly and as deterministically as possible, without blocking. In fact some RTOS actually invoke timer callbacks in the interrupt context rather then a special service task in any case, so it is a good guide to follow regardless of what RTOS you are using.

Woodworker answered 3/2, 2018 at 14:59 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.