从零开始学ARM
上QQ阅读APP看书,第一时间看更新

1.2.3 ARM处理器

任何一款ARM处理器都由两大部分组成:ARM内核、外设。

ARM内核包括寄存器组、指令集、总线、存储器映射规则、中断逻辑和调试组件等。ARM内核是由ARM公司设计并以销售方式授权给各个芯片厂商使用。例如,为高速度设计的Cortex A8、A9,它们是ARMv7a架构;Cortex M3、M4是ARMv7m架构;前者是ARM内核,后者是指令集的架构(亦简称架构)。

外设部分包括计时器、ADC、存储器、I2C、UART、SPI、RAM等,它们完全由各芯片厂商自己设计,使外设与ARM内核衔接配套。不同的芯片厂商有不同的外设,因此构成了数量和规格庞大的ARM芯片产业。

1.ARM处理器分类

ARM7、ARM9、ARM11统称为经典的ARM处理器,ARM11处理器之后,也就是从ARMv7架构开始,ARM的命名方式有所改变。新的处理器家族以Cortex命名,并分为3个系列,分别是Cortex-A、Cortex-R、Cortex-M。很巧合,又是A、R、M这3个字母, ARM处理器分类如图1-17所示。

图1-17 ARM处理器分类

(1) Cortex-A系列

应用处理器:面向移动计算、智能手机、服务器等市场的高端处理器。这类处理器主要针对日益增长的消费娱乐和无线产品设计,运行的时钟频率很高(超过1GHz),支持如Linux、Android、Windows等操作系统需要的内存管理单元。用于具有高计算要求、运行丰富应用程序的操作系统及提供交互媒体和图形体验的应用领域,如智能手机、平板计算机、汽车娱乐系统、数字电视、电子阅读器、家用网络、家用网关和其他各种产品。

(2) Cortex-R系列

实时处理器:面向实时应用的高性能处理器系列,针对需要运行实时操作的系统及应用,如汽车制动系统、动力传动解决方案、大容量存储控制器等深层嵌入式实时应用。多数实时处理器不支持MMU(存储管理部件),不过其通常具有MPU(微处理器和内存保护单元)、Cache和其他针对工业应用设计的存储器功能。实时处理器运行在比较高的时钟频率(大于200MHz),响应延迟非常低。虽然实时处理器不能运行完整版本的Linux和Windows操作系统,但是支持大量的实时操作系统(RTOS)。

(3) Cortex-M系列

微控制器处理器:微控制器处理器通常面积很小、能效比很高。通常这些处理器的流水线很短,最高时钟频率很低(市场上有此类的处理器也可以运行在200MHz之上)。新的Cortex-M系列处理器非常容易使用。该系列面向微控制器领域,主要针对成本和功耗敏感的应用,如智能测量、人机接口设备、汽车和工业控制系统、家用电器、消费性产品和医疗器械等。

(4) Cortex-SC系列

除了上述3大系列处理器,还有一个主打高安全性的Cortex-SC系列处理器,主要用于政府安全芯片。其处理器性能和功能如图1-18所示。

图1-18 ARM处理器性能和功能

ARM11系列包括了ARM11 MPCore处理器、ARM1176处理器、ARM1156处理器和ARM1136处理器,它们是基于ARMv6架构的。

ARM Cortex-A5处理器、Cortex-A7处理器、Cortex-A8处理器、Cortex-A9处理器和Cortex-A15处理器属于Cortex-A系列,基于ARMv7-A架构。

Cortex-A53处理器、Cortex-A57处理器属于Cortex-A50系列,首次采用64位ARMv8架构。

2020年ARM发布了一款全新的CPU架构Cortex-A78,它基于ARMv8.2架构的指令集。

2021年ARM发布了基于ARMv9的架构:Cortex-X2、Cortex-A710和Cortex-A510。

2.ARM技术特征

ARM的成功,一方面得益于它独特的公司运作模式,另一方面,当然来自ARM处理器自身的优良性能。作为一种先进的RISC(精简指令集计算机)处理器,ARM处理器有如下特点。

(1)体积小、低功耗、低成本、高性能。

(2)支持Thumb(16位)/ARM(32位)双指令集,能很好地兼容8位或16位器件。

