8

特定の割り込みが発生した結果として実行する必要があるコードがいくつかあります。

割り込み自体のコンテキストで実行したくありませんが、スレッドモードで実行したくありません。

実行を促進した高レベルの割り込みよりも低い優先度で実行したいと思いますが、スレッドレベルよりも高い優先度(および他のいくつかの割り込みも同様)で実行したいと思います。

他の割り込みハンドラのいずれかを使用する必要があると思います。

使用するのに最適なものはどれで、それらを呼び出す最良の方法は何ですか?

現時点では、使用していない周辺機器の割り込みハンドラーを使用し、NVIC を介して直接ビットを設定することでそれらを呼び出すことを計画していますが、より良い、より公式な方法があることを望んでいました。

ありがとう、

4

5 に答える 5

16

ARM Cortex は、PendSV と呼ばれる非常に特殊な種類の例外をサポートしています。この例外を正確に使用して作業を行うことができるようです。実質的にすべての ARM Cortex 用プリエンプティブ RTOS は、PendSV を使用してコンテキスト スイッチを実装します。

これを機能させるには、PendSV を低く優先する必要があります (NVIC の PRI_14 レジスタに 0xFF を書き込みます)。また、PendSV より上のすべての IRQ に優先順位を付ける必要があります (NVIC のそれぞれの優先順位レジスタに低い数値を書き込みます)。メッセージ全体を処理する準備ができたら、優先度の高い ISR から PendSV をトリガーします。

*((uint32_t volatile *)0xE000ED04) = 0x10000000; // trigger PendSV

その後、ARM Cortex CPU は、ISR と、それによってプリエンプトされた可能性のある他のすべての ISR を終了し、最終的に PendSV 例外にテールチェーンします。これは、メッセージを解析するためのコードがあるべき場所です。

PendSV は他の ISR によってプリエンプトされる可能性があることに注意してください。これで問題ありませんが、すべての共有リソースをコードのクリティカル セクション (簡単に割り込みを無効にして有効にする) で保護することを忘れないでください。ARM Cortex では、__asm("cpsid i") を実行して割り込みを無効にし、__asm("cpsie i") で割り込みを有効にします。(ほとんどの C コンパイラは、この目的のために組み込みの組み込み関数またはマクロを提供します。)

于 2010-05-02T22:31:32.267 に答える
3

RTOSを使用していますか?一般に、このタイプのことは、割り込みによって何らかの作業を行うように通知される優先度の高いスレッドを持つことによって処理されます。

RTOS を使用しておらず、少数のタスクしかなく、割り込みによって開始される作業がリソースをあまり消費しない場合は、優先度の高い作業を割り込みハンドラーのコンテキストで実行するのが最も簡単かもしれません。これらの条件が満たされない場合、あなたが話していることを実装することは、基本的なマルチタスク OS 自体の始まりになります。それ自体が興味深いプロジェクトになる可能性がありますが、単に作業を完了させたい場合は、単純な RTOS を検討することをお勧めします。

あなたが行っている作業についていくつかの詳細を述べたので、過去に同様の問題をどのように処理したかの概要を以下に示します。

UART 経由で受信したデータを処理するために、タスクを完全にサポートしていない単純なシステム (つまり、タスクは単純なwhileループでラウンドロビン処理される) を扱うときに使用した 1 つの方法は、共有キューを使用することです。 UART から受信したデータ用。UART 割り込みが発生すると、UART の RDR (受信データ レジスタ) からデータが読み取られ、キューに入れられます。キュー ポインターが破損しないようにこれに対処する秘訣は、キュー ポインターを慎重に揮発性にし、割り込みハンドラーのみがテール ポインターを変更し、データを読み取る「フォアグラウンド」タスクのみが変更されるようにすることです。キューをオフにすると、ヘッド ポインターが変更されました。高レベルの概要:

  • プロデューサー (UART 割り込みハンドラー):

    1. 読んqueue.headqueue.tail地元の人に。
    2. ローカル テール ポインターをインクリメントします (実際のポインターではありませんqueue.tail)。キューのバッファーの末尾を超えてインクリメントした場合は、キュー バッファーの先頭にラップします。
    3. 比較local.tailしてlocal.head- それらが等しい場合、キューはいっぱいであり、適切なエラー処理を行う必要があります。
    4. それ以外の場合は、新しいデータをlocal.tailポイントに書き込むことができます
    5. queue.tail == local.tail を設定できるのは今だけです
    6. 割り込みから戻る (または、必要に応じて、送信キューからの読み取りなど、他の UART 関連タスクを処理する)
  • 消費者 (フォアグラウンドの「タスク」)

    1. 読んqueue.headqueue.tail地元の人に。
    2. local.head==の場合local.tail、キューは空です。戻って次のタスクに仕事をさせます
    3. が指すバイトを読み取るlocal.head
    4. 必要に応じてインクリメントlocal.headしてラップします。
    5. セットqueue.head=local.head
    6. ステップ 1 に進む

シーケンスの問題がないことを確認するために 、queue.headおよび でqueue.tailあることを確認してください(または、これらのビットをアセンブリに書き込みます)。volatile

ここで、UART 受信データ キューが、フォアグラウンド タスクが実行される機会を得る前に受信できるすべてのバイトを保持するのに十分な大きさであることを確認してください。フォアグラウンド タスクは、「メッセージ プロセッサ」タスクに渡すメッセージを構築するために、データをキューから独自のバッファにプルする必要があります。

于 2010-05-02T01:28:32.227 に答える
1

あなたが求めていることは、Cortex-M3 では非常に簡単です。ソフトウェアで優先度の低い ISR をトリガーできるように、STIR レジスタを有効にする必要があります。優先度の高い ISR が重要な処理を完了すると、優先度の低い割り込みをトリガーして終了します。NVIC は、他に重要な処理がない場合、優先度の低いハンドラーにテール チェーンします。

于 2010-11-24T00:20:32.953 に答える
0

「より公式な方法」またはむしろ従来の方法は、優先度ベースのプリエンプティブ マルチタスク スケジューラと「遅延割り込みハンドラ」パターンを使用することです。

于 2010-05-02T10:50:40.963 に答える
0

プロセッサのドキュメントを確認してください。通常は割り込み内でクリアする必要があるビットを書き込むと、一部のプロセッサが割り込みます。現在、SiLabs c8051F344 を使用しており、スペック シートのセクション 9.3.1 では次のようになっています。

「ソフトウェアは、任意の割り込み保留フラグをロジック 1 に設定することで、割り込みをシミュレートできます。フラグに対して割り込みが有効になっている場合、割り込み要求が生成され、CPU は割り込み保留フラグに関連付けられた ISR アドレスにベクトルします。」

于 2010-05-04T16:01:29.680 に答える