Atmel AT91SAM7S マイクロコントローラーをいじっていますが、IRQ ハンドラーはスーパーバイザー モードで実行され、メイン ループ コードはシステム モードで実行されるようです。さらに、RAM の特定の部分を予約して、スーパーバイザー モード コードでスタックとして使用することになっています。デモ プログラムから取得したスタートアップ アセンブリ コードは、既定で 128 バイトを予約しています。
スーパーバイザー モード用に別のスタック スペースを予約する必要があるのはなぜですか。システムモード(メイン)と同じスタックを使用できないのはなぜですか?メイン ループ コードとはまったく異なるスタックを持つ割り込み処理コードの利点は何ですか? IRQ 処理の現在のアセンブリ コードは、割り込みハンドラにジャンプする前に IRQ モードからスーパーバイザ モードに切り替わっていることがわかります。代わりにユーザーモードで割り込みハンドラを実行するのが適切でしょうか? もしそうなら、私が注意する必要があることはありますか?
割り込みに独自のスタックがある場合、最悪の場合に割り込みによって使用されるスタック領域の上限を見積もる必要があるためです。割り込みがメインと同じスタックを使用する場合、実際に十分な RAM が利用可能である限り、それを行う必要はありません (これは確かに、それほど多くは使用しません)。
私が考えることができる唯一のことは、何らかのメモリ保護を備えたオペレーティング システムを実装している場合、別のスタックを用意すると便利だということです。しかし、私はそれをしていないので、それは問題ですか?
PS 私は AVR とその割り込み処理に精通しています。
明確化
CPU がアドレス 0x18 にジャンプすると、割り込み処理が開始されるようです。このアドレスには、次の への分岐命令が含まれていAT91F_Irq_Handler
ます。私の知る限り、プロセッサは自動的に割り込みモードに入ります。このアセンブリは、どの割り込みラインがトリガーされたかに応じて、(C) 関数に分岐する前にスーパーバイザーモードに切り替わります。Advanced Interrupt Controller (AIC) から分岐アドレスを取得します。
AT91F_Irq_Handler:
/* Manage Exception Entry */
/* Adjust and save LR_irq in IRQ stack */
sub lr, lr, #4
stmfd sp!, {lr}
/* Save r0 and SPSR (need to be saved for nested interrupt) */
mrs r14, SPSR
stmfd sp!, {r0,r14}
/* Write in the IVR to support Protect Mode */
/* No effect in Normal Mode */
/* De-assert the NIRQ and clear the source in Protect Mode */
ldr r14, =AT91C_BASE_AIC
ldr r0 , [r14, #AIC_IVR]
str r14, [r14, #AIC_IVR]
/* Enable Interrupt and Switch in Supervisor Mode */
msr CPSR_c, #ARM_MODE_SVC
/* Save scratch/used registers and LR in User Stack */
stmfd sp!, { r1-r3, r12, r14}
/* Branch to the routine pointed by the AIC_IVR */
mov r14, pc
bx r0
/* Manage Exception Exit */
/* Restore scratch/used registers and LR from User Stack */
ldmia sp!, { r1-r3, r12, r14}
/* Disable Interrupt and switch back in IRQ mode */
msr CPSR_c, #I_BIT | ARM_MODE_IRQ
/* Mark the End of Interrupt on the AIC */
ldr r14, =AT91C_BASE_AIC
str r14, [r14, #AIC_EOICR]
/* Restore SPSR_irq and r0 from IRQ stack */
ldmia sp!, {r0,r14}
msr SPSR_cxsf, r14
/* Restore adjusted LR_irq from IRQ stack directly in the PC */
ldmia sp!, {pc}^