ARM 架构基础:Cortex-M 与指令集

FreeGuideOnline 最新 2026-06-15

ARM 架构基础:Cortex-M 与指令集

ARM 架构是嵌入式系统中最主流的处理器架构,拥有高性能、低功耗的特性。其中,Cortex-M 系列是专门为微控制器和实时控制系统设计的 32 位 RISC 处理器核心,广泛应用于 IoT、汽车电子、工业控制和消费类产品中。理解 Cortex-M 的体系结构和指令集,是掌握嵌入式底层开发的前提。

Cortex-M 处理器家族概览

Cortex-M 系列按性能和应用场景分为多个子系列,它们共享统一的 Thumb/Thumb-2 指令集和 NVIC 中断控制器,但功能特性逐步升级。

系列 核心特点 典型应用
Cortex-M0 / M0+ 极小面积、极低功耗,最小指令集 传感器节点、简单外设
Cortex-M3 平衡性能与功耗,带硬件除法和 MPU 通用嵌入式控制
Cortex-M4 在 M3 基础增加 DSP 扩展与 FPU 数字信号处理、电机控制
Cortex-M7 六级流水线、双发射,带 FPU 和 Cache 高性能实时控制
Cortex-M23 / M33 ARMv8-M 架构,TrustZone 安全 安全物联网设备

所有 Cortex-M 处理器都只支持 Thumb/Thumb-2 指令集,无需切换 ARM 状态,这使得代码密度高且执行效率优秀。

编程模型

操作模式与特权级别

Cortex-M 有两种操作模式,两种特权级别:

  • 线程模式(Thread mode):执行普通应用程序代码,可运行在特权级或用户级。
  • 处理模式(Handler mode):执行异常/中断服务程序,始终运行在特权级。

特权级别分为 特权级(Privileged)用户级(Unprivileged)。用户级代码对某些寄存器和存储器区域受限,是安全应用的基础。

核心寄存器组

Cortex-M 拥有 16 个通用寄存器 (R0~R15) 和若干特殊功能寄存器。

  • R0 ~ R12:通用数据寄存器,32 位,其中 R0~R7 为低组寄存器,几乎所有指令均可直接访问;R8~R12 为高组寄存器,部分 16 位 Thumb 指令不可直接访问。
  • R13 (SP):堆栈指针。它有两个实体:主堆栈指针 MSP(复位后默认使用,用于异常处理)和进程堆栈指针 PSP(用于用户线程)。当前处于哪种模式由 CONTROL 寄存器决定。
  • R14 (LR):链接寄存器,保存子程序或异常返回地址。
  • R15 (PC):程序计数器,指向当前指令地址。直接修改 PC 可实现跳转,读取 PC 可以获得下一条指令地址(因流水线,值为当前地址 + 4)。
  • xPSR:程序状态寄存器,分为 APSR(应用 PSR)、IPSR(中断号)、EPSR(执行 PSR)。常用标志 N(负数)、Z(零)、C(进位/借位)、V(溢出)在 APSR 中。
  • CONTROL 寄存器:控制堆栈指针选择和特权级。
  • PRIMASK:全局中断屏蔽寄存器,置 1 时屏蔽所有可配置优先级的中断(NMI 和 HardFault 除外)。

存储器映射采用统一编址

Cortex-M 使用 32 位地址总线,可寻址 4GB 存储空间。存储器映射由架构定义,规范了代码区、SRAM、外设、PPB 等区域。例如,0x00000000 起始存放初始 SP 和向量表;0x20000000 起始为片上 SRAM;0x40000000 起始外设区;0xE000E000 起始为系统控制块(SCB)和 NVIC。所有 I/O 寄存器映射到存储器地址,通过 LDR/STR 访问,没有专用 I/O 指令。

ARM 指令集:Thumb 与 Thumb-2

早期的 ARM 处理器支持 32 位 ARM 指令集和 16 位 Thumb 指令集,需要通过状态切换。Cortex-M 系列只实现了 Thumb-2 技术,它混合了 16 位和 32 位指令,无需状态切换。Thumb-2 既保留了高代码密度的 16 位指令,又增加了功能强大的 32 位指令,可以完成复杂操作而无需拆分成多条指令。

关键特性:

  • 大多数 16 位指令只能访问 R0-R7,而 32 位指令可访问全部寄存器。
  • 32 位指令可包含内置移位、扩展操作数,实现单指令完成乘加、加载/存储带更新等操作。
  • 指令编码长度可通过上半核的半字自动识别,处理器自动解析,编程时无需关心。

