ARM的异常处理

当异常中断发生时,系统执行完当前指令后,将跳转到相应的异常中断处理程序处执行。当异常中断处理程序执行完成后,程序返回到发生中断指令的下条指令处执 行。在进入异常中断处理程序时,要保存被中断程序的执行现场,从异常中断处理程序退出时,要恢复被中断程序的执行现场。

 

1、引起异常的原因
    (1)、指令执行引起的异常
    软件中断、未定义指令(包括所要求的协处理器不存在对于协处理器指令)、预取址中止(存储器故障)、数据中止。
    (2)、 外部产生的中断
    复位、FIQ、IRQ。

 

2、ARM中异常中断的种类
     (1)、复位(RESET)
    a、当处理器复位引脚有效时,系统产生复位异常中断,程序跳转到复位异常中断处理程序处执行,包括系统加电和系统复位。
    b、通过设置PC跳转到复位中断向量处执行称为软复位。
    (2)、未定义的指令
    当ARM处理器或者是系统中的协处理器认为当前指令未定义时,产生未定义的指令异常中断,可以通过改异常中断机制仿真浮点向量运算。
     (3)、软件中断
    这是一个由用户定义的中断指令(SWI)。 该异常由执行 SWI 指令产生, 可用于用户模式下的程序调用特权操作指令。在实时操作系统中可以通过该机制实现系统功能调用。
    (4)、指令与取终止(Prefech Abort)
    如果处理器预取的指令的地址不存在,或者该地址不允许当前指令访问,当被预取的指令执行时,处理器产生指令预取终止异常中断。
    (5)、数据访问终止(DATAABORT)
    如果数据访问指令的目标地址不存在,或者该地址不允许当前指令访问,处理器产生数据访问终止异常中断。
    (6)、外部中断请求(IRQ)
    当处理器的外部中断请求引脚有效,而且CPSR的寄存器的I控制位被清除时,处理器产生外部中断请求异常中断。系统中个外设通过该异常中断请求处理服务。
    (7)、快速中断请求(FIQ)
    当处理器的外部快速中断请求引脚有效,而且CPSR的F控制位被清除时,处理器产生外部中断请求异常中断。

3、异常的响应过程
    除了复位异常外,当异常发生时,ARM处理器尽可能完成当前指令(除了复位异常)后,再去处理异常。并执行如下动作:
    (1)、将引起异常指令的下一条指令的地址保存到新模式的R14中,若异常是从ARM状态进入,LR寄存器中保存的是下一条指令的地址(当前PC+4或 PC+8,与异常的类型有关);若异常是从Thumb状态进入,则在LR寄存器中保存当前PC的偏移量,这样,异常处理程序就不需要确定异常是从何种状态 进入的。例如:在软件中断异常SWI,指令MOV PC,R14_svc总是返回到下一条指令,不管SWI是在ARM状态执行,还是在Thumb状态执行。
    (2)、将CPSR的内容保存到要执行异常中断模式的SPSR中 。(注 意:如果通过程序修改CPSR进入异常模式,硬件将不会将CPSR保存到SPSR中)
    (3)、设置CPSR相应的位进入相应的中断模式。
    (4)、通过设置CPSR的第7位来禁止IRQ。如果异常为快速中断和复位。则还要设置CPSR的第6位来禁止快速中断。
    (5)、给PC强制赋向量地址值。
    ARM处理器内核会自动执行以上几步,程序计数器PC总是跳转到相应的固定地址。
    如果异常发生时,处理器处于Thumb状态,则当异常向量地址加载入PC时,处理器自动切换到ARM状态,则异常处理返回时,自动切换到Thumb状态, 即中断处理只在ARM状态下处理。
 
4、异常中断处理返回
    异常处理完毕之后,ARM微处理器会执行以下几步操作从异常返回:
    (1)、将所有修改过的用户寄存器从处理程序的保护栈中恢复。
    (2)、将SPSR复制回CPSR中,将连接寄存器LR的值减去相应的偏移量后送到PC中。
    (3)、若在进入异常处理时设置了中断禁止位,要在此清除。
    复位异常处理程序不需要返回。


当系统运行时,异常可能会随时发生,为保证在 ARM 处理器发生异常时不至于处于未知状态,在应用程序的设计中,首先要进行异常处理,采用的方式是在异常向量表中的特定位置放置一条跳转指令,跳转到异常处理程序,当 ARM 处理器发生异常时,程序计数器 PC 会被强制设置为对应的异常向量,从而跳转到异常处理程序, 当异常处理完成以后,返回到主程序继续执行.


