引用文档(强调他们的)
计时器回调函数在定时服务任务的上下文中执行。因此,计时器回调函数必须永远不要尝试阻止。例如,计时器回调函数不得调用 vTaskDelay()、vTaskDelayUntil(),或者在访问队列或信号量时指定非零块时间。
FreeRTOS 参考书详细阐述了更多内容,但没有明确的解释
调用诸如 xQueueReceive() 之类的函数是可以的,但是 仅当设置了函数的 xTicksToWait 参数(指定函数的块时间)时 到 0。调用诸如 vTaskDelay() 之类的函数是不行的,因为调用 vTaskDelay() 将始终 将调用任务置于"已阻止"状态。
我的问题是:为什么会出现这样的问题?我正在等待一个信号量,它由计时器回调中的中断设置,到目前为止它工作正常。(它用于使用 USB 批量终结点发送长数据包。
唯一的问题可能会延迟其他等待计时器吗?
语句:
计时器回调函数在定时服务任务的上下文中执行。
是关键。 如果回调阻塞,则表示您正在阻止定时服务任务,如果允许它发生,则会延迟其他定时器操作,并且无法实现 RTOS 调度保证。
定时服务任务将对循环中在该时钟周期中已过期的所有计时器执行计时器操作。 如果计时器回调要执行延迟或阻止操作,则会延迟所有尚未调用但为同一时钟周期安排的计时器操作,并且如果后续时钟周期中的所有操作在服务任务被阻止时到期,则会延迟这些操作。
如果要执行的操作需要阻塞(甚至只需要大量时间),正确的操作是让回调发出独立任务的信号来执行该操作。 计时器回调应被视为中断服务例程 - 尽可能快速、确定地运行完成,而不会阻塞。事实上,一些RTOS实际上在中断上下文中调用计时器回调,而不是在任何情况下的特殊服务任务,因此无论您使用什么RTOS,这都是一个很好的指南。