3

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 のキューのポインターを直接処理する場合に機能します。

アドバイスや情報が必要ですか?

4

3 に答える 3

1

共有メモリは、少なくとも揮発性として宣言する必要があります。

volatile xQueueRegistryItem rxQueueStore[MAX_NUMBER_OF_RX_QUEUES] ;
volatile int numberOfQueuesRegistered ;

そうしないと、コンパイラは、実行の異なるスレッド(ISRとメインスレッドの間)の概念がないため、これらへの読み取りまたは書き込みを最適化する可能性があります。

また、一部のPIC Cランタイム起動オプションは、起動時間を最小限に抑えるために静的データのゼロ初期化を適用しないことを思い出します。このような起動を使用している場合は、明示的に初期化する必要がありますnumberOfQueuesRegistered。いずれにせよ、そうすることは良い考えだと思います。

RxMessageISRの場合が「リモートモジュール」の場合と同じではないことは、コードからは明らかではありません。RxMessage受信スレッドがデータを処理している間にISRがデータを変更する可能性があるため、共有しないでください。それらを共有できれば、共有メモリとセマフォで十分なので、そもそもキューを持つ理由はありません。

補足として、にポインタを キャストする必要はありませんvoid*。ポインタ以外のものを渡した場合にコンパイラがエラーを発行するのを防ぐため、通常はそうしないようにする必要があります。aの要点は、void*任意のポインタ型を受け入れることができるということです。

于 2011-05-02T18:51:16.043 に答える
1

私はリチャードが正しいと思います。問題は、ここに投稿したコード内にない問題である可能性があります。

キューで待機している受信タスクで、何らかの形で一時停止を呼び出していますか? キューで待機しているブロックされているタスクで vTaskSuspend() を呼び出すと、一時停止されたタスクは pxSuspendedTaskList に移動され、イベント キューで待機していることを「忘れ」ます。タスクは NULL に設定されます。

キューで待機している間に、受信タスクが一時停止されているかどうかを確認することができます。それが役に立ったことを願っています。乾杯!

于 2011-04-30T18:02:17.293 に答える
1

一見すると、明らかに間違っていることはわかりません。問題は、can_rx0_queue がどのように宣言されているか、割り込みがどのように入力されているか、どのポートを使用しているかなど、あなたが示したコードの外にある可能性があります。

FreeRTOS ホームページhttp://www.FreeRTOS.orgからリンクされている FreeRTOS サポート フォーラムがあります。

よろしく。

于 2011-04-01T12:32:09.297 に答える