嵌入式系统应用开发基础
上QQ阅读APP看本书,新人免费读10天
设备和账号都新为新人

2.3 ARM处理器的内部编程结构

2.3.1 ARM7TDMI应用内核的结构及引出信号线

1.ARM7TDMI应用内核的结构

尽管ARM处理器不同版本的结构是有差异的,但它们各自的内部组成还是存在不少相同的地方。下面以ARM7TDMI内核为例讨论其内部的编程结构。

所谓的编程结构就是与编程有关的,或程序指令可以涉及的结构内容。ARM7TDMI内核采用了冯·纽曼结构,其构建的应用内核结构框图如图2-7所示。

图2-7 ARM7TDMI应用内核的结构框图

由图2-7可看出,一个ARM7TDMI应用核包含了以下主要功能部件。

①ARM7TDMI内核。

②测试访问口控制器(Test Access Port,TAP)。TAP的作用是实现对芯片所有引出脚的监控,用户可以通过宿主机经JTAG接口向TAP控制器发送各种JTAG命令,促使各输出引脚产生规定的信号,或者是将各输入引脚的状态读出,从而在CPU没有任何存储器程序运行的情况下,使各引脚产生与特定程序运行时相同的信号变化效果,以此来达到对系统硬件电路的调试。关于JTAG技术的具体内容将在后续的章节中介绍。

③内嵌的在线仿真(In-Circuit Emulator,ICE)逻辑。为了方便快捷地对芯片内部的电路进行调试,在ARM7TDMI及后续的应用内核中都增加了ICE逻辑,以硬件的方式提供对电路调试的支持。具体是在JTAG逻辑的基础上增加了硬件断点寄存器、比较器等。通过这些功能部件就可以实现断点设置、三总线触发条件设置等调试环境,从而实现快速的程序调试和实时跟踪。

④数据线分离器(BUS Splitter)。由于ARM应用内核是以可扩展的片上结构形式提供的,不同的芯片厂家会在此基础上构造不同的具体应用电路。为了提高数据的吞吐量,有些电路需要分离的数据输入和数据输出线,所以ARM应用内核提供了两套数据线结构方案:一套是分离的数据输入和数据输出线;另一套是输入输出共用的数据线。但目前大多数的应用芯片采用的是输入输出共用一组数据线的方案,对此数据线分离器不起作用。

2.ARM7TDMI内核的结构及引出信号

ARM7TDMI内核的结构框图如图2-8所示,分类的引出信号如图2-9所示。

图2-8 ARM7TDMI内核的结构框图

图2-9 ARM7TDMI内核的引出信号

2.3.2 ARM内核编程结构要素

1.ARM微处理器的工作状态

RISC处理器的特点之一是具有统一的指令代码长度,而且多数为32位。但考虑到在某些应用中采用16位的代码进行指令编码已经完全符合应用需要,若都使用32位长度编码的指令显然会造成存储空间的浪费,因此ARM处理器设置了两种指令代码长度的指令模式供用户灵活的选用。32位代码长度的指令集称为ARM指令集,16位代码长度的指令集称为Thumb指令集。不同长度的指令代码将工作于不同的工作状态下,运行ARM指令的工作状态称为ARM状态,运行Thumb指令模式的工作状态称为Thumb状态。

①ARM状态:以状态寄存器中的标志位T=0为标志,所有运行的指令都是32位的,对应的代码存储空间以32位对齐。

②Thumb状态:以状态寄存器中的标志位T=1为标志,所有运行的指令都是16位的,对应的代码存储空间以16位对齐。

程序运行过程中可以由一种指令程序段转移到另一种指令程序段,但同时也必须进行相应的工作状态切换。

ARM处理器的初始工作状态处于32位的ARM状态,所读取和执行的必须是ARM指令。当需要转换到16位指令集运行时,需要采用专门的程序转移指令进行。通常的做法是采用带状态转换的转移指令“BX Rm”实现。该指令中操作码BX中的B表示转移(Branch),X表示进行ARM与Thumb的工作状态转换(eXchange)。操作数Rm是包含了转移目标地址的寄存器,该地址将指向Thumb指令程序的起始地址。也可以采用相同的方法由Thumb指令段转移到ARM指令段。

当处理器处于Thumb状态时,若操作数寄存器的最低位为0,执行BX指令时可以使微处理器从Thumb状态切换到ARM状态。另外若发生异常(如IRQ、FIQ、Undef、Abort、SWI等),且异常处理程序为ARM状态,异常处理返回时将自动切换回原来的Thumb状态。此外,在处理器进行异常处理时,把PC指针放入异常模式链接寄存器中,并从异常向量地址开始执行程序,也可以使处理器切换到ARM状态。