(3)大量使用寄存器,指令执行速度更快。

(4)大多数数据操作在寄存器中完成。

(5)寻址方式灵活简单,执行效率高。

(6)指令长度固定。

ARMv7采用的是32位架构,ARM的基本数据类型有以下3种。

(1) byte:字节,8 bit。

(2) halfword:半字,16 bi(t 半字必须与2字节边界对齐)。

(3) word:字,32 bit(字必须与4字节边界对齐)。存储器可以看作序号为0~232−1的线性字节阵列。

3.ARM工作模式

ARM7处理器、ARM9处理器、ARM11处理器的工作模式一共有7种。Cortex系列的ARM处理器工作模式有8种,多了1个“Monitor”(监控)模式,如表1-3所示。

表1-3 ARM处理器工作模式

(1)用户模式:用户模式是用户程序的工作模式,它运行在操作系统的用户态,在该模式下,系统没有权限去操作其他硬件资源,只能处理它自己的数据,也不能切换其他模式,要想访问硬件资源或切换其他模式,只能通过软中断或异常操作。

(2)系统模式:系统模式是特权模式的一种,不受用户模式的限制。用户模式和系统模式共用一套寄存器,操作系统在该模式下可以方便地访问用户模式的寄存器,而且操作系统的一些特权任务可以使用这个模式访问一些受控的资源。

(3)一般中断模式:一般中断模式也叫普通中断模式,用于处理一般的中断请求,通常在硬件产生中断信号之后处理器自动进入该模式,该模式为特权模式一种,可以自由访问系统硬件资源。

(4)快速中断模式:快速中断模式是相对一般中断模式而言的,它用来处理时间要求比较紧急的中断请求,主要用于高速数据传输及通道处理。

(5)管理模式:管理模式是CPU上电后的默认模式,因此该模式主要用于系统的初始化,软中断处理也在该模式下运行,当用户模式下的用户程序请求使用硬件资源时可通过软中断进入该模式。

(6)中止模式:中止模式用于支持虚拟内存或存储器保护,当用户程序访问非法地址,或者没有权限读取的内存地址时,会进入该模式,在Linux下编程时经常出现的段错误通常都是在该模式下发出并返回的。

(7)未定义模式:未定义模式用于支持硬件协处理器的软件仿真,CPU在指令的译码阶段不能识别该指令操作时,会进入未定义模式。

(8) Monitor模式:为了安全而扩展出的用于执行安全监控程序的模式,也是一种特权模式。

除用户模式以外,其余的7种模式被称为特权模式或非用户模式;其中除去用户模式和系统模式以外的6种又被称为异常模式,常用于处理中断或异常,以及用于需要访问受保护的系统资源等情况。

ARM之所以设计出这么多种模式,就是为了应对CPU运行时出现的各种突发事件,在应用程序的运行时,任何一个时间点可能发生很多异常事件,如关机、接收到网卡信息、访问非法内存、系统解析到了非法指令等,因此CPU不仅要能处理这些异常,还要能够从异常中再返回原来的应用程序并继续执行。

4.ARM寄存器

Cortex A系列的ARM处理器共有40个32位寄存器,其中33个为通用寄存器,7个为状态寄存器。用户模式和系统模式共用同一组寄存器,如图1-19所示。

通用寄存器包括R0~R15,可以分为以下3类。

● 未分组寄存器:R0~R7。

● 分组寄存器:R8~R14、R13(SP)、R14(LR),R8_fiq~R12_fiq在快速中断模式下单独使用。

● 程序计数器:R15。

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

在所有运行模式下,未分组寄存器都指向同一个物理寄存器,它们未被系统用作特殊的用途。在异常处理运行模式转换时,不同运行模式的处理器均使用相同的物理寄存器,可能造成寄存器中数据的覆盖。

图1-19 ARM寄存器

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

分组寄存器每一次访问的物理寄存器都与当前处理器的运行模式有关。对R8~R12来说,每个寄存器对应2个不同的物理寄存器,当使用快速中断模式时,分组寄存器访问寄存器 R8_fiq~R12_fiq;当使用除快速中断模式以外的其他模式时,分组寄存器访问寄存器R8_usr~R12_usr。

