欢迎光临
我们一直在努力

ARM Cortex-M 寄存器全家桶:从“三大神器”到完整图谱

🔥作者简介: 一个平凡而乐于分享的小比特,中南民族大学通信工程专业研究生,研究方向无线联邦学习 🎬擅长领域:驱动开发,嵌入式软件开发,BSP开发 ❄️作者主页:一个平凡而乐于分享的小比特的个人主页 ✨收录专栏:硬件知识,本专栏为记录项目中用到的知识点,以及一些硬件常识总结 欢迎大家点赞 👍 收藏 ⭐ 加关注哦!💖💖

在这里插入图片描述

🧠 ARM Cortex-M 寄存器全家桶:从“三大神器”到完整图谱

你以为MCU只有SP、LR、PC? 那你就错过了 R0–R12、xPSR、PRIMASK 这些幕后高手! 今天一张图 + 真实调试案例,彻底搞懂 Cortex-M 寄存器军团 🎯


📌 先搞清一个概念:专用 ≠ 特殊功能

类型寄存器特点
通用寄存器 R0–R12 随意用,加减乘除、存变量
专用寄存器 SP、LR、PC 有特殊任务,但CPU自动维护
核心特殊寄存器 xPSR、PRIMASK、CONTROL 管中断、管状态、管模式

✅ 今天重点:专用寄存器(SP/LR/PC)+ 核心状态寄存器(xPSR等)


🗺️ ARM Cortex-M 完整寄存器图谱

┌─────────────────────────────────────────────────────┐
│ ARM Cortex-M 寄存器组 │
├─────────────────────────────────────────────────────┤
│ │
│ 【通用寄存器 – 13个】 │
│ ┌────┬────┬────┬────┬────┬────┬────┬────┐ │
│ │ R0 │ R1 │ R2 │ R3 │ R4 │ R5 │ R6 │ R7 │ │
│ └────┴────┴────┴────┴────┴────┴────┴────┘ │
│ ┌────┬────┬────┬────┬────┬────┬────┬────┐ │
│ │ R8 │ R9 │R10 │R11 │R12 │ SP │ LR │ PC │ │
│ └────┴────┴────┴────┴────┴────┴────┴────┘ │
│ ↑ ↑ ↑ │
│ 通用 专用 专用 │
│ │
│ 【特殊功能寄存器】 │
│ ┌──────────────┬─────────────────────────┐ │
│ │ xPSR │ 程序状态寄存器(组合体) │ │
│ ├──────────────┼─────────────────────────┤ │
│ │ PRIMASK │ 中断屏蔽(0=开,1=关) │ │
│ ├──────────────┼─────────────────────────┤ │
│ │ FAULTMASK │ 硬 fault 屏蔽 │ │
│ ├──────────────┼─────────────────────────┤ │
│ │ BASEPRI │ 优先级阈值屏蔽 │ │
│ ├──────────────┼─────────────────────────┤ │
│ │ CONTROL │ 堆栈/特权模式控制 │ │
│ └──────────────┴─────────────────────────┘ │
│ │
└─────────────────────────────────────────────────────┘


🧩 拆解 xPSR(程序状态寄存器)—— 最容易被忽略的“裁判”

xPSR 实际上是 3个寄存器的合体:

xPSR (32位)
┌─────────┬──────────┬─────────────┐
│ APSR │ IPSR │ EPSR │
│(算术标志)│(中断号) │ (执行状态) │
└─────────┴──────────┴─────────────┘
bit[31:27] bit[16:6] bit[24:17]

各个击破表:

部分全称典型位啥时候用
APSR Application PSR N(负数)、Z(零)、C(进位)、V(溢出) 判断 if / while 条件
IPSR Interrupt PSR 当前中断编号 中断里判断“谁叫我”
EPSR Execution PSR Thumb 状态位(永远是1) 确认是否在 Thumb 模式

🎬 场景示例:判断两个数大小

int a = 10, b = 20;
if (a > b) { ... } // 编译成减法:a – b

执行 CMP R0, R1 后:

  • 结果负数 → APSR 的 N 位 = 1
  • CPU 根据 N 位决定是否跳转 ✅

🛡️ 中断控制三兄弟:PRIMASK / FAULTMASK / BASEPRI

┌─────────────────────────────────────────────┐
│ 中断屏蔽寄存器(按权限排序) │
├──────────────┬───────────────┬─────────────┤
│ PRIMASK │ FAULTMASK │ BASEPRI │
│ 关所有中断 │ 连硬fault都关 │ 关低优先级 │
│ (除NMI) │ (最暴力) │ (最温柔) │
└──────────────┴───────────────┴─────────────┘

