ARM中断体系结构-结合软硬件分析

先概述下中断发生时的软硬件处理流程。
硬件:中断源->中断控制器筛选->CPU核保存当前工作状态,跳到对应异常向量表
软件:根据中断号,执行对应中断服务程序,执行完毕恢复各类寄存器值,并返回。

AREA INT, CODE, READONLY                                                     
IMPORT RST_DO
ENTRY    
b       RST_DO  
b       EXTENT_INSTRU
b   SWI_DO
b       ABORT_PREFETCH_DO
b       ABORT_DATA_DO
mov     R1,    R1       
b       IRQ_DO
b       FIQ_DO   

刚开始看到这部分代码会觉得比较蒙,这些指令都是无条件跳转,我们怎么知道它的具体实现逻辑呢?这就需要看技术文档结合ARM核的硬件执行过程分析。

首先,这里的八行代码对应ARM七种异常(有一行 mov R1, R1 保留)。这就是ARM对应的中断向量表,每行占4个字节,从0x00000000开设存放各类异常的发生时执行的跳转指令。当有异常发生,ARM核自动完成的事件包括:1)异常模式下的LR保存程序当前地址PC;2)异常模式的SPSR保存当前状态寄存器CPSR;3)设置PC值跳到异常向量表执行对应的指令。*也就是说一旦异常发生如IRQ中断发生,硬件会自动执行上述b IRQ_DO*
这里写图片描述
中断控制器是中断源和CPU核之间的中介。当有事件发生,硬件会设置某个寄存器,CPU每执行完一条指令都会通过硬件查看这个寄存器,根据这个寄存器的情况CPU决定是否中断当前程序流程,跳到固定的地址去处理这个事件。中断源会有很多,而ARM核只有IRQ、FIQ两者,所以需要中断控制器暂存并筛选出某个中断源给CPU核。
这里写图片描述
IRQ(普通中断)可能有多个中断源到达,中断控制器要判断哪些中断源被屏蔽掉了,再从没被屏蔽掉的中断源中选出优先级最高的中断源。FIQ(快速中断)MODE=1时表示是快速中断。FIQ每次只有一个中断能够进来所以流程更为简单。

软件需要完成的工作包括1)保存下面程序可能用到的通用寄存器;2)跳到中断服务程序进行处理;3)处理完毕,恢复通用寄存器值,把SPSR恢复到CPSR,处理LR使它为异常返回的地址给PC。

IRQ_DO      
stmfd   sp!, {r0,r1}          
ldr r0, =IRQ_R1          
str r1, [r0]
ldmfd   sp!, {r0}
ldr r1, =IRQ_R0           
str r0, [r1]   
add r13, r13, #4        
sub r14, r14, #4
mov r0, r14              
mrs r1, spsr
orr r1, r1, #0x80          
msr cpsr_cxsf, r1       
stmfd   sp!, {r0}
stmfd   sp!, {r14}
stmfd   sp!, {r1}             
dr  r0, =IRQ_R1    
ldr r1, [r0]
stmfd   sp!, {r1}   
ldr r1, =IRQ_R0    
ldr r0, [r1]
stmfd   sp!, {r0}                 
ldmfd   sp!, {r0,r1}            ;恢复原先保存的R0和R1
stmfd   sp!, {r0-r12}       ;将r0--r12全部压入中断以前模式下的堆栈

IMPORT  int_vector_handler
bl  int_vector_handler      ;跳转到中断源判断和中断处理程序
ldmfd   sp!, {r0-r12}           ;恢复原先保存的R0-R12
ldmfd   sp!, {r14}
msr cpsr_cxsf, r14
ldmfd   sp!, {r14}              ;将原先保存的SPSR_irq恢复到CPSR中
ldmfd   sp!, {pc}

中断处理是个多级的流程,跳到上述的中断处理程序bl int_vector_handler 进行中断源判断进而选出到底执行哪个中断服务程序。
这里写图片描述
定义结构体:中断源号,和其对应的中断服务程序

typedef struct int_vector{
        U8      IntNum;
        void    (*handler)(void);
}INT_VECTOR;

根据中断源号码选出对应的中断服务函数,并执行

void int_vector_handler(void)
{
    U32 intnum;
    U8 i = 0;
    intnum = *(RP)(INTC_IFSR); 
    while (intnum != 1)
    {
        intnum = intnum >> 1;
        i++;
    }
    (*vector[i].handler)(); //通过调用相应的处理函数
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值