为什么 FreeRTOS 软件计时器回调不能使用阻塞 API

Why can't FreeRTOS software timer callback use blocking API

引用文档(强调他们的)

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.

FreeRTOS参考书说的比较详细,又没有解释清楚

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.

我的问题是:为什么会出现这样的问题?我在定时器回调中等待一个由中断设置的信号量,到目前为止它运行良好。 (它用于使用 USB 批量端点发送长数据包。)

唯一的问题可能会延迟其他等待计时器吗?

声明:

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

是关键。如果您的回调阻塞,那么您正在阻塞定时器服务任务,如果允许它发生会延迟其他定时器操作,并且 RTOS 调度保证无法实现。

定时器服务任务将在一个循环中对所有在该滴答中已过期的定时器执行定时器操作。如果您的计时器回调要执行延迟或阻塞操作,这将延迟所有尚未调用但已安排在同一滴答中的计时器操作,并且如果它们在服务任务被阻塞时到期,则会延迟后续滴答中的所有操作。

如果要执行的操作需要阻塞(甚至只需要花费大量时间),正确的操作是让您的回调 signal 执行一个独立的任务那个行动。定时器回调应该像中断服务例程一样对待 - 运行 尽可能快速和确定地完成,而不会阻塞。事实上,一些 RTOS 实际上在中断上下文中调用定时器回调,而不是在任何情况下调用特殊的服务任务,因此无论您使用什么 RTOS,它都是一个很好的指南。