对R13、R14来说,每个寄存器对应7个不同的物理寄存器,其中一个为用户模式和系统模式共用,另外6个物理寄存器对应其他6种不同的运行模式,并采用以下记号来区分不同的物理寄存器。

R13_mode R14_mode

其中mode可为usr、fiq、irq、svc、abt、und、mon。

① 寄存器R13(SP)

寄存器R13在ARM指令集中常被用作堆栈指针,用户也可使用其他的寄存器作为堆栈指针,而在Thumb指令集中,某些指令强制要求使用寄存器R13作为堆栈指针。

处理器的每种运行模式均有自己独立的物理寄存器R13,在用户应用程序初始化时,要初始化每种运行模式下的寄存器R13,使其指向该运行模式的栈空间。这样,当程序的运行进入异常模式时,可以将需要保护的寄存器中的数据保存至R13所指向的堆栈,而当程序从异常模式返回时,再从该堆栈中恢复数据,采用这种方式可以保证异常发生后程序也能正常执行。

② 寄存器R14(LR)

当执行子程序调用指令(BL)时,R14可得到R15(程序计数器)的备份。

在每一种运行模式下,都可用R14保存子程序的返回地址,当用指令BL或BLX调用子程序时,将程序计数器的当前值复制给R14,执行完子程序后,又将R14的值复制回程序计数器,即可完成子程序的调用返回。以上的描述可用指令完成,如下。

从子程序返回。

方法1:MOV PC, LR或BX LR

方法2: 在子程序入口处使用以下指令将R14存入堆栈。

STMFD SP!,{,LR}

对应地,使用以下指令可以完成子程序返回。

LDMFD SP!,{,PC}

(3) 程序计数器R15(PC)

寄存器R15用作程序计数器,在ARM状态下,bit[1:0]为0,bit[31:2]用于保存PC值,在Thumb状态下,bit[0]为0,bit[31:1]用于保存PC值。

例如,在ARM状态下,如果PC的值是0x40008001,那么在寻址时,查找的地址为0x40008000,低2位会自动被忽略掉。

由于ARM架构采用了多级流水线技术,对ARM指令集而言,PC总是指向当前指令后两条指令的地址,即PC的值为当前指令的地址值加8byte,公式如下。

PC值=当前程序执行位置+8

(4) CPSR、SPSR

CPSR(当前程序状态寄存器)可在任何运行模式下被访问,它包括条件码标志位、控制位、当前处理器模式标志位,以及其他相关的控制和状态位。每一种运行模式下又都有一个专用的物理状态寄存器,被称为SPSR(备份的程序状态寄存器),当异常发生时, SPSR用于保存CPSR的当前值,从异常模式退出时则可由SPSR来恢复CPSR。

CPSR格式如图1-20所示。

图1-20 CPSR格式

① 条件码标志位

N、Z、C、V均为条件码标志位,它们的内容可被算术或逻辑运算的结果改变,并且可以决定某条指令是否被执行。在ARM状态下,绝大多数的指令是有条件执行的,在Thumb状态下,仅分支指令是有条件执行的,各条件码标志位说明如下。

● N:当用两个补码表示的带符号数进行运算时,N=1表示运行结果为负,N=0表示运行结果为正或零。

● Z:Z=1表示运算结果为零,Z=0表示运行结果非零。

● C:可以用以下4种方法设置C的值。

加法运算:当运算结果产生了进位,C=1,否则C=0。

减法运算:当运算结果产生了借位,C=0,否则C=1。

对于包含移位操作的非加/减运算指令,C为移出值的最后一位。

对于其他的非加/减运算指令,C的值通常不改变。

● V:对于加/减运算指令,当操作数和运算结果为二进制补码表示的带符号位溢出时,V=1表示符号位溢出;对于其他的非加/减运算指令V的值通常不改变。

● Q:在ARMv5及以上架构的E系列处理器中,Q标志位用来表示增强的DSP(数字信号处理)运算指令是否发生了溢出。在其他版本的处理器中,Q标志位无定义。

● J:仅ARMv5TE-J架构支持,T=0、J=1时,处理器处于Jazelle状态,该位也可以和其他位组合。

● E:大小端控制位。