2.ARM体系结构的数据存储格式

如同其他计算机体系结构中的存储器构成方式一样,ARM体系结构可以支持的存储器最小寻址单位为字节。按照字节地址形成的存储器寻址空间称为线性地址空间。可以将存储器看成从零地址开始的字节的线性组合。在ARM体系结构中将4字节定义为一个字(Word),2字节定义为半字。如果从0地址开始存放字数据,0号字节到3号字节放置第一个字数据,从第4号字节到第7号字节放置第二个字数据,依次排列。作为32位的微处理器,ARM体系结构所支持的最大寻址空间为4GB(32根地址线寻址232字节)。但由于ARM内核的数据宽度为32位,一次就可以从存储器读写4个字节的数据。当ARM处理器向以字节为单位编址的线性地址空间写入字数据(或半字)数据时,就存在一个字(或半字)中高位字节和低位字节与存储器连续的4个字节单元(或2个字节单元)字节对应的问题。即到底是字数据中的低字节对应4个字节存储空间的低地址单元、高字节对应存储空间的高地址单元,还是字数据中的低字节对应4个字节存储空间的高地址单元、高字节对应存储空间的低地址单元。ARM体系结构可以支持这两种方式的存储格式,并分别称之为大端格式和小端格式。下面以12个字节数据0,1,2,3,4,5,6,7,8,9,10,11按先后顺序以字为单位写入从0地址开始的12个字节存储单元为例对大端格式和小端格式具体加以说明。

1)大端格式(Big-Endian)

在这种格式中,字数据的高字节存储在低地址中,而字数据的低字节则存放在高地址中,将3个字数据0X0B0A0908、0X07060504、0X03020100存入存储器的位置如图2-10所示。

图2-10 以大端格式存储字数据

2)小端格式(Little-Endian)

与大端存储格式相反,在小端存储格式中,低地址中存放的是字数据的低字节,高地址存放的是字数据的高字节。将上例3个字数据存入存储器的位置如图2-11所示。

在嵌入式系统应用中大部分采用的是小端格式。

图2-11 以小端格式存储字数据

3.ARM微处理器的指令长度及数据类型

ARM微处理器的指令长度可以是32位(在ARM状态下),也可以是16位(在Thumb状态下)。ARM处理器尽管数据线是32位,但是数据长度可以按照字节(8位)、半字(16位)、字(32位)三种方式访问外部存储器中的数据。如果访问的是字数据则需要地址值的最低两位保持0,使数据按4字节对齐;若访问的是半字数据则需要地址值的最低位保持0,使数据按2字节对齐。字节数据的访问地址可以是任意线性值。

4.ARM微处理器的工作模式

为了保证计算机系统程序运行的可靠性,大多数的多任务操作系统都设计为系统程序和用户程序相互隔离的工作环境下,其主要目的是为了防止用户程序有意或无意对系统程序可能造成的破坏。用户程序通常只具有很有限的资源访问权限,重要的系统资源都是由系统程序掌控的。用户程序只能通过特定的方式向操作系统申请提供所需的资源访问服务。不同的处理器会提供不同的资源访问权限的硬件支持结构,例如,Intel 80386以上的CPU就提供了4级不同的保护模式工作权限,Windows和Linux都仅采用了其中的2级。

ARM处理器同样也支持多用户程序下对系统程序和用户程序设置不同访问权限,而且为了加快异常的响应过程更是设置了多种针对不同异常的工作模式。因此ARM处理器包括用户模式、系统模式、快速中断模式、普通中断模式、数据访问中止模式、未定义指令中止模式,以及管理模式共7种工作模式。不同的工作模式具有不同的特权级别,表现在对系统资源的访问权限不同。但任意时刻程序都只能运行于这些工作模式内其中的一种。

处理器当前的工作模式由状态寄存器CPSR中的最低5位M[4:0]标示和确定。

1)用户模式:usr(user)

用户程序的执行模式是所有模式中特权级别最低的工作模式。在该模式下,运行的程序不能访问某些受保护的系统资源,也不能轻易改变自身的工作模式,但是可以通过软中断或其他异常的产生,进入具有特权级的模式环境下来使用那些受限制的资源。

除了用户模式外的其他6种工作模式都可以自由访问系统资源和在程序中改变自身的工作模式,所以以下的6种模式也称为特权模式。

2)系统模式:sys(system)

