2

我正在玩 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}^
4

1 回答 1

3

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

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

您当然可以选择监督程序 r13用作异常堆栈,许多人可能会喜欢它的有界行为和更快的 IRQ 延迟,因为堆栈已预设并可供ISR主体使用。

于 2013-09-20T20:24:41.923 回答