1、1 12 ARM是一类微处理器,同时也是一个公司的名字。ARM公司于1990年11月在英国剑桥成立(原名Advanced RISC Machine),专门从事基于RISC技术的芯片设计、开发和授权。目前,ARM处理器(即采用ARM IP核的处理器)已遍及工业控制、通信系统、无线通讯、网络系统、消费类电子产品、成像和安全产品等各类产品市场。截止到2012年,基于ARM技术设计的处理器已经占据32位RISC微处理器约80%以上的市场份额,ARM技术正在逐步渗入到我们生活的各方面。3 ARM处理器是第一个为商业用途开发的RISC微处理器。ARM所采用的体系结构对于传统的RISC体系结构既有继承,又有
2、舍弃和发展,即完全根据实际设计的需要仔细研究,没有机械照搬。最初的ARM设计最关心的是必须保持设计的简单性。ARM的简单性在ARM的硬件组织和实现方面比指令集的结构方面体现的更明显。但是ARM仍保留一些CISC的特征,并且因此达到比纯粹的RISC更高的代码密度,使得ARM在开始时就获得了其功率效率和较小的核面积的优势。4 ARM微处理器内核中普遍采用了流水线结构,随着ARM内核的发展,其流水线结构越来越复杂。常见的ARM处理器内核流水线如图12-1所示。图12-1 ARM处理器内核流水线工作示意图5 迄今为止,ARM体系结构共定义了8个版本,版本号分别为v1v8,从版本v1到v8,ARM体系的
3、指令集功能不断扩大。同时,各版本中还有一些变种,这些变种定义该版本指令集中不同的功能。ARM处理器系列中的各种处理器,实现技术各不相同,性能差别很大,应用场合也不同,但只要它们支持同一ARM体系版本,基于它们的应用软件将是兼容的。需要注意,ARM的体系结构版本号并不是ARM核的版本号。6 常见的ARM体系架构与ARM核的版本对应关系见表12-1。表12-1常见的ARM体系架构与ARM核的版本对应关系7 基于ARM的处理器内核简称ARM内核,内核并不是芯片,ARM内核与其他部件组合(如存储器、定时器和片内外设接口等)在一起才构成芯片。图12-2 ARM芯片内部主要模块示意图8ARM芯片中只有处理
4、器内核由ARM公司设计,其他外围模块由获得ARM公司处理器IP授权的芯片厂商自行设计。芯片厂商针对不同的应用领域,通过设计具有很强针对性的专用硬件加速器,根据外设搭配不同的接口电路等设计出适用于专业领域的SOC芯片,从而实现基于相同处理器内核芯片产品的差异化。ARM处理器内核不但包括CPU,还包括高速缓存、MMU控制器、嵌入式跟踪宏单元、TCM接口、总线控制逻辑、AHB接口、协处理器、中断控制器等电路模块。整个ARM处理器内核的核心是CPU。虽然随着ARM处理器内核的升级,其CPU也不断改进,但其基本结构主要由32位ALU、31个32位通用寄存器及6个状态寄存器、32个8位乘法器、32个桶形移
5、位寄存器、指令译码及控制逻辑、指令流水线和数据/地址寄存器组成。9 图12-3ARM CPU基本组成模型10 ARM处理器是32位处理器,但兼容16位指令集和数据类型。从编程的角度看,ARM处理器有以下两种操作状态:ARM状态 32位,处理器执行的是字的ARM指令;Thumb状态 16位,处理器执行的是半字的Thumb指令。在程序执行过程中,处理器可以随时在这两种操作状态之间切换。值得注意的是,操作状态的切换并不影响处理器的工作模式或寄存器的内容。ARM处理器复位后开始执行代码时,应该处于ARM状态。12.2 ARM编程模型12.2.1 处理器状态11 ARM指令集和Thumb指令集均有切换处
6、理器状态的指令,并可在两种操作状态之间切换。两个状态可以按以下方法切换:进入Thumb状态 当操作数寄存器的状态位(最低位)为1时,执行BX指令就可以进行Thumb状态。如果处理器在Thumb状态发生异常(所有异常处理都在ARM状态下执行),则当异常处理返回时自动切换到Thumb状态。进入ARM状态 操作数寄存器的状态位(最低位)为0时,执行BX指令就可以进行ARM状态。处理器进行异常处理时,把PC的值放入异常模式链接寄存器中,从异常向量地址开始执行程序,系统自动进入ARM状态。处理器状态的切换12 ARM体系结构支持7种处理器模式:用户模式、快中断模式、中断模式、管理模式、中止模式、未定义模
7、式和系统模式。具体参考表12-2。12.2.2 处理器模式13表12-2 处理器模式及其用途 除用户模式外,其它模式为特权模式。ARM内部寄存器和一些片内外设在硬件设计上只允许(或可选为只允许)特权模式下访问。此处,特权模式可以自由地切换处理器模式,而用户模式不能直接切换别的模式。有5种处理器模式称为异常模式,它们是:快中断模式、中断模式、管理模式、中止模式、未定义模式。它们除了可以通过程序切换进入外,也可以由特定的异常进入。当特定的异常出现时,处理器进入相应的模式。每种模式都有某些附加的寄存器,以避免异常退出时用户模式的状态不可靠。系统模式与用户模式一样不能由异常进入,且使用与用户模式完全相
8、同的寄存器。然而系统模式是特权模式,不受用户模式的限制。有了系统模式,操作系统要访问用户模式的寄存器就比较方便。同时,操作系统的一些特权任务可以使用这个模式,以访问一些受控的资源而不必担心异常出现时的任务状态变得不可靠。14 ARM处理器共有37个32位寄存器:31个通用寄存器 R0R15、R13_svc、R14_svc、R13_abt、R14_abt、R13_unt、R14_unt、R13_irq、R14_irt和R8_frqR14_frq;6个状态寄存器 CPSR、SPSR_svc、SPSR_abt、SPSR_unt、SPSR_irq和SPSR_fiq。这些寄存器并不是在同一时间全都可以被
9、访问,具体哪些寄存器可编程访问,取决于处理器状态和具体的操作模式。12.2.3 寄存器集15(1)通用寄存器(2)程序计数器(PC)(3)程序状态寄存器(PSR)(4)条件码标志位(5)控制位(6)ARM状态寄存器与Thumb状态寄存器之间的关系1612.2.3 寄存器集12.2.3 寄存器集通用寄存器包括R0R15,可以分为两类:不分组寄存器(R0R7)和分组寄存器(R8R14)。1)不分组寄存器(R0R7)。在处理器的所有模式下,不分组寄存器中的每个都指向一个物理寄存器,且未被系统用于特殊用途。因此,在中断或异常处理中进行模式切换时,由于不同的处理器模式均使用相同的物理寄存器,可能会破坏寄
10、存器中的数据,进行程序设计时应引起注意。(1)通用寄存器172)分组寄存器(R8R14)。分组寄存器中的每一次所访问的物理寄存器都与处理器当前的模式有关。若要访问特定的物理寄存器,则要使用规定的物理寄存器名字后缀。物理寄存器名字形式如下:R13_R14_其中,是寄存器后缀,分别使用usr、svc、fiq、irq、abt和und表示6种模式。18,每个寄存器对应2个不同的物理寄存器,当使用fiq模式时访问寄存器R8_fiqR12_fiq;当使用除fiq模式外的其他模式时访问寄存器R8 R12。,每个寄存器对应6个不同的物理寄存器。其中的一个物理寄存器是用户模式和系统模式公用的,其余5个分别用于5
11、种异常模式。寄存器R13通常作为堆栈指针(SP),用于保存当前处理器工作模式下堆栈的栈顶地址。作为链接寄存器(LR),用于保存子程序的返回地址。当子程序折返回地址保存在堆栈中,R14也可作为通用寄存器。处理器在不同模式时,允许每种模式都有自已的栈顶和链接寄存器。19(2)程序计数器(PC)20 PC作为程序计数器,用于保存处理器要取的下一条指令的地址。R15作为程序计数器,用于保存处理器要取的下一条指令的地址。ARM状态下,所有的ARM指令都是32位长度的,指令以字对准保存;Thumb状态下,所有的Thumb指令都是16位长度的,指令以半字对准保存。由于ARM体系采用多级流水线技术,对于ARM
12、指令集而言,PC总是指向当前指令之后两条指令的地址,即PC的值为当前指令的地址加8。(3)程序状态寄存器(PSR)程序状态寄存包括当前程序状态寄存器(CPSR)和备份程序状态寄存器(SPSR)。所有处理器模式下都可以访问当前程序状态寄存器。CPSR包括条件标志位、中断禁止位、当前处理器模式标志,以及其他一些相关的控制和状态位。在每一种异常工作模式下,都有一个备份状态寄存器。当异常发生时,SPSR用于保存CPSR的当前值,当从异常退出时,可用SPSR来恢复CPSR。用户模式和系统模式不属于异常模式,因此这两种模式没有SPSR,当在这两种情况下访问SPSR时,结果是未知的。CPSR和SPSR的格式
13、如图12-4所示。21图 12-4 CPSR/SPSR格式22(4)条件码标志位 N、Z、C和V均为条件码标志位。其内容可被算术或逻辑运算指令的结果所改变,并全由条件码标志位状态可以决定某条指令是否执行。标志N。当两个用补码表示的带符号数进行运算时,N=1表示结果为负数;N=0表示运算结果为正数或零。标志Z。Z=1表示指令运算结果为0;Z=0表示指令运算结果为非零。23 标志C。对于加法运算(包括比较指令CMN),C=1表示加法运算产生进位(即无符号数溢出),C=0表示加法运算未产生进位;对于减法运算(包括比较指令CMP),C=0表示减法运算产生借位(即无符号数溢出),C=1表示减法运算未产生
14、借位;对于包含移位操作的非加/减运算指令,C为移出值的最后一位;对于其他非加/减运算指令,C的值通常不改变。标志V。对于加法/减法指令,当操作数和运算结果为二进制的补码表示的带符号数时,V=1表示符号位溢出,V=0表示符号位未溢出;对于其他的非加/减运算指令,V的值通常不改变。24(5)控制位25CPSR的低8位,即I、F、T和M0M4称为控制位。当发生异常时这些位可以被改变。当处理器运行在特权模式时,这些位也可以由程序修改。中断禁止位I和F。I=1表示禁止IRQ中断,F=1表示禁止FIQ中断。T标志位。对于ARM体系结构v4及以上版本的T系列处理器,T=0表示程序运行于ARM状态,T=1表示
15、程序运行于Thumb状态;对于ARM体系结构v4及以上版本的非T系列处理器,T=0表示程序运行于ARM状态,T=1表示执行下一条指令以引起未定义的指令异常。注意:绝对不要强制改变CPSR寄存器中的T位。如果这样做,处理器则会进入一个无法预知的状态。运行模式位M0M4。这些模式位决定处理器的模式。见表12-4。不是所有模式位的组合都定义了有效的处理器模式,因此,请注意不要使用表中没有列出的组合。保留位。CPSR中的其他位为保留位,当改变CPSR中的条件码标专位或控制位时,不要改变保留位,在程序中也不要使用保留位来存储数据。保留位将用于ARM版本的扩展。2627表12-4 模式位的含义(6)ARM
16、状态寄存器与Thumb状态寄存器之间的关系28Thumb状态下的寄存器集是ARM状态下的寄存器集的子集。用户可以访问8个通用寄存器(R0R7)、PC、SP、LR、SPSR和CPSR。每种特权模式都有一组SP、LR、SPSR。Thumb状态寄存器与ARM状态寄存器集有如下的关系:Thumb状态R0R7与ARM状态R0R7相同。Thumb状态CPSR和SPSR与ARM状态CPSR和SPSR相同。Thumb状态SP映射到ARM状态R13。Thumb状态LR映射到ARM状态R14。Thumb状态PC映射到ARM状态PC(R15)。具体关系如图12-5所示。29图12-5 Thumb寄存器在ARM状态寄
17、存器上的映射 Thumb状态下,寄存器R8R15并不是标准寄存器集的一部分,但用户可以使用汇编语言程序有限制地访问这些寄存器,将其用作快速的寄存器。使用带特殊变量的MOV指令,数据可以在低寄存器(R0R7)和高寄存器(R8R15)之间进行传送;高寄存器的值可以使用CMP指令进行比较或使用ADD指令加上低寄存器的值。ARM处理器支持的数据类型有字节、半字和字。字节 字节的长度为8位(bit);半字 半字的长度为16位(bit),半字必须以2字节为边界对齐;字 字的长度为32位(bit)。字必须以4字节为边界对齐。这三种数据类型都支持无符号数和带符号数,当任意一种类型描述为unsigned时,N位
18、数值使用正常的二进制格式表示范围为 的非负整数;当任意一种类型描述为signed时,N位数值使用2的补码格式表示范围为 的整数。ARM指令的长度刚好是1个字(分配为占用4个字节)。Thumb指令的长度刚好一个半字(占用2个字节)。所有数据操作都以字为单位。加载和存储指令可以以字节、半字和字进行操作,当加载字节或半字时自动实现零扩展或符号扩展。12.2.4 体系结构直接支持的数据类型300 21N11221NN12.2.5 存储器及存储器映射I/OARM处理器采用冯诺依曼结构,指令和数据共用一条32位数据总线,只有加载、存储和交换指令可访问存储器中的数据。ARM公司的规范仅定义了内核与存储系统之
19、间的信号及时序(局部总线),而现实的芯片一般在外部总线与内核的局部总线之间有一个存储器管理部件将局部总线的信号和时序转换为现实的外部总线信号和时序。因此,外部总信的信号和时序与具体的芯片有关,不是ARM的标准。具体到某个芯片的外部存储系统的设计,需要参考其芯片的数据手册或使用手册等资料。311.地址空间 2.存储器格式 3.指令的预取和自修改代码 4.存储器映射的I/O 1.地址空间 ARM体系结构使用单个平面的232个8位字节地址空间,对存储器能支持的最大寻址空间为4G(232)。ARM体系统结构将存储器看成从0 x00000000地址开始的以字节为单位的线性组合。每个字数据占4个字节单位,
20、每个半字数据占2个字节单位。字节地址按照无符号数排列,从0到232-1。地址空间可以看作是包含230个32位字,地址以字为单位进行分配,也就是将地址除以4。地址为A的字包含4个字节,地址分别为A、A+1、A+2和A+3。在ARM体系结构v4及以上版本中,地址空间还可被看包含231个16位半字。地址按照半字进行分配。地址为A的半字包含2个字节,地址分别为A和A+1。322.存储器格式 地址空间的规则要求地址A:位于地址A的字包含的字节位于地址A、A+1、A+2和A+3。位于地址A的半字包含的字节位于地址A、A+1。位于地址A+2的半字包含的字节位于地址A+2和A+3。位于地址A的字包含的字节位于
21、地址A和A+3。33小端格式(little-ednian)在小端格式中,一个字当中最低地址的字节被看作是最低位字节,最高地址的字节被看作是最高位字节。因此,存储器系统字节0连接到数据线,如图12-6所示。34图12-6 字内字节的小端地址大端格式(big-endian)在大端格式中,ARM处理器将最高位字节保存在最低地址字节,将最低位字节保存在最高地址字节。因此,存储器系统字节0连接到数据线3124,如图12-7所示。35图12-7 字内字节的大端地址 一个具体的的基于ARM的芯片可能只支持小端存储器系统,也可能只支持大端存储器系统,还可能两者都支持,但默认格式通常为小端格式。ARM指令集不包
22、含任何直接选择大、小端的指令。但是,一个同时支持大、小端的基于ARM的芯片,可以在硬件上配置(一般使用芯片的引脚来配置)来匹配存储器系统所使用的规则。如果芯片有一个标准系统控制协处理器,则系统控制协处理器的寄存器1的Bit7可用于改变配置输入。36 如果一个基于ARM的芯片将存储系统配置为其中一种存储器格式(如小端),而实际连接的存储器系统配置为相反的格式(如大端),那么只有以字为单位的指令取指、数据加载和数据存储能够可靠实现。勘察的存储器访问将出现不可预测的结果。当标准系统控制协处理器连接到支持大、小端的ARM处理器时,协处理器寄存器1的Bit7在复位时清零。这表示ARM处理器在复位后立即配
23、置为小端存储器系统。如果它连接到一个大端存储器系统,那么复位处理程序要尽早做的事情之一就是切换到大端存储器系统,并必须在任何可能的字节或半字数据访问发生或Thumb指令执行之前执行。373.指令的预取和自修改代码 许多ARM处理器实现在前一条指令的执行尚未完成时将指令从存储器取出。这个动作称为指令的预取。指令的预取并不是实际执行指令。如有下面两种典型的情况时,指令就可不被执行:当异常发生时,当前指令执行完毕,所有预取的指令都被丢弃,指令的执行从异常向量开始。当发生跳转时,预取的在分支指令后的指令将被丢弃。ARM处理器可以自由选择预取的指令比当前执行点提前多少(即半导体厂商在设计具体的芯片时可以
24、自由选择预取的指令比当前执行点提前多少),甚至可以动态改变预取指令的数目。最初的ARM处理器实现在当前执行的指令之前预取两条指令,不过现在可以选择多于或少于两条指令。38 注意:当指令读取PC时,它得到的指令地址比它自身地址落后了两条地址:对于ARM指令,得到的地址是它自身地址+8;对于Thumb指令,得到的地址是它自身地址+4。最初的ARM处理器实现在PC读取的两指令偏移量和两指令预取之间存在关联。但这一关联不是结构上的。一个预取不同数目指令的ARM处理器实现仍能保证读取PC所得的地址比它自身地址落后两条指令。同自由选择多少条预取指令一样,ARM处理器实现可选择沿着哪条可能的执行路径进行预取
25、指。例如,在一条分支指令之后,它可选择预取分支指令之后的指令或者是转移目标地址的指令。这称为“转移预测”。39自修改代码 所有形式的指令预取都有一个潜在的问题,即存储器中的指令可能在它被预取之后,被执行之前发生改变。如果发生这种情况,对存储器中的指令进行修改通常并不妨碍已取指的指令备份执行完毕。40 例如:在下面的代码序列中,STR指令使用ADD指令的备份取代了它后面的SUB指令:LDR r0,AddInstr STR r0,NextInstr NextInstr SUB r1,r1,#1 AddInstr ADD r1,r1,#1 当代码第一次执行时,STR指令之后执行的指令通常是SUB指令
26、,因为SUB指令在存储器中的指令发生改变之前已经被预取了,ADD指令不会被执行,除非第二次执行该代码序列。41ARM处理器不能保证上面所述的方式执行,因此:当代码第一次执行时,在STR指令之后有可能立即产生一个中断。如果这样,已经预取的SUB指令将被丢弃。当中断处理程序返回时,位于NextInstr处的指令被再次预取,而这次则执行ADD指令。因此,虽然SUB指令通常最有可能被执行,但也有可能执行ADD指令。如果指令被再次执行,ARM处理器或存储器系统允许预取指令的备份,并使用这些备份而不是重新预取。如果发生这种情况,在代码序列按照第二及以下可能执行时,SUB指令可能被执行。发生这种情况的主要原
27、因是存储器系统包含独立的指令和数据缓存。但是,也存在其它可能性。例如,一些分支预测的硬件保存了分支后的指令。总之,应当尽可能避免使用涉及自修改代码的编程技术。然而在许多系统中,几乎不可能完全避免自修改代码的使用。例如,任何一个允许将程序装入存储器然后执行的系统都使用自修改代码。42指令存储器屏障(IMB)每个ARM处理器实现都定义了一系列的操作,使自修改代码序列可以可靠地执行。这一串代码称为指令存储器屏障(IMB),它通常同时取决于ARM处理器的实现和存储器系统的实现。IMB序列必须在新的指令已经保存到存储器之后而尚未执行时执行。例如,在程序被加载之后并且在转移到它的入口之前。任何不以这种方式
28、使用IMB的自修改代码序列都可能会执行不确定的动作。根据IMB所执行的确定的操作顺序取决于ARM处理器和存储器的实现,建议在软件设计时使IMB序列作为一个调用程序来替换与系统相关的模块,而不是直接插入到需要的地方。这样易于移植到其它ARM处理器和存储器系统。43 另外,在许多实现当中,IMB序列包含了只能在特权模式下使用的操作,例如,标准系统控制协处理器提供的缓存清零和无效操作。为了允许用户模式程序使用IMB序列,推荐将其作为一个操作系统调用程序,由SWI指令调用。在SWI指令使用24位立即数的系统中指定所要求的系统服务,通过下面的指令即可请求IMB序列:SWI 0 xF00000这是一个无参
29、数调用,不返回结果,应当使用与带原型的C函数调用相同的调用约定:void IMB(void);区别在于使用SWI指令而不是BL指令调用。44 有些实现可对已保存的新指令使用地址范围的知识来减少IMB执行的时间。因此,还可执行另外一个操作系统调用程序。该调用程序只根据指定的地址范围执行IMB。在SWI指令使用24位立即数的系统中指定所要求的系统服务,通过下面的指令来请求:SWI 0 xF00001应当使用与带原型的C函数调用相似的调用约定:void IMBRange(unsigned long start_addr,unsigned long end_addr);此处地址范围从start_add
30、r(包含)到end_addr(不包含)。45注意:当使用标准的ARM过程调用标准时,start_addr在R0中传递,而edd_addr则在R1中传递。对于某些ARM处理器实现来说,即使使用小地址范围,IMB执行的时间也可能非常长(数千个时钟周期)。对于自修改代码的小规模使用,这样很可能受到较大损失。因此,建议自修改代码只用于不可避免或有足够的执行时间的情况。464.存储器映射的I/O 执行ARM体系统结构I/O功能的标准是使用存储器映射的I/O。加载或存储I/O值时,使用提供给I/O功能的特殊存储器地址。通常,从存储器映射的I/O地址加载用于输入,而存储到存储器映射的I/O地址则用于输出。加
31、载和存储都可用于执行控制功能,用于取代它们正常的输入或输出功能。存储器映射的I/O位置的动作通常不同于正常的存储器位置的动作。例如,正常存储器位置的两次连续加载,每次都会返回相同的值,除非中间插入了保存的操作。对于存储器映射的I/O位置,第二次加载返回的值可以不同于第一次返回的值。因为第一次加载的副作用(例如从缓冲区移走已加载的值)或是因为插入另一个存储器映射I/O位置的加载和存储的副作用。47(1)从存储器映射的I/O取指 在前面章节中讲到,不同ARM处理器的实现(可以理解为不同的芯片)在存储器取指时会有相当大的区别。因此,建议存储器映射的I/O位置只用于数据的加载和存储,而不用于取指。任何
32、依赖于从存储器映射I/O位置取指的系统设计都可能难于移植到将来的ARM实现。48(2)对存储器映射I/O的数据访问 一个指令序列在执行时,会在不同的点访问数据存储器,产生加载和存储访问的时序。如果这些加载和存储访问的是正常的存储器位置,那么它们在访问相同的存储器位置时只是执行交互操作。结果,对不同存储器位置的加载和存储可以按照不同于指令的顺序执行,但不会改变最终的结果。这种改变存储器访问顺序的自由可被存储器系统用来提高性能(例如,通过使用高速缓存和写缓冲器)。49对同一存储器位置的访问还拥有其它可用于提升性能的特性 从相同的位置连续加载(没有产生存储)产生相同的结果。从一个位置执行多加载操作,
33、将返回最后保存到该位置的值。对某个数据规格的多次访问,有时可合并成单个的更大规模的访问。例如,分别存储一个字所包含的两个半字可合并成存储单个字。50访问存储器映射的I/O位置时不能进行优化,它们的时间顺序绝对不能改变 如果存储器字、半字或字节访问的对象是存储器映射的I/O位置,那么一次访问会产生副作用,使后续访问改变成一个不同的地址。如果是这样,那么不同时间顺序的访问将会使代码序列产生不同的最终结果。因此,当访问存储器映射的I/O位置时不能进行优化,它们的时间顺序绝对不能改变。51存储器访问的数据规格都不会改变 对于存储器映射的I/O,另外还有很重要的一点,那就是每次存储器访问的数据规格都不会
34、改变。例如,在访问存储器映射的I/O时,一个指定从4个连续字节地址读出数据的代码序列决不能合并成单个字的读取,否则会使代码序列的最终执行结果不同于期望的结果。相似地,将字的访问分解成多个字节的访问可能会导致存储器映射I/O设备无法按照预期进行操作。52访问存储器映射的I/O时的要求 限制存储器映射I/O位置的存储器属性。例如,在标准存储器系统结构中,存储器位置必须是无高速缓存和无缓冲区的。限制访问存储器映射I/O位置的规格或对齐方式。例如,如果一个ARM实现带有16位外部数据总线,它可以禁止对存储器映射I/O使用32位访问,因为32位访问无法在单个总线周期内执行。要求额外的外部硬件。例如,带1
35、6位外部数据总线的ARM实现可以允许对存储器映射的I/O使用32位访问,但要求外部硬件将两个16位总线访问合并成对I/O设备的单个32位访问。53如果数据存储器访问序列包含一些符合要求的访问和一些不符合要求的访问,那么:对于符合要求的访问,其数据规格和数目都被保护,没有互相合并或没有与不符合要示的访问以任何方式合并。不符合要求的访问可以互相合并。符合要求的访问彼此的时间的顺序被保护,但它们相以于那些不符合要求的访问的时间顺序不能保证。5412.2.6 异常只要正常的程序流被暂时中止,处理器就进入异常模式。当发生异常时,处理器在处理异常之前,必须先保存当前的状态。当异常处理完成后,需要将处理器的
36、状态恢复到处理异常之前,之后当前程序方可继续执行。ARM处理器允许多个异常同时发生,它们将会按固定的优先级进行处理。本小节内容:1.ARM支持的异常类型2.异常优化级与异常嵌套3.异常向量4.异常响应和返回过程5.中断延迟6.复位551.ARM支持的异常类型56ARM体系结构支持的异常类型有7种,如表12-5所示,分为如下3类:指令执行引起的直接异常 软件中断、未定义指令和指令预取 中止都属于这一类;指令执行引起的间接中断 数据中止属于这一类;外部产生的与指令流无关的异常 复位、IRQ和FIQ属于这一类。表12-5 ARM体系结构支持的异常类型57当多个异常同时发生时,系统根据固定的优化级处理
37、异常的处理次序。异常优先级按下列顺序排列了优先权,复位优先级最高,未定义指令和SWI优先级最低。2.异常优化级与异常嵌套5859(1)复位从确定的状态启动处理器,使得所有其他未解决的异常都和当前处理器运行的状态不再有关,因此具有最高优先级。(2)未定义指令和SWI都依靠指令的特殊译码产生,由于两者是互斥的指令编码,因此不能同时发生。60(3)中断优先级判决最复杂的情况是FIQ、IRQ和第三个非复位的异常同时发生时:由于FIQ比IRQ优先级高并将IRQ屏蔽,所以IRQ被忽略,直到FIQ处理程序明确地将IRQ使用或返回到用户代码为止;如果第三个异常是数据中止,那是因为进入数据中止异常并未将FIQ屏
38、蔽,所以处理器将在进入数据中止处理程序后立即进入FIQ处理程序。数据中止将在FIQ处理程序返回时对其进行处理;如果第三个异常不是数据中止,将立即进入FIQ处理程序。当FIQ和IRQ两者都完成时,程序将返回到产生第三个异常的指令,在余下所有的情况下异常将重现并进行相应的处理。3.异常向量61表12-6 ARM异常向量62一般来说,在异常向量处将包含一条跳转指令,跳转到异常处理程序。但由于 FIQ占据最高向量地址,它可以立即执行。当ARM处理器发生异常时,程序计数器PC被强制设置为对应的异常向量,从而转到异常处理程序,当异常处理程序完成后,返回到主程序继续执行。异常发生后,除了复位异常立即中止当前
39、指令之外,其余异常都是在处理器完成当前指令后再执行异常处理程序。ARM处理器对异常中断的响应过程如下所述:1)保存处理器当前状态、中断屏蔽位以及条件标志位。这是通过将当前程序状态寄存器CPSR的内容保存到将要执行的异常中断对应的SPSR寄存器中实现的;2)设置当前程序状态寄存器CPSR中相应的位。包括:设置CPSR中的位,使处理器进入相应的模式;设置CPSR中的位,禁止IRQ中断,当进入FIQ模式时,禁止FIQ中断;3)将寄存器LR_mode设置成返回地址;4.异常响应和返回过程634)将程序计数器值(PC)设置成该异常中断的异常向量地址,从而跳转到相应的异常中断处理程序处执行。异常处理完成后
40、必须返回到原来程序处继续执行,为达到这一目的,需要执行四个基本操作:恢复原来被保护的用户寄存器;恢复被中断的程序的处理器状态,即将SPSR_mode寄存器内容复制到CPSR中;返回到发生异常中断的指令的下一条指令处执行,即将LR_mode寄存器的内容复制到程序计数器PC中;清除CPSR中的中断禁止标志I和F,开放外部中断和快速中断。64(1)最大中断延迟 当FIQ使能时,最坏情况下FIQ的延迟时间包含:1)Tsynemax(请求通过同步器的最长时间)。Tsynemax为4个处理器周期(由内核决定);2)Tldm(最长指令的完成时间)。最长的指令是加载包括PC在内所有寄存器的LDM指令。Tldm
41、在零等待状态系统中的执行时间为20个处理器周期;3)Texc(数据中止异常进入时间)。Texc为3个处理器周期;4)Tfiq(FIQ进入时间)。Tfiq为2个处理器周期(由内核决定)。5.中断延迟65总的延迟时间是29个处理器周期,在系统使用40MHz处理器时钟时,略微超过0.7ms。当在时间结束后,处理器执行在0 x1C处的指令。(2)最小中断延迟FIQ或IRQ的最小中断延迟是请求通过同步器的时间加上Tfiq(共6个处理器周期)。66当nRESET信号被拉低时(一般外部复位引脚电平的变化和芯片的其它复位源会改变这个内核信号),内核中止正在执行的指令,并且地址总线继续增加。当nRESET信号再
42、次变为高电平时,ARM处理器执行下列操作:1)强制M4:0变为b10011(管理模式);2)置位CPSR中的I和F位;3)清零CPSR中的T位;4)强制PC从地址0 x00开始对下一条指令进行取指;5)返回到ARM状态并恢复执行。在复位后,除PC和CPSR之外的所有寄存器的值都不确定。6.复位67ARM处理器是基于精简指令集计算机(RISC)原理设计的,指令集和相关译码机制较为简单。ARM体系结构具有32位ARM指令集和16位Thumb指令集,ARM指令集效率高,但是代码密度低;而Thumb指令集具有较高的代码密度,却仍然保持ARM的大多数性能上的优势,它是ARM指令集的子集。所有的ARM指令
43、都是可以有条件执行的,而Thumb指令仅有一条指令具备条件执行功能。ARM程序和Thumb程序可相互调用,相互之间状态切换开销几乎为零。6812.3 ARM编程指令 寻址方式是根据指令中给出的地址码字段来实现寻找真实操作地址的方式。ARM处理器有8种基本寻址方式。1)寄存器寻址;2)立即寻址;3)寄存器移位寻址;4)寄存器间接寻址;5)基址寻址;6)多寄存器直接寻址;7)堆栈寻址;8)相对寻址。12.3.1 ARM处理器寻址方式691.32位ARM指令集(1)分支指令;(2)数据处理指令;(3)加载和存储指令;(4)协处理指令;(5)杂项指令12.3.2 指令集70 ARM指令集提供了两条产生
44、异常的指令,通过这两条指令可以用软件的方法实现异常。软件中断指令(SWI);断点中断指令(BKPT)。2.16位Thumb指令集(1)分支指令 分支指令又称转移指令,用于实现程序流程的转移,这类指令可用来改变程序的执行流程或调用子程序。在ARM程序中可使用专门的分支指令,也可以通过直接向程序计数器(PC)写入转移地址值的方法实现程序流程的转移。通过向程序计数器(PC)写入转移地址值,便可以在4GB的地址空间中任意转移;若在转移之前结合使用ARM的MOV LR,PC等指令,则可保存将来的返回地址值,从而实现在4GB地址空间中的子程序调用。71 分支指令除了允许数据处理或加载指令通过PC来改变控制
45、流以外,还提供了一个24位的符号偏移,可实现最大32MB向前或向生的地址空间转移。转移和链接(BL)选项在跳转后将指令地址保存在R14(LR)当中。这样通过将LR复制得到PC可实现子程序的返回。另外,有的分支指令可在指令集之间进行切换。此时,分支指令执行完成后,处理器继续执行Thumb指令集的指令。这样就允许ARM代码调用Thumb子程序,而ARM子程序也可返回到Thumb调用程序。Thumb指令集中相似的指令可实现对应的Thumb ARM的切换。72(2)数据处理指令 数据处理指令分为数据传送指令、算术/逻辑运算指令、比较指令、乘法指令等几种类型。数据传送指令用于寄存器之间进行数据的传输。算
46、术运算指令完成基本的加、减运算。逻辑运算指令完成常用的逻辑运算,算术/逻辑运算指令要将运算结果保存在目的寄存器中,并且需要更新CPSR中的标志位。比较指令不保存运算结果,只更新CPSR中的标志。数据传送指令 算术/逻辑运算指令比较指令 乘法指令73数据传送指令 主要用于将一个寄存器中的数据传送到另一个寄存器中,或者将一个立即数传送到寄存器中,这类指令通常用来对寄存器初始化。数据传送指令包括数据直接传送指令和数据取反传送指令。74算术/逻辑运算指令 算术/逻辑运算指令一共有12条,它们使用相同的指令格式。它们最多使用两个源操作数来执行算术或逻辑操作,并将结果写入目标寄存器。也选择根据结果更新条件
47、代码标志。两个源操作数中,其中一个一定是寄存器,另一个有两种基本形式:立即数或是寄存器,可选择移位。如果操作数是一个移位寄存器,移位计数可以是一个立即数或另一个寄存器的值。可以指定4种移位的类型。每一条算术/逻辑运算指令都可以执行算术/逻辑和移位操作。这样就可轻松实现各种不同的分支指令。75比较指令 比较指令通常用于将一个寄存器与一个32位的值进行减法运算,根据结果更新CPSR中的标志位。对于比较指令,不需要使用S后缀即可改变标志位的值。需要注意的是,其运算结果不保存,因而不影响其他寄存器的内容。比较指令更新标志位后,其他指令可能通过条件发送来改变程序的执行顺序。比较指令源操作数的格式与算术/
48、逻辑指令相同,包括移位操作的功能。76乘法指令 乘法指令是将一对寄存器的内容相乘,然后根据指令类型把结果累加到其他的寄存器。ARM处理器支持的乘法指令与乘加指令共有6条。根据运算结果可分为32位运算和64位运算两类。64位乘法又称为长整型乘法指令,由于结果太长,不能放在一个32位的寄存器中,所以把结果存放在两个32位的寄存器Rdlo和Rdhi中。Rdlo存放低32位,Rdhi存放高32位。与前述的数据处理指令不同,指令中的所有源操作数和目的寄存器都必须为通用寄存器,不能为立即数或被移位了的寄存器。同时,目的寄存器Rd和操作数Rm必须是不同的寄存器。77(3)加载和存储指令 ARM指令系统中的加
49、载和存储指令,用于在ARM寄存器和存储器之间传送数据。加载指令用于将存储器中的数据传送到寄存器,存储指令则将寄存器中的数据传送到存储器中。处理器对存储器的访问只能通过加载和存储指令实现。ARM指令系统中有3种加载和存储指令:加载和存储寄存器指令、加载和存储多个寄存器指令和交换寄存器和存储器指令。加载和存储寄存器指令在ARM寄存器和存储器之间提供灵活的单数据项传送方式。支持的数据项类型为字节(8位)、半字(16位)和字(32位)。78加载和存储寄存器指令 加载寄存器指令可将一个32位字、一个16位半字或一个8位字节从存储器装入寄存器。字节和半字在加载时自动实现零扩展和符号扩展。存储寄存器指令可以
50、将一个32位字、一个16位半字或一个8位字节从寄存器保存到存储器。加载和存储寄存器指令有3种主要的寻址模式,这3种模式都使用指令指定的基址寄存器和偏移量:79 在偏移寻址模式中,将基址寄存器值加上或减去一个偏移量得到存储器地址;在前变址寻址模式中,存储器地址的构成方式与偏移寻址模式相同,但存储器地址会回写到基址寄存器;在后变址寻址模式中,存储器地址为基址寄存器的值。基址寄存器的值加上或减去偏移量的结果写入基址寄存器。在每种情况下,偏移量都可以是一个立即数或是一个变址寄存器的值。基于寄存器的偏移量也可使用移位操作来调整。80加载和存储多个寄存器指令 加载多个寄存器(LDM)和存储多个寄存器(ST