特殊寄存器
Cortex-M 内核寄存器,控制执行状态与中断屏蔽,没有内存地址,只能用 MRS/MSR 指令读写。
是什么
特殊寄存器(Special Register)和 R0~R15 一样属于内核寄存器,但不映射到内存地址(不能用指针、不能 = 0x40000000 这种写法访问),只能靠两条专用指令:
| 指令 | 方向 | 例 |
|---|---|---|
MRS Rd, <特殊寄存器> | 读:特殊寄存器 → 通用寄存器 | MRS R0, PRIMASK |
MSR <特殊寄存器>, Rn | 写:通用寄存器 → 特殊寄存器 | MSR PRIMASK, R0 |
CMSIS 已封装成 __get_PRIMASK() / __set_PRIMASK(x) 这类内联函数,工程里直接用即可。
注意区分「内存映射的外设寄存器」,见文末拓展。
典型特殊寄存器
| 寄存器 | 位宽 | 作用 |
|---|---|---|
| XPSR | 32 | 状态寄存器:APSR + EPSR + IPSR 三段拼成 |
| PRIMASK | 1 | 全局中断总开关(除 NMI/HardFault) |
| FAULTMASK | 1 | 连 HardFault 一起屏蔽(除 NMI) |
| BASEPRI | ≤9 | 按优先级门限屏蔽低优先级中断 |
| CONTROL | 2 | 特权级 + 栈指针选择 |
XPSR(展开)
一条 MRS R0, XPSR 读出的 32 位被三段瓜分:
| 段 | 位宽 | 位域 | 作用 |
|---|---|---|---|
| APSR | 5 位 | [31:27] | N/Z/C/V/Q 条件标志 |
| EPSR | 9 位 | [26:24] + [15:10] | T(Thumb) + ICI/IT 执行状态 |
| IPSR | 9 位 | [8:0] | 当前异常号 |
| 保留 | — | 其余 | — |
APSR(应用状态,5 位)
| 位 | 名 | 含义 |
|---|---|---|
| N | Negative | 运算结果最高位为 1(负数) |
| Z | Zero | 结果为 0 |
| C | Carry | 进位/借位(加法、移位) |
| V | oVerflow | 有符号溢出 |
| Q | saturation | 饱和标志(DSP 指令粘滞位) |
条件分支、比较跳转(
if/cmp+bxx)判断的就是 N/Z/C/V。
EPSR(执行状态,9 位)
- T(Thumb,bit24):恒为 1,表示处于 Thumb 状态(Cortex-M 只支持 Thumb)。
- ICI/IT:中断继续(Interrupt-Continuable Instruction)+ If-Then 条件执行的状态位。
IPSR(中断状态,9 位)
存当前正在执行的异常号:
| 值 | 含义 |
|---|---|
| 0 | 线程模式(正常跑 main/任务) |
| 1 | Reset |
| 2 | NMI |
| 3 | HardFault |
| 15 | SysTick |
| ≥16 | 外部 IRQ |
HardFault 调试时读 IPSR 能确认「挂在哪个异常」,见 HardFault调试。
PRIMASK / FAULTMASK / BASEPRI(中断屏蔽三件套)
| 寄存器 | 屏蔽范围 | 开关 | 对应指令 |
|---|---|---|---|
| PRIMASK | 所有可屏蔽中断(NMI、HardFault 除外) | 1=关,0=开 | CPSID I / CPSIE I |
| FAULTMASK | 所有中断 + HardFault(NMI 除外) | 1=关,0=开 | CPSID F / CPSIE F |
| BASEPRI | 优先级值 ≥ N 的中断 | 写 0=不屏蔽 | — |
- 优先级数值越大优先级越低;BASEPRI 写 N = 屏蔽所有「优先级值 ≥ N」的低优先级中断。
- FAULTMASK 用在「正在处理 HardFault、怕被再次嵌套打断」的场景。
- 临界区常见套路(备份-关闭-恢复):
uint32_t primask = __get_PRIMASK(); // 1. 备份
__disable_irq(); // 2. 关中断(PRIMASK=1)
/* 临界区代码 */
__set_PRIMASK(primask); // 3. 恢复原状态CONTROL
只有 2 位,且只能在特权模式下写:
| 位 | 名 | 含义 |
|---|---|---|
| 0 | nPRIV | 线程模式特权级:0=特权,1=非特权 |
| 1 | SPSEL | 栈指针:0=用 MSP,1=用 PSP |
- 与 操作模式和状态 的特权/线程模式、MSP/PSP 一一对应。
- RTOS 切任务时靠 SPSEL 在 MSP(内核/中断栈)和 PSP(任务栈)之间切换。
- 有 FPU 的 M4F 还有 bit2 FPCA(浮点上下文激活),无 FPU 则只有 2 位。
拓展:8051 的 SFR 不是「特殊寄存器」
8051 的 SFR(Special Function Register,特殊功能寄存器) 和本文的「特殊寄存器」是两回事:
| Cortex-M 特殊寄存器 | 8051 SFR(特殊功能寄存器) | |
|---|---|---|
| 本质 | 内核寄存器 | 内存映射寄存器 |
| 地址 | 无地址,MRS/MSR 访问 | 有地址:内部 RAM 高 128 字节 0x80~0xFF |
| 用途 | 控制内核执行/中断屏蔽 | 操作外设(P0/P1 端口、TMOD 定时器等) |
真正对应 8051 SFR 的,是 Cortex-M 的外设寄存器:挂在总线地址上,用 *(volatile uint32_t *)0x40000000 这种写法读写。这类寄存器会被外设硬件随时改变,所以必须加 volatile 防止被编译器优化掉,详见 volatile 关键字。Cortex-M 外设寄存器另起笔记再展开。