いつポーリング方式を使用する必要があり、いつ割り込みベースの方式を使用する必要がありますか?両方を使用できるシナリオはありますか?
14 に答える
対象のイベントが次の場合:
- 非同期
- 急
- まれ
その場合、割り込みベースのハンドラーが理にかなっています。
対象のイベントが次の場合:
- 同期(つまり、小さなウィンドウ内でいつ期待するかを知っている)
- 緊急ではない (つまり、ポーリング間隔が遅くても悪影響はありません)
- 頻繁 (つまり、ポーリング サイクルの大部分が「ヒット」を作成します)
その場合、ポーリングの方が適している可能性があります。
その他の考慮事項には、OS 用のデバイス ドライバーを作成するのか、それともスレッドをサポートしないベア メタル コードを作成するのかが含まれます。ベア メタルの状況では、多くの場合、CPU はビジーでないときにループしているだけなので、何かをポーリングしている可能性があります。
ポーリングは通常、不必要に多くの CPU サイクルを消費するため、可能な限り避ける必要があります ((a) 短時間だけポーリングする場合、または (b) ポーリング ループで妥当な時間スリープする余裕がある場合を除きます)。 )。CPU サイクルを浪費することは、パフォーマンスの観点から悪いだけでなく、電力消費も増加させます。これは、バッテリ駆動の組み込みアプリケーションにとって問題になる可能性があります。
ポーリングまたは割り込みを決定するときは、追跡しようとしているイベントの性質とそれに対する応答を完全に理解する必要があります。
割り込みは、何も起こっていないときは処理を必要としませんが、何かが起こっているときはすべての注意を払う必要があります。イベントが外部であり、ノイズの多いエッジまたは高速パルスがある場合、これにより割り込みで大きな問題が発生する可能性があるため、割り込みのセットアップに注意する必要があります。
この例では、割り込みルーチンはレーザー ビームがクリアになったことに応答し、レーザー ビームがブロックされるイベントに備えてセットアップしています。
BEAM_INTR_EN = TRUE; /*re-enable the beam interrupts*/
/*Set the beam interrupt for the next clear to blocked event*/
BEAM_INTR_EDGE = CLEAR_TO_BLOCKED;
BEAM_INTR_FLAG = FALSE; /*Clear the interrupt*/
このコードには 2 つの弱点があります。1) 割り込みフラグがクリアされる前にレーザー ビームが再びブロックされた場合 (BEAM_INTR_FLAG = FALSE;)。割り込みが失われ、コードがレーザー ビームの状態と同期しなくなります。
2) バックグラウンド ルーチンで割り込みを設定する場合、またはこのコードがオンになっている優先度よりも高い優先度で割り込みを設定する場合は、割り込みを有効にするときに注意が必要です。割り込みフラグが有効になる前にすでに (誤って) 設定されていた場合、割り込みルーチンは有効になるとすぐに誤って呼び出され、おそらく間違ったエッジで呼び出されます。
1) を修正する最も簡単な方法は、割り込みを設定した後で再確認し、発生した場合は割り込みを強制することです。修正するには 2) 割り込みの有効化をダブル チェックの後に移動します。
/*Set the beam interrupt for the next clear to blocked event*/
BEAM_INTR_EDGE = CLEAR_TO_BLOCKED;
BEAM_INTR_FLAG = FALSE; /*Clear the interrupt*/
/*Double check beam state to see if it has already gone blocked*/
if (BEAM_STATE == BEAM_BLOCKED)
{
BEAM_INTR_FLAG = TRUE; /*Force the interrupt to re-enter the ISR after exiting*/
}
BEAM_INTR_EN = TRUE; /*re-enable the beam interrupts*/
割り込みを強制すると、システムは同じステート マシンで動作し、死角をカバーするために手動で強制するだけです。
基本的:
Set the edge to detect the next interrupt event
Clear the interrupt flag
if (the event has already occurred)
{
Set the interrupt flag to force the interrupt
}
Enable the interrupt
イベントへの応答時間を一定にする必要がある場合 (たとえば、入力ラインがハイになってイベント信号を送信してから 1ms +/-10us 後)、通常は割り込みが最適です。
イベントへの応答時間が特定の時間内でなければならない場合 (たとえば、入力ラインが High になってから 1ms 以内にイベント信号を送信する)、割り込みが最適です。
割り込みの問題は、スレッド化について考え始める必要があり、2 つのコードが同時に同じデータにアクセスできることです。
割り込みは、何かが起こるのを待っている間にプロセッサを低電力モード (スリープ/アイドルなど) に移行できるようにするのにも適しています。
プロセッサが実行することが 1 つしかない場合、ポーリングはイベントに対して非常にタイトな時間応答を与える可能性があると述べましたが、多くの場合、割り込みハードウェアはイベントに応答するのに数サイクルかかりますが、タイトなポーリング ループはそれを行います。
イベントがタイミング クリティカルではなく、ノイズの可能性がある場合 (誰かがスイッチを押すなど)、ポーリングにより、長期的な遷移を見逃すことなく単純なフィルタリングが可能になります。よくある間違いは、セットアップ時に複数回ポーリングすることです。
void fnInitialiseSystem(void)
{
if (MODE_INPUT == MODE_A) /*First polling of the MODE_INPUT*/
{
PR2 = PR2_MODE_A;
}
else
{
PR2 = PR2_MODE_B;
}
OpenTimer2( TIMER_INT_ON &
T2_PS_1_1 &
T2_POST_1_8 );
if (MODE_INPUT == MODE_A) /*Second polling of the MODE_INPUT*/
{
CurrentMode = MODE_A;
PROBE_INT_EDGE = CLEAR_TO_BLOCKED;
}
else
{
CurrentMode = MODE_B;
PROBE_INT_EDGE = BLOCKED_TO_CLEAR;
}
}
上記の例では、MODE_INPUT は外部スイッチです。MODE_INPUT がポーリングされる 2 回が異なる場合、予期しない動作になります。このような種類の信号を読み取るときは、フィルタリングを使用して入力の長期的な状態を判断し、フィルタリングされたバージョンでアクションを実行するのが最善です。
たとえば、スイッチのデバウンスでは、定期的に (1 ミリ秒ごとに?) スイッチをチェックし、それらの数 (たとえば 16) がフィルタリングされたバージョン (スイッチが開いている) と異なる (スイッチが閉じている) 場合は、結果を更新し、必要なアクションを実行します。 . 信号のエイリアシングには注意してください。発振信号は安定しているように見える場合があります。
ポーリングと割り込みの使用例は、繰り返しますが、頻繁には変更されませんが変更時にノイズが多い入力の使用です。繰り返しになりますが、スイッチはこの良い例です。コードは、スイッチの状態の変化をチェックする割り込みを設定できます。割り込みが発生すると、スイッチの状態が「安定」するまで定期的にスイッチをポーリングできます。状態または元の状態に戻る)。これにより、何も起こっていないときの処理オーバーヘッドが低くなり、何かが起こっているときのノイズ フィルタリングの利点が得られます。
実際には両方を使用する必要がある場合もあります。たとえば、イベントが散発的であるが、高速バーストで発生する場合。最初に割り込みに応答し、次に割り込みポーリングを再度有効にする前に、別のイベントが既に発生しているかどうかを確認し、割り込みコンテキスト切り替えのオーバーヘッドを回避する必要がある場合があります。Linux Network Interface はこのモードで動作すると思います。
ポーリングと割り込みの方法を分析しているときに出会った
いくつかの興味深いリンクを次に示します-http://web.engr.oregonstate.edu/~traylor/ece473/lectures/interrupts.pdf-非常に興味深いリンク
http ://www.atarimagazines .com/compute/issue149/60_Interrupts_made_easy.php
http://www.electro-tech-online.com/micro-controllers/8440-interrupt-vs-polling.html
http://www.microchip.com/forums/m397196 -print.aspx
http://www.cs.huji.ac.il/course/2006/67630/Lectures/interrupts.pdf
http://sunsite.nus.edu.sg/LDP/LDP/tlk/node86.html
これが役に立てば幸いです。
簡単な答えは、ポーリングが遅すぎる場合に割り込みメソッドを使用することです。(遅すぎるということは、ポーリングがデータを失った場合、割り込みメソッドが必要であることを意味します)
低レイテンシが必要な場合は、割り込みが優先されます。ある条件を 1 秒間に N 回ポーリングすると、平均して、実際に発生してから 1/N の半分の時間でその条件が検出されます。
絶対的な決定論的タイミングが必要な場合は、ポーリングが好まれることがあります。割り込みはその性質上、予測不可能なタイミングで発生し、タイミング分析を非常に複雑にする可能性がありますが、ポーリングされたシステムでは、締め切りの遵守について証明可能な声明を出すのは比較的簡単です。
ポーリング モードは、割り込みハンドラーの開始と終了に関連するオーバーヘッドが単純なポーリングよりも多くの CPU サイクルを使用する、頻繁にイベントが発生するシステムで役立ちます。たとえば、IP ルーターでポーリングを使用して、パケット処理に使用できる CPU 帯域幅を最大化できます。
決定を下す可能性のある多くの設計上の制約があります。私のアプリには、割り込みとポーリングの組み合わせがあります。
- 外部クロック ソースと内部クロック ソースが割り込みをトリガーします。同期できるように、両方のタイムスタンプを正確に記録することが重要です。
- 着信シリアル メッセージは、割り込みをトリガーします。受信 FIFO は、オーバーフローする前に処理する必要があります。
- FIFO が部分的に空になると、発信メッセージによって割り込みがトリガーされます。アンダーフローする前に再充填する必要があります。
- バックグラウンドでポーリングされる ISR のセット セマフォ。これには 2 つの利点があります。
- 着信イベントを処理するために必要な計算は長くなる可能性があります。それが ISR に残されると、他の ISR がサービス期限を超えて遅れる可能性があります。
- イベントは順序付けできます。たとえば、ポーリング ループを使用すると、メッセージが予想よりも少し早く到着することがあっても、ADC データの収集と着信メッセージの解析の間に常に X の計算が行われるようにすることができます。
必ず割り込みを使用してください。そうすれば、データを失うことはありません。イベント駆動型またはスレッド化されたアプリケーションでは、最も遅いシグナルでも割り込み駆動にする必要があります。
ポーリングを使用する必要があるのは、スケジューラを使用していて、ハードウェアのバッファが十分に深く、データが失われないことを保証するときだけです。
基本的に、ポーリング モードは、ハードウェアまたはソフトウェアの理由により割り込みモードが使用できない場合に使用されます。したがって、消費電力、パフォーマンスなどの観点からは、割り込みモードの方が望ましいです (Paul R に同意します)。ポーリング モードは、プロトタイピング、ペリフェラルを必要としないコア、および一部のテスト目的で使用することもできます。
主な 5 つの方法論があります。
1) ブラインド
CPU は x ミリ秒ごとにデータをチェックします。ETCチェック12番ピン。
2)ポーリング(ビジー/待機)
パケットが転送された後に UART がフラグを上げるように、CPU は常にフラグをチェックし、フラグが上がるのを待っています。フラグレジスタを永遠にチェックします。(最高の応答時間) しかし、CPU は他に何も実行できません。
3) 割り込み:
CPU は正常に動作し、割り込みが発生すると、CPU はコンテキストを ISR に切り替えます。ピン 18 が立ち下がりエッジを検出した場合、ISR (1) を実行します。応答時間は悪くなく、ISR がアクティブでない間、CPU は何でもできます。いつ起こるかわからない緊急アプリで行います。
4) 定期的なポーリング:
CPU は処理を行っていますが、ミリ秒ごとにピン 11 をチェックしています。その間、ブラインドは何もしていません。緊急のアプリではなく、応答時間が悪いのは、ハードウェアが割り込みを発生させるとは思えない場合です。タイマー割り込みを使用して作成できます。
5) ダイレクトメモリアクセス。
高度なインターフェース アプローチ。メモリとの間でデータを直接転送します。入力はメモリに直接読み込まれます。出力はメモリから直接書き込まれます。どちらもコントローラーを使用します。