Проблема с массивом очередей во FreeRTOS - PullRequest
3 голосов
/ 01 апреля 2011

Я создаю приложение 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, если я возьму указатель по extern.

Нужны ли какие-либо советы или информация?

Ответы [ 3 ]

1 голос
/ 30 апреля 2011

Я думаю, что Ричард прав.Проблема может быть в проблемах, которые не входят в ваш код, который вы разместили здесь.

Вы вызываете какую-либо форму приостановки для получающей Задачи, которая ожидает в Очередь?Когда вы вызываете vTaskSuspend () для Задачи, которая заблокирована в ожидании очереди, приостановленная Задача будет перемещена в pxSuspendedTaskList, и он «забудет», что ожидает в очереди событий, поскольку pvContainer xEventListItem в этойЗадача будет иметь значение NULL.

Возможно, вы захотите проверить, не приостановлена ​​ли ваша принимающая задача во время ожидания в очереди.Надеюсь, что это помогло.Ура! * * 1005

1 голос
/ 02 мая 2011

Ваша общая память должна быть как минимум объявлена ​​как volatile:

volatile xQueueRegistryItem rxQueueStore[MAX_NUMBER_OF_RX_QUEUES] ;
volatile int numberOfQueuesRegistered ;

, иначе компилятор может оптимизировать чтение или запись в них, потому что он не имеет понятия о различных потоках выполнения (между ISR и основнойнить).

Также я напоминаю, что некоторые параметры запуска PIC C не применяют нулевую инициализацию статических данных, чтобы минимизировать время запуска, если вы используете такой запуск, выдолжен явно инициализировать numberOfQueuesRegistered.Я бы предположил, что это было бы хорошей идеей в любом случае.

Из вашего кода не ясно, что RxMessage в ISR не совпадает с RxMessageв «удаленном модуле»;они не должны использоваться совместно, поскольку это позволит ISR потенциально изменять данные, пока их обрабатывает принимающий поток.Если бы они могли быть общими, то не было бы никакой причины иметь очередь во-первых, поскольку общей памяти и семафора было бы достаточно.

В качестве дополнительного примечания никогда не нужно приводить указатель до void*, и вам, как правило, следует избегать этого, поскольку это не позволит компилятору выдать ошибку, если вы передадите что-то, кроме указателя.Весь смысл void* в том, что он может принимать любой тип указателя.

1 голос
/ 01 апреля 2011

На первый взгляд я не вижу ничего явно неправильного. Проблема может быть за пределами кода, который вы показали, например, как объявляется can_rx0_queue, как вводится прерывание, какой порт вы используете и т. Д.

Существует форум поддержки FreeRTOS, связанный с домашней страницей FreeRTOS http://www.FreeRTOS.org

С уважением.

...