🚦 对比表格:

寄存器写法效果使用场景
PRIMASK __disable_irq() 普通中断不响应 临界区代码
FAULTMASK 极少直接操作 HardFault 也不响应 系统级灾难恢复
BASEPRI BASEPRI = 0x50 只响应优先级 < 0x50 的中断 RTOS 中保护关键段

🔬 真实调试案例:观察寄存器如何工作

硬件平台:STM32F103 (Cortex-M3) 工具:Keil MDK + 软件仿真

案例代码:

int global_var = 0;

void delay(int n) {
while(n);
}

int add(int a, int b) {
return a + b;
}

int main() {
int x = 10;
int y = 20;
int z;

z = add(x, y); // 第1个断点:函数调用前
global_var = z; // 第2个断点:函数返回后

delay(1000);
while(1);
}

🔍 调试观察表(在断点1停住)

【断点1:调用 add() 之前】

寄存器名称 | 当前值 | 说明
—————|———-|———————————–
R0 | 0x0000000A | 参数 a = 10 (第一个参数)
R1 | 0x00000014 | 参数 b = 20 (第二个参数)
R2 | 0x00000000 | 未使用
… | … |
SP (R13) | 0x20000800 | 栈顶指针
LR (R14) | 0x08000234 | 返回地址 = 调用后下一条指令
PC (R15) | 0x08000120 | 当前指向 add() 的第一条指令
xPSR | 0x21000000 | T=1 (Thumb模式), 无算术标志
PRIMASK | 0x00000000 | 中断全开

🎬 单步执行 add() 内部:

add:
ADD R0, R0, R1 ; R0 = 10 + 20 = 30
BX LR ; 返回

【执行 ADD 后】:

  • R0 = 30(返回值约定放 R0)
  • xPSR 的 Z 位 = 0(不是零)
  • PC 指向 BX LR 指令

🚪 执行 BX LR 瞬间:

┌──────────────────────────────────────┐
│ CPU 悄悄做的事: │
│ 1. LR (0x08000234) → PC │
│ 2. SP 恢复到调用前 │
│ 3. 继续执行 main 里的 z = 30 │
└──────────────────────────────────────┘

🔥 进阶调试:中断触发瞬间

假设在 delay(1000) 里来一个定时器中断:

【硬件自动压栈入栈】 (无代码干预)

压栈内容 | 保存到哪里
——————-|——————-
PC (返回地址) | 栈里 (SP-4)
xPSR | 栈里 (SP-8)
R0-R3 | 栈里 (SP-24)
LR | 栈里 (SP-28) → 这里 LR 会被改成特殊值 0xFFFFFFF9

此时 SP 已向下移动 32 字节

💡 LR = 0xFFFFFFF9 是 ARM 里的“魔法数字” 表示:返回时要从栈里恢复所有寄存器(而不是直接用 LR)


📊 寄存器总结对比表(完整版)

类别寄存器大小谁维护不设置后果
参数传递 R0–R3 32位 编译器 函数传参错乱
通用计算 R4–R11 32位 编译器
通用 + 特殊 R12 (IP) 32位 链接器临时用 极少出错
栈顶指针 SP (R13) 32位 CPU + OS 堆栈溢出 → HardFault
返回地址 LR (R14) 32位 CPU 函数回不来
指令指针 PC (R15) 32位 CPU 程序跑飞
状态字 xPSR 32位 CPU 条件判断错误
中断开关 PRIMASK 1位 程序员 临界区被中断破坏

🧪 速查小抄(贴在工作台上)

┌─────────────────────────────────────┐
│ R0 ── 返回值 / 第一个参数 │
│ R1-R3 ── 剩余参数 │
│ R4-R11 ── 要保护的值(函数内保存) │
│ SP ── 永远指着栈顶 │
│ LR ── 记着回家的路 │
│ PC ── 现在执行到哪 │
│ xPSR ── 算术结果 + 当前中断号 │
│ PRIMASK ── 一键断所有中断 │
└─────────────────────────────────────┘


🎯 最后一句真传

普通程序员看 R0–R12 高手看 SP、LR、PC 大师看 xPSR + PRIMASK

赞(0)
未经允许不得转载:171主机测评 » ARM Cortex-M 寄存器全家桶:从“三大神器”到完整图谱
分享到: 更多 (0)

评论 抢沙发

  • 昵称 (必填)
  • 邮箱 (必填)
  • 网址