前言:
本文是根据哔哩哔哩网站上“正点原子[第二期]Linux之ARM(MX6U)裸机篇”视频的学习笔记,在这里会记录下正点原子 I.MX6ULL 开发板的配套视频教程所作的实验和学习笔记内容。本文大量引用了正点原子教学视频和链接中的内容。
引用:
正点原子IMX6U仓库 (GuangzhouXingyi) - Gitee.com
《【正点原子】I.MX6U嵌入式Linux驱动开发指南V1.5.2.pdf》第 8.1 章
《正点原子资料_A盘/02开发板原理图/IMX6ULL_MINI_V2.2(Mini底板原理图).pdf》
-
资料盘
开发板资料链接: https://pan.baidu.com/s/1j5Jzbdx9i-g0cWIi3wf2XA 提取码:ag1u
正文:
本文是 “正点原子[第二期]Linux之ARM(MX6U)裸机篇--第6.3讲” 的读书笔记。
1. ARM Contex-A7 寄存器介绍
本节介绍 ARM Contex-A 的内核寄存器,注意不是芯片的外设寄存器,本节主要参考 《ARM Contex-A(armV7)编程手册V4.0.pdf》第三章 ARM Processor Modes And Registers。
ARM构架提供了 16 个 32 位通用寄存器(R0~R15)供软件使用,前 15 个寄存器(R0~R14)可以用作通用寄存器,R15 是程序计数器 PC (Program Counter),用来保存将要执行的指令。ARM 还提供了一个当前程序状态寄存器 CPSR (Current Program Status Register) 和一个备份程序状态寄存器 SPSR (S Program Status Register),SPSR 寄存器就是 CPSR 寄存器的备份。这18个寄存器如图 6.3.1 所示。
上一小节我们讲到 ARM Contex-A7 有9种运行模式,每一种运行模式都有一组与之对应的寄存器组。每一种模式可见的寄存器包括15个通用寄存器(R0~R14),一两个状态寄存器,和一个程序计数器PC。在这些寄存器中,有些是所有模式公用的同一个物理寄存器,有一些是个模式自己拥有的,各个模式所拥有的寄存器如下表所示。
在上图中浅色字体的是与 User 模式所共有的寄存器,蓝绿色背景的是各个模式所独有的寄存器。可以看出,在所有模式总,低寄存器组(R0~R7)是共享同一组物理寄存器的,只是一些高寄存器组在不同的模式下有自己独有的寄存器,比如 FIQ 模式下 R8~R14 是独立的物理寄存器。假如某个程序在 FIQ 模式下访问 R13 寄存器,那它实际访问的是寄存器 R13_fiq,如果程序在 SVC 模式下访问 R13 寄存器,那它实际访问的是寄存器R13_svc 。总结一下,ARM Contex-A 内核的寄存器组组成如下:
- 34个通用寄存器,包括R15 程序计数器(PC),这些寄存器是32位的。
- 8个状态寄存器
- HYP模式下一个独有的 ELR_Hyp寄存器
1.1 通用寄存器
R0-R15 就是通用寄存器,通用寄存器可以分为一下3类
- 未备份寄存器,即 R0~R7
- 备份寄存器,即 R8~R14
- 程序计数器PC,即 R15
1.1.1 未备份寄存器
未备份寄存器指的是 R0~R7 这8个寄存器,因为在所有的处理器模式下这个8个寄存器都是同一个物理寄存器,在不同模式下下,这8个寄存器的数据就会被破坏。所以这8个寄存器没有被用作特殊用途。
1.1.2. 备份寄存器
备份寄存器中的 R8 ~ R12 这 5 个寄存器有两种物理寄存器,在快速中断模式下 FIQ 它们对应着 Rx_irq(x=8~12)物理寄存器,其它模式下对应着 Rx(8~12)物理寄存器。FIQ是快速中断模式,看名字就知道这个中断模式要求快速执行。FIQ模式下中断处理程序可以使用 R8 ~ R12 寄存器,因为 FIQ 模式下下 R8~R12 是独立的,因此中断可以不用执行保存和恢复中断现场的指令,从而加速中断的执行过程。
备份寄存器 R13 一共8个物理寄存器,其中一个是用户模式(User)和系统模式(Sys)公用的,剩下一个分别对应7种不同的模式。R13 也叫做 SP (Stack Pointer),用来做栈指针。基本上每种模式都有一个自己的R13寄存器,应用程序会初始化R13,使其指向该模式专用的栈地址,这就是常说的初始化SP指针。
备份寄存器R14一共有7个物理寄存器,其中一个是用户模式(User)和系统模式(Sys)和超级监视模式(Hyp)所共有的,剩下的6中分别对应着6中不同的模式。R14也称为连接寄存器(LR),LR寄存器在ARM中的主要用途有以下2种:
- 每种处理器模式使用R14(LR)来存放当前子程序的返回地址,如果使用 BL 或则 BLX 来调用子函数的话,R14(LR)用来存放当前函数的返回地址,在子函数中,将R14(LR)的值赋值给R15(PC)即可完成子函数的返回,比如在子程序中使用如下代码:
MOV PC, LR @寄存器LR中的值赋值给PC,实现跳转
或者可以在子程序入口将LR入栈:
PUSH {LR} @将LR寄存器入栈
在子程序的最后出栈即可
POP {PC} @将上面压栈的LR寄存器出栈给PC寄存器,严格意义上来讲应该是将@LR-4 赋
@赋值给PC,应为是3级流水线,这里只是演示代码 - 当异常发生时,该异常模式对应的R14寄存器被设置成该异常模式将要返回的地址,R14也可以当做普通寄存器使用。
1.1.3. 程序计数器R15
程序计数器R15也叫做PC,R15保存着当前正在执行的指令地址加8字节,这是因为ARM的流水线机制导致的。ARM处理器3级流水线:取指->译码->执行,这3级流水香循环执行,比如当前正在执行第一条指定的同时,也对第二条指令译码,第三条指令也同时被去除存放到 R15 (PC)中。我们喜欢以当前你正在执行的指令作为参考点,也就是以第一条执行为参考点,那么 R15(PC)中存放就是第三条指令,换句话说R15(PC)总是指向当前正在执行的指令地址再加上2条指令的地址。对于32位的ARM处理器,每条指令时4个字节,所以
R15(PC)值 = 当前执行的程序位置 + 8 个字节
1.2 程序状态寄存器
所有的处理器模式都公用一个 CPSR (Current Program State Register)物理寄存器,因此 CPSR 可以在任何模式下访问。CPSR 是当前程序状态寄存器,该寄存器包含了条件标志位,当前处理器模式标志等一些状态为以及一些控制位。所有的处理器模式都公用一个CPSR必然会导致冲突,为此,除了 User 和 Sys 这两个模式以外,其它7个模式都配备了一个专用的物理状态寄存器,叫做 SPSR (备份程序状态寄存器),当特定的异常中断发生时,SPSR寄存器用来保存当前策划给你续状态寄存器(CPSR)的值,当异常退出以后可以用SPSR中保存的值来回复CPSR。
因为User和Sys两个模式不是异常模式,所以并没有配置SPSR,因此不能再User和Sys模式下访问SPSR,会导致不可预知的结果。由于SRSR是CPSR的备份,因此SPSR和CPSR的寄存器结构相同,如下图所示
位位置 | 功能 |
N(bit31) | 当两个补码表示的有符号整数运算的时候,N=1表示运算结果为负数,N=0表示结果为正数。 |
Z(bit30) | Z=1表示运算结果为零,Z=0表示运算结果不为0,对于CMP指令,Z=1表示比较的两个数大小相等。 |
C(bit29) | 在加法指令中,当结果产生了进位,则C=1,表示无符号数运算发生了上溢,其它结果C=0。 在加法指令中,当运算中发生借位,则C=0,表示无符号运算发生下溢,其它情况c=1。 对于包含一位操作的非加/减法运算指令,C中包含最后一次溢出的位的数值,对于其它非加/减法运算指令,C位的值通常不收影响。 |
V(bit28) | 对于加/减法运算指令,当操作数和运算结果表示为二进制的补码表示的带符号数时,V=1表示符号位溢出,通常其它不会影响V位。 |
Q(bit27) | 仅ARM V5TE_j 构架支持,表示饱和状态,Q=1表示累积饱和,Q=0表示累积不饱和。 |
IT[1:0](bit26:25) | 和 IT[7:2] (bit15:bit10)一起表示IT[7:0],作为IF_THEN指令状态。 |
J(bit24) | 仅ARM V5TE_j 构架支持,J=1 表示处于 Jazelle 状态,此位通常和 T(bit5)位一起表示当前所使用的指令集,如表 6.3.2.1 所示: |