vault backup: 2026-06-10 11:17:10
This commit is contained in:
@@ -0,0 +1,201 @@
|
||||
---
|
||||
tags: [嵌入式系统, 复习, ARM架构]
|
||||
create time: 2026-06-10 11:11
|
||||
---
|
||||
|
||||
# ARM处理器架构
|
||||
|
||||
## 概述
|
||||
本文档深入讲解ARM处理器的架构设计,包括命名规则、存储体系结构、流水线、寄存器组织、CPSR位域、工作模式以及FIQ/IRQ中断机制。ARM架构是嵌入式系统考试的重点内容。
|
||||
|
||||
## 正文
|
||||
|
||||
### 1. ARM概述
|
||||
|
||||
ARM(Advanced RISC Machines)是一系列**处理器核心**的名称,不是一家公司的名字。ARM公司采用**IP授权**模式——设计处理器核心,将设计方案授权给芯片厂商(如高通、三星、ST)进行制造。
|
||||
|
||||
ARM的核心特点:
|
||||
- **RISC架构**(精简指令集计算机):指令数量少,指令长度固定,执行效率高
|
||||
- **低功耗**:适合移动设备和嵌入式场景
|
||||
- **IP授权模式**:ARM自己不生产芯片
|
||||
|
||||
### 2. ARM7TDMI命名规则
|
||||
|
||||
以经典的ARM7TDMI为例,其后缀含义如下:
|
||||
|
||||
| 后缀 | 全称 | 含义 |
|
||||
|------|------|------|
|
||||
| T | Thumb | 支持Thumb指令集(16位) |
|
||||
| D | Debug | 支持JTAG调试 |
|
||||
| M | Multiplier | 增强型乘法器 |
|
||||
| I | ICE | 支持嵌入式ICE(In-Circuit Emulator) |
|
||||
|
||||
### 3. 冯·诺依曼 vs 哈佛架构
|
||||
|
||||
这是嵌入式系统的经典考点:
|
||||
|
||||
**冯·诺依曼架构**(ARM7采用):
|
||||
- 指令和数据**共享**同一条总线和同一存储空间
|
||||
- 不能同时取指令和读写数据
|
||||
- 结构简单,成本低
|
||||
|
||||
**哈佛架构**(ARM9及以上采用):
|
||||
- 指令和数据使用**独立的**总线和存储空间
|
||||
- 可以同时取指令和读写数据
|
||||
- 性能更高,但结构更复杂
|
||||
|
||||
> [!question] ARM7为什么选择冯·诺依曼架构?
|
||||
> ARM7面向低成本嵌入式应用,冯·诺依曼架构只需一组总线,可以减少芯片面积和引脚数量,降低功耗和成本。对于ARM7的应用场景,性能已经足够。
|
||||
|
||||
### 4. ARM7三级流水线
|
||||
|
||||
ARM7处理器使用三级流水线:
|
||||
|
||||
| 阶段 | 名称 | 操作 |
|
||||
|------|------|------|
|
||||
| 1 | Fetch(取指) | 从存储器取出指令 |
|
||||
| 2 | Decode(译码) | 解析指令含义,读取寄存器 |
|
||||
| 3 | Execute(执行) | 执行运算,写回结果 |
|
||||
|
||||
在理想情况下,三级流水线使得每个时钟周期都能完成一条指令(吞吐率为1 CPI)。但当发生分支跳转时,流水线需要清空并重新填充,导致性能损失。
|
||||
|
||||
> [!tip] 流水线级数与PC值的关系
|
||||
> 在ARM7三级流水线中,当前执行的指令地址是PC-8(因为PC已经预取了两条指令之后的内容)。这个细节在调试时很重要。
|
||||
|
||||
### 5. 寄存器组织
|
||||
|
||||
ARM7共有**37个**32位寄存器,但在任意时刻只能访问其中一部分:
|
||||
|
||||
- **User/SYS模式**:可访问**17个**(R0-R15 + CPSR)
|
||||
- **其他特权模式**:可访问各自的SPSR,以及部分私有寄存器
|
||||
|
||||
#### 特殊功能寄存器
|
||||
|
||||
| 寄存器 | 名称 | 功能 |
|
||||
|--------|------|------|
|
||||
| R13 | SP(Stack Pointer) | 栈指针,指向当前栈顶 |
|
||||
| R14 | LR(Link Register) | 链接寄存器,保存子程序返回地址 |
|
||||
| R15 | PC(Program Counter) | 程序计数器,指向下一条要取的指令 |
|
||||
| R12 | IP(Intra-Procedure-call) | 过程调用中间暂存寄存器 |
|
||||
|
||||
> [!question] 为什么每个异常模式都有自己独立的R13(SP)?
|
||||
> 因为每个模式有自己的运行栈。如果所有模式共享一个SP,当中断发生时可能破坏正在使用的栈数据,导致系统崩溃。
|
||||
|
||||
### 6. CPSR位域详解
|
||||
|
||||
**CPSR**(Current Program Status Register,当前程序状态寄存器)是ARM中最关键的寄存器之一:
|
||||
|
||||
```mermaid
|
||||
graph LR
|
||||
subgraph CPSR["CPSR Bit Fields"]
|
||||
direction LR
|
||||
N["N[31]"] --> Z["Z[30]"] --> C["C[29]"] --> V["V[28]"]
|
||||
V --> D["D[27]"] --> I["I[7]"] --> F["F[6]"] --> T["T[5]"]
|
||||
T --> M["M[4:0]"]
|
||||
end
|
||||
|
||||
style N fill:#ef9a9a
|
||||
style Z fill:#ffcc80
|
||||
style C fill:#fff176
|
||||
style V fill:#a5d6a7
|
||||
style I fill:#90caf9
|
||||
style F fill:#90caf9
|
||||
style T fill:#ce93d8
|
||||
style M fill:#f48fb1
|
||||
```
|
||||
|
||||
**条件标志位(N, Z, C, V)**:
|
||||
|
||||
| 标志位 | 位号 | 含义 |
|
||||
|--------|------|------|
|
||||
| N | [31] | **负数**标志:运算结果最高位为1时置位 |
|
||||
| Z | [30] | **零**标志:运算结果为0时置位 |
|
||||
| C | [29] | **进位**标志:加法产生进位或减法无借位时置位 |
|
||||
| V | [28] | **溢出**标志:有符号运算溢出时置位 |
|
||||
|
||||
**控制位**:
|
||||
|
||||
| 标志位 | 位号 | 含义 |
|
||||
|--------|------|------|
|
||||
| I | [7] | IRQ禁止:置1时禁止IRQ中断 |
|
||||
| F | [6] | FIQ禁止:置1时禁止FIQ中断 |
|
||||
| T | [5] | Thumb状态:置1表示Thumb状态,置0表示ARM状态 |
|
||||
| M[4:0] | [4:0] | 处理器模式选择位 |
|
||||
|
||||
> [!question] 如果CPSR的N=1、Z=0,这意味着什么?
|
||||
> N=1表示上一次运算结果为负数,Z=0表示结果不为零。如果此时用BMI(Branch Minus)指令,分支将被执行,因为BMI条件是N=1。
|
||||
|
||||
### 7. SPSR
|
||||
|
||||
**SPSR**(Saved Program Status Register)保存的是进入异常模式**之前**的CPSR值。
|
||||
|
||||
当异常发生时,硬件自动将当前CPSR保存到对应异常模式的SPSR中。异常返回时,通过 `MOVS PC, LR` 指令将SPSR恢复回CPSR,从而恢复之前的状态。
|
||||
|
||||
> [!warning] User模式没有SPSR
|
||||
> User模式不是异常模式,所以没有SPSR。如果需要保存User模式的状态,必须通过软件方式实现。
|
||||
|
||||
### 8. 七种工作模式
|
||||
|
||||
ARM处理器有7种工作模式:
|
||||
|
||||
```mermaid
|
||||
graph TD
|
||||
subgraph nonPriv["Non-Privileged"]
|
||||
USR["USR - User Mode"]
|
||||
end
|
||||
|
||||
subgraph priv["Privileged Modes"]
|
||||
SYS["SYS - System Mode"]
|
||||
SVC["SVC - Supervisor Mode"]
|
||||
ABT["ABT - Abort Mode"]
|
||||
UND["UND - Undefined Mode"]
|
||||
IRQ["IRQ - IRQ Mode"]
|
||||
FIQ["FIQ - FIQ Mode"]
|
||||
end
|
||||
|
||||
SYS -.-> |"Same registers as USR"| USR
|
||||
SVC --> |"Reset enters here"| SVC
|
||||
|
||||
style USR fill:#bbdefb
|
||||
style SYS fill:#c8e6c9
|
||||
style SVC fill:#ffcc80
|
||||
style ABT fill:#ffab91
|
||||
style UND fill:#ef9a9a
|
||||
style IRQ fill:#ce93d8
|
||||
style FIQ fill:#f48fb1
|
||||
```
|
||||
|
||||
| 模式 | 编码 | 说明 | 进入方式 |
|
||||
|------|------|------|----------|
|
||||
| USR | 10000 | 用户模式,非特权 | 正常程序执行 |
|
||||
| SYS | 11111 | 系统模式,特权 | 与USR共享寄存器 |
|
||||
| SVC | 10011 | 管理模式 | **复位**、SWI |
|
||||
| ABT | 10111 | 中止模式 | 存储器访问异常 |
|
||||
| UND | 11011 | 未定义模式 | 未定义指令异常 |
|
||||
| IRQ | 10010 | 中断模式 | IRQ中断 |
|
||||
| FIQ | 10001 | 快速中断模式 | FIQ中断 |
|
||||
|
||||
几个关键点:
|
||||
- **复位后进入SVC模式**,这是系统上电后的初始状态
|
||||
- **USR不是异常模式**,因此没有SPSR
|
||||
- **SYS模式**与USR共享寄存器,但具有特权权限
|
||||
|
||||
### 9. FIQ vs IRQ
|
||||
|
||||
| 比较维度 | FIQ | IRQ |
|
||||
|----------|-----|-----|
|
||||
| 优先级 | **更高** | 较低 |
|
||||
| 私有寄存器 | R8-R14(7个) | R13-R14(2个) |
|
||||
| 向量表位置 | 0x0000001C(末尾) | 0x00000018 |
|
||||
| 响应速度 | 更快(寄存器保留多,切换少) | 较慢 |
|
||||
| 嵌套 | 支持 | 支持 |
|
||||
|
||||
FIQ更快的原因:
|
||||
1. 有更多的**私有寄存器**(R8-R14),中断处理时不需要保存/恢复通用寄存器
|
||||
2. 向量表位于地址空间末尾,可以直接放置ISR代码,**无需跳转**
|
||||
|
||||
> [!question] 为什么FIQ的向量表放在0x0000001C(最后),而不是和其他异常一样在前面?
|
||||
> 把FIQ的处理程序直接放在向量表位置0x0000001C开始的地方,可以省去一次跳转指令。因为从0x0000001C到中断向量表结束还有空间,足够放几条关键指令。
|
||||
|
||||
## 关联笔记
|
||||
- [[嵌入式系统/试题册/index|试题册索引]]
|
||||
Reference in New Issue
Block a user