2

最初に、私はすでにこれを読んでいて、理解できなかったか、明確な答えが得られなかったと言います。私はARMを学ぼうとしているAVRの男です。ATMEL から ATSAM4LC2AA をプログラミングしています。ISR ハンドラーに遭遇した場合、グローバル割り込みを無効にする必要がありますか? もしそうなら、これは正しいコードですか?

void USARTx_Handler(void)
{
    /* Disable interrupts */
    irqflags_t flags = cpu_irq_save();

    /* Read USART Status. */
    Do_small_task();

    /* Enable interrupts */
    cpu_irq_restore(flags);
}
4

2 に答える 2

1

cpu_irq_save() は通常、割り込みを無効にせず、フラグの状態を返すだけです。現在の割り込みと優先度の低いすべての割り込みは、既に無効になっています。cpu_irq_restore(flags) は、フラグを復元します。USARTx_Handler() がフラグの状態を変更しない限り、これらの呼び出しが必要になる理由がわかりません。通常、USARTx_Handler() を呼び出す前に「コンテキスト」を保存したカーネル (オペレーティング システム) コードがいくつかあります。

これがネストされた割り込みでない場合、ARM はスレッド モードからハンドラー モードに変更され、割り込みを処理します。実際の割り込み (例外) を処理する USARTx_Handler() の外側の典型的なカーネル (オペレーティング システム) コードは、USARTx_Handler() を呼び出します。次に、USARTx_Handler(void) が戻ると、ARM を以前の状態に復元するのはカーネル コードです。スレッドモードに (ネストされた割り込み状態でない限り)。

マルチスレッド カーネル (RTOS の一部のバージョンなど) の場合、割り込み関数が戻るときに最終的に別のスレッドへのコンテキスト スイッチをもたらす割り込みハンドラーから呼び出すことができる関数が含まれる場合があります。

更新- Tedi のコメントに基づいて、cpu_irq_save() は割り込みも無効にします (割り込みを無効にする前にフラグを保存しているようです)。関数名は cpu_irq_save_and_disable_irq() のほうがよいかもしれませんが、おそらく長すぎます。ドキュメントがこれらの関数がどのように機能するかを示している限り、名前はそれほど重要ではありません。

これにより、USARTx_Handler() が呼び出された後、cpu_irq_disable が実際に割り込みを無効にする前にいつでもタイミング ウィンドウが作成され、より優先度の高い割り込みが USARTx_Handler() をプリエンプトする可能性があります。また、cpu_irq_restore() によって割り込みが有効になった後 (ここでは仮定) のいつでも、USARTx_Handler() が戻る前に、より優先度の高い割り込みが USARTx_Handler() をプリエンプトすることもできます。しかし、少なくとも cpu_irq_save() と cpu_irq_restore() の間で割り込みが無効になっていることを知っています。

USARTx_Handler() で優先度の高い割り込みを無効にしたくない場合はどうしますか? そのために必要な特別な呼び出しはありますか?

ここで使用されているカーネル/RTOS については何も知らないので、この方法で割り込みハンドラーを実装することの意味についてはわかりません。問題の 1 つは、割り込みチェーンがハンドラー モードからスレッド モードに戻るときにコンテキスト スイッチが発生するようなカーネル関数を呼び出すことができるネストされた割り込みをカーネルがサポートしている場合です。

また、NMI (ノンマスカブル割り込み) の処理方法の問題もあります。一部の RTOS はこれを処理しないため、組み込みデバイスが NMI ハンドラで特別なハードウェア ベースの割り込み (IRQ) を設定し、NMI から戻るだけで解決できます。 NMI。他の RTOS は、ネストされた IRQ や NMI からのシステム コールを処理できます。

于 2016-11-01T01:39:10.477 に答える