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?
答案 0 :(得分:3)
声明:
定时器回调函数在定时器服务任务的上下文中执行。
是关键。如果您的回调,阻止,您正在阻止计时器服务任务,如果允许这样做会延迟其他计时器操作,并且无法完成RTOS计划保证。
计时器服务任务将对循环中该刻度中已过期的所有计时器执行计时器操作。如果您的计时器回调是执行延迟或阻止操作,那将延迟尚未调用但计划在同一时间点的所有计时器操作,并且如果在服务任务被阻止时它们到期,则会延迟后续滴答中的所有操作。
如果要执行的操作需要阻止(或者甚至只需要花费大量时间),那么正确的操作就是让您的回调信号成为执行操作的独立任务。定时器回调应该像中断服务程序一样对待 - 尽可能快速且尽可能确定地运行到完成,而不会阻塞。事实上,有些RTOS实际上会在中断上下文中调用定时器回调,而不是在任何情况下调用特殊服务任务,因此无论您使用什么RTOS,它都是一个很好的指南。