What will happen if the FreeRTOS timer task is blocked for 20 ms?

What will happen if the FreeRTOS timer task is blocked for 20 ms, with a timer tick period of 1 ms? Of course, it will not be able to call any other timer callbacks while it’s blocked and some timer callbacks might be called to late because of the blocking, but can anything serious go wrong inside the RTOS?

Because it’s just a task it can’t affect the scheduler or other tasks. You just might mess up your other timers. However, I’d try to avoid that.

1 Like

Will all other currently scheduled timers have their delay prolonged by 20 ms? I once looked at all the context switches on an oscilloscope and if I remember correctly the timer task was switched in and out at every timer tick.

I don’t think so. When the timer task is blocked it’s blocked and is not scheduled and doesn’t run.

1 Like

If it is being scheduled in and out at every timer tick, it is not blocked.

1 Like

No, when I looked at it on the oscilloscope, it was not blocked, it was used correctly. But I’m thinking that the “natural behavior” of the timer task is that it should get switched in and out at every timer tick and since I’m blocking it for 20 ms I’m messing something up (something doesn’t get incremented as it should or similar)?

One possible explanation is a 20ms CPU busy loop in one of your timers. That is not blocking in the sense FreeRTOS uses the term though.

No, I’m referring to the proper xTimers.

Sorry, your explanations are unclear. Can you share some code and point out your problem?

Several months ago I looked at all the context switches on an oscilloscope, just because I wanted to make sure that the task executions made sense. At the time, I did not experience any issues and all my timer callbacks were executing very little code (less that 1 ms). I seem to remember that I thought to myself “oh how strange, the timer task gets switched in and out at every timer tick”. I’m working from home today and don’t have access to the development board I used so I can’t verify whether I remember correctly or not.

Fast forward to today and I was informed of an issue in a completely different product. A function seems to block forever at a call to xEventGroupWaitBits every once in a while. However, we can see very clearly that an interrupt routine (not related to the timer task) calls xEventGroupSetBitsFromISR so it’s very mysterious that xEventGroupWaitBits keeps blocking. My colleague noticed that this issue would only occur when calling the particular function from the timer task so he moved the function call to a different task and he thought the problem was solved. However, this did not make any sense to me and I wanted to double-check that it’s not dangerous (although not recommended) to block the timer task for about 20 ms. The mysterious issue about xEventGroupWaitBits blocking forever occasionally even though xEventGroupSetBitsFromISR is called is something I will probably start a new thread about asking for debugging help.

When I had written my first post in this thread, I got curious, what if there was already an xTimer running before the 20 ms blocking happened, let’s say for 500 ms, will this now expire 520 ms later instead? I asked this follow-up question just out of curiosity, I think it’s interesting to try to understand how the RTOS works under the surface. Given my observation on the oscilloscope, it seems to me that the timer task needs to be switched in at every timer tick and if it’s blocked for 20 ms some count value might get messed up.

Not strange at all. The timer task works by keeping a list of all active timers along with their remaining timer ticks until expiration. It is woken at every timer tick, decrements the expiration times of every active timer and executes those timers whose expiration times have reached 0. I do not have the code in front of me, so I do not know if there is any “intelligent” logic involved that attempts to recover from starved timers (for exampke by not doing the decrement as “mechanical” as I sketched out but by keeping a list of future timestamps instead and matching the current timestamp against the expected future time stamp) which would allow some kind of recovery.

If any of your callbacks takes too long to allow one ore more executions of the above logic, the behavior is really hard to predict without looking at the source code. The advice is to avoid it or alternatively, create your own software timers independent of the FreeRTOS timer task.

1 Like

One thing to note is that xEventGroupSetBitsFromISR() - Set a bit (flag) or bits in an RTOS event group from an interrupt uses/needs the timer task. So I could imagine that one could be trapped by a deadlock when waiting for an event group bit in a timer callback (blocking in a timer callback is bad design anyway !) which is set by an ISR. But that’s just guessing because I didn’t use event groups in practice yet.

1 Like

But wouldn’t it always deadlock then? It works fine 99.99% of the time.

The Timer task doesn’t need to be woken up on every tick, as it checks when the next active timer will expire, and block on the timer command queue for the time for that to happen. If you have a timer with period 1, that will happen every tick.

Also, since the “PendFromISR” and EventGroupSetBitsFromISR use the timer task to operation, the timer task should be a relatively high priority task, so having a timer callback do a lot of work has the risk of causing issues with the programs meeting of deadlines.

I seem to remember, at least in the past, that there was a corner case where a long running or maybe it was a blocking timer callback could trigger an assert in some specific situation (maybe at timer counter rollover).

1 Like

The function that is called from the timer task contains very few instructions, most of the time it’s just blocked at xEventGroupWaitBits which means even low priority tasks are allowed to execute most of the time.

But, as was pointed out, if the EventGroup is signaled from an ISR, that won’t happen as that needs the timer task to process a request, which it can’t while blocked.

But it works 99.99% of the time.

Which means you are, at least not normally, signaling that event group from an ISR.

As I pointed out, at least with previous code, would need to dig in to see if it is still there, there was a corner case (maybe timer rollover) where a blocking callback would trigger an assert. The issue is that in that condition timer callbacks are called with the scheduler suspended, so they can not block.

With a 16-bit processor and 16-bit ticks that isn’t that uncommon of ann occurrence. With a 32-bit tick it will be rare.

No, it keep a list (actually 2) of the active timers with a time stamp of when they are to expire. (The second list is of timers that don’t expire until the tick counter wraps, so they are in the NEXT set of time stamps).