2016-07-21 2 views
0

別のタスクによって変更されますはこのように、二つの異なるFreeRTOSタスクで実行されている、私は2台の状態マシン、<code>A</code>と<code>B</code>を持つC++の設計を持って

A::task() 
{ 
    while (1) 
    { 
     switch (m_state) 
     { 
     case A1: 
      // Do A1 stuff 
      break; 
     case A2: 
      // [1] Do A2 stuff before yielding to B::task() 
      // [2] Do more A2 stuff after resuming from B::task() 
      break; // [3] 
     default: 
      break; 
     } // switch: state 
    } // while: task loop 
} 

B::task() 
{ 
    while (1) 
    { 
     switch (m_state) 
     { 
     case B1: 
      // Do B1 stuff 
      break; 
     case B2: 
      // Do B2 stuff 
      break; 
     default: 
      break; 
     } // switch: state 
    } // while: task loop 
} 

今、BAの状態を(非同期的に、コールバックを介して)変更する能力があります。これはすべて正常に動作しますが、私がしたいのは、その状態が変更されたときにAのマシンが "再起動"することです(つまり、最後に実行していた作業からbreak[1])以前の状態のコード[2]は、break[3]と状態変化が起こる前に継続しません。

この動作は達成できますか?

+0

条件変数が必要なようです。つまり、BがAの状態をA2に設定すると、Aはbが通知する条件変数を待機します。より簡単な例は、Aの状態をA2に設定する前にBが取るmutexを持つことです。 AはA2の処理を完了した後、Bがそれを解放するまでの間に生じるmutexを取得しようとします。 – AndyG

答えて

1

いいえ、あなたがしたいことは、あなたが記述したやり方では合理的な可能性ではないと思います。タスクAが先取りされると、スケジューラはタスクAのコンテキストを保存し、タスクBのコンテキストを復元します。タスクAの保存されたコンテキストには、切り替えられたときに使用されていたローカル変数とプログラムカウンタ(命令のアドレス実行していた)。コンテキストAを復元して別の場所で実行するには、タスクAの保存済みコンテキストを復元してから復元する必要があります。私はそれが妥当なものだとは思わない。

これはいい考えですが、タスクBがタスクAの状態を変更するたびに、タスクBがタスクAを削除して再作成できるかどうかは分かりません。

もう1つのアイデアは、タスクAがタスクの途中である間に優先されないようにすることです。タスクAの状態が大きすぎてプリエンプションを長時間無効にすることができない場合、おそらく状態を複数の小さな状態に分けることができます。

+0

答えをありがとう。それは私がうまくそれを達成することができないように感じました。タスクを再作成することは、実際にはシステムの動作の中では選択肢にはならないので、その考えは破棄されます。タイムクリティカルな機能のためにスケジューラーを非常に頻繁に停止させてしまいますが、大きなコンテキストではスケジューラーを実行するオプションはありません。 –

+0

タスクへの再入力時に変数に問い合わせる方法はありますか?それはタスク自体よりも低いですか?私はスケジューラの観点からセマフォのようなものを想定していますか? –

+0

タスクは、それがプリエンプトされたことを認識しません。したがって、タスクが再開されたときに何か違うことをすることはできません。タスクのコードはタスクのコードです。私はそれが再開するポイントで余分なコード命令を挿入することは合理的だとは思わない。プリエンプションのテストはコンパイル時にコードに含まれていて、プリエンプションが発生する前に時間がわからないため、すべてのステートメントの後でテストを繰り返す必要があります。 – kkrambo

関連する問題