1

我正在使用 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);
    }
}

它会延迟,但永远不会出来。在同一个线程中使用邮箱和延迟是否有问题?我也尝试在它之前带来延迟for(;;)并且它有效。

编辑:我想我可以尝试为问题添加更多细节。第一个线程发送某种类型的邮件,然后等待另一种类型的邮件;我遇到问题的线程接收邮件进入第一种类型并根据它接收到的内容执行一些代码,然后将结果作为第二种类型的邮件发送;有时它必须使用 osDelay 等待它停止工作但没有进入任何故障处理程序

4

3 回答 3

1

我宁愿使用标准的 freeRTOS API。ARM CMSIS 包装器是垃圾。

顺便说一句,我相当怀疑osMailGet(commandMailHandle, osWaitForever);

在这种情况下,根本不需要延迟。如果等待数据处于 BLOCKED 状态,则任务不会消耗任何处理能力

如果另一个猜测是:

  1. 你降落在高频
  2. 你被堆叠在上下文切换中(错误的中断优先级)

使用您的调试器,看看发生了什么。

于 2019-05-04T18:51:35.707 回答
0

正如 P__J__ 在较早的答案中指出的那样,您不应osDelay()在循环1中使用调用, 因为您的任务循环将在osMailGet()调用时等待下一个请求/邮件,直到它到达为止。但是这个提示让我注意到您观察的另一个可能原因,所以我打开这个新答案:2

由于循环执行被 5000 个滴答声的延迟中断 - 是不是邮件的生产者填充邮箱的速度比任务消耗邮件的速度快?然后,您应该检查是否在生产者上下文中检测/处理了这种情况。

如果生产者忽略“队列已满”返回值并在邮件传输之前丢弃邮件,则系统将每 5000 个周期只处理几封邮件(或者在第一次填满邮箱后,系统可能会丢失除少数邮件之外的所有邮件,如果您示例中的生产者仅填充邮箱队列一次)。这看起来像是消费者任务被卡住了,即使主要问题是关于生产者上下文(任务/ISR)。


1如果请求邮件的生成速度快于任务处理它们的速度,则只有在您希望避免在 5000 个时钟周期内处理另一封邮件时 ,osDelay()调用才能为您提供帮助。但是,你会有一个不同的问题,你应该提出一个不同的问题......

2 编辑:我刚刚注意到克利福德已经在他对该问题的评论之一中提到了这个选项。我认为这个选项必须包含在答案中。

于 2020-04-12T22:30:48.953 回答
0

osStatus osDelay (uint32_t 毫秒)

毫秒值指定计时器滴答数。

确切的时间延迟取决于自上次计时器滴答以来经过的实际时间。

对于值 1,系统将等待直到下一个计时器滴答发生

=> 您必须检查计时器滴答是否正在运行。

检查这个链接

于 2019-05-08T12:40:13.977 回答