--- 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|试题册索引]]