FreeRTOS中的队列数组问题

3

我是一位有用的助手,可以为您翻译以下it技术相关内容。在构建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. 如果我通过extern获取队列指针,删除注册部分并直接在xQueueSendFromISR中使用指针,则代码可以工作。

需要任何建议或信息吗?


我在你提供的代码示例中没有看到任何问题。你确定队列被正确创建了吗?你的代码是否进入了中断例程,并且操作系统运行良好(没有栈溢出或类似地址错误的问题)? - greydet
3个回答

1

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

volatile xQueueRegistryItem rxQueueStore[MAX_NUMBER_OF_RX_QUEUES] ;
volatile int numberOfQueuesRegistered ;

否则编译器可能会优化掉对它们的读写,因为它没有不同执行线程(中断服务程序和主线程)的概念。
此外,我记得一些 PIC C 运行时启动选项不适用于静态数据的零初始化,以最小化启动时间,如果您正在使用这样的启动,则应明确初始化 numberOfQueuesRegistered。我建议在任何情况下都这样做是个好主意。
从您的代码中并不清楚 ISR 中的 RxMessage 与“远程模块”中的 RxMessage 不是同一个;它们不应该共享,因为这将允许 ISR 在接收线程处理数据时可能修改数据。如果它们可以共享,那么首先就没有必要有队列,因为共享内存和信号量就足够了。
顺便说一句,永远不需要将指针强制转换为 void*,通常应避免这样做,因为它会防止编译器在传递其他指针类型时发出错误。void* 的整个重点在于它可以接受任何指针类型。

1

我认为Richard是正确的。问题可能是你在这里发布的代码之外的问题。

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

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


1
乍一看,我没有看到任何明显的问题。问题可能在您展示的代码之外,例如can_rx0_queue如何声明,中断如何进入,您使用哪个端口等。
有一个FreeRTOS支持论坛,可以从FreeRTOS主页http://www.FreeRTOS.org链接过去。
祝好。

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接