第2章ARM体系结构硅谷芯微技术贡献网址:本章中,将着眼于ARM9内核、处理器状态与模式、内部寄存器、程序状态寄存器、异常、中断及其向量表和存储系统的学习,这是成为一个应用工程师必备的基础。本章中程序范例除非特别声明,否则处理器均处于ARM状态,执行字方式的ARM指令。第2章目录1.ARM9TDMI2.ARM的模块、内核和功能框图3.ARM处理器状态4.ARM处理器模式5.ARM内部寄存器6.当前程序状态寄存器7.ARM体系的异常、中断及向量表8.ARM体系的存储系统9.课后练习2.1ARM9TDMIARM9TDMI是基于ARM体系结构v4版本的高端ARM核(注意:核并非芯片,ARM核与其他部件(如RAM、ROM、片内外设)组合在一起才构成现实的芯片)。ARM9TDMI是从ARM7核发展而来的。ARM9TDMI后缀的涵义如下:■T:支持高密度Thumb指令集扩展;■D:支持片上调试;■M:支持64位乘法指令;■I:带EmbeddedICE硬件仿真功能模块。ARM9TDMI-S是ARM9TDMI的可综合(synthesizable)版本(软核),对应用工程师来说,除非芯片生产厂商对ARM9TDMI-S进行了裁剪,否则在逻辑上ARM9TDMI-S与ARM9IDMI没有太大区别,其编程模型与ARM7TDMI一致。•2.1.1存储器的字与半字(1)ARM处理器使用了冯·诺依曼(vonNeumann)结构,提供单一的主存接口。比如ARM7处理器就是标准的冯·诺依曼(vonNeumann)结构。而ARM9处理器的CPU/MMU/CACHE系统是指令和数据分开的,不过通常也还是提供单一的主存接口,因此ARM9处理器也可以看成是哈佛(Harvard)结构。从大的方面讲,无论哪种ARM处理器结构,都可以看成是是冯·诺依曼(vonNeumann)结构,指令和数据共用一条32位总线,因此只有装载、存储和交换指令可以对存储器中的数据进行访问。ARM处理器直接支持8位字节、16位半字或者32位字的数据类型。其中,以能被4整除的地址开始连续的4个字节构成1个字,字的数据类型为4个连续的字节。从偶数地址开始连续的2个字节构成一个半字,半字的数据类型为2个连续的字节。ARM指令的长度刚好是1个字,Thumb指令的长度刚好是一个半字。•2.1.1存储器的字与半字(2)如果一个数据是以字方式存储的,那么它就是字对齐的,否则就是非字对齐的。如果一个数据是以半字方式存储的,那么它就是半字对齐的,否则就是非半字对齐的,半字与字对齐的实际情况见表2.1。表2.1半字与字对齐方式半字对齐字对齐地址特征0x40020x40040x40060x4008.0x40040x40080x400C0x4010.bit0=0其他位置为任意值bit1=0,bit0=0其他位置为任意值•2.1.1存储器的字与半字(3)注意:ARM处理器直接支持对齐的半字或字数据的存取,也就是可以使用一条相应的指令来实现对应操作(详见第三章)。如果访问非对齐的半字或字数据,将需要多条指令组合才能实现对应的操作,这对程序的执行效率影响较大。因此,在C语言编程中,定义的多字节变量或结构体,最好使其为对齐存放。•2.1.25级流水线(1)ARM处理器使用流水线来增加处理指令流的速度,这样可使几个操作同时进行,并使处理和存储器之间的操作更加流畅、连续,能提供1.1MIPS/MHz的指令执行速度。相比ARM7(3级流水线),ARM9增加了2个功能部件分别访问存储器并写回结果,且将读寄存器的操作转移到译码部件上,使流水线各部件在功能上更平衡。5级流水线如图2.1所示(其中PC为程序计数器),流水线使用5个阶段,因此指令分为5个阶段执行。■取指:从存储器装载一条指令;■译码:识别将要被执行的指令;■执行:处理指令,产生ALU运算结果或产生存储器地址(对于存储器访问指令来讲);■访存:访问数据存储器;■回写:将执行结果写回寄存器。•2.1.25级流水线(2)图2.1ARM9的5级指令流水线取指译码执行访存回写从存储器取出指令对指令使用的寄存器进行译码,并从从寄存器组只能感读出寄存器产生ALU运算结果或产生存储器地址(对于存储器访问指令来讲)访问存储器将执行结果写回到寄存器ARMThumbPCPCPC-4PC-2PC-8PC-4PC-12PC-6PC-16PC-8•2.1.25级流水线(3)在传统的80C51单片机中,处理器只有完成一条指令的读取和执行后,才会开始下一条指令的处理所以PC总是指向正在“执行”的指令。而ARM9处理器采用5级流水线,具有5个工位,将指令的处理分为5个阶段,分别是取指、译码、执行、访存和回写。因此ARM“正在执行”第3条指令的同时对第4条指令进行译码,将第5条指令从存储器中取出,对第2条指令完成访存操作,对第1条指令完成回写操作。那么一条ARM9流水线只有在取第6条指令的时,第一条指令才算完成执行。也就是说,在流水线中同时存在5条指令,它们分别处于不同的处理阶段。下面用图2.2来进一步阐述5级流水线的处理机制,这样更加形象和具体。该图反映了处理器处于第三个周期时的PC指向。在执行“指令1”的同时对“指令2”进行译码,并将“指令3”从存储器中取出。也就是说当“指令1”•2.1.25级流水线(4)完成执行时,才开始对“指令4”的取指处理。由此可见,与PC有关的阶段只有取指、译码和执行,即执行PC-8处的指令的同时,对PC-4处的指令进行译码操作,对PC处的指令进行取指操作。而访存与回写则与PC无关。图2.2ARM9的5级最佳流水线指令执行顺序取指译码执行回写取指译码执行访存回写取指译码执行访存回写取指译码执行回写T1T2T3T4时钟周期MOVR0,R1LDRR3,[R4]STRR9,[R13]MOVR6,R7PC-8PC-4PCPC+4指令1指令2指令3指令4当前周期•2.1.25级流水线(5)无论处理器处于何种状态,程序计数器R15(即PC)总是指向“正在取指”的指令,而不是指向“正在执行”的指令或正在“译码”的指令。一般来说,人们习惯性约定将“正在执行的指令作为参考点”,称之为当前第1条指令。因此,PC总是指向第3条指令,或者说PC总是指向当前正在执行的指令地址再加2条指令的地址。当处理器处于ARM状态时,每条指令长为4字节,所以PC的值为正在执行的指令地址加8字节,即:当处理器处于Thumb状态时,每条指令长为2字节,所以PC的值为正在执行的指令地址加4字节,即:PC值=当前程序执行位置+8字节PC值=当前程序执行位置+4字节•2.1.25级流水线(6)下面通过示例程序来进一步了解实际读取PC时要注意的问题,如程序清单2.1所示:程序清单2.1PC的读取假设地址0x4000上的ADD指令是处理器“正在执行”的第1条指令,该指令的功能是把PC+4的值放到PC寄存器里(通常用于程序跳转)。由于PC总是指向第三条指令,即0x4008就是“正在取指”的指令的地址,从而可以得出地址:PC+4=0x4008+4=0x400C,于是将地址值0x400C写入PC寄存器,千万不要误认为是写入地址值0x4004。0x4000ADDPC,PC,#4;正在被执行的指令,将地址值PC+4写到PC0x4004...;正在被译码的指令0x4008...;正在被取指的指令,PC=0x40080x400C...;PC+4=0x400C•2.1.25级流水线(7)注意:从上面的描述可以发现只有流水线被指令填满时才能发挥最大效能,即每时钟周期完成一条指令的执行(仅指单周期指令)。如果程序发生跳转,流水线会被清空,这将需要几个时钟才能使流水线再次填满。因此,尽量少地使用跳转指令可以提高程序执行效率,解决方案就是尽量使用指令的“条件执行功能”,详见第三章。2.2ARM的模块、内核和功能框图ARM的模块框图见图2.3,功能框图见图2.4,内核框图见图2.5。ARM模块包含了CPU协处理器接口信号、读与写数据总线(WDATA和RDATA)、EmbeddedICE硬件仿真功能模块和片上调试系统等必备的功能。数据总线上没有双向路径,图2.3对这些作了简化。如图2.4所示,ARM微处理器与传统的8位单片机相比,在很多地方都有相似之处。例如,同样也包含了时钟、存储器接口、存储器管理接口、总线控制、仲裁等基本功能模块;所不同的是增加了功能更加强大的协处理器接口、调试接口、同步的EmbeddedICE-RT扫描调试访问接口等。图2.3ARM模块框图EmbeddedICE-RT宏单元扫描链2CPU扫描链1数据总线EmbeddedICE-RTTAP控制器协处理器接口信号DBGRNG(0)DBGRNG(1)DBGEXT(0)DBGEXT(1)SIZE[1:0]PORT[1:0]TRANS[1:0]LOCKWRITEADDR[31:0]WDATA[31:0]RDATA[31:0]DBGTCKENDBGTMSDBGnTRSTDBGTDIDBGTDO图2.4ARM功能框图ARM9TDMI-SCLKCLKENnIRQnFIQnRESETCFGBIGENDDMORELOCKDBGINSTRVALIDDBGRQDBGBREAKDBGACKDBGnEXECDBGEXT[1]DBGEXT[0]DBGENDBGRNG[1]DBGRNG[0]DBGCOMMRXDBGCOMMTXDBGTCKENDBGTMSDBGTDIDBGnTRSTDBGTDODBGnTDOENADDR[31:0]WDATA[31:0]RDATA[31:0]ABORTWRITESIZE[1:0]PROT[1:0]TRANS[1:0]CPnTRANSCPnOPCCPnMREQCPSEQCPTBITCPnlCPACPB同步的EmbeddedICE-RT扫描调试访问接口存储器接口存储器管理接口协处理器接口调式接口仲裁时钟中断总线控制图2.5ARM内核框图地址寄存器地址增量器扫描调试控制寄存器组37x32位寄存器(6个状态寄存器)乘法器桶形移位器32位ALU写数据寄存器指令流水线读数据寄存器Thumb指令译码器指令译码和逻辑控制CLKCLKENCFGBJGENCnIRQnFIQnRESETABORTLOCKWRITESIZE[1:0]PROT[1:0]TRANS[1:0]DBG输出DBG输入CP控制CP握手WDATA[31:0]RDATA[31:0]ADDR[31:0]2.3ARM处理器状态嵌入式系统在某些应用场合对存储成本或空间要求比较苛刻,为了让用户更好地控制代码量,于是设计了2套指令系统,分别为ARM指令集和Thumb指令集。其中ARM指令集为32位(字)长度,具有最完整的功能;Thumb指令集为16位(半字)长度,能实现ARM指令集的大部分功能。在功能上可以认为Thumb是ARM指令集的子集(见图2.6),图2.6两种指令集的关系ARM指令集Thumb指令集但其却具有极高的代码密度(平均缩减30%的代码量)。既然ARM处理器共存2种指令集,那么到底何时执行ARM指令集,何时执行Thumb指令集呢?ARM处理器有2个处理器状态与这2套指令集分别对应。以“当前程序状态寄存器CPSR”中的控制位T反映处理器正在操作的状态,即哪种指令集正在执行。当T=0时,处理器处于ARM状态,执行ARM指令;当T=1时,处理器处于Thumb状态,执行Thumb指令。由此可见,ARM处理器的2种操作状态分别为:■ARM状态:32位,处理器执行字方式的ARM指令,处理器在系统上电时默认为ARM状态;■Thumb状态:16位,处理器执行半字方式的Thumb指令。注意:ARM和Thumb状态间的切换并不影响处理器模式或寄存器内容。只有当处理器处于ARM状态时,ARM指令集才有效,反之只能使用Thumb指令集。当处理器处于Thumb状态,处理器“只能”执行16位的Thumb指令;也就是说,无论处理器处于何种状态,ARM指令集与Thumb指令集不能同时混合使用。从一个ARM例程调