Cortex-M 常用指令详解

以下指令均属于 Thumb-2 指令子集,适用于所有 Cortex-M 核心(部分高级指令需要特定架构版本,会特别说明)。

数据传送指令

指令 功能说明 示例
MOV Rd, #imm 立即数传送到寄存器,仅限 8 位立即数? 32 位 MOV 可支持 16 位或更多 MOV R0, #0x55
MOV Rd, Rm 寄存器间传送 MOV R1, R0
LDR Rd, [Rn, #offset] 从存储器加载字,基址 Rn 加偏移 LDR R0, [R1, #4]
STR Rm, [Rn, #offset] 将寄存器存储到存储器 STR R0, [R1, #0x10]
LDRH/LDRB/STRH/STRB 加载/存储半字或字节 LDRH R2, [R3, #2]
LDM/STM 多寄存器加载/存储 LDMIA R0!, {R1-R3}

注意:LDR/STR 的立即数偏移范围因指令长度而异,32 位指令支持更大立即数。R0! 表示回写,即基址更新。

数据处理指令

指令 功能说明 示例
ADD Rd, Rn, Rm 加法 ADD R0, R1, R2
ADD Rd, Rn, #imm3 加法,3位立即数 ADD R0, R1, #5
SUB Rd, Rn, Rm 减法 SUB R0, R1, R2
AND/ORR/EOR 按位与/或/异或 AND R0, R1, R2
MVN Rd, Rm 取反传送 MVN R0, R1
LSL/LSR/ASR/ROR 移位操作,可结合MOV使用 LSL R0, R1, #3
SXTx/UXTx 符号/零扩展 (32位指令) SXTB R0, R1

比较与测试指令

这些指令不修改目标寄存器,仅更新 APSR 标志位。

  • CMP Rn, RmCMP Rn, #imm :计算 Rn - Rm,更新 N、Z、C、V。
  • CMN Rn, Rm :计算 Rn + Rm,更新标志。
  • TST Rn, Rm :按位与,更新 N、Z。
  • TEQ Rn, Rm :按位异或,更新 N、Z。

通常跟随条件执行的分支指令,但 Cortex-M 大部分指令不直接支持条件码(只有条件分支和 IT 块)。可以利用与标志位配合的分支指令如 BEQBNE

分支指令

指令 说明 示例
B label 直接跳转,范围 ±16MB(32位指令更大) B main_loop
BL label 带链接跳转,将返回地址存入 LR,用于函数调用 BL func
BX Rm 跳转到寄存器所存地址,可切换 ARM/Thumb(Cortex-M 中保持 Thumb) BX LR 用于返回
BLX Rm 带链接的间接跳转 BLX R3
CBZ/CBNZ 比较为零/非零并跳转(16位指令) CBZ R0, label

条件分支则根据标志位:BEQ(等于),BNE(不等),BCS(进位置1),BCC(进位清0),BMI(负数),BPL(非负),BVS(溢出),BVC(无溢出),BHI(高于),BLS(低于或相同)等。

乘法和除法指令

Cortex-M3/M4/M7 提供硬件乘法和除法。

  • MUL Rd, Rn, Rm :32 位乘法,结果取低 32 位。
  • MLS Rd, Rn, Rm, Ra :乘减,Rd = Ra - Rn*Rm。
  • MLA Rd, Rn, Rm, Ra :乘加,Rd = Ra + Rn*Rm。
  • UMULL/SMULL :长乘法,64 位结果。
  • SDIV/UDIV :有符号/无符号除法。

Cortex-M4/M7 的 DSP 指令还包括单周期 16 位双乘法、饱和算术、SIMD 加/减等,需要汇编中显式指定。

位操作与比特带

Cortex-M3 及以上支持位操作,主要通过比特带(Bit Band)实现。存储器中有两个 1MB 的比特带区域(SRAM 和外设),每个字映射到一个别名区,对别名区的一个字的写入转换为对目标比特的原子置位/清零。汇编指令层面还可使用 BFC/BFIUBFX/SBFX 等 32 位指令进行位域操作。

  • BFC Rd, #lsb, #width :将 Rd 的指定范围清零。
  • BFI Rd, Rn, #lsb, #width :将 Rn 低 width 位插入 Rd 的指定位置。
  • UBFX Rd, Rn, #lsb, #width :无符号提取位域并零扩展到 32 位。

状态寄存器访问与修饰指令

  • MRS Rd, <psr> :将特殊寄存器(如 PRIMASK、CONTROL)读取到通用寄存器。
  • MSR <psr>, Rn :将通用寄存器的值写入特殊寄存器,常用于屏蔽中断或切换堆栈指针。
  • CPSID I / CPSIE I :快速屏蔽/开启中断(写 PRIMASK)。
  • WFI / WFE :等待中断/事件,进入低功耗状态。
  • ISB/DSB/DMB :指令/数据/存储器屏障,保证流水线和存储器访问顺序,在操作寄存器前可能需要 DSB。

寻址模式

Cortex-M 指令支持多种灵活的寻址方式,使得结构化数据操作非常高效。

  • 立即数偏移寻址LDR R0, [R1, #4],偏移量直接内嵌。
  • 寄存器偏移寻址LDR R0, [R1, R2],R2 作为偏移。
  • 前索引寻址LDR R0, [R1, #4]!,先将 R1=R1+4,再加载到 R0,等效于 *++ptr。
  • 后索引寻址LDR R0, [R1], #4,先加载 R0 = *R1,再 R1=R1+4,等效于 *ptr++。
  • PC 相对寻址LDR R0, [PC, #offset],常用于加载文本池中的常量。
  • SP 相对寻址LDR R0, [SP, #offset],访问堆栈局部变量。

这些寻址模式也适用于 STRLDRH/LDRB 等指令。

异常与中断模型

Cortex-M 使用统一的向量异常处理机制,由嵌套向量中断控制器 NVIC 管理。

  • 异常向量表:位于存储器开始处(通常 0x00000000),每个表项为 4 字节,存放入口地址。前 16 个异常为系统异常(复位、NMI、HardFault、SVCall、PendSV、SysTick 等),之后是外部中断 IRQ0~IRQn。
  • 异常进入:硬件自动压栈(依次压入 xPSR, PC, LR, R12, R3, R2, R1, R0),保存返回地址到 LR(特殊值 EXC_RETURN),从向量表加载对应处理程序地址到 PC,切换到 Handler 模式,使用 MSP。
  • 异常返回:通过将 EXC_RETURN 写入 PC 触发返回,硬件自动出栈,恢复状态。通常用 BX LRPOP {PC} 返回。
  • 尾链优化:当一个异常结束时,若有待处理异常,可直接切换到新的异常处理,省去多余的压栈出栈。
  • NVIC 优先级:支持最多 256 级优先级,高优先级可抢占低优先级,相同优先级则使用尾链。

在编程时,可以用 C 语言的 __attribute__((naked)) 或嵌入汇编进行异常处理,也可直接编写 void SysTick_Handler(void) 函数,编译器会自动生成返回指令。

汇编编程基础示例

以下是一个简单的汇编程序,实现 LED 闪烁控制,假设外设地址已知。

.syntax unified
.cpu cortex-m3
.thumb

.global _start

_start:
    LDR R0, =0x40021018   @ 加载 RCC 时钟使能寄存器地址
    LDR R1, [R0]
    ORR R1, R1, #0x10     @ 使能 GPIO 端口 B 时钟
    STR R1, [R0]

    LDR R0, =0x40010C04   @ GPIOB 端口配置寄存器低地址 (CRL)
    LDR R1, [R0]
    BIC R1, R1, #0xF0     @ 清除 PB1 配置位
    ORR R1, R1, #0x20     @ 设置为推挽输出,50MHz
    STR R1, [R0]

loop:
    LDR R0, =0x40010C0C   @ GPIOB 输出数据寄存器 (ODR)
    LDR R1, [R0]
    EOR R1, R1, #0x02     @ 翻转 PB1
    STR R1, [R0]

    LDR R2, =0x100000     @ 简单延时循环
delay:
    SUBS R2, R2, #1
    BNE delay

    B loop

上述代码使用 LDR 伪指令加载地址常量,ORR 置位,EOR 翻转位,实现了基础的 GPIO 控制。

总结

Cortex-M 架构通过统一的 Thumb-2 指令集、精简高效的寄存器模型和实时优化的异常处理机制,为嵌入式系统提供了强大的处理能力。掌握其编程模型、常用指令、寻址方式以及异常处理流程,是进行嵌入式固件开发或系统优化的基石。后续可结合具体芯片参考手册,深入实践外设驱动和实时任务设计。