● A:A=1 禁止不精确的数据异常。

② 控制位

CPSR的低8位(包括I、F、T和M[4:0])称为控制位,当发生异常时这些位可以被改变,如果处理器运行在特权模式下,这些位也可以由程序修改。

● I、F:中断禁止位。I =1,禁止IRQ中断;F=1,禁止FIQ中断。要想在程序中实现禁止中断,那么就需要将CPSR[7]置1。

● T:T = 0、J=0,处理器处于ARM状态;T=1、J=0,处理器处于Thumb状态;T = 1、J=1处理器处于ThumbEE状态。

● M[4:0]:运行模式位。决定处理器的运行模式如表1-4所示。

表1-4 CPSR控制位

要想理解U-Boot、Linux的启动及异常处理的流程,必须熟练掌握寄存器的操作。

5.指令集

指令集是处理器结构中最重要的一个部分,用ARM的术语亦称为ISA(指令集体系结构)。指令集可以说是CPU的灵魂,要想使用CPU,我们只能通过指令集中的指令来进行操作。

对于32位的CPU,它的指令就是一个32位的二进制序列,不同的值代表不同的指令, CPU的硬件能完美地解析并执行这些指令,如寻址、运算、异常处理指令等。例如,当我们使用手机玩游戏的时候,我们发出的每一个招式,其实最终都是被转化成了一系列的机器指令。

(1) CISC和RISC

CISC(复杂指令集计算机)和RISC(精简指令集计算机)是两大类主流类型的CPU指令集计算机。

CISC以Intel、AMD的x86、CPU为代表,而RISC以ARM、IBM Power为代表。设计RISC的初衷是由于CISC CPU的复杂度高,所以想要设计一款计算机使其能选择在单个CPU周期完成的指令,以降低CPU的复杂度,并将复杂操作交给编译器。

ARM指令集是RISC架构,RISC把着眼点放在如何使计算机的结构更加简单和如何使计算机的处理速度更加快速上。RISC选取了使用频率最高的简单指令,抛弃复杂指令,固定指令长度,减少指令格式和寻址方式,不用或少用微码控制。这些特点使得RISC架构非常适合嵌入式处理器。

在功耗方面,一个4核的Intel i7的CPU功率为130W。而一块ARM A8单个核心的CPU,设计功率只有2W。对于移动设备,功耗是一个远比性能更重要的指标。

在价格方面,ARM公司并没有垄断CPU的生产和制造,只是进行CPU设计,然后把对应的知识产权授权出去,让其他厂商来生产ARM架构的CPU。它甚至还允许这些厂商基于ARM的架构和指令集设计属于自己的CPU,如高通、苹果、三星、华为,它们都拿到了基于ARM体系架构设计和制造CPU的授权。ARM公司只收取对应的专利授权费用。多个厂商之间的竞争,使得市场上ARM芯片的价格很便宜。

在指令数量方面,早期的RISC,其指令数比CISC少,但后来,很多RISC指令集中的指令数反超了CISC,因此,需要根据引用指令的复杂度而非数量来区分两种指令集。

RISC可以实现以相对少的晶体管设计极快的微处理器。通过研究发现,它只有大约20%的指令是常用的,并将处理器能执行的指令数目减到最少,优化执行过程,提高处理器的工作速度。一般来说,RISC的处理器比同等的CISC的处理器的工作速度快50%~75%,也更容易设计和纠错。

当然,CISC也是通过操作内存、寄存器、运算器来完成复杂指令的。它处理复杂指令时,先将复杂指令转换为一个微程序,微程序在制造CPU时就已存储于微存储器中。一个微程序包含若干条微指令(亦称微码)。CISC微程序的执行不可被打断,而RISC微程序的执行可以被打断,这也是RISC和CISC的差别,所以理论上RISC可更快响应中断。

(2) ARM指令格式

ARM指令格式如图1-21所示。

图1-21 ARM指令格式

操作码:操作码就是汇编语言里的mov、add、bl等符号码。

操作数地址:用于说明该指令需要的操作数所在地址是在内存里还是在CPU的内部寄存器里。

实际上,机器指令格式远比图1-21所示的复杂,图1-22所示是常用的ARM指令机器码。