该模式具有与用户模式完全相同的寄存器组,但是却可以访问系统资源。它与其他5种特权模式的不同处是不可以通过异常方式进入。这种方式用于运行具有系统资源访问特权的操作系统任务。

除了用户和系统模式外的其他5种工作模式都是通过特定的异常/中断事件发生后自动进入的,所以也称为异常模式。ARM处理器中共有7种异常,详情见后续内容。

3)快速中断模式:fiq(fast interrupt request)

当ARM处理器的外部快中断引脚产生有效信号时将触发快中断异常,从而使处理器进入快速中断模式。该模式用于处理器与外设的快速数据传输。

4)中断模式:irq(interrupt request)

当ARM处理器的外部普通中断引脚产生有效信号时将触发本中断异常,从而使处理器进入中断模式。该模式用于普通方式下的处理器与外设的数据传输。

5)数据访问中止模式:abt(abort)

当数据或指令预取中止时进入该模式,可用于虚拟存储及存储保护。

6)未定义指令中止模式:und(undefined)

当未定义的指令执行时进入该模式,可用于支持硬件协处理器的软件仿真。

7)管理模式:svc(supervisor)

管理模式是常用的系统程序运行模式,也是处理器复位状态下的工作模式。即当系统复位或开机时将引发复位异常,并因此进入管理模式。另外通过执行软中断调用指令SWI也可以进入管理模式,用户程序可因此方式访问系统资源。

在上述的7种工作模式中,大多数情况下处理器都会处于系统模式(运行操作系统程序)或用户模式(运行用户程序)下,只有当系统产生中断或异常时处理器才会暂时转入相应的中止或中断模式,服务完成后仍将返回原运行模式。而管理模式通常是用于运行那些为系统程序或用户程序能够正常运行做准备的程序。处理器在上电或复位时的初始状态将处于管理模式,初始的复位程序基本上用于实现对系统进行初始化、自检等准备性操作,之后将转入系统模式(如果有操作系统)。

在7种工作模式中,用户模式的权限最低,不仅不能访问受保护的系统资源,而且不可以自行由指令实现工作模式的切换,即不可以通过改写CPSR内容实现工作模式的转换,对CPSR只能读不能写。而其他的6种工作模式则属于特权模式,不仅可以访问受保护的系统资源,而且可以直接由指令修改CPSR的工作模式位域从而转换到其他工作模式。这6种特权模式除了系统模式外的其他5种模式又归类为异常模式,它们的工作模式状态转换会伴随对应异常的产生而自动实现。表2-5给出了不同工作模式的转换方法。

表2-5 各种工作模式的进入和退出方法

5.ARM7TDMI内核的指令流水线

ARM7TDMI内核设计为三级流水线,如图2-12所示。了解指令的流水线结构是为了正确地理解当前执行的指令和当前指令指针PC值的关系,特别是在各种异常情况下如何正确设置异常返回的地址。在图2-12所示的例子中,在时钟周期3时执行的指令是指令1,同时进行指令译码的是指令2,而同时又进行的取指令操作的是指令3。即执行指令1时的当前指令指针PC值所指向的是指令1后面的第2条指令,即指令3。PC值对于ARM指令集为指令1的地址值加8,Thumb指令集为加4。例如ARM指令1的存储地址为0x1000,PC值就为0x1008。所以在后续的转移操作或异常处理程序内设置返回指令地址时需要进行相应的处理。

图2-12 ARM7TDMI内核的三级指令流水线结构

2.3.3 ARM内核的寄存器组织

ARM处理器共有37个32位的内部寄存器,其中31个为通用寄存器,6个为状态寄存器。当ARM处理器处于7种工作模式下的任何一种时,每种模式下只能使用一组17或18个内部寄存器,系统和用户模式为17个,其他模式为18个。在这37个寄存器中有些寄存器是7种工作模式下共用的,而另外一些则专属于不同的工作模式。图2-13是不同工作模式下可使用内部寄存器的分属情况,图中带左下角阴影的是专属特定工作模式的寄存器,没有阴影的是可在多种工作模式下共用的寄存器。这些可共用的寄存器包括16个通用寄存器R0~R15、1个当前程序状态寄存器CPSR。但需要注意的是这些可共用的寄存器并不是所有工作模式都可共用,其中有些寄存器只在部分工作模式下可共用,并且在ARM指令集状态下和Thumb指令集状态下这些寄存器组还有少许区别。

图2-13 ARM微处理器的内部寄存器组

1.通用寄存器(R0~R15)

