为什么ARM管理员模式有自己的堆栈?

时间:2013-09-20 19:10:59

标签: assembly arm interrupt

我正在使用Atmel AT91SAM7S微控制器,看起来IRQ处理程序应该在管理程序模式下执行,而主循环代码在系统模式下执行。另外,我应该保留一部分RAM用作管理员模式代码的堆栈。我从演示程序中获得的启动程序集代码默认保留128个字节。

为什么我必须为管理员模式保留单独的堆栈空间;为什么它不能只使用相同的堆栈作为系统模式(主)?具有与主循环代码完全不同的堆栈的中断处理代码有什么好处?我看到IRQ处理的当前汇编代码在跳转到中断处理程序之前从IRQ模式切换到管理程序模式。改为在用户模式下执行中断处理程序是否合适?如果是这样,有什么我需要小心的吗?

我问,因为如果中断有自己的堆栈,我需要估计最坏情况下中断使用多少堆栈空间的上限。如果中断使用与main相同的堆栈,那么就没有必要这样做,只要实际上有足够的RAM可用(大多数情况下,我不会那么多)。

我唯一能想到的是,如果你正在实现一种具有某种内存保护的操作系统,那么拥有一个单独的堆栈会很有用。但既然我不这样做,那有关系吗?

P.S。我熟悉AVR及其中断处理。

澄清

当CPU跳转到地址0x18(其中包含一条到AT91F_Irq_Handler的分支指令)时,中断处理开始出现。据我所知,处理器自动进入中断模式;根据触发的中断线,该组件在分支到(C)函数之前切换到 supervisor 模式。它从高级中断控制器(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}^

1 个答案:

答案 0 :(得分:3)

您不必将主管r13 用作堆栈。您可以将其用作通用寄存器来保存某些内容,然后转换到系统模式并在该模式下运行 ISR 的其余部分。它很灵活,如果你愿意,你可以有一个不同的堆栈;你不像其他建筑一样手铐。您可以使用一些保存区域指针填充 supervisor r13 ,或者通常将指针(或双指针)填充到当前正在执行的任务中。如果您希望 ISR 返回,则需要保存lrspsr以及任何其他将被破坏的寄存器。我认为最初,正常的ARM将处于中断模式;也许你有一些其他处理程序已经转换到管理员模式系统模式通常具有内核堆栈/任务控制块,并且它在多任务系统中切换。 管理员模式异常处理的常用模式。

如果您只有一个任务并且想要使用它的堆栈,则可以使用以下内容。在 supervisor 中保存上下文后,转换到系统模式并执行 ISR 的其余部分。只需恢复包括lrcpsr在内的寄存器,即可返回正确的模式,程序计数器和条件代码。

你当然有选项 supervisor r13 用作异常堆栈,许多人可能会喜欢有限行为和更快的IRQ延迟,因为堆栈是预设并准备好由主 ISR 正文使用。