FreeRTOS中的队列数组问题

时间:2011-04-01 11:52:25

标签: c embedded queue rtos freertos

我正在构建一个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中的队列指针。

是否需要任何建议或信息?

3 个答案:

答案 0 :(得分:1)

乍一看,我看不出任何明显的错误。问题可能超出了您所显示的代码,例如如何声明can_rx0_queue,如何输入中断,您使用的是哪个端口等。

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

问候。

答案 1 :(得分:1)

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

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

您可能想要检查在等待队列时是否曾暂停您的接收任务。希望有所帮助。干杯!

答案 2 :(得分:1)

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

volatile xQueueRegistryItem rxQueueStore[MAX_NUMBER_OF_RX_QUEUES] ;
volatile int numberOfQueuesRegistered ;

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

我还记得一些PIC C运行时启动选项不应用静态数据的零初始化以便最小化启动时间,如果使用这样的启动,则应明确初始化{{1 }}。我建议在任何情况下这样做都是个好主意。

从您的代码中可以看出,ISR中的numberOfQueuesRegistered 与“远程模块”中的RxMessage 不相同;它们不应该被共享,因为这将允许ISR在接收线程处理它时可能修改数据。如果它们可以共享,那么首先就没有理由建立队列,因为共享内存和信号量就足够了。

作为旁注,从来没有必要将指针转换为 RxMessage,并且通常应该避免这样做,因为它会阻止编译器发出错误如果你要传递指针以外的东西。 void*的重点在于它可以接受任何指针类型。