这些小活动你都参加了吗?快来围观一下吧!>>
电子产品世界 » 论坛首页 » 嵌入式开发 » MCU » RealView编译器中断嵌套的方法

共1条 1/1 1 跳转至

RealView编译器中断嵌套的方法

助工
2008-09-23 14:34:19     打赏

更多文章请访问 www.realview.com.cn 
重入中断处理程序
如果中断处理程序再次激活了中断,然后调用一个子例程,并且产生了另个一中断,则在第二个 IRQ 产生时,存储在 lr_IRQ 中的子例程的返回地址将被破坏。 在 C 语言中使用 __irq 关键字不会对 SPSR 进行存储和恢复,而这是重入中断处理程序所要求的,因此必须使用汇编语言编写顶层中断处理程序。

在跳转到嵌套子例程或 C 函数前,重入中断处理程序必须保存 IRQ 状态、切换处理器模式并为新的处理器模式保存状态。 还必须确保堆栈对新的处理器模式是 8 字节对齐的,然后才能调用符合 AAPCS 编译的 C 代码,该代码可能使用 LDRD 或 STRD 指令或 8 字节对齐堆栈分配的数据。 有关堆栈对齐问题的详细信息,请参阅 ARM 网站上的 ABI for the ARM Architecture Advisory Note - SP must be 8-byte aligned on entry to AAPCS-conforming functions(ARM 体系结构的 ABI 告知说明 - 进入符合 AAPCS 的函数时 SP 必须是 8 字节对齐的)(ARM GENC-007024)。

在 ARMv4 及以后版本可切换至系统模式。 系统模式使用了用户模式寄存器,并启用您的异常处理程序可能需要的特权访问。 有关详细信息,请参阅 系统模式。 相反,在 ARMv4 之前的 ARM 体系结构中,必须切换到超级用户模式。

Note
该方法适用于 IRQ 和 FIQ 中断。 但是,因 FIQ 中断是最先得到服务的,而通常仅有一个中断源,所以,可能不必提供重入特性。

IRQ 处理程序中安全地再次激活中断所需的步骤如下:

构造返回地址并保存在 IRQ 堆栈中。

保存工作寄存器、非被调用方保存的寄存器以及 spsr_IRQ。

清除中断源。

切换至系统模式,保持禁用 IRQ。

检查堆栈是否是 8 字节对齐的,在必要时进行调整。

保存用户模式链接寄存器以及所做的调整,体系结构 v4 或 v5TE 的 SP_usr 使用 0 或 4。

再次激活中断并调用 C 中断处理程序函数。

C 中断处理程序返回时,禁用中断。

恢复用户模式链接寄存器和堆栈调整值。

必要时重新调整堆栈。

切换到 IRQ 模式。

恢复其他寄存器和 spsr_IRQ。

从 IRQ 返回。

Example 6.15 显示了对于 ARMv4/v5TE 处理器,这些步骤在系统模式下的实现。 Example 6.16 适用于 ARMv6 处理器。

Example 6.15.


    PRESERVE8

    AREA INTERRUPT, CODE, READONLY

    IMPORT C_irq_handler

 

IRQ

    SUB     lr, lr, #4             ; construct the return address

    STR     lr, [sp, #-4]!         ; and push the adjusted lr_IRQ

    MRS     r14, SPSR              ; copy spsr_IRQ to r14

    STMFD   sp!, {r0-r4,r12, r14}  ; save AAPCS regs and spsr_IRQ

    BL identify_and_clear_source

    MSR     CPSR_c, #0x9f          ; switch to SYS mode, IRQ is

                                   ; still disabled. USR mode

                                   ; registers are now current.

    AND     r1, sp, #4             ; test alignment of the stack

    SUB     sp, sp, r1             ; remove any misalignment (0 or 4)

    STMFD   sp!, {r1, lr}          ; store the adjustment and lr_USR

    MSR     CPSR_c, #0x1f          ; enable IRQ

    BL      C_irq_handler          ; branch to C IRQ handler

    MSR     CPSR_c, #0x9f          ; disable IRQ, remain in SYS mode

    LDMFD   sp!, {r1,lr}           ; restore stack adjustment and lr_USR

    ADD     sp, sp, r1             ; add the stack adjustment (0 or 4)

    MSR     CPSR_c, #0x92          ; switch to IRQ mode and keep IRQ

                                   ; disabled. FIQ is still enabled.

    LDMFD   sp!, {r0-r4, r12, r14} ; restore registers and

    MSR     SPSR_csxf, r14         ; spsr_IRQ

    LDMFD   sp!, {pc}^             ; return from IRQ.

    END


Example 6.16. 嵌套中断(ARMv6,非向量中断)


IRQ_Handler

    SUB lr, lr, #4

    SRSFD #0x1f!               ; Save LR_irq and SPSR_irq to System mode stack

    CPS #0x1f                      ; Switch to System mode

    STMFD sp!, {r0-r3,r12}         ; Store other AAPCS registers

    AND r1, sp, #4

    SUB sp, sp, r1

    STMFD sp!, {r1, lr}

    BL identify_and_clear_source

    CPSIE i                        ; Enable IRQ

    BL C_irq_handler

    CPSID i                        ; Disable IRQ

    LDMFD sp!, {r1,lr}

    ADD sp, sp, r1

    LDMFD sp!, {r0-r3, r12}        ; Restore registers

    RFEFD sp!                      ; Return using RFE from System mode stack


这些示例假设 FIQ 为永久启用。




关键词: RealView     编译器     中断     嵌套     方法     模式    

共1条 1/1 1 跳转至

回复

匿名不能发帖!请先 [ 登陆 注册 ]