
作者简介 一个平凡而乐于分享的小比特中南民族大学通信工程专业研究生研究方向无线联邦学习擅长领域驱动开发嵌入式软件开发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]各个击破表部分全称典型位啥时候用APSRApplication PSRN负数、Z零、C进位、V溢出判断 if / while 条件IPSRInterrupt PSR当前中断编号中断里判断“谁叫我”EPSRExecution PSRThumb 状态位永远是1确认是否在 Thumb 模式 场景示例判断两个数大小inta10,b20;if(ab){...}// 编译成减法a - b执行CMP R0, R1后结果负数 →APSR 的 N 位 1CPU 根据 N 位决定是否跳转 ✅️ 中断控制三兄弟PRIMASK / FAULTMASK / BASEPRI┌─────────────────────────────────────────────┐ │ 中断屏蔽寄存器按权限排序 │ ├──────────────┬───────────────┬─────────────┤ │ PRIMASK │ FAULTMASK │ BASEPRI │ │ 关所有中断 │ 连硬fault都关 │ 关低优先级 │ │ (除NMI) │ (最暴力) │ (最温柔) │ └──────────────┴───────────────┴─────────────┘ 对比表格寄存器写法效果使用场景PRIMASK__disable_irq()普通中断不响应临界区代码FAULTMASK极少直接操作HardFault 也不响应系统级灾难恢复BASEPRIBASEPRI 0x50只响应优先级 0x50 的中断RTOS 中保护关键段 真实调试案例观察寄存器如何工作硬件平台STM32F103 (Cortex-M3)工具Keil MDK 软件仿真案例代码intglobal_var0;voiddelay(intn){while(n--);}intadd(inta,intb){returnab;}intmain(){intx10;inty20;intz;zadd(x,y);// 第1个断点函数调用前global_varz;// 第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 | T1 (Thumb模式), 无算术标志 PRIMASK | 0x00000000 | 中断全开 单步执行 add() 内部add: ADD R0, R0, R1 ; R0 10 20 30 BX LR ; 返回【执行 ADD 后】R0 30返回值约定放 R0xPSR 的 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–R332位编译器函数传参错乱通用计算R4–R1132位编译器-通用 特殊R12 (IP)32位链接器临时用极少出错栈顶指针SP (R13)32位CPU OS堆栈溢出 → HardFault返回地址LR (R14)32位CPU函数回不来指令指针PC (R15)32位CPU程序跑飞状态字xPSR32位CPU条件判断错误中断开关PRIMASK1位程序员临界区被中断破坏 速查小抄贴在工作台上┌─────────────────────────────────────┐ │ R0 ── 返回值 / 第一个参数 │ │ R1-R3 ── 剩余参数 │ │ R4-R11 ── 要保护的值函数内保存 │ │ SP ── 永远指着栈顶 │ │ LR ── 记着回家的路 │ │ PC ── 现在执行到哪 │ │ xPSR ── 算术结果 当前中断号 │ │ PRIMASK ── 一键断所有中断 │ └─────────────────────────────────────┘ 最后一句真传普通程序员看 R0–R12高手看 SP、LR、PC大师看 xPSR PRIMASK