【问题标题】:Problem with Array of Queues in FreeRTOSFreeRTOS 中的队列数组问题
【发布时间】:2011-07-27 15:28:09
【问题描述】:

我正在构建一个 FreeRTOS 应用程序。我创建了一个模块,它从另一个模块注册一个 freeRTOS 队列句柄,当这个模块模块发生中断时,它会向所有注册的队列发送一条消息。但似乎我能够从队列中发送消息,但无法在另一个模块中接收它。

这是我的代码。

远程模块:-

  CanRxMsg RxMessage;
  can_rx0_queue = xQueueCreate( 10, sizeof(CanRxMsg) ); // can_rx0_queue is globally defined 
  // Register my queue with can module
  if (registerRxQueueWithCAN(can_rx0_queue) == -1)
  {
    TurnLedRed();
  }  

  while(1)
  {
        if(can_rx0_queue){
      while( xQueueReceive( can_rx0_queue, ( void * ) &RxMessage, portMAX_DELAY))
      {
}
.....

这里是注册模块

#define MAX_NUMBER_OF_RX_QUEUES 2

//xQueueHandle rxQueueStore[MAX_NUMBER_OF_RX_QUEUES];

typedef struct QUEUE_REGISTRY_ITEM
{
//  signed char *pcQueueName;
  xQueueHandle xHandle;
} xQueueRegistryItem;

xQueueRegistryItem rxQueueStore[MAX_NUMBER_OF_RX_QUEUES];

int numberOfQueuesRegistered;

#define cError -1

#define cSuccess 0

void processInterrupt()
{
 for(int i=0; i < numberOfQueuesRegistered; i++)
  {
    if(xQueueSendFromISR(rxQueueStore[i].xHandle,(void *) &RxMessage,&tmp) != pdTRUE)
        TurnLedRed();
    if(tmp)resched_needed = pdTRUE;
  }

  portEND_SWITCHING_ISR(resched_needed);
}

int registerRxQueueWithCAN(xQueueHandle myQueue)
{
  if(numberOfQueuesRegistered == MAX_NUMBER_OF_RX_QUEUES)
  {
    // Over Flow of registerations
    TurnLedRed();
    return cError; 
  }else 
  {
    rxQueueStore[numberOfQueuesRegistered].xHandle = myQueue;
    numberOfQueuesRegistered++;
  }
  return cSuccess;
}

几点:-

  1. xQuehandle 的类型定义为“void *”
  2. 如果删除注册的东西,如果我通过外部获取指针,则代码可以直接使用 xQueueSendFromISR 中的队列指针。

需要任何建议或信息吗?

【问题讨论】:

  • 我在您提供的代码示例中没有发现任何问题。您确定队列创建良好,您的代码进入中断例程并且操作系统运行良好(没有堆栈溢出或类似地址错误)?

标签: c embedded queue rtos freertos


【解决方案1】:

你的共享内存至少应该被声明为 volatile:

volatile xQueueRegistryItem rxQueueStore[MAX_NUMBER_OF_RX_QUEUES] ;
volatile int numberOfQueuesRegistered ;

否则编译器可能会优化对这些的读取或写入,因为它没有不同执行线程的概念(在 ISR 和主线程之间)。

我还记得一些 PIC C 运行时启动选项不应用静态数据的零初始化以最小化启动时间,如果您使用这样的启动,您应该显式初始化 numberOfQueuesRegistered .我建议这样做无论如何都是一个好主意。

从您的代码中不清楚 ISR 中的 RxMessage 与“远程模块”中的 RxMessage不同;它们不应该被共享,因为这将允许 ISR 在接收线程处理数据时潜在地修改数据。如果它们可以共享,那么一开始就没有理由拥有队列,因为共享内存和信号量就足够了。

作为旁注,永远不需要将指针 void*,您通常应该避免这样做,因为它会阻止编译器发出错误,如果您将传递除指针以外的其他内容。 void* 的全部意义在于它可以接受任何指针类型。

【讨论】:

    【解决方案2】:

    我认为理查德是对的。问题可能不在您在此处发布的代码中。

    您是否对正在等待队列的接收任务调用任何形式的暂停?当您在阻塞等待队列的任务上调用 vTaskSuspend() 时,暂停的任务将被移动到 pxSuspendedTaskList 并且它将“忘记”它正在等待事件队列,因为 xEventListItem 的 pvContainer 在任务将被设置为 NULL。

    您可能想检查您的接收任务是否在等待队列时被挂起。希望有帮助。干杯!

    【讨论】:

      【解决方案3】:

      乍一看,我看不出有什么明显的错误。问题可能在您显示的代码之外,例如 can_rx0_queue 是如何声明的、中断是如何输入的、您使用的是哪个端口等。

      有一个 FreeRTOS 支持论坛,链接自 FreeRTOS 主页http://www.FreeRTOS.org

      问候。

      【讨论】:

        猜你喜欢
        • 2021-07-30
        • 2017-06-08
        • 2018-11-27
        • 1970-01-01
        • 2018-01-12
        • 1970-01-01
        • 1970-01-01
        • 2021-07-24
        • 2021-02-19
        相关资源
        最近更新 更多