6.7.3. リエントラント割り込みハンドラ

割り込みハンドラが割り込みを再イネーブルしてサブルーチンを呼び出した後、別の割り込みが発生すると、このサブルーチンの(lr_IRQ にストアされる)復帰アドレスは 2 番目の IRQ の発生時に破壊されます。C 言語で __irq キーワードを使用しても、リエントラント割り込みハンドラに必要な SPSR の保存と復元は行われないため、トップレベルハンドラはアセンブリ言語で記述する必要があります。

リエントラント割り込みハンドラは、IRQ 状態を保存し、プロセッサモードを切り替え、入れ子のサブルーチンまたは C 関数に分岐する前に新しいプロセッサモードの状態を保存する必要があります。

ARMv4 以上では、システムモードに切り替えることができます。システムモードではユーザモードレジスタを使用しながら、例外ハンドラで必要とされる可能性がある特権アクセスが可能です。詳細については、システムモードを参照して下さい。ARMv4 よりも前の ARM アーキテクチャでは、この処理を行う場合にはスーパーバイザモードに切り替える必要があります。

Note

この方法は、IRQ と FIQ の両方の割り込みに使用できます。しかし、FIQ 割り込みはできるだけ速く処理されるうえ、通常は 1 つの割り込みソースしか存在しないため、リエントラントな機能が実装される必要はないかもしれません。

IRQ ハンドラで安全に割り込みを再イネーブルするには、以下の手順に従って下さい。

  1. 復帰アドレスを作成し、IRQ スタックに保存します。

  2. 作業レジスタと spsr_IRQ を保存します。

  3. 割り込みソースをクリアします。

  4. システムモードに切り替え、割り込みを再イネーブルします。

  5. ユーザモードのリンクレジスタと、被発呼側で保存されないレジスタを保存します。

  6. C 言語の割り込みハンドラ関数を呼び出します。

  7. C 言語の割り込みハンドラが復帰するとき、ユーザモードレジスタを復元し、割り込みをディセーブルします。

  8. IRQ モードに切り替え、割り込みをディセーブルします。

  9. 作業レジスタと spsr_IRQ を復元します。

  10. この IRQ から復帰します。

Example 6.15 は、システムモードでの方法を示しています。レジスタ r12 および r14 は、lr_IRQ がスタックにプッシュされた後に一時作業レジスタとして使用されます。

Example 6.15. 

    PRESERVE8

    AREA INTERRUPT, CODE, READONLY
    IMPORT C_irq_handler
IRQ
    SUB     lr, lr, #4        ; construct the return address
    STMFD   sp!, {lr}         ; and push the adjusted lr_IRQ
    MRS     r14, SPSR         ; copy spsr_IRQ to r14
    STMFD   sp!, {r12, r14}   ; save work regs and spsr_IRQ

    ; Add instructions to clear the interrupt here
    ; then re-enable interrupts.


    MSR     CPSR_c, #0x1F     ; switch to SYS mode, FIQ and IRQ
                              ; enabled.USR mode registers
                              ; are now current.
    STMFD  sp!, {r0-r3, lr}   ; save lr_USR and non-callee
                              ; saved registers
    BL      C_irq_handler     ; branch to C IRQ handler.
    LDMFD   sp!, {r0-r3, lr}  ; restore registers
    MSR     CPSR_c, #0x92     ; switch to IRQ mode and disable
                              ; IRQs.FIQ is still enabled.

    LDMFD   sp!, {r12, r14}   ; restore work regs and spsr_IRQ
    MSR     SPSR_cf, r14
    LDMFD   sp!, {pc}^        ; return from IRQ.
     END

このサンプルでは、FIQ が永久にイネーブルされていると想定されています。

Copyright © 2002-2006 ARM Limited. All rights reserved.ARM DUI 0203GJ
Non-Confidential