限られた情報に基づいて、次のことを前提として回答を試みます。
- 単純な自作スケジューラを使用して、単純な基準に基づいて task1 と task2 を呼び出します。
- task1 と task2 は完了するまで実行されます (つまり、互いに先取りされません)。
- データはバイトベースのストリームです (パケットが必要な場合は、わずかに異なる実装が必要です)
組み込みシステムを設計するときに私が通常試みていることは、セマフォの使用を最小限に抑え、ロックのないデータ フローをモデル化することです。これを以下に説明します。
非同期 (ロックフリー) 通信キュー http://www.freeimagehosting.net/uploads/477741db06.gif
ISR は、スレッドセーフな FIFO キューを使用してタスクから切り離すことができます。例はhttp://msmvps.com/blogs/vandooren/archive/2007/01/05/creating-a-thread-safe-producer-consumer-queue-in-c-without-using-locks にあります。 aspx
このような実装 (ロックなし) には OS の依存関係がなく、簡単にサポートできるはずです。これにより、デッドロックのない明確な生産者と消費者の設計も実現します。
タスクが自作のスケジューラーによってトリガーされると仮定すると、そこでイベント (空でない fifo) をチェックすることを選択できます。つまり、if (TRUE == fifo_filled(my_read_queue)) { タスク 1 を呼び出す }
次に、タスク 1 とタスク 2 の同期について説明します。task1 がデータを生成しているだけの場合は、同じメカニズムを使用できます。タスク 1 がデータを書き込み、タスク 2 が読み取ることができるキュー (fifo) がある場合、タスクは分離されます。繰り返しますが、これはスケジューラーで確認できます (if (TRUE==fifo_filled(task1_to_2_queue() ) { invoke task2) }
さらに必要な場合 (つまり、タスクが完了まで実行されず、プリエンプトされる場合) は、同期するための何らかのメカニズムが必要になります。オプションには以下が含まれます: - とにかく (無料の) オペレーティング システムまたは単純なスケジューラを使用する - 独自に作成する (私の経験: for ループといくつかの if ステートメントと同じくらい単純な場合にのみ実行する必要があります) - 単純なスケジューラを使用します (はるかに多くの完全な RTOS よりも軽量) - コードをリファクタリングして、タスク 1 とタスク 2 を 1 つに統合します。その場合、効果的にスケジューラーをアプリケーション コードの一部にします。
注: この説明で使用したサンプル関数 (fifo_filled() ) は、サンプル コードの一部ではありません。(read != write) の場合は true を返す必要があります。また、サンプル コードではグローバル変数 read と write を使用しています。複数のキューを処理できる関数をグーグルで検索するか、読み取り/書き込み変数とバッファ変数を構造体に移動して、パラメーターで構造体を参照することができます。
別の方法として、割り込みを無効にしてクリティカル セクションを作成する方法があります。ただし、システムの結合が強くなり、コードの再利用が難しくなるため、これを制限するようにしています。