图1-22 ARM指令机器码

注:Cond为条件码,Operand2为操作数,Offset为偏移量,L为分支跳转指令。

关于这些机器指令格式,后面我们会挑选其中几个进行分析,对于大部分初学者,没有必要花费太多精力去研究这些机器指令,只需要大概了解即可。

(3)指令流水线

流水线技术通过多个功能部件并行工作来缩短程序执行时间,提高处理器核的效率和吞吐率,从而成为微处理器设计中最重要的技术之一。

① 3级流水线

截止到ARM7系列,ARM处理器使用简单的3级流水线,如图1-23所示,它包括下列流水线级。

取指令:从寄存器装载一条指令。

译码:识别被执行的指令并为下一个周期准备数据通路的控制信号。在这一级,指令占有译码逻辑,不占用数据通路。

执行:处理指令并将结果写回寄存器。

图1-23 3级流水线

当处理器执行简单的数据处理指令时,流水线使平均每个时钟周期内,处理器能完成1条指令,但单独执行1条指令需要3个时钟周期,吞吐率为每个周期1条指令。

对于3级流水线,PC寄存器里的值并不是正在执行的指令的地址,而是预取指令的地址,这个知识点很重要,后面我们会详细举例来证明。

处理器要满足高性能的要求,因此需要优化处理器的组织结构。提高性能的方法主要有如下两种方法。

● 提高时钟频率。提高时钟频率必然会缩短指令执行周期,所以要简化流水线每一级的逻辑运算,增加流水线的级数。

● 减少每条指令的平均指令周期数(CPI)。优化多于1条完整流水线周期的指令实现方法,以使其占有较少的周期,或者减少因指令造成的流水线停顿,也可以将两者结合起来。

较高性能的ARM核使用了5级流水线,而且具有单独的指令和数据存储器。 在Cortex-A8中有一条13级的流水线,但是ARM公司没有公开技术相关的细节。

从经典ARM系列到现在的Cortex系列,ARM处理器的结构越来越复杂,但没改变的是CPU的取指令和地址关系,不管处理器采用几级流水线,都可以按照最初的3级流水线的操作特性来判断其当前的PC位置。

② 指令对流水线影响

为方便理解,下面我们以3级流水线为例,讲解不同指令对流水线的影响,最佳流水线如图1-24所示。

● 最佳流水线

图1-24 最佳流水线

这是一个理想的实例,所有的指令都在寄存器中执行,且处理器完全不用离开芯片。在每一个周期都有一条指令被执行,流水线的容量得到了充分的利用,指令周期数(CPI)为1。

● LDR流水线如图1-25所示。

图1-25 LDR流水线

该实例中,在6个时钟周期内共执行了4条指令,指令周期数(CPI)为1.5。与最佳流水线不同,装载(LDR)操作将数据移进SoC,导致数据总线被占用,随后紧接写周期将数据写回寄存器。

1)数据总线在周期1、2、3中被使用,周期6用于取指令,周期4用于装载数据,而周期5是一个内部周期,用来将载入的数据写回寄存器。

2)周期3为执行周期,用于产生地址。

3)周期4为数据周期,用于从存储器中取数据。

4)周期5为写回周期,通过数据总线和ALU将数据写回。

5)周期6的执行被推迟了,直到周期5数据写回完成(使用ALU)。同样,内部周期是不需要等待的,但读写存储器时可能需要。

● 分支流水线如图1-26所示。

分支指令用于实现指令流的跳转,并存储返回地址到寄存器R14。

图1-26 分支流水线

1)周期1用于计算分支指令的目的地址,同时完成一次指令预取,流水线被阻断。在任何情况下都要完成预取指令,因为若判决地址已产生,此时已来不及停止预取指令。

2)周期2在分支指令的目的地址(0x40008FEC)完成取指令,如果L位已设置返回地址,则将指令存于寄存器R14。

3)周期3完成目的地址(0x4008FF0)的取指令,并重新填满流水线。

4)指令BL的执行需要3个时钟周期。

● 中断流水线如图1-27所示。

图1-27 中断流水线

中断的反应时间至少有7个时钟周期。

