4.ARM_异常处理

概述

异常处理的过程:

处理器在正常执行程序的过程中可能会遇到一些不正常的事件发生,这时处理器就要将当前的程序暂停下来转而去处理这个异常的事件,异常事件处理完成之后再返回到被异常打断的点继续执行程序。

什么是异常处理机制:

异常处理机制就是处理器在遇到异常时的处理方法,不同的处理器的异常处理机制是不同的。

对于不同的处理器,异常处理机制大致相同,但在细节上有所不同。比如处理器认为哪些事情是异常、处理异常的动作是什么,如何跳转到异常处理程序、如何处理异常,跳到异常处理程序后要做些什么、异常处理结束后如何返回断点。

什么是异常源:

异常源就是处理器认为哪些事情是异常,不同的处理器的异常源是不同的。对于ARM的异常源如下:

异常源种类含义
FIQ快速中断请求引脚有效
IRQ外部中断请求引脚有效
Reset复位电平有效
Software Interrupt执行swi指令,软中断
Data Abort数据终止,CPU读数据时出现问题
Prefetch Abort指令预取终止,CPU读指令时出现问题
Undefined Instruction遇到不能处理的指令,CPU读取的指令不认识

注意:这里的FIQ、IRQ、Abort、Undefined这些都是异常源种类,而不是ARM模式。尽管它们的名字类似但完全没有关系。

异常模式:

ARM模式有8种,分别是User、FIQ、IRQ、SVC、Abort、Undef、System、Monitor,其中FIQ、IRQ、SVC、Abort、Undef这五个属于异常模式。异常源对应的ARM模式关系如下:

比如:当CPU获取到了Data Abort或者Prefetch Abort这两种异常源时,CPU会切换到Abort模式。

具体的ARM模式见博文:"2.ARM_ARM是什么" - "ARM概述" - "5、ARM工作模式"。博文链接如下:2.ARM_ARM是什么-优快云博客

异常处理的实现过程

1、相关过程

异常处理的实现过程比较复杂,但最终要完成的目的都是 "将当前的程序暂停下来转而去处理这个异常的事件,异常事件处理完成之后再返回到被异常打断的点继续执行程序" 这个过程。

1.1 产生异常后

ARM产生异常后,这个节点在上图的1位置。CPU所做的事情如下,这些事情是CPU自动完成的。

拷贝CPSR的内容到SPSR_<mode>

这一步的目的是保存现场,以便于CPU处理完异常后恢复现场。因为CPU在接收到异常后会进入对应的模式,并且需要做一些处理事件,而CPSR存储的是当前CPU的状态,所以在CPU处理中断时CPSR会被修改,因此需要备份CPSR,从而在异常处理结束后能够恢复原CPU的状态

比如:CPU接收到了Data Abort的异常源,该异常源对应的模式是Abort,那么就会将CPSR拷贝到SPSR_abt

修改CPSR

修改的内容:禁止FIQ和IRQ的响应、修改模式位进入相应的模式、修改状态位进入ARM状态

疑惑:禁止了IRQ、FIQ,那STM32是如何实现中断抢占的。

保存返回地址到LR_<mode>

这一步的目的也是保存现场,以便于CPU处理完异常后能够返回原程序的中断节点位置继续执行。LR中保存的是PC指向的当前指令的下一条指令的地址

比如:CPU接收到了Data Abort的异常源,该异常源对应的模式是Abort,那么将中断节点的地址保存到R14_abt。

设置PC为相应的异常向量

这时PC跳转到的是异常相邻表对应的地址,这并不是异常处理程序,而是CPU设置的一个固定的地址空间。

比如:CPU接收到了Data Abort的异常源,在异常向量表中规定的Data Abort异常源对应的内存地址是0x10,那么这之后PC = 0x10。

1.2 异常处理

ARM异常处理时,这个节点在上图的2位置。

异常处理程序由自己编写,CPU通过异常向量表的指向,跳转到你自行编写的异常处理程序去执行。

1.3 异常返回

ARM异常返回时,这个节点在上图的3位置。

拷贝SPSR_<mode>的内容到CPSR

这一步的目的是恢复现场,主要是恢复CPU的状态。因为在异常处理时CPSR的内容被改变,再次回到用户模式执行代码时需要对CPSR进行恢复。

拷贝LR_<mode>的内容到PC 

这一步的目的也是恢复现场,主要是指定CPU运行代码的位置。因为异常处理函数与主要逻辑的代码并不是在一起的,因此需要在执行完异常处理函数后再跳回断点处,继续执行主要逻辑的代码。

2、知识点补充

中断抢占:

同等优先级的中断不能被打断,高优先级的中断可以抢占低优先级的中断。

当处理中断时IRQ位被置1,代表禁止IRQ的中断,此时FIQ未被置1。当CPU接收到FIQ后,会抢占IRQ,先去处理FIQ的事件,处理完成之后再返回IRQ处理,处理完成IRQ之后再返回正常程序。

因此在ARM产生异常后,当该异常为IRQ时,会修改CPSR禁止IRQ响应,但不禁止FIQ响应;当当该异常为FIQ时,IRQ和FIQ都会禁止。

处理SWI的CPSR修改值:

当处理软中断时,IRQ位被置1,FIQ未被置1。效果与处理IRQ的效果一样。

异常向量表:

异常向量表的本质就是内存种的一段代码,总空间占有32字节,每4个字节表示一个异常源的入口。偏移地址与异常向量表的对应关系如下:

偏移地址异常向量表
0x00Reset
0x04Undef
0x08SWI
0x0CPrefetch Abort
0x10Data Abort
0x14Reserved(保留,无意义)
0x18IRQ
0x1CFIQ

异常向量表规定了每个异常源只有4个字节的空间,这代表该地址下并不是存放异常处理函数原型的代码,而是存放了一条ARM指令,用于跳转到指定的异常处理函数原型的代码。

异常向量表的基地址默认为0x00,对于ARM-Cortx A系列的CPU,其异常向量表可以通过协处理器进行修改基地址。

在ARM中,复位时PC指向的时0x00,因此在Reset处一般存放一个跳转到异常向量表之后的指令

异常优先级:

异常优先级就是规定当有多个异常产生时,先处理哪一个异常。具体的异常优先级规定如下:

FIQ和IRQ的区别:

FIQ和IRQ都是中断,但FIQ比IRQ处理的速度要快,具体原因如下:

  • FIQ在异常向量表位于最末

因为FIQ在异常向量表位于最末,所以不像IRQ只有4字节的空间存储跳转数据,而是可以直接在FIQ的中断向量表后直接写异常处理函数,这样就省去了跳转步骤。

  • FIQ模式有5个私有寄存器(R8-R12)

因为FIQ存在私有的寄存器, 而IRQ的寄存器与User模式下的寄存器是共用的,所以IRQ在使用寄存器时需要先压栈User部分的内容,再进行寄存器的使用;而FIQ的寄存器是私有的,就少去了压栈的过程。

  • FIQ的优先级高于IRQ

因为优先级高,所以FIQ可以抢占IRQ,这样FIQ就是先执行的,因此反应速度快。 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值