我正在玩 Atmel AT91SAM7S 微控制器,看起来 IRQ 处理程序应该在主管模式下执行,而主循环代码在系统模式下执行。另外,我应该保留一部分 RAM 以供主管模式代码用作堆栈。我从一个demo程序中得到的启动汇编代码默认保留128字节。
为什么我要为supervisor模式保留单独的堆栈空间;为什么不能只使用与系统模式(主)相同的堆栈?中断处理代码具有与主循环代码完全不同的堆栈有什么好处?我看到当前用于 IRQ 处理的汇编代码在跳转到中断处理程序之前从 IRQ 模式切换到主管模式。在用户模式下执行中断处理程序是否合适?如果是这样,我有什么需要注意的吗?
我问是因为如果中断有自己的堆栈,我需要估计在最坏情况下中断将使用多少堆栈空间的上限。如果中断使用与 main 相同的堆栈,则无需这样做,只要实际上有足够的 RAM 可用(这是肯定的,我不会使用那么多)。
我唯一能想到的是,如果您要实现具有某种内存保护的操作系统,那么拥有一个单独的堆栈会很有用。但既然我不这样做,那有关系吗?
PS 我熟悉 AVR 及其中断处理。
澄清
当 CPU 跳转到地址 0x18 时,中断处理似乎开始了,该地址包含到AT91F_Irq_Handler
下面的分支指令。据我所知,处理器自动进入中断模式;根据触发的中断线,此程序集在跳转到 (C) 函数之前切换到监督模式。它从高级中断控制器 (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}^