在上节课的介绍里,我们引入了异常的概念和处理流程,以及知道中断也是一种异常。
本节主要学习CPU的7种Mode、2种State和相关的寄存器及异常的处理流程。
1. ARM体系下的COU有 7 种工作模式(Mode):
usr : 用户模式 -------> ARM处理器正常的程序执行状态。 sys :系统模式 -------> 用于高速数据传输或通道处理。 ----und(Unddefined) :未定义指令中止模式 -------> 当未定义的指令执行时进入该模式,可用于支持硬件协处理器的软件仿真 这5种 | src (Supervisor) : 管理模式 -------> 操作系统使用的保护模式 属于 ----| abt (Abort) :数据访问中止模式 -------> 当数据或指令预取中止时进入该模式,可用于虚拟存储及存储保护。 异常 | irq (IRQ) :中断模式 -------> 用于通用的中断处理 ----fiq (FIQ) :快速中断模式 -------> 用于高速数据传输或通道处理
1.1 abt(数据访问中止模式):(该类异常又分为两类):
a. 指令预取中止:∵ CPU是以流水线方式来执行指令的,即执行当前指令时,同时在解析第二条指令并读取第三条指令,在读取第 3 条指令时称为预取,可能会发生错误。
b. 比如 CPU 想要读写某个地址,可能这个过程中会出错
1.2 除 usr 模式外,其他模式均属于特权模式。
在这 6 种特权模式下,它们可以随遍切换到其它任何模式。在用户模式下,不能直接切换到其它模式。
大多数程序运行于用户模式,进入特权模式是为了处理中断、异常,或者访问被保护的系统资源。
其中注意 usr模式 为什么不能直接进入其他模式?
用户模式在有操作系统的情况下是给应用程序去使用的,写应用程序的人水平千差万别,不能保证程序是好是坏,
那么可以让应用程序运行于 usr模式,限制应用程序的权限,防止它破坏整个系统。
1.3 CPSR (Current Program Status Register) 寄存器: 当前程序状态寄存器。
CPSR 中一些位被用于标识各种状态,一些位被用于标识当前处于什么工作模式。
1.4 为什么有那么多异常模式?
发生某些异常时会对应进入某种异常模式,在这种异常模式下,更容易来处理这种异常(更专业☺)。
1.5 每种异常模式下有哪些资源的差别呢?
实际上就是寄存器的差别。寄存器笔记在第3节。
2. 2 种State:
2.1 CPU 工作状态
ARM state :此时处理器执行 32 位的字对齐的ARM指令。
Thumb state :此时处理器执行的 16 位的半字对齐的Thumb指令。
1 2 eg: 3 |------ ARM : 该指令编译成 4 Byte机器码 4 MOV R0, R1 ---| 5 |------ Thumb : 该指令编译成 2 Byte机器码 6 7 ===> 使用Thumb指令集,就是为了减小程序使用的空间
韦老师的程序几乎都是在ARM状态下运行,而CPU一上电就处于ARM状态,所以无需关心CPU的工作状态。
2.2 现在区分一下ARM指令集与Thumb指令集:
Thumb 指令可以看作是ARM指令压缩形式的子集,是针对代码密度的问题而提出的,它具有16位的代码密度但是它不如ARM指令的效率高。
Thumb不是一个完整的体系结构,不能指望处理器只执行Thumb指令而不支持ARM指令集。因此,Thumb指令只需要支持通用功能,必要时可以借助
完善的ARM指令集,比如所有的异常自动进入ARM状态。在编写Thumb指令时先要使用伪指令CODE16声明,而且在ARM指令中要使用BX指令跳转
到Thumb指令,以切换处理器状态,编写ARM指令时,则可以使用伪指令CODE32声明。
3. 寄存器:
3.1 通用寄存器
a. 画灰色三角形代表该寄存器是该模式下特有的寄存器,这些寄存器称为备份寄存器。
b. 每种工作模式有 16 个寄存器 + 1 个/ 2 个 (1个或2个取决于工作模式)程序状态寄存器。
c. 31个通用寄存器 如下:
1 r0 -- r15 : -----> 16 个寄存器 (其中r0到r7,外加r15, 各个工作模式下都是一样的) 2 r8_fiq -- r14_fiq : -----> 7 个寄存器 (FIQ快中断模式独有) 3 r13_svc-- r14_svc : -----> 2 个寄存器 (svc管理模式独有) 4 r13_abt-- r14_abt : -----> 2 个寄存器 (abt数据访问中止模式独有) 5 r13_irq-- r14_irq : -----> 2 个寄存器 (irq中断模式独有) 6 r13_und-- r14_und : -----> 2 个寄存器 (und未定义指令中止模式独有) 7 16 + 7 + 2 + 2 + 2 + 2 = 31 个通用的32位寄存器 8
eg:假设执行 MOV R0, R8 ,在System&User 模式与FIQ 模式下,R0是同一个寄存器(实际上任何一种模式下,R0都是同一个寄存器),
但在访问R8时,FIQ模式下访问的是其专有的 r8_fiq 寄存器。
1 |--- sys: MOV R0, R8 2 MOV R0, R8 ===>| 3 |--- fiq: MOV R0, R8_fiq
d. 5 种模式下至少会有各自的R13 和 R14专属寄存器。
R13 称为栈指针寄存器, 通常用于保存栈指针。
R14 称为程序链接寄存器(subroutine Link Register),当执行 BL 子程序调用指令时,R14得到R15(程序计数器PC)中的备份。
而当发生中断或异常时,对应的R14_svc、R14_irq、R14_fiq、R14_abt、R14_und 保存R15返回值,即保存发生异常时的指令地址,以后返回时,可以返回
R14所指示的地方。
||
|| |--- 保存现场: 保存被中断模式的寄存器,其中FIQ快中断模式有多个自己专属的寄存器,本身就不会占用其他模式的寄存器,
/ | 所以自然会省下保存其他模式下寄存器的时间,加快处理速度,但在Linux系统中,并不会使用FIQ模式
这里简单复习一下中断处理流程 ---| --- 处理 :
| --- 恢复 :
3.2 备份寄存器(banked register)
进入某个工作模式后就使用对应的那组寄存器。r8_fiq -- r14_fiq、r13_svc-- r14_svc、r13_abt-- r14_abt、r13_irq-- r14_irq、r13_und-- r14_und均属于备份寄存器。
3.3 当前程序状态寄存器(Current Program Status Register) : CPSR
CPSR中各位意义如下:
(1) T 位: 置位时,CPU处于Thumb状态;否则处于ARM状态。
(2) 中断禁止位:I 位和 F位属于中断禁止位。他们被置位时,IRQ中断,FIQ中断分别被禁止。
(3) 工作模式位:表明CPU当前处于什么工作模式。可以编写这些位,使CPU进入指定的工作模式。
(4) 条件标志位:Z 位
1 eg: 2 CMP R0, R1 ; 如果R0 = R1 的话,Zero位置1 3 4 beq xxx ; 这条指令会判断一下这个寄存器里面的 Z 位,如果这一位等于1的话,它就会跳转; 若等于0的话,就不跳转。
3.4 CPSR 的备份寄存器: SPSR(Saved Program States Register)
SPSR(Saved Program States Register):不同模式下,有SPSR_fiq、SPSR_svc、SPSR_abt、SPSR_irq、SPSR_und 5 个不同的寄存器。
每种模式下的SPSR寄存器用来保存被中断模式下的CPSR的值
4. 异常的处理流程:
4.1 异常发生时,将切换进入相应的工作模式,ARM920t的CPU核硬件自动完成如下操作:
(1) 对于通用寄存器,在异常工作模式的连接寄存器R14(即对应的R14_svc、R14_irq、R14_fiq、R14_abt、R14_und)中保存前一个工作模式的下一条指令地址。
对于ARM状态,对应连接寄存器保存的值 = 当前PC值 +4 或 +8(参考下表)。
(2) 对于程序状态寄存器,异常模式的 SPSR = 上个模式的CPSR。
(3) 将CPSR寄存器的工作模式位(M0--M4)设置为这个异常对应的工作模式, 进入异常模式。
(4) 令PC值等于这个异常模式在异常向量表中的地址,即跳转去执行异常向量表中的相应指令。
打开u-bootcpuarm920t 目录下的start.S,异常向量表如下图所示:
1 b reset ;复位异常 0x0 2 ldr pc, _undefined_instruction ;未定义的指令异常 0x4 遇到没有定义的指令 3 ldr pc, _software_interrupt ; 软件中断异常 0x8 4 ldr pc, _prefetch_abort ;内存操作异常 0xc 5 ldr pc, _data_abort ; 数据异常 0x10 6 ldr pc, _not_used ; 未使用 0x14 7 ldr pc, _irq ; 中断IRQ异常 0x18 这里也证明中断是一种异常 8 ldr pc, _fiq ; 快速中断FIQ异常 0x1c
4.2 从异常工作模式退出回到之前的工作模式,这需要通过软件完成如下操作:
(1) 对于通用寄存器,前面进入异常工作模式时,连接寄存器R14中保存了前一工作模式的一个指令地址 ,将它减去一个适当的值(参考上表)后赋给PC寄存器。
即 PC = R14 - 某个值。
(2) 对于程序状态寄存器,退回的工作模式的CPSR = 异常模式下SPSR的值。
(3) 如果发生的是中断的话(其他异常模式不用管这一步),清除中断