Embedded FreeRTOS卡在osDelay中

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;

我正在使用STM32F446和STM32CubeMX创建的样板文件(用于外围设备初始化和中间件,如带有CMSIS-V1接口的FreeRTOS)进行一个项目。 我有两个线程使用邮箱进行通信,但我遇到了一个问题:其中一个线程体是

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
    的部分-这可能是相关的。在实时系统中,删除任务应被视为“不寻常的”-显示的代码未显示您可能正在执行的位置或原因