尽管R0~R15称为通用寄存器,但实际上并不是完全通用的。由图2-13可以看出,只有R0~R7是7种工作模式都可共用的,所以这8个寄存器又称为未分组寄存器;而R8~R14只在部分工作模式下可共用,所以称为分组寄存器,它们在不同的工作模式下可共用的寄存器有所不同。另外由于R15的主要功能是作为程序计数器PC,所以在使用中具有一定的特殊性。

1)未分组寄存器(Unbanked Register)R0~R7

所谓的未分组寄存器,也就是所有的工作方式下都可共用的那些寄存器。这些寄存器共有8个,用关键字符号R0~R7表示。使用中需要注意的是,当一种工作方式转换为另一种工作方式之前,应及时保存这些寄存器内的中间结果,否则原有内容将被新工作方式下的程序破坏,因为在另外一种工作模式下仍然可直接使用这些寄存器。

2)分组寄存器(Banked Register)R8~R14

所谓的分组寄存器,也就是不同工作方式下各自的专属寄存器。这些寄存器分别对应不同工作模式时可共用的寄存器有所不同。例如,在FIQ工作方式下将使用专用的R8~R12寄存器,并用关键字R8_irq~R12_irq表示;而其他6种工作方式将共用同一组R8~R12寄存器。为FIQ工作方式设置专用的寄存器组R8_irq~R12_irq的目的是为了在快中断请求的响应过程中利用它们加快处理的速度。

3)特殊的通用寄存器R13、R14、R15

在16个通用寄存器中有3个寄存器R13、R14、R15有着其他通用寄存器不具有的特殊功能,它们除了可以作为通用寄存器使用外,还分别固定的作为堆栈指针寄存器SP(R13)、链接寄存器LR(R14)和程序计数器PC(R15)。

①堆栈指针寄存器R13。R13的主要作用是作为堆栈指针,即SP(Stack Pointer)使用。5种异常工作方式因各自异常处理程序中堆栈的专用性,所以需要专属的R13作为堆栈指针,分别用关键字R13_fiq、R13_svc、R13_abt、R13_irq、R13_und加以区分,而用户方式和系统方式则共用一个堆栈指针寄存器R13。由于处理器的每种运行模式均有自己独立的物理寄存器R13,在用户应用程序的初始化部分,一般都要初始化每种模式下的R13,使其指向该运行模式的栈空间,这样当程序运行进入异常模式时,可将需要保护的寄存器内容放入R13所指向的堆栈;而当程序从异常模式返回时,则从对应的堆栈中恢复。采用这种方式可以保证异常发生后程序的正常执行。当R13不作为堆栈指针时也可以作为通用寄存器使用。

②链接寄存器R14。R14称为链接寄存器(Link Register,LR),其作用实际上就是用于保存程序调用或异常响应中的返回地址参考值。当执行BL子程序调用指令或进行各种异常响应时,处理器会自动将R15(程序计数器PC)的值复制到R14中。当子程序结束时可根据R14的内容获取子程序及异常处理的返回地址。在其他情况下,R14仍可作为通用寄存器使用。另外当发生中断或异常时,也将产生与程序调用相类似的程序转地址执行,即进入中断或异常处理程序,但随之会产生工作方式的转换,处理器将由原来的工作模式(系统或用户)进入相应的异常工作模式,所以对应5种异常工作方式需要设置5个专属的返回地址寄存器LR,它们分别是R14_fiq、R14_svc、R14_irq、R14_abt和R14_und用来保存R15的返回值。而用户方式和系统方式将如同R13,共用一个R14。R14也可作为通用寄存器使用,但一定是其中没有有用的返回地址时。

需要注意的是R14获得的拷贝值并不一定是真正的返回地址值,有些需要针对不同的工作模式进行一些调整,具体方法见后续内容。

③程序计数器R15。寄存器R15在处理器运行过程中固定的作为程序计数器(Program Counter,PC),用于提供将要读取的后续指令地址,其内容会自动加4(ARM指令)或加2(Thumb指令)。在ARM状态下,由于指令都以字为读取单位,所以PC中指令地址值的最低两位[1:0]始终为0,以保证对存储器的取指令操作以字对齐。同理,在Thumb状态下由于指令都是以半字为读取单位的,所以PC中指令地址值的最低位[0]始终为0,以保证对存储器的取指令操作以半字对齐。

尽管R15也可以作为通用寄存器,但由于改变PC的值就意味着改变程序的走向,所以在将R15作为通用寄存器使用时必须谨慎,否则将会产生难以预料的结果。

