Timer callbacks task

I use the vTaskSetThreadLocalStoragePointer() area to store information related to sending out messages to either a console port or a debug port. If a task tries to printf without these values having been set, the system crashes. I call these streams “SYSOUT” and “SYSERR” and they are directed to different UART ports.

I would like to be able to send out messages from Timer (expired) callback functions. Questions:

  1. I think the idle task is the one calling the timer (expired) callback function. Is this correct??
  2. if so, is there an easy/correct way to set the vTaskSetThreadLocalStoragePointer() values of the idle task? For example, can I obtain the TaskHandle_t for the idle task? Does the idle task have LocalStoragePonters?
  3. sending out a message involves entering the data into a queue. To prevent the idle task from stalling, my plan would be to drop the message if the queue was full.

Comments? Answers?

How is the thread local storage related to printing?

No, it is not correct. I recommend reading the software timers chapter in the freely available book, or perusing the software timers information on the FreeRTOS.org site.

Thank for replying, Richard. If the idle task does not call timer’s callback, then I assume the scheduler does.

The scheduler calls the timer task. This task then calls makes the call to the elapsed timer callbacks if needed.

Please do familiarise yourself with the extensive documentation as pointed out by Richard. It will save you a lot of time in the long run as it will avoid you making assumptions on how the RTOS operates.

1 Like

Sergent, thank you for the link to the TimerTask. Am I correct in thinking the TimerTask is not an “ordinary” task? For example, the docs say not to do anything that blocks, while ordinary tasks can be blocked.

So does the timer task run only one call back at a time? Or can one callback take control while another is running, via time slicing. The write up implies there is a single timer task, that implies to me that only one timer-expired callback run at a time.

The timer task in mostly a normal task, and as such it can only call one callback at a time, and can’t do anything until that callback returns, which is one reason the callbacks shouldn’t block, as that will delay all the other callbacks that might want to run in the mean time.

It is a bit special in that FreeRTOS as a number of API calls that work by sending messages to this task to make things happen.

richard, Thank you I am getting a clearer picture now. Since the timer task calls the expire callbacks, and the timer task is mostly an ordinary task, I assume that the timer task and therefore a callback can lose control to a non-timer task via time slicing.

Perhaps then using something like vTaskSuspendAll() would be a way to stop messages from various tasks from intermixing their text while adding bytes to an output queue. Is this call a low impact, non-blocking call to be sure only one task at a time is transfering a message to the output queue. (I never generate message from interrupt routines, so this seems better than taskENTER_CRITICAL() although the latter may be even faster.

Yes, the timer task can be time sliced out, or if a timer callback blocks (which you really want to avoid) another task can take control.

Timer callbacks really want to avoid blocking, and should be quick, to avoid interfering with each other. There also is (or at least used to be, haven’t checked recently) a corner case where if a call back blocked over the tick rollover you could hit an assert. This means that timer callbacks shouldn’t be sending data to queue that might be full or wait for things like a mutex. Typically I have the callbacks just send events or messages to tasks which do the real work. (Like sending a message that an operation has been going on too long and the task needs to abort the operation with a time out).

For sending streams of data to serial ports and the like, I tend to wrap all those streams with a mutex, so that an output can temporarily lock the stream to puts its message in, without interference from other tasks. Also, rather than using a queue, you can use a stream buffer which is more designed for that application (and thus more efficient), if multiple tasks might write to the stream buffer, you must use a mutex to guard is so only one accesses the buffer at at time, as it doesn’t support the multi-task contention that a Queue does.

The replies to all your questions were in short passages of text in the links I posted.