3

私は 8051 マイクロコントローラーでプログラミングを行っていましたが、割り込みを処理しているときに奇妙なことに気づきました。割り込みが発生したとします。その割り込みの処理中に、優先度の高い別の割り込みが発生しています。コントローラーは、優先度の高い割り込みの処理に飛び込んでから、優先度の低い割り込みに戻るべきではありませんか?

以下は私の質問を示しています。キーパッドは、外部割り込み 1 (優先度が低い) をトリガーするように配線されており、タイマー 0 割り込み (優先度が高い) が有効になっています。


// With this snippet, the LED-s are blinking as expected.
#include <8051.h>
#include <stdint.h>
#include <stdbool.h>

__xdata __at (0x9000) uint8_t KEYPAD;
__xdata __at (0xA000) uint8_t LED;

uint8_t LedState = 0x00;
bool Running = false;

void StopperIsr() __interrupt TF0_VECTOR
{
    LedState = ~LedState;
    LED      = LedState;
    TR0      = 0;   // Prevent the timer restating right away.
    Running = false;
}

void StopperStart()
{
    TL0 = 0;
    TH0 = 0;
    TR0 = 1;      // Start timer 0
    Running = true;
}

void main()
{
    ET0  = 1;     // Enable timer 0 interrupt.
    EA   = 1;     // Enable global interrupts.
    TMOD = T0_M0; // Set timer 0 to 16-bit mode.

    while(1) {
      if (false == Running) {
        StopperStart();
      }
    }
}

// The stopper is used inside external interrupt 1 ISR and since timer 0 has
// higher priority, the LED-s should be blinking just like in the previous snippet.
// This is not the case. Instead, on keypress, the ISR is called (LED gets 0xFF),
// but timer 0 ISR is never entered.
#include <8051.h>
#include <stdint.h>
#include <stdbool.h>

__xdata __at (0x9000) uint8_t KEYPAD;
__xdata __at (0xA000) uint8_t LED;

uint8_t LedState = 0x00;
bool Running = false;

void StopperStart()
{
    TL0 = 0;
    TH0 = 0;

    TR0 = 1;      // Start timer 0.
    Running = true;
}

void StopperIsr() __interrupt TF0_VECTOR
{
    LedState = ~LedState;
    LED      = LedState;

    TR0      = 0;  // Stop the timer.
    Running = false;
}

void KeypadIsr() __interrupt IE1_VECTOR
{
    LedState = 0xFF;
    LED      = LedState;

    while(1) {
      if (!Running) {
        StopperStart();
      }
    }
}

void main()
{
    EX1  = 1;     // Enable keypad interrupt on external interrupt 1.
    ET0  = 1;     // Enable timer 0 interrupt.
    TMOD = T0_M0; // Set timer 0 to 16-bit mode.
    EA   = 1;     // Enable global interrupts.
    KEYPAD = 0;   // Reset the keypad to its initial state.
}
4

2 に答える 2

4

申し訳ありませんが、ここでは完全に間違った答えが最高として受け入れられました。同時に、TurboJ は正しい答え (実際には 1 つ以上) を与えましたが、これはコメントとしてのみ表示されます。

8051 マイクロ (または複数の割り込み優先レベルを持つその他のもの) は、より高いレベルの割り込みが保留中だった場合、関連するすべての割り込みが有効になっていて、優先順位が正しく設定されている場合、完了するまで割り込みを実行しません。優先度の高い割り込みハンドラが実行されます。同じ優先順位の割り込みは、あらかじめ決められた順序でスキャンされますが、同じレベルの割り込みには割り込みできませんでした。8051 ではデフォルトですべての割り込みが同じレベルに設定されており、それが示されている例の問題でした (@TurboJ が正しく指摘しているように)

これが当てはまらない場合、いくつかの割り込み優先度レベルを持つことのポイントは何ですか? 優先度の高い割り込みハンドラが優先度の低い割り込みハンドラに割り込む概念を「割り込みネスティング」と呼びます。

于 2013-03-14T14:29:05.507 に答える
2

おそらく「同時」という言葉は間違っていると思います。それを考えると、優先順位の高い方が勝ちます。「並行」という言葉の方が適切かもしれません。プロセッサが優先度の高いものにジャンプすると思うかもしれませんが、そうではありません。1つしかありません実際のプロセッサに入る割り込みライン。したがって、プロセッサに関する限り、割り込みを処理しているか、処理していないかのどちらかです (ラインがシグナル状態かシグナル状態でないか)。複数の割り込みをその単一のラインに多重化するのに役立つ割り込みコントローラーがあり、優先度の決定に役立つのは割り込みコントローラーです。より大きなマイクロコントローラでは、割り込みコントローラとプロセッサの間にもう少し分離がありますが、8051 にはまだあります...もう少し隠されています. いずれにせよ、割り込み処理が開始されると、保留中の割り込みの方が優先度が高い場合でも、マイクロコントローラーは次の割り込みが通知される前に完了するまでその割り込みを処理します。

これがどのように機能するかの詳細については、Atmel の 8051 のハードウェア ガイドを参照してください。実装に固有のものですが、ほとんどの実装はかなり近いです (それらはすべて、元の 8051 マイクロの元のセマンティクスを維持しようとします)。ページ 2-112 で、割り込みが処理されることについて説明しています。セクション 2.16.1 は次のように述べています。

RETI 命令が検出されるまで、その場所から実行が続行されます。RETI 命令は、この割り込みルーチンが進行中ではないことをプロセッサに通知し、スタックから上位 2 バイトをポップして、プログラム カウンタをリロードします。中断されたプログラムの実行は、中断したところから続行されます

ここで重要なのは最初の行です。そのRETI命令が実行されるまで、次の割り込みは処理されません。

于 2012-09-12T07:36:08.250 に答える