新闻中心

EEPW首页>嵌入式系统>设计应用> ARM的异常处理过程分析

ARM的异常处理过程分析

作者: 时间:2016-12-01 来源:网络 收藏
异常类型
Mode
异常向量
内容
IRQ异常
IRQ
0x00000018
LDR PC,[PC,#0x18]或者0xE59FF018
IFQ异常
IFQ
0x0000001C
LDR PC,[PC,#0x18]
0xE59FF018
0x00000038
Address of OS_CPU_ARM_ExceptIrqHndlr()
0x0000003C
Address of OS_CPU_ARM_ExceptFiqHndlr()
有必要的讨论一下,为什么在向量中存储的是指令: LDR PC,[PC,#0x18],我们从上面的地址可以知道,IRQ异常处理函数地址被存储到了0x00000038中,异常向量与该地址之间的差值是0x20,那么为什么在其中存储的值只是0x18呢?这还要讨论ARM的流水线结构,当前执行的命令相比PC指向的地址差0x08。也就是当前执行的指令的地址是PC-0x08.当PC指向异常向量以后(取值),还需要等待一个时钟(译码)之后才会被执行(真正意义上的执行操作),而这时PC值已经被更新了。指向了Vector+0x8的位置,因此我们可以知道,当执行向量中的代码时,这时PC=Vector+0x8,而这时相对于固定的0x20-0x08=0x18,这也就是为什么是LDR PC,[PC,#0x18],而不是LDR PC,[PC,#0x20].
采用上面的例子说明IRQ的向量为0x00000018,而设定好的固定地址用来存储对应异常处理函数地址的地址是0x00000038,当CPU执行完PC = 0x00000018以后,还需要译码、才能被执行,这时候PC值已经更新为PC = 0x00000018 + 0x08;这时候固定地址距离PC的相对位置位0x00000038 – PC = 0x18,而该地址中保存了IRQ中断的通用处理函数OS_CPU_ARM_ExceptIrqHndlr()的地址,LDR PC,[PC,#0x18]这条指令是指将PC+0x18地址处的内容加载到PC中,实质上也就完成跳转到异常处理函数的操作。
这样处理的好处是因为LDR的加载范围是一个固定值+-32M,我们不能保证异常处理程序的地址刚好在+-32M左右,采用这种LDR PC, ADDR(固定地址)的形式就能实现大范围的跳转操作。
我们仅仅以FIQ中断处理的形式进行讨论,其他的异常有一定的相似性,只是在返回地址上存在差别。这段代码主要是完成寄存器的压栈,返回地址的调整,保存等操作。具体的看下面的分析:
AREA CODE, CODE, READONLY
CODE32
OS_CPU_ARM_ExceptFiqHndlr
;修改中断返回地址,这属于进入真正处理函数前的返回地址调整,具体的返回地址依据前面保存的R14进行相应的修改。
SUB LR, LR, #4 ; LR offset to return from this exception: -4.
;压栈操作
STMFD SP!, {R0-R12, LR} ; Push working registers.
;保存链接寄存器
MOV R2, LR ; Save link register.
;设置好ID号,这是非常必要的,只有这样才能辨别属于那种异常
MOV R0, #OS_CPU_ARM_EXCEPT_FIQ ; Set exception ID
/*跳转到通用的异常处理函数,传递的参数是异常ID号*/
BOS_CPU_ARM_ExceptHndlr ; Branch to global exception handler.
OS_CPU_ARM_ExceptHndlr(except_type)是一个通用的异常处理函数,可以对除了IRQ以外的其他异常进行控制操作。在这个通用处理函数中又调用了下面的函数OS_CPU_ARM_ExceptHndlr_BreakExcept()或者OS_CPU_ARM_ExceptHndlr_BreakTask()。这两个函数中又调用了通用处理函数OS_CPU_ExceptHndlr(),然后OS_CPU_ExceptHndlr()中调用具体的中断处理操作。
一般的OS_CPU_ExceptHndlr()处理形式,可以认为是一个模板如下:
void OS_CPU_ExceptHndlr (INT32U except_type)
{
/* Determine behavior according to exception type (except_type) */
/* If an IRQ or FIQ,具体的可能要使用中断向量等形式实现*/
while (there are interrupting devices) {
/* Clear interrupting device */
OS_CPU_SR_INT_En(); /* Enable nesting, if desired */
/* Handle interrupt */
}
}
这是其中的一段关于IRQ中断的文字复述:
IRQ中断的基本的流程图如下:
以上的uC/OS-II异常处理就分析完了,这种方式的实现实质上是采用了通用模板的形式,这样实现出来的形式只需要控制一定的,具体的一些IRQ中断处理函数(如定时器,GPIO等的中断),与具体的厂商有很大的关系,有的厂商采用硬件寄存器的方式进行设计,有的采用软件方式实现,因此具体的中断。
后面我再分析我们通常认为的中断(实质上就是IRQ和IFQ中某一个具体中断)处理方式
上一页 1 2 3 下一页

评论


技术专区

关闭