1)周期1:内核被告知中断在现行指令执行完之前不会被响应(对于MUL和LDM/STM指令响应时间会有长的延迟);在解码阶段,中断被解码(中断已使能,并设置了相应标志位)。如果中断已使能,则正常的指令将不会被解码。

2)周期2:此时总是进入ARM状态。执行中断(获取IR向量的地址),保存CPSR于 SPSR,改变CPSR模式为IRQ模式并禁止进一步的 IRQ中断输入。

3)周期3:保存PC的地址(0x400800C)于R14_irq,从IRQ异常处理向量表中的地址(0x00000018)处取指令。

4)周期4:解码向量表中的指令,调整R14_irq。

5)周期5:执行跳转指令。

6)周期6:取异常处理子程序的第一条指令。

7)周期7:从子程序返回:SUBS pc,lr,#4。

这将恢复工作模式并从响应中断前的下一条指令处(0x40008008)取指令,如果有多个中断,需堆栈保存返回地址。

6.协处理器

ARM体系结构允许通过增加协处理器来扩展指令集。例如,控制Cache和存储管理单元的CP15协处理器、设置异常向量表地址的MRC指令。

ARM支持16个协处理器,在程序执行过程中,每个协处理器忽略属于ARM处理器和其他协处理器的指令,当一个协处理器不能执行属于它的协处理器指令时,就会产生一个未定义的异常中断,在异常中断处理程序中,可以通过软件模拟该硬件的操作,例如,如果系统不包含向量浮点运算器,则可以选择浮点运算软件模拟包来支持向量浮点运算。

ARM协处理器指令包括以下3类。

(1)用于ARM处理器初始化ARM协处理器的数据操作。

(2)用于ARM处理器的寄存器和ARM协处理器的寄存器间的数据传送操作。

(3)用于在ARM协处理器的寄存器和内存单元之间传送数据。

这些指令包括如下5条。

(1) CDP:协处理器数据操作指令。

(2) LDC:协处理器数据读入指令。

(3) STC:协处理器数据写入指令。

(4) MCR:ARM寄存器到协处理器寄存器的数据传送指令。

(5) MRC:协处理器寄存器到ARM寄存器的数据传送指令。

关于协处理器指令,我们只需要知道以上几个常用指令即可。

7.Jazelle

Jazelle读作杰则来,是 Java字节码状态,是为了运行Java虚拟机而添加的一种状态。ARM的Jazelle技术在硬件上提供了对Java字节码的支持,大大提高了系统的性能, Jazelle技术处理流程如图1-28所示。

图1-28 Jazelle技术处理流程

8.ARM授权

ARM 主要有3种授权等级:使用层级授权、内核层级授权和架构层级授权,其中架构层级授权等级最高,企业可以对ARM指令集进行改造从而自行设计处理器。例如苹果、三星、高通、华为等企业,它们都必须向ARM公司购买各架构下的不同层级授权,根据企业的使用需求购买相应的层级授权。

(1)架构层级授权

架构层级授权是指有了该授权,用户可以对ARM架构进行大幅度改造,甚至可以对ARM指令集进行扩展或缩减,苹果公司就是一个很好的例子,在使用ARMv7-A架构基础上,扩展出了自己的苹果Swift架构。

(2)内核层级授权

内核层级授权是指有了该授权,用户可以在该内核基础上加上外设,如USART、GPIO、SPI、ADC等,最后形成了企业独有的MCU。

(3)使用层级授权

用户要想使用一款处理器,得到使用层级授权是最基本的,这就意味着用户只能使用已定义好的IP核嵌入其设计中,不能更改已定义的IP核,也不能借助该IP核创造基于该IP核的封装产品。因此,如果某企业分别拿到架构层级授权和使用层级授权,那么意味着某企业可以在ARM指令集基础上根据需要创建内核架构,并可添加各种SoC外设,比如通信接口、显示器控制接口、GPIO等,从而生产出自己的处理器芯片。

举个例子,我写了一篇文章,我告诉张三,你可以将文章修改后使用,这种授权便是架构层级授权,我告诉李四,你可以在你的文章中引用我的文章,这种授权便是内核级授权,我告诉王五,你只能对我的文章进行转发,但不能做任何更改,这种授权便是使用层级授权。