2009-08-03 12 views
3

これは実際には組み込みシステムのファームウェアの設計上の問題です 独立して実行される(同じ優先度の)2つのISRがあります。 これらのISRは、h/wがデータを生成するとトリガされます。 私はtask1とtask2の間で同期するために配置されなければならないメカニズムが必要です。タスク2は、タスク1で計算された特定の値について知っていなければならず、タスク2で特定の値を計算する際に考慮する必要があります。 使用するOSプリミティブがありません。つまり、システムにはオペレーティングシステムがありません。 タスク1は、ISR2のコンテキスト内でISR1およびタスク2のコンテキスト内で実行されます。 私たちが使用するプロセッサはSTMicroelectronics 32コントローラです2つのタスク間の同期

EDIT:追加情報 プロセッサは、データで準備ができたら割り込みをトリガする特定のIPに接続されています。これらのIPは、入力ストリーミングフレームデータのアキュムレータのタイプとして機能します。

+0

あなたはどのプラットフォームで作業していますか? – Amber

+0

2つのISRが同じ優先順位を持っているとすれば、相互に割り込むことはできますか?そうでない場合、追加の同期は必要ありません。 –

+0

@Matthem - 通常、ISRは割り込みが入るとディセーブルにします。しかし、これはチェックするのが良いことです。 – Robert

答えて

2
  • 無効にする価値観を共有
2

から読み出しや書き込みをした後、私はあなたに答えを与えることをしようとするでしょう前に読書や共通の価値観への書き込み

  • 再度有効に割り込みを中断制限された情報に基づいて、次のように仮定します。

    • シンプルな自作スケジューラ単純な基準に基づいてtask1およびtask2を呼び出す。
    • task1およびtask2が完了するまで実行する。
    • データが組み込みシステムを設計するセマフォの使用を最小限に抑えることであるとき、私は通常しようと何バイトベースストリーム(あなたがパケットを必要とする場合は、わずかに異なる実装が必要です)

    です)お互いを先取りしていない、とモデルのロックフリーのデータフロー。

    asynchronous (lock free) communication queues 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)){invoke task 1}

    ここで、task1とtask2の同期について説明します。 task1がデータを生成しているだけの場合、同じメカニズムを使用することができます。task1がタスク2で読み取ることができるデータを書き込むキュー(fifo)がある場合、タスクはデカップリングされます。

    さらに必要な場合(つまり、タスクが完了するまでには実行されませんが、プリエンプションが行われている場合)、スケジューラでこれを確認することができます(TRUE == fifo_filled(task1_to_2_queue()){invoke task2}同期するためのメカニズムが必要です。オプションは次のとおりです: - とにかく(無料の)オペレーティングシステムまたはシンプルなスケジューラを使用してください - 自分自身を作成し​​てください(私の経験:forループといくつかのif文と同じように単純な場合のみ行うべきです) - (完全なRTOSよりはるかに軽量) - task1とtask2を1つに統合するためのリファクタリングコード。その場合、スケジューラーをアプリケーション・コードの一部に効果的に組み込むことができます。

    注:この説明で使用した関数の例(fifo_filled())は、サンプルコードの一部ではありません。 (read!= write) また、サンプルコードではグローバル変数readとwriteを使用しています。複数のキューを扱う機能を持つGoogleのいずれかをアップグレードするか、読み込み/書き込みとバッファ変数を構造体に移動し、パラメータの構造体を参照することができます。

    代替方法は、割り込みディセーブルを使用してクリティカルセクションを作成することです。しかし、私は頻繁に強いシステム結合を作成し、コードを再利用するのが難しくなるので、これを制限しようとします。

  • +0

    イラストを大きくしてもらえますか? –

    +0

    が完了しました。誤ってサムネイルへのリンクがありました.... – Adriaan

    +0

    素晴らしい、ありがとう!図の場合は –

    4

    私は割り込みコンテキストで重い処理をしません、ちょうどデータを読み、フラグを設定します。

    メインループのシンプルなスケジューラでフラグをチェックし、必要に応じてタスクを実行することができます。したがって、タスクは互いに干渉することができず、他のタスクの一貫性のない出力を見ることができません。

    タスクは、別のタスクをアクティブにするようなフラグを設定することもできます。例えば。 Task2はTask1の値を必要とするため、Task1はTask2をアクティブにできます。

    ISRで読み取られるデータには、バッファが必要です。着信データのタイミングに応じて、リングバッファまたはダブルバッファになる可能性があります。

    2

    私は、OSがないという観点から、C以外の実際のフレームワークやレジスタなどは出てこないのです。私がやる方法は、他のISRが見ることができる各ISRの状態変数を持つことです。 ISR1に入ると、ISR2のタスクの状態をチェックし、必要に応じて操作するだけです。次に、ISR2が呼び出され、自身の状態とISR1の状態をチェックし、適切であると判断して動作します。私は、ヘッダファイル内のENUMを使用して、明快(INIT、WAITONDATAなど)の状態を列挙し、各状態を処理するISRのスイッチを使用します。次に、共有する必要のあるデータを両方のISRが見ることができるようにしてください。

    もちろん、ISRで多くの計算をしたくないという人もいます。イベントが発生したか、または何らかのデータが存在することを示すフラグを設定し、メインループのデータを処理したいだけです。 ISRの処理が長すぎるため、システムがブロックされません。メインループ(またはメインループからのデータ操作を行うために少なくとも呼び出す関数)とISRにも見られる状態変数と同じ方法でこれを行います。 ISRの状態を変更し、メインループ機能の状態を確認してください。必要に応じて雑用を行います。

    忘れないでください - ISRの変数を更新する場合は、volatileとして定義する必要があります。

    volatile uint8 state = INIT;

    たとえば、

    関連する問題