1

組み込みシステム コードでイベントがどのように使用されているか知りたいです。

主な目的は、イベント フラグがコードでどのように設定/リセットされるかを正確に知ることです。また、どのタスクがどのイベント フラグを使用しているか、およびフラグのどのビットが各タスクによってセット/リセットされているかを識別する方法。

それについての提案やコメントをお寄せください。

前もって感謝します。


(編集1:以下の回答の説明からコピー)

必要な詳細を指定しておらず申し訳ありません。実際、vxworks/Itron/OSEK OS を使用して C 言語で記述されたアプリケーションの分析に興味があります。たとえば、vxworks にはイベント処理をサポートする eventLib ライブラリがあります。このようなシステム ルーチンを使用して、タスク内のイベントを処理する方法を知りたいです。イベントフラグとは(グローバル/ローカルですか...または何ですか?)、イベントフラグのビットを設定する方法、およびタスクフラグとイベントフラグの間の可能な関係はどれですか??

AND および OR モードでタスクが複数のイベントを待機するにはどうすればよいですか?? 以下に示すシナリオが危険に見える例を 1 つ見つけましたが、なぜですか??

            Scenarios is ==> *[Task1 : Set(e1), Task2 : Wait(e1) and Set(e2), Task3 : Wait(e2) ]*                                             

1つのタスクが複数のイベントフラグを待ち合わせたり、複数のタスク間の循環依存(デッドロック)がタスクとイベントの関係で危険なケースであることは知っていますが、上記のシナリオがどのように危険なのか、私には理解できません....親切に説明してください.

                (Are there any more such scenarios possible in task-event handling which should be reviewed in code ?? ) 

上記の情報で十分だと思います....

4

7 に答える 7

2

多くの組み込みシステムは、割り込みサービス ルーチン (ISR) を使用してイベントを処理します。特定の「フラグ」に対して ISR を定義し、イベントを処理した後にそのフラグをリセットします。

たとえば、アナログからデジタルへの変換 (ADC) を実行するデバイスがあるとします。デバイスでは、ADC が変換を完了するたびに起動する ISR を用意し、ISR 内で処理するか、データが利用可能であることを他のタスクに通知することができます (通信プロトコルを介して送信する場合)。それが完了したら、ADC フラグをリセットして、次の変換で再び起動できるようにします。

通常、デバイスのマニュアルで一連の ISR が定義されています。場合によっては、必要に応じて処理できる汎用フラグを提供することもあります。ルーチンを起動させたフラグをリセットするたびに。

于 2008-10-22T05:32:09.883 に答える
2

VxWorks の eventLib は、UNIX の signal() に似ています。何かが発生したことを別のスレッドに示すことができます。イベントでデータを渡す必要がある場合は、代わりにメッセージ キューを使用することをお勧めします。

イベントは、送信者と受信者の間で「グローバル」です。各送信者はイベントの対象タスクを示すため、システム内に複数のイベント マスクが存在し、各送信者/受信者のペアが独自の解釈を持つ場合があります。

基本的な例:

 #define EVENT1       0x00000001
 #define EVENT2       0x00000002
 #define EVENT3       0x00000004
 ...
 #define EVENT_EXIT   0x80000000

 /* Spawn the event handler task (event receiver) */
 rcvTaskId = taskSpawn("tRcv",priority,0,stackSize,handleEvents,0,0,0,0,0,0,0,0,0,0);
 ...

 /* Receive thread: Loop to receive events */
 STATUS handleEvents(void)
 {
     UINT32 rcvEventMask = 0xFFFFFFFF;

     while(1)
     {
         UINT32 events = 0;

         if (eventReceive(rcvEventMask. EVENTS_WAIT_ANY, WAIT_FOREVER, &events) == OK)
         {
             /* Process events */
             if (events & EVENT1)
                 handleEvent1();
             if (events & EVENT2)
                 handleEvent2();
             ...
             if (events & EVENT_EXIT)
                 break;
         }
     }

     return OK;
 }

通常、イベントの送信者は、ハードウェア ドライバー (BSP) または別のスレッドです。目的のアクションが発生すると、ドライバーは関連するすべてのイベントのマスクを作成し、それらをレシーバー タスクに送信します。

送信側は、受信側のタスク ID を取得する必要があります。taskID はグローバルにすることができます。

int RcvTaskID = ERROR;
...
eventSend(RcvTaskID, eventMask);

レシーバーによってドライバー/センダータスクに登録できます。

static int RcvTaskID = ERROR;

void DRIVER_setRcvTaskID(int rcvTaskID)
{
    RcvTaskID = rcvTaskID;
}
...
eventSend(RcvTaskID, eventMask);

または、ドライバー/送信側タスクが受信側 API メソッドを呼び出して、イベント (ラッパー) を送信できます。

static int RcvTaskID;
void RECV_sendEvents(UINT32 eventMask)
{
    eventSend(RcvTaskID, eventMask);
}
于 2008-10-22T17:01:38.867 に答える
1