向量表是异常发生时,ARM内核跳转地址组成的表,通常用跳转指令跳转到对应的处理程序。

 

进入模式

0x0000,0000

复位

管理模式

0x0000,0004

未定义指令

未定义模式

0x0000,0008

软件中断

管理模式

0x0000,000C

中止(预取指令)

中止模式

0x0000,0010

中止(数据)

中止模式

0x0000,0014

保留

保留

0x0000,0018

IRQ

IRQ

0x0000,001C

FIQ

FIQ

 

 

当异常发生时,内核会跳转到向量表的相应位置,并执行当中的指令,通常,在向量表中会存放一些B,LDR PC等跳转指令,用来跳转到对应的处理程序,下面给出一个一地址0x00000000开始的向量表例子:

 

b       reset            ; 复位 0x00000000

ldr pc, _undefined_instruction ;未定义的指令异常 0x00000004

ldr     pc, _software_interrupt     ;软件中断异常    0x000000008

ldr     pc, _prefetch_abort          ;预取指令    0x0000000c

ldr     pc, _data_abort               ;数据        0x00000010

ldr     pc, _not_used                  ;未使用      0x00000014

ldr     pc, _irq                       ;慢速中断异常   0x00000018

ldr     pc, _fiq                       ;快 速中断异常    0x0000001c

 

/*  中断向量表入口地址 */

_undefined_instruction:    .word undefined_instruction

_software_interrupt:  .word software_interrupt

_prefetch_abort:  .word prefetch_abort

_data_abort:        .word data_abort

_not_used:          .word not_used

_irq:                     .word irq

_fiq:                     .word fiq

碰到异常时,PC会被强制设置为对应的异常向量,从而跳转到相应的处理程序,然后再返回到主程序继续执行。 这些引导程序的中断向量,是仅供引导程序自己使用的,一旦引导程序引导Linux内核完毕后,会使用自己的中断向量。

ARM发生中断(irq)的时候,总是会跑到0x18上执行啊。那Linux内核又怎么 能使用自己的中断向量呢?原因在于Linux内核采用页式存储管理。开通MMU的页面映射以后,CPU所发出的地址就是虚拟地址而不是物 理地址 。就Linux内核而言,虚拟地址0x18经过映射以后的物理地址就是0xc000 0018。所以Linux把中断向量放到0xc000 0018就可以了。

异常优先级
ARM的异常优先级如下表所示:
异常                           优先级               I位                F位
复位                               1                     1                   1
数据中止                       2                     1                   -
快速中断请求               3                     1                   1
中断请求                       4                     1                   -
预取指中止                   5                     1                   -
软件中断                       6                     1                   -
未定义指令                   6                     1                   -
从上表还可 以看出, cpsr的I位和F位可以屏蔽或使能某些异常
复位程序 具有最高的优先级,是系统启动(或复位)时调用的程序。1)它应该对异常处理程序的系统进行初始化(包括配置存储器和cache)。2)保证在IRQ和FIQ中断允许之前初始化外部的中断源,避免在还没有设置好相应的处理程序前产生中断。3) 设置好各种处理器模式的堆栈指针。
数据中止异常 指示访问了无效的存储器地址,或者当前代码没有正确的数据访问权限。 它不屏蔽FIQ,所以在处理过程中可以处理IRQFIQ中断 的优先级比IRQ中断的优先级要高,且 内核进入FIQ处理程序时,把FIQ和IRQ都禁止了 ,因此,任何外部中断源都不能被处理,如果要实现嵌套或者优先级时就要对上下文进行适当处理然后用软件使能中断。同样,要实现IRQ的嵌套,也要相应的上下文操作和软件开中断, 但IRQ不能屏蔽FIQ请 求当IRQ中断请求出现时,只有当FIQ异常和数据中止异常都没有发生时,IRQ处理程序才被调用 ,并屏蔽IRQ中断,直到中断源被清除。
预取指中断 会屏蔽IRQ异常,但不影响FIQ。     
当上述的所有异常都没有发生,此时系统可以处理SWI异常,cpsr会被置成管理模式。如果要实现SWI的嵌套,也要保存r14(lr)和spsr。 SWI和未定义指令异常共享同一优先级,所以两者不能同时出现。
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值