由于ARM7TDMI内核结构采用了三级流水线技术,对于ARM指令集而言,PC总是指向当前执行指令的下两条指令的地址,即PC的值为当前指令的地址值加8个字节。

4)不同工作模式下可使用内部寄存器小结

对应ARM的7种工作模式下的任一模式,可以访问以上所讨论的一组16个通用寄存器和一到两个状态寄存器。其中的未分组寄存器R0~R7是7种工作模式所共用的,而分组寄存器对应不同的工作模式各具有独自的寄存器。特别在5种异常模式下,大部分都有自己专用的R13和R14,其中快中断模式更是具有R8~R14共7个专属寄存器。表2-6给出了每种运行模式下对应可访问的寄存器组合。

表2-6 工作模式及其所使用的寄存器对应表

CPSR可在任何运行模式下被访问,它包括条件标志位、中断禁止位、当前处理器模式标志位,以及其他一些相关的控制和状态位。

每一种运行模式下又都有一个专用的状态,当异常发生时,SPSR用于保存CPSR的当前值,从异常退出时则可由SPSR来恢复CPSR。

由于用户模式和系统模式不属于异常模式,因此,它们没有SPSR,当在这两种模式下访问SPSR时,其结果是未知的。

2.程序状态寄存器

在表2-6中可以看到,每种工作模式下除了拥有16个通用寄存器外,还有一个共用的寄存器CPSR,各异常模式下还拥有其各自专属的寄存器SPSR_xxx。

寄存器CPSR称为当前程序状态寄存器(Current Program Status Register),寄存器SPSR称为备份的程序状态寄存器(Saved Program Status Register)。计算机中的程序状态寄存器主要用途是记录和反映处理器的工作状态及某些指令执行结果所产生的特殊标识,同时也会用其中的某些位来设置一些控制信息。

ARM体系结构下无论什么工作模式都共用一个当前程序状态寄存器CPSR,而对应五种异常模式又分别有五个备份的程序状态寄存器SPSR_xxx。这是由于大部分情况下处理器是运行系统程序和用户程序,分别对应系统模式和用户模式。而异常处理程序通常只是临时占用一下处理器的执行时间,且大多数要返回原程序主体去运行,所以在进入异常处理程序时需要将主程序断点处的程序状态寄存器内容加以保存,以备返回后所用。

ARM体系结构中的程序状态寄存器结构如图2-14,其主要作用有以下三个。

图2-14 程序状态寄存器格式

1)记录和反映处理器某些指令执行结果所产生的特殊标识(位31~位27)

主要有N、Z、C、V、Q共5个,这些特殊标识的位状态是由处理器根据部分指令(如算数和逻辑运算指令)运行结果自动设置的,且主要作为后续指令的执行条件,所以也常常称为条件码。ARM的许多指令都可以以这些条件码作为执行的条件。这几个状态位也可以通过指令MSR和LDM进行访问。这些条件码的具体含义如表2-7。

表2-7 条件码标志的具体含义

2)允许或禁止对IRQ和FIQ请求响应位I(位7)和F(位6)
  • I=0表示允许响应IRQ中断请求,I=1表示禁止响应IRQ中断请求;
  • F=0表示允许响应FIQ中断请求,I=1表示禁止响应FIQ中断请求。

3)记录和反映处理器的当前工作模式位T(位5)和M[4:0](位4~位0)

①标识处理器当前是Thumb态还是ARM态且仅适用于V4及以上结构版本位T(位5)。

注意:不能直接用MSR指令对CPSR中的T位进行设置,否则将产生不可预见的后果。一般只能通过BX指令或在异常返回时利用SPSR到CPSR的内容拷贝隐含地进行。

②标识处理器当前是何种工作模式M[4:0](位4~位0)。这些位反映了处理器的当前运行模式,通常是在工作模式切换时由处理器自动设置的(如产生异常)。尽管也可以由指令来设置,但只能是在非用户模式下进行(特权模式下)。如果对此不是很清楚,最好不要盲目进行更改。这些位的具体含义如表2-8所示。

表2-8 运行模式位M[4:0]的具体含义

由表2-8可知,并不是所有的运行模式位的组合都是有效的,其他的组合结果会导致处理器进入一个不可恢复的状态。

注意:PSR中的其余位为保留位,当改变PSR中的条件码标志位或者控制位时,保留位不要被改变,在程序中也不要使用保留位来存储数据。保留位将用于ARM版本的扩展。

对CPSR内容的改动一般发生在以下几种情况:

  • 改变条件标志;
  • 禁止或允许中断;
  • 改变处理器的工作模式。