Embedded FreeRTOS卡在osDelay中
我正在使用STM32F446和STM32CubeMX创建的样板文件(用于外围设备初始化和中间件,如带有CMSIS-V1接口的FreeRTOS)进行一个项目。 我有两个线程使用邮箱进行通信,但我遇到了一个问题:其中一个线程体是Embedded FreeRTOS卡在osDelay中,embedded,stm32,freertos,rtos,cmsis,Embedded,Stm32,Freertos,Rtos,Cmsis,我正在使用STM32F446和STM32CubeMX创建的样板文件(用于外围设备初始化和中间件,如带有CMSIS-V1接口的FreeRTOS)进行一个项目。 我有两个线程使用邮箱进行通信,但我遇到了一个问题:其中一个线程体是 void StartDispatcherTask(void const * argument) { mailCommand *commandData = NULL; mailCommandResponse *commandResponse = NULL;
void StartDispatcherTask(void const * argument)
{
mailCommand *commandData = NULL;
mailCommandResponse *commandResponse = NULL;
osEvent event;
for(;;)
{
event = osMailGet(commandMailHandle, osWaitForever);
commandData = (mailCommand *)event.value.p;
// Here is the problem
osDelay(5000);
}
}
它到达了延迟点,但从未离开。在同一线程中使用邮箱和延迟是否有问题?我还尝试在(;;)的之前引入延迟,结果成功了
编辑:我想我可以尝试为这个问题添加更多细节。第一个线程发送某种类型的邮件,然后等待另一种类型的邮件;我遇到问题的线程接收第一种类型的邮件,根据接收的内容执行一些代码,然后将结果作为第二种类型的邮件发送;有时,它必须使用osDelay等待,然后停止工作,但不进入任何故障处理程序我宁愿使用标准的FreeRTOSAPI。手臂是垃圾
顺便说一句,我相当怀疑osMailGet(commandMailHandle,osWaitForever)代码>
在这种情况下,根本不需要延迟。如果在阻塞状态下等待数据,则任务不会消耗任何处理能力
如果另一种猜测是:
你正在高频着陆
您被堆叠在上下文开关中(错误的中断优先级)
使用调试器查看发生了什么。osStatus osDelay(uint32_t毫秒)
毫秒值指定计时器刻度的数量
确切的时间延迟取决于自上次计时器滴答声以来经过的实际时间
如果值为1,系统将等待下一个计时器滴答声出现
=>您必须检查计时器是否正在运行
检查此项正如p_uuj_uu在前面的回答中指出的,您不应该在循环1中使用osDelay()
调用
因为任务循环将在下一个请求/邮件的osMailGet()
调用处等待,直到它无论如何到达。
但是这个暗示让我注意到了你观察的另一个可能的原因,所以我打开这个新的答案:2
由于循环执行被5000个时钟的延迟中断,邮件的生产者填充邮箱的速度会比任务消耗邮件的速度快吗?然后,您应该检查是否在生产者上下文中检测/处理了这种情况
如果制作者忽略“队列已满”返回值,并在邮件发送之前丢弃邮件,则系统每5000次只处理几封邮件(或者,如果您示例中的制作者只填充邮箱队列一次,则在首次填充邮箱后,系统可能会丢失除几封邮件以外的所有邮件)。
这可能看起来像消费者任务被卡住了,即使主要问题是关于生产者上下文(任务/ISR)
一,
osDelay()
调用只有在请求邮件的生成速度快于任务处理速度的情况下,才能帮助您避免在5000个刻度内处理另一封邮件。
但是,你会有一个不同的问题,你应该打开一个不同的问题
二,
编辑:我刚刚注意到Clifford在对这个问题的评论中已经提到了这个选项。我认为这个选项必须包含在一个答案中。这句话的第一行是一个意见,最好作为评论发布,因为它不是答案的一部分。可能是“垃圾”导致了v2 API的出现,但freeRTOS并没有更好,主观上更糟(IMO)。@ArenaLor连接调试器,看看它在哪里卡住了。正如我所写的,可能是在上下文转换上。但是观点是不正确的,在答案中没有位置(就像观点在问题中没有位置一样)。人们可能需要使用它是有原因的(例如代码的可移植性),因此,除了不应该有基于意见的答案这一事实之外,对我来说,这不是完全的垃圾,因为我可以在不深入了解freeRTOS API和@Clifford所说的代码的可移植性的情况下启动一个项目(例如,我可以随时切换到Keil RTX)@ArenaLor:P_u_J_u______________________________________________________调度程序不会再猜测它。如果需要的话,您至少应该在输入延迟之前循环处理所有排队的消息。更可能的情况是延迟正在完成,它将进入osMailGet()
,在那里它将永远等待(或者至少直到某个消息或它发送出去)是的,我的意思是邮件被正确地获取,然后它到达延迟,但再也无法到达osMailGet。我的观点是,你是如何确定这一点的?你的代码在循环中没有任何外部可观察的,所以你必须使用调试器和断点来确定这一点-你没有提到。从外部看除了分配给commandData的小时间段外,始终显示为“已阻止”(并且对其不做任何处理).是的,我实际上是在使用Keil v5进行调试;我在osDelay
上设置了一个断点,然后它就到达了,但是如果我让它再次运行,我可以看到它被困在prvCheckTasksWaitingTermination
函数中“编辑”中描述的代码听起来不像是相同的代码。您是否验证了问题中显示的代码与“根据接收的内容执行某些代码”的代码的失败方式相同其中?SYSTICK是否正在运行?SYSTICK中断处理程序是否正在执行?问题中应出现关于prvCheckTasksWaitingTermination
的部分-这可能是相关的。在实时系统中,删除任务应被视为“不寻常的”-显示的代码未显示您可能正在执行的位置或原因