我正在使用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}^
答案 0 :(得分:3)
您不必将主管r13 用作堆栈。您可以将其用作通用寄存器来保存某些内容,然后转换到系统模式并在该模式下运行 ISR 的其余部分。它很灵活,如果你愿意,你可以有一个不同的堆栈;你不像其他建筑一样手铐。您可以使用一些保存区域指针填充 supervisor r13 ,或者通常将指针(或双指针)填充到当前正在执行的任务中。如果您希望 ISR 返回,则需要保存lr
,spsr
以及任何其他将被破坏的寄存器。我认为最初,正常的ARM将处于中断模式;也许你有一些其他处理程序已经转换到管理员模式? 系统模式通常具有内核堆栈/任务控制块,并且它在多任务系统中切换。 管理员模式是异常处理的常用模式。
如果您只有一个任务并且想要使用它的堆栈,则可以使用以下内容。在 supervisor 中保存上下文后,转换到系统模式并执行 ISR 的其余部分。只需恢复包括lr
和cpsr
在内的寄存器,即可返回正确的模式,程序计数器和条件代码。
你当然有选项将 supervisor r13 用作异常堆栈,许多人可能会喜欢有限行为和更快的IRQ延迟,因为堆栈是预设并准备好由主 ISR 正文使用。