编辑整理 by Staok。
本文大部分内容摘自"100ask imx6ull"开发板的配套资料(如《IMX6ULL裸机开发完全手册》等等),侵删。进行了精髓提取,方便日后查阅。过于基础的内容不会在此提及。如有错误恭谢指出!
注:在 Github 上的原版文章日后可能会更新,在其它位置发的不会跟进。文章的 Gitee 仓库地址,Gitee 访问更流畅。
ARM & Linux 相关
p.s 汇编基本指令和 ARM 的汇编启动代码看 "ARM异常处理 及其模板" 文件夹里的 startup.s 文件。
cpsr 寄存器详情
运行模式
Cortex-A7架构的运行模式有9种。运行模式可以通过软件进行任意切换,也可以通过中断或者异常来进行切换。大多数的程序都运行在用户模式,用户模式下是不能访问系统所有资源的,有些资源是受限的,要想访问这些受限的资源就必须进行模式切换。但是用户模式是不能直接进行切换的,用户模式下需要借助异常来完成模式切换,当要切换模式的时候,应用程序可以产生异常,在异常的处理过程中完成处理器模式切换。
模式 | 描述 |
---|---|
User | 用户模式,非特权模式,大部分程序运行的时候就处于此模式 |
Sys(System) | 系统模式,用于运行特权级的操作系统任务 |
FIQ | 快速中断模式,进入 FIQ 中断异常 |
IRQ | 一般中断模式 |
ABT(Abort) | 数据访问终止模式,用于虚拟存储以及存储保护 |
SVC(Supervisor) | 超级管理员模式,供操作系统使用 |
UND(Undef) | 未定义指令终止模式 |
MON(Monitor) | 用于安全扩展模式 |
Hyp | 用于虚拟化扩展 |
几点说明:
-
板子上电时,CPU处于SVC模式,它用的是SVC模式下的寄存器。
-
程序运行时发生了中断,CPU进入IRQ模式,它用的IRQ模式下的寄存器。
-
CPU发生某种异常时,比如读取内存出错,它会进入ABT模式,使用ABT模式下的寄存器来处理错误。
每一种模式对应使用的寄存器
几点说明:
-
如果某个程序处于 FIQ 模式下访问寄存器 R13(SP),那它实际访问的是寄存器 SP_fiq。
-
如果某个程序处于 SVC 模式下访问寄存器 R13(SP),那它实际访问的是寄存器 SP_svc。
-
除了 FIQ 模式,寄存器 R0~R12 都是通用的,即模式之间切换前这些寄存器的值应该保存。
-
假如某个ARM处理器是三级流水线:取指->译码->执行,循环执行,那么程序计数器 R15(PC) = 当前执行指令地址 + 4 * 2 个字节。
-
未定义指令异常的个别用法:在某些系统中,代码可能包含用于协处理器(例如VFP协处理器)的指令,但是系统中不存在相应的VFP硬件。另外,VFP硬件有可能无法处理特定指令,而是想调用软件来对其进行模拟。或者,可能会禁用VFP硬件,采用异常处理,以便可以启用它,然后重新执行指令。使用未定义的指令,可以实现一些仿真器(软件模拟硬件的实现)。比如在你的芯片中,它并未支持某条硬件除法指令,但是你还可以在代码中使用它。当CPU执行这条指令时会发生异常,在异常处理函数中,你用软件来实现该指令的功能。对于不是特别设置的未定义指令,在异常处理函数中不能处理它时,通常做法是记录适当的调试信息,并关掉(kill)对应的应用程序。在某些情况下,未定义指令异常的另一个用途是实现用户断点:调试器(如gdb)去修改代码,替换断点位置的指令为一条未定义指令。
-
SVC异常的个别用法:软中断 swi 指令可以触发此异常,获得 SVC 权限。在Linux中对文件的open/read/write等APP层的系统函数,它的本质都是执行SVC指令,从而进入Linux内核中预设的SVC异常处理函数,在内核里操作文件。可以使用寄存器或者操作码中某个字段将参数传递给SVC处理程序。
程序状态寄存器 cpsr
所有运行模式都共用一个 CPSR 物理存在的寄存器叫 程序状态寄存器,CPSR 可以在任何模式下被访问。当特定异常中断发生时,备份程序状态寄存器 SPSR 用来保存 CPSR 的值,当异常退出以后可以用 SPSR 中保存的值来恢复 CPSR。
各个位的说明:
-
N(bit31):当两个有符号整数(补码表示)运算时,结果用N表示,N=1/0 表示 负数/正数。
-
Z(bit30):对于 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/0 表示累积饱和/累积不饱和。
-
IT[1:0] (bit26:25) 和 IT[7:2] (bit15:bit10)一起组成 IT[7:0],作为 IF-THEN 指令执行状态。
-
J(bit24) 和 T(bit5):控制指令执行状态,表明本指令是ARM指令还是Thumb指令。{J,T} = b00 为 ARM;= b01 为 Thumb;= b11 为 ThumbEE;= b10 为 Jazelle。
-
GE[3:0] (bit19:16):SIMD(单指令多数据,处理器为提升并行操作的一种功能) 指令有效,大于或等于。
-
E(bit9):大小端控制位,E=1/0 表示大/小端模式。
-
A(bit8):禁止异步中断位,A=1 表示禁止异步中断。
-
I(bit7):I=1/0 代表 禁止/使能 IRQ。
-
F(bit6):F=1/0 代表 禁止/使能 FIQ。
-
M[4:0]:运行模式控制位,如表
M[4:0] 运行模式 10000 User 模式 10001 FIQ 模式 10010 IRQ 模式 10011 Supervisor(SVC)模式 10110 Monitor(MON)模式 10111 Abort(ABT)模式 11010 Hyp(HYP)模式 11011 Undef(UND)模式 11111 System(SYS)模式
在用户模式下,无法改变处理器模式的M位[4:0]来切换模式和A,I和F位来使能或者禁止异步中止、IRQ和FIQ。
大小端模式
-
大端模式(Big-endian),是指数据的高字节保存在内存的低地址中,而数据的低字节保存在内存的高地址中。
-
小端模式(Little-endian),是指数据的高字节保存在内存的高地址中,而数据的低字节保存在内存的低地址中。