2017-02-14 3 views
0

私はデータを処理し、かなり長い時間がかかるライブラリの一部を持っています。場合によっては、関数の結果を待つことはできませんが、実行する必要がある他のタスクがあります。 OSが問題のないシステムでは、スケジューラがそれを手助けすることができます。 しかし、利用可能なOSがないシステムもあります。これらのシステムでは、私は何か似通ったものを実現したい、つまり、関数が呼び出されて、一定の期間(たとえば10ms)後にいくつかの計算と戻りが行われます。その後、他の処理が実行され、データ処理関数が再び呼び出され、その位置で離されます。OSスケジューラのないタイムスライス機能

while(1) { 
    process_data(); // resumes from where it returned before, runs for 10ms and returns 
    do_other_stuff(); 
    and_some_more_stuff(); 
} 

これはどのように達成できますか?

私は既にprotothreadsのコンセプトを見つけましたが、これは計算に10msかかる可能性のあるx命令ごとにPT_WAITのようなものを追加する必要があることを意味します。他の方法はありますか?

+1

コードでトリガできる「スペア」割り込み(外部コントローラからトリガされた割り込みではない)がある場合は、それを「フック」することができます。たとえば、ゼロ除算(この特定の例は注意してください。これは、SWの開発の後半でそのようなバグを捕まえる能力を失うためです)。それ以外の場合は、タイムスロットを定義し、無限ループをこれらのスロットに分割し、各スロットで目的の操作を実行します。 –

+1

Protothreadsは魔法のように中断可能な関数を作成しませんが、内部の動作はCマクロ内に隠されていますが、ループから常に飛び出るように関数を変更する必要があります。ですから、もしあなたがこれをやろうとしたら、小さなチャンクで作業するようにあなたの関数を単純に変更してみませんか?あるいは、低レベルの割り込み(メイン関数など)内で処理を行い、優先度の高い割り込みを使用して実行を中断し、定期的な間隔で「重要なこと」を実行します。 – Groo

+0

あなたの問題に直面したときに普通にやることは、小さなタスクスケジューラを追加/作成することです(これは[this](http://playground.arduino.cc/Code/TimerScheduler)と同じくらい簡単かもしれません)。複数のタスクを実行している。あるいは、小さな関数(例えば 'do_other_stuff()/ and_some_more_stuff() 'のように)を実行します。タイマー割り込み、または 'process_data()'関数を書き直して長時間実行するのではなく、ちょうど小さなデータを処理し、それがどれだけ来たかを記憶して、次に呼び出されたときに中断したところで処理を再開します。 – nos

答えて

2

process_data関数をステートマシンとして実装します。長すぎる処理アルゴリズムを複数の短いステップ/状態に分割します。 process_data内の静的状態変数を宣言し、各呼び出しの前の状態を覚えておいてください。 process_dataが呼び出されるたびに、1つの状態しか実行されません。それが再び呼び出されると、それは中断した箇所を拾い上げ、次のステップを実行します。この方法では、各呼び出しに要する時間は、設計時にステップをどのように分割するかによって決まります。実行時に実行時間を制限することはできません。

処理が繰り返しループで実行されている場合は、ループ内のハードウェアタイマーを読み取り、制限時間に達するとループから抜け出すことができます。しかし、静的変数を使用して、処理が中断された次の呼び出しを思い出してください。

2

other_stuffが合理的に短い限り、タイマーISRで行うことができます。

(RT)OSのタスクコンテキスト節約を使用したくない場合は、独自に実装する必要があります。長時間実行される処理関数を分割して処理コンテキストを保存して戻しますあなたのメインディスパッチポイントまで。次のステップが完了したら、保存したコンテキストに戻って、中断したところで処理を再開してください。

最終的には、一度作業が完了すると、マルチタスキングタイムスライスOSのほとんどの部分を実装している可能性があります。

関連する問題