私は Arduino Uno (素晴らしい小さなデバイス!)を持っています。 2つの割り込みがあります。それらをおよび1と呼びましょう。 attachInterrupt()
を使用して、割り込み0にハンドラーをアタッチし、割り込み1に別のハンドラーをアタッチします。 http://www.arduino.cc/en/Reference/AttachInterrupt を使用します。
割り込みがトリガーされ、ハンドラーを呼び出します。ハンドラーは、いくつかの処理を実行します。割り込み1がトリガーされたときに、割り込みのハンドラーがまだ実行中の場合、 何が起こるか?
中断する1中断する割り込み、または中断する1割り込みのハンドラの実行が完了するまで待機しますか?
この質問は特にArduinoに関連していることに注意してください。
Arduino(別名AVR)ハードウェアでは、意図的に発生を許可する条件を作成しない限り、ネストされた割り込みは発生しません。
Avr-libから:
AVRハードウェアは、割り込みベクトルに入る前にSREGのグローバル割り込みフラグをクリアします。したがって、通常、割り込みはハンドラーが終了するまでハンドラー内で無効のままになり、そこでRETI命令(コンパイラーが割り込みハンドラーの通常の関数エピローグの一部として発行する)は、最終的にさらに割り込みを再度有効にします。そのため、通常、割り込みハンドラはネストしません。ほとんどの割り込みハンドラーでは、これが望ましい動作です。無限に再帰的な割り込み(UART割り込み、またはレベルトリガーによる外部割り込みなど)を防ぐために必要な場合もあります。まれな状況では、割り込みハンドラでできるだけ早くグローバル割り込みフラグを再度有効にして、他の割り込みを絶対に必要以上に遅延させないようにすることが望ましい場合があります。これは、割り込みハンドラーですが、これにより、コンパイラーが生成した関数プロローグ内に、グローバル割り込みを無効にして実行するいくつかの命令が残ります。
割り込み1は割り込み0を割り込みますか、それとも割り込み1は割り込み0のハンドラの実行が完了するまで待機しますか?
ISR(Interrupt Service Routine)内で割り込みを明確に再度有効にしない限り、現在実行中の割り込みはすべて完了し、次の割り込みが処理される前に、さらに1つのマシンコード命令が完了します。
ほとんど割り込みは、割り込みを処理する必要があるかどうかを確認するために、命令間でチェックされるプロセッサ内のフラグを設定します。フラグは優先順にチェックされます。宇野でそれは:
1 Reset
2 External Interrupt Request 0 (pin D2) (INT0_vect)
3 External Interrupt Request 1 (pin D3) (INT1_vect)
4 Pin Change Interrupt Request 0 (pins D8 to D13) (PCINT0_vect)
5 Pin Change Interrupt Request 1 (pins A0 to A5) (PCINT1_vect)
6 Pin Change Interrupt Request 2 (pins D0 to D7) (PCINT2_vect)
7 Watchdog Time-out Interrupt (WDT_vect)
8 Timer/Counter2 Compare Match A (TIMER2_COMPA_vect)
9 Timer/Counter2 Compare Match B (TIMER2_COMPB_vect)
10 Timer/Counter2 Overflow (TIMER2_OVF_vect)
11 Timer/Counter1 Capture Event (TIMER1_CAPT_vect)
12 Timer/Counter1 Compare Match A (TIMER1_COMPA_vect)
13 Timer/Counter1 Compare Match B (TIMER1_COMPB_vect)
14 Timer/Counter1 Overflow (TIMER1_OVF_vect)
15 Timer/Counter0 Compare Match A (TIMER0_COMPA_vect)
16 Timer/Counter0 Compare Match B (TIMER0_COMPB_vect)
17 Timer/Counter0 Overflow (TIMER0_OVF_vect)
18 SPI Serial Transfer Complete (SPI_STC_vect)
19 USART Rx Complete (USART_RX_vect)
20 USART, Data Register Empty (USART_UDRE_vect)
21 USART, Tx Complete (USART_TX_vect)
22 ADC Conversion Complete (ADC_vect)
23 EEPROM Ready (EE_READY_vect)
24 Analog Comparator (ANALOG_COMP_vect)
25 2-wire Serial Interface (I2C) (TWI_vect)
26 Store Program Memory Ready (SPM_READY_vect)
(リセットはマスクできないことに注意してください)。
低レベルの割り込みが進行している可能性があります(例:TIMER0_OVF_vect)。それがビジーである間に、他の複数の割り込みイベントが発生する可能性があります(CPUの対応するビットを設定します)。それらは、実際に時間内に発生する順序ではなく、上記の順序でサービスされます。
保留中の割り込みをキャンセルするために、つまりフラグをクリアするために書き込むことができるハードウェアレジスタがあります。
「1つ以上のマシンコード命令」について言及する理由は、プロセッサが、割り込みが有効でない割り込みから有効な割り込みに遷移するときに、常に1つの命令が常に実行されることを保証するように設計されているためです。
これにより、次のようなコードを記述できます。
interrupts (); // guarantees next instruction executed
sleep_cpu (); // sleep now
これがないと、スリープ状態になる前に割り込みが発生する可能性があります。つまり、スリープが発生する前にではなく、スリープ中にの割り込みが発生することに依存していたため、スリープが解除されることはありません。
FreescaleとAtmelのモロニックが、どちらも非常に同じ命令名を使用していますが、意味が逆になっています。
そのため、私はinterrupts
とnoInterrupts
のニーモニックを好んでいますが、その目的は非常に明確であるためです。これらは、コアインクルードファイルの定義によって実装されます。
ドキュメント Arduinoの割り込みが優先されることを述べます:
スケッチが複数のISRを使用する場合、一度に実行できるのは1つだけです。他の割り込みは、現在の割り込みが終了した後に、それらが持っている優先順位に依存する順序で実行されます。
また、追加情報へのリンクも提供します。
割り込みの詳細については、 Nick Gammonのメモ を参照してください。
セクション割り込み優先度とはとによると、割り込みが無効になっているときに割り込みが発生しますか?と結論付けることができます。
したがって、異なる割り込みは互いに割り込みません。それらは優先順位に従って実行されます。