ECOS对于ARM平台异常的处理分析

首先异常向量表的代码如下:

__exception_handlers:
#ifdef CYGSEM_HAL_ROM_RESET_USES_JUMP
// Assumption:  ROM code has these vectors at the hardware reset address.
// A simple jump removes any address-space dependencies [i.e. safer]
        b       reset_vector                    // 0x00
#else        
        ldr     pc,.reset_vector                // 0x00
#endif        
        ldr     pc,.undefined_instruction       // 0x04
        ldr     pc,.software_interrupt          // 0x08 start && software int
        ldr     pc,.abort_prefetch              // 0x0C
        ldr     pc,.abort_data                  // 0x10
#ifdef CYGNUM_HAL_ARM_VECTOR_0x14
        .word   CYGNUM_HAL_ARM_VECTOR_0x14
#else
        .word   0                               // unused
#endif
        ldr     pc,.IRQ                         // 0x18
        ldr     pc,.FIQ                         // 0x1C


对于undefined/software/abort/prefech异常来说,依次眺望以下标号位置:

        .code   32
undefined_instruction:
        ldr     sp,.__undef_exception_stack     // get good stack
        stmfd   sp!,{r0-r5}                     // save some supervisor regs
        mrs     r1,spsr
        tst     r1,#CPSR_THUMB_ENABLE
        subeq   r0,lr,#4                // PC at time of interrupt (ARM)
        subne   r0,lr,#2                // PC at time of interrupt (thumb)
        mov     r2,#CYGNUM_HAL_EXCEPTION_ILLEGAL_INSTRUCTION
        mov     r3,sp
        b       call_exception_handler

        .code   32
software_interrupt:
        stmfd   sp!,{r8}
        ldr     r8,.__undef_exception_stack     // get good stack
        stmfd   r8!,{r0-r5}                     // save some supervisor regs
        mov     r3,r8
        ldmfd   sp!,{r8}
        mrs     r1,spsr
        tst     r1,#CPSR_THUMB_ENABLE
        subeq   r0,lr,#4                // PC at time of SWI (ARM)
        subne   r0,lr,#2                // PC at time of SWI (thumb)
        mov     r2,#CYGNUM_HAL_EXCEPTION_INTERRUPT
        b       call_exception_handler

        .code   32
abort_prefetch:
        ldr     sp,.__undef_exception_stack     // get good stack
        stmfd   sp!,{r0-r5}                     // save some supervisor regs
        sub     r0,lr,#4                        // PC at time of interrupt
        mrs     r1,spsr
        mov     r2,#CYGNUM_HAL_EXCEPTION_CODE_ACCESS
        mov     r3,sp
        b       call_exception_handler

        .code   32
abort_data:
        ldr     sp,.__undef_exception_stack     // get good stack
        stmfd   sp!,{r0-r5}                     // save some supervisor regs
        sub     r0,lr,#4                        // PC at time of interrupt
        mrs     r1,spsr
        mov     r2,#CYGNUM_HAL_EXCEPTION_DATA_ACCESS
        mov     r3,sp
        b       call_exception_handler


对于IRQ和FIQ的处理如下:

1、发生FIQ或者IRQ时首先跳转到异常向量表对应类型的向量跳转指令,对于IRQ和FIQ而言,处理过程基本一致,FIQ会多一点处理,所以以下分析从FIQ中断开始;

2、首先检查中断发生前的处理器模式;

        // We can get here from any non-user mode.
        mrs     r8,spsr                 // CPSR at time of interrupt
        and     r9,r8,#CPSR_MODE_BITS   // isolate pre-interrupt mode
        cmp r9,#CPSR_IRQ_MODE
        bne 1f

3、如果在IRQ中发生FIQ中断,则关闭FIQ中断,并立刻返回继续处理之前的IRQ中断;

        // If FIQ interrupted IRQ mode, just return with FIQ disabled.
        // The common interrupt handling takes care of the rest.
        orr r8,r8,#CPSR_FIQ_DISABLE
        msr spsr,r8
        subs pc,lr,#4

4、如果在其他模式中发生FIQ中断,则保存中断发生前的CPSR和PC地址保存到临时堆栈中,禁止IRQ和FIQ,进入IRQ模式,把先前临时堆栈中的CPSR和PC地址恢复到IRQ模式下对应的SP和LR寄存器中;

IRQ模式         SP寄存器 = FIQ中断发生前的处理器CPSR

                        LR寄存器 = FIQ中断发生前的处理器运行地址

                        SPSR = FIQ中断发生前的处理器CPSR

说明:由于FIQ中断保存的中断前处理器CPSR和PC地址已经转移到IRQ模式下保存起来了,所以以下的处理对于FIQ和IRQ都一样;

===================================================================

 

5、将中断发生前的R0-R5状态存入临时堆栈,因为后面的处理需要占用这些寄存器;然后依次初始化R1-R5如下:

R0 = 中断发生时的PC地址

R1 = 中断发生时的CPSR

R2 = 中断向量index

R3 = 临时堆栈指针

R4 = 当前中断模式下的CPSR

R5 = ??

 

6、切换到Supervisor Mode,在该模式下禁止FIQ中断,将当前模式的svc_sp,、当前模式的svc_lr、中断向量index、中断发生时的CPSR、中断发生时的PC地址依次压入堆栈,注意此时的堆栈为Supervisor Mode已经初始化的地址;

 Supervisor Mode下的堆栈寄存器

Supervisor Mode下的链接寄存器

中断向量index

中断发生时的CPSR

中断发生时的PC地址    <===SP

 

7、如果中断前处于USER模式,则需要往堆栈中继续保存其他寄存器,包括r8-r12, sp, lr;Supervisor Mode下堆栈的数据分布如下:

Supervisor Mode下的堆栈寄存器

Supervisor Mode下的链接寄存器

中断向量index

中断发生时的CPSR

中断发生时的PC地址

User mode下的LR寄存器

User mode下的SP寄存器

User mode下的R12-R8寄存器    <===SP

 

8、如果中断前不是处于USER模式,则将Supervisor Mode下的SP和CPSR分别暂存到R0和R2中;然后切换回中断前的模式(需要禁止FIQ和IRQ,ARM状态);

R0 = Supervisor Mode下的SP寄存器

R2 = Supervisor Mode下的CPSR寄存器

在中断前的模式下,把r8-r12,sp,lr保存到Supervisor Mode下的堆栈空间;然后切换回Supervisor Mode,同时要更新当前模式下堆栈指针;

 Supervisor Mode下的堆栈寄存器

Supervisor Mode下的链接寄存器

中断向量index

中断发生时的CPSR

中断发生时的PC地址

中断前mode下的LR寄存器

中断前mode下的SP寄存器

中断前mode下的R12-R8寄存器    <===SP

 

10、无论中断前是否处于USER模式,都会跳到此步骤;将之前保存到临时堆栈的R0-R5以及没有改动的R6/R7一起保存到Supervisor Mode下的堆栈中;此时当前模式堆栈内容如下排列:

Supervisor Mode下的堆栈寄存器

Supervisor Mode下的链接寄存器

中断向量index

中断发生时的CPSR

中断发生时的PC地址

中断前mode下的LR寄存器

中断前mode下的SP寄存器

中断前mode下的R12-R0寄存器    <===SP

 

11、
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值