蓝色部分是本人还有点疑问的,欢迎朋友们指正,谢谢。
不知道什么原因上传后排版就变了,并且图不好传上来,在此只发关键章节,对此感兴趣的朋友可以来信索取全部文档。
sailor_forever
异常或中断是用户程序中最基本的一种执行流程或形态,这部分对ARM 架
构下异常处理程序的编写作一个全面的介绍。
ARM一共有7 种类型的异常,按优先级从高到低排列如下:
Reset
Data Abort
FIQ
IRQ
Prefetch Abort
SWI
Undefined instruction
请注意在ARM 的文档中,使用术语exception 来描述异常。Exception 主要
是从处理器被动接受异常的角度出发描述,而interrupt 带有向处理器主动申请的
色彩。在本文中,对“异常”和“中断”不作严格区分,都是指请求处理器打断
正常的程序执行流程,进入特定程序循环的一种机制。
如以前介绍异常向量表时所提到过的,每一个异常发生时,总是从异常向量
表开始起跳的,最简单的一种情况是:
图-1 异常向量表
向量表里面的每一条指令直接跳向对应的异常处理函数。其中FIQ_Handler()
可以直接从地址0x1C处开始,省下一条跳转指令。但是当执行跳转的时候有2 个问题需要讨论:跳转范围和异常分支。
我们知道ARM 的跳转指令(B)是有范围限制的(±32MB),但很多情况
下不能保证所有的异常处理函数都定位在向量表的32MB 范围内,需要大于32MB 的长跳转(有多条指令),而且因为向量表空间的限制只能由一条指令完成。这可以通过下面二种方法实现。
(a) MOV PC, #imme_value
把目标地址直接赋给PC 寄存器。
但是这条指令受格式限制并不能处理任意立即数,只有当这个立即数能够表示为一个8-bit 数值通过循环右移偶数位而得到,才是合法的。例如:MOV PC, #0x30000000 是合法的,因为0x30000000 可以通过0x03 循环右移4 位而得到。而 MOV PC, #30003000 就是非法指令。
(b) LDR PC, [PC+offset]
把目标地址先存储在某一个合适的地址空间,然后把这个存储器单元上的32
位数据传送给PC 来实现跳转。
这种方法对目标地址值没有要求,可以是任意有效地址。但是存储目标地址
的存储器单元必须在当前指令的±4KB 空间范围内。
注意在计算指令中引用的offset 数值的时候,要考虑处理器流水线中指令预
取对PC 值的影响,三级预取指令,即 pc为当前地址加 8(2个指令),以图-2 的情况为例:
offset = address location – vector address – pipeline effect
= 0xFFC – 0x4 – 0x8
= 0xFF0
图-2 利Literal pool 实现跳转
ARM内核只有二个外部中断输入信号nFIQ 和nIRQ,但对于一个系统来说,
中断源可能多达几十个。为此,在系统集成的时候,一般都会有一个异常控制器
来处理异常信号。
图-3 中断系统
这时候,用户程序可能存在多个IRQ/FIQ 的中断处理函数,为了从向量表
开始的跳转最终能找到正确的处理函数入口,需要设计一套处理机制和方法。
图-4 中断分支
(a) 硬件处理
有的系统在ARM 的异常向量表之外,又增加了一张由中断控制器控制的特
殊向量表(IRQ中断)。当由外设触发一个中断以后,PC 能够从IRQ中断处自动跳到由AIC保存的这张特殊向量表中去,特殊向量表中的每个向量空间对应一个具体的中断源,共32个,AT91RM9200采用了这种方法。
举例来说,下面的系统一共有20 个外设中断源,特殊向量表被直接放置在
普通向量表后面。
图-5 额外的硬件异常向量表
当某个外部中断触发之后,首先触发ARM 的内核异常,中断控制器检测到
ARM 的这种状态变化,再通过识别具体的中断源,使PC 自动跳转到特殊向量
表中的对应地址,从而开始一次异常响应。需要检查具体的芯片说明,是否支持这类特性。(和软件处理方法中的2区别在于此向量表是由硬件中断控制器保存的,而2中的中断向量表是用户自己定义的)
(b) 软件处理
多数情况下是用软件来处理异常分支,典型的是44b0和2410。因为软件可以通过读取中断控制器(INTOFFSET)来获得中断源的详细信息。
图-6 软件控制中断分支
因为软件设计的灵活性,用户可以设计出比上图更好的流程控制方法来。下
面是一个例子:
图-7 灵活的软件分支设计
Int_vector_table 是用户自己开辟的一块存储器空间,里面按次序存放异常处
理函数的地址。IRQ_Handler() 从中断控制器获取中断源信息,然后再从
Int_verctor_table 中的对应地址单元得到异常处理函数的入口地址,完成一次异
常响应的跳转。这种方法的好处是用户程序在运行过程中,能够很方便地动态改
变异常服务内容(动态改变异常处理函数的入口地址即可,2410采取了此方法)。
当任何一个异常发生并得到响应时,ARM 内核自动完成以下动作: