ARM异常处理详解

前言:

学习一门处理器最重要的就是掌握该处理器的指令集异常处理。

异常概念:

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

例如:

我现在正在学习,然后我妈叫我吃饭,这时我要停止学习去吃饭,吃完饭后我就重新到我吃饭之前学习的点继续学习。此时,吃饭就是一个异常事件    

ARM异常处理详解_第1张图片

 对于CPU,假设它在按顺序执行用户程序,而到了某一个位置,CPU要去处理异常,就会跳转到异常处理程序中,按顺序执行。

注意:用户程序和异常处理程序都是编程人员自己写的

假设我正在玩游戏,用户程序就是游戏,在玩游戏的途中,我觉得声音小了,按按钮加大声音,这时,相当于去处理异常了,跳转到了异常处理程序中,运行完后返回用户程序执行异常的那个位置。

异常与中断的区别

他们两个都是计算机系统中的事件,最重要的区别是,中断是外围设备向处理器发出的,可以理解为硬件,而异常是程序执行过程中出现的,可以理解为软件。即中断与硬件有关,异常与软件有关。

中断的产生是异步的,也就是说,它可以在任何时候发生,用于通知处理器要处理的事件,而异常的产生是同步的,也就是说,它只会在程序执行到某个特定的指令时发生,用于表示程序出现了错误或异常情况

处理中断需要保存当前程序的上下文,并跳转到中断服务程序中执行相应操作;处理异常则不需要保存当前程序的上下文,而是立即跳转到异常处理程序中处理异常情况。

异常处理机制

对于不同的处理器,他们对异常的处理流程大致相似,但是不同的处理器在具体的实现机制上有问题:比如处理器遇到哪些事件被认为是异常事件遇到异常事件后处理器有哪些操作处理器如何跳转到异常处理程序如何处理异常处理完异常后有如何返回到被打断的程序继续执行等。这些细节称为异常处理机制

ARM如何处理异常

ARM异常源

导致异常产生的事件称为异常源

上述处理机制中的第一条,处理器遇到哪些事件被认为是异常事件,就是哪些事件可以打断正在运行的程序

例如正在上课,老师叫李明出去,这只会打断李明的运行,而不会打断其他人。

ARM的7类异常源

ARM异常源
FIQ 快速中断请求引脚有效
IRQ        外部中断请求引脚有效
Reset 复位电平有效
Software Interrupt 执行swi指令
Data Abort 数据终止
Prefetch Abort 执行预取中止
Undefined Instruction 遇到不能处理的指令

异常模式

在ARM的8个基本工作模式中有5个属于异常模式,即ARM遇到异常后会切换成对应的异常模式

异常源 FIQ IRQ Reset/SWI Data Abort/Prefetch Abort Undefined Instruction
异常模式 FIQ IRQ SVC About Undef

ARM产生异常后的动作(自动完成)

  1. 拷贝CPSR中的内容到对应异常模式下的SPSR_保存内容
  2. 修改CPSR的值
    2.1 修改中断禁止位禁止相应的中断
    2.2 修改模式位进入相应的异常模式
    2.3 修改状态位进入ARM状态
  3. 保存返回地址对应d下的LR_保存地址
  4. 设置PC为相应的异常向量(异常向量表对应的地址)

ARM产生异常,会跳转去实现异常处理程序,那么这些动作怎么实现的?

如上,第一步,会将CPSR的内容拷贝到对应异常模式下的SPSR_

CPSR(Current Program Status Register):当前处理器状态

ARM异常处理详解_第2张图片

正如我们所知,ARM处理器做完异常处理后会以当前内容继续执行程序,那么就需要有一个寄存器保存CPSR(当前处理器)的值,即使用SPSR_来保存CPSR内容。

第二步,修改CPSR值。

我们已经拷贝了之前的CPSR的值,所以可以放心修改。首先要确保它在处理异常时不能被中断。

例如:

我正在写作业,我妈叫我去吃饭,那么我在吃饭的过程中,就不能有其他的中断来影响我,所以直接修改相应的禁止位。

IRQ禁止位被设置为1时,处理器将禁止所有外部中断的触发。就比如正在处理异常时,任何硬件操作信息都不能中断异常进行,但是异常优先级高的可以停止异常优先级低的先执行高优先级异常。

修改值的第二三步就好理解了,当执行异常处理程序时,模式位会变为相应异常模式,而异常处理程序的状态位是ARM状态。

第三步,保存返回地址。

正如我们所知,异常处理结束后会返回到遇到异常地址的下一个地址,不能执行完异常后自己的家都忘了在哪,所以我们需要保存返回地址,以便回到正确的家。

第四步,设置PC为相应的异常向量。

大家发现没有,看了上面三个步骤,好像都是在原地进行的,也就是在遇到异常的那个地址进行的,修改了很多,也保存了很多,但是并没有跳转到异常处理程序中。那么第四步即是跳转操作了,通过设置PC为相应的异常向量,跳转到异常处理程序中。

异常向量表是什么?

  • 异常向量表本质是内存中的一段代码
  • 表中为异常源分配了四个字节的存储空间
  • 遇到异常后处理器自动将PC修改为对应的地址,如下图,IRQ异常PC将会修改为0x18

ARM异常处理详解_第3张图片

 思考:

遇到异常后PC会跳转到异常向量表,那么我们能不能在每一个异常向量表下写我们的异常程序?这样可以跳转到对应地址后直接执行,是不是很方便?

答案:

错误,如上述第二点所知,异常向量表只为每个异常源分配了四个字节的内存,而异常程序通常很大,四个字节肯定装不下,所以这种方法是错误的。

那么在对应的异常向量表中,会写一个跳转程序使其跳转到你自己写的异常处理程序入口

ARM异常执行结束后,返回的动作(自己编写)

  1. 将SPSR_的值复制给CPSR,使处理器恢复之前的状态(内容
  2. 将LR_的值复制给PC,使程序跳转回被打断的地址继续执行(地址

至此,ARM遇到异常并执行的过程就是这样

总结一下:

网卡或者其他程序发出异常(假设为IRQ),在遇到异常而没跳转之前,那么会执行开头四步骤,赋值,修改,存地址,PC跳转,其中修改操作要进行三步,中断、模式、状态,PC要跳转到对应的异常向量表的异常源地址。这样实现了跳转操作。跳转后,每一个异常源里有跳转程序,这时才跳转到自己写的异常处理程序入口,也就是说跳转到执行异常程序经历了两次跳转。执行过程就是自己写的程序那样执行,执行结束后,会将之前赋值给SPSR_(存放的内容)值赋值给CPSR,而LR_(存放的地址)赋值给PC,使其跳转到被打断的地址而且保持之前状态继续执行。

异常优先级

当两个或者多个异常同时被遇到,那么异常处理的顺序就是重要问题,异常优先级就是处理这个问题的关键。

如下表,多个异常同时产生的服务顺序:

ARM异常处理详解_第4张图片

注意一下三个:

  • Reset(复位操作)优先级最高
  • FIQ比IRQ优先级高

 FIQ的响应速度比IRQ快的原因

  1. FIQ在异常向量表中位于表尾,所以可以直接把异常处理程序写到异常向量表之后,省去跳转时间。
  2. FIQ模式有5个私有寄存器(r8~r12),执行中断处理程序前无需压栈保存寄存器,可直接处理中断
  3. FIQ的优先级高于IRQ
    1. 两个中断同时发生先响应FIQ
    2. FIQ可以打断RIQ,但是RIQ不能打断FIQ

你可能感兴趣的:(ARM学习,arm开发)