この質問では、より多くのコンテキストを提供する必要があります。組み込みシステムは、さまざまな言語、オペレーティング システム (オペレーティング システムなしを含む)、フレームワークなどを使用して作成できます。イベントがどのように生成されるかについて普遍的なものがないのと同様に、組み込みシステムでイベントがどのように作成および処理されるかについても普遍的なものはありません。コンピューティング全般で作成および処理されます。

于 2008-10-22T05:31:17.543 に答える
1

イベントを表すさまざまなビットを設定、クリア、およびチェックする方法を知りたい場合は、この例が役立ちます。基本的な戦略は、(通常はグローバルな) 変数を宣言し、1 ビットを使用して各条件を表すことです。

unsigned char bit_flags = 0;

これで、イベントをビットに割り当てることができます:

#define TIMER_EXPIRED   0x01   // 0000 0001
#define DATA_READY      0x02   // 0000 0010
#define BUFFER_OVERFLOW 0x04   // 0000 0100

また、ビットごとの演算子を使用して、ビットを設定、クリア、およびチェックできます。

// Bitwise OR: bit_flags | 00000001 sets the first bit.
bit_flags |=  TIMER_EXPIRED;  // Set TIMER_EXPIRED bit.

// Bitwise AND w/complement clears bits: flags & 11111101 clears the 2nd bit.
bit_flags &= ~DATA_READY;     // Clear DATA_READY bit.

// Bitwise AND tests a bit.  The result is BUFFER_OVERFLOW
// if the bit is set, 0 if the bit is clear.
had_ovflow = bit_flags & BUFFER_OVERFLOW;

ビットの組み合わせを設定またはクリアすることもできます。

// Set DATA_READY and BUFFER_OVERFLOW bits.
bit_flags |=  (DATA_READY | BUFFER_OVERFLOW);

これらの操作がマクロとして実装されていることがよくあります。

#define SET_BITS(bits, data)    data |=  (bits)
#define CLEAR_BITS(bits, data)  data &= ~(bits)
#define CHECK_BITS(bits, data)  (data & (bits))

また、割り込みと割り込みサービス ルーチンに関する注意: これらは高速で実行する必要があるため、通常の ISR は単純にフラグを設定するか、カウンターをインクリメントするか、データをコピーしてすぐに終了します。その後、フラグを確認して、自由にイベントに参加できます。おそらく、ISR で時間のかかる、またはエラーが発生しやすいアクティビティを実行したくないでしょう。

お役に立てば幸いです。

于 2008-11-06T05:21:17.483 に答える
0

必要な詳細を指定しておらず申し訳ありません。実際、vxworks/Itron/OSEK OS を使用して C 言語で記述されたアプリケーションの分析に興味があります。たとえば、vxworks にはイベント処理をサポートする eventLib ライブラリがあります。このようなシステム ルーチンを使用して、タスク内のイベントを処理する方法を知りたいです。イベントフラグとは(グローバル/ローカルですか...または何ですか?)、イベントフラグのビットを設定する方法、およびタスクフラグとイベントフラグの間の可能な関係はどれですか??

上記の情報で十分だと思います....

于 2008-10-22T05:38:50.913 に答える
0

私が設計した組み込みシステムの 1 つのファミリ (約 128KB のフラッシュと 3.5KB の RAM を搭載した PIC18Fxx マイクロ) では、1/16 秒の分解能 (CPU への 16Hz パルス入力で測定) で最大 16 個のタイマーを処理するライブラリを作成しました。 )。コードは、いずれかのタイマーが期限切れ状態にあるか、専用のウェイクアップ ピンが信号を送信しているかどうかを判断するように設定されています。そうでない場合は、次のタイマーが期限切れになるかウェイクアップ入力の状態が変化するまでスリープします。非常に便利なコードですが、振り返ってみると、おそらく 16 の 1 セットではなく、8 つのタイマーの複数のグループで動作するように設計する必要がありました。

有用であることがわかったタイミング ルーチンの重要な側面は、ほとんどが割り込みによって駆動されないことです。代わりに、16Hz カウンターからタイマーを更新する「都合の良いときにポーリング」ルーチンがあります。割り込みを介して実行されないタイマーを使用することは時々奇妙に感じられますが、そのようにすることで、奇妙な時間に発生する割り込みについて心配する必要がなくなります。タイマーによって制御されるアクションが (スタックの入れ子やその他の制限により) 割り込み内で発生できない場合、割り込み内のタイマーについて心配する必要はありません。経過した時間を追跡するだけです。

于 2011-02-02T05:40:28.927 に答える
0

組み込みレベルでイベント駆動型プログラミングを使用することに興味がある場合は、実際にQPを調べる必要があります。これは優れた軽量フレームワークであり、Miro Samek による「Practical UML Statecharts in C/C++」という本を入手すると、組み込み Linux カーネル (ISR など) でシステム イベントを処理する方法から、ビルドでそれらを処理および作成する方法まで、すべてを見つけることができます。あなたの環境としてQP。(ここにイベントの例へのリンクがあります)。

于 2011-12-08T23:26:54.090 に答える