ARM Cortex-M 架构:从处理器家族到异常处理
ARM Cortex-M 系列,说白了就是嵌入式世界里的「瑞士军刀」。我最早接触 ARM 是在大学实验室,那时候还是 ARM7TDMI,烧程序得用并口线。后来转到 Cortex-M,第一感觉就是——这玩意儿太友好了。你想想看,一个 32 位处理器,功耗能控制在毫瓦级,中断响应还快得离谱,这不就是为嵌入式量身定做的吗?
ARM 处理器家族:一张图看懂
ARM 处理器分三大类:Cortex-A、Cortex-R、Cortex-M。名字好记——A 是 Application(应用),R 是 Real-time(实时),M 是 Microcontroller(微控制器)。
| 系列 | 典型场景 | 我见过的坑 |
|---|---|---|
| Cortex-A | 手机、平板、Linux 系统 | 跑 Linux 没问题,但裸机开发?别自找麻烦 |
| Cortex-R | 硬盘控制器、汽车刹车 | 硬实时要求高,但开发工具贵 |
| Cortex-M | 传感器、电机控制、IoT 设备 | 入门简单,但中断优先级设错会死机 |
我个人习惯是:做消费电子用 M4 或 M7,做低功耗电池设备用 M0+。选型选对了,后面少走一半弯路。
Cortex-M 系列特点:为什么它这么火?
Cortex-M 有几个硬核特点,我一个个说。
- Thumb-2 指令集:16 位和 32 位指令混用。代码密度高,性能也不差。我在一个 Flash 只有 64KB 的项目里,靠 Thumb-2 硬是把功能塞进去了。
- 嵌套向量中断控制器(NVIC):中断优先级可配置,支持抢占。嗯,这里要注意——优先级分组搞错了,低优先级中断可能永远得不到响应。
- 低功耗模式:Sleep、Deep Sleep、Standby。我做过一个温湿度采集器,用 Deep Sleep 模式,两节 AA 电池撑了半年。
- 系统节拍定时器(SysTick):专为 OS 设计的 24 位递减定时器。跑 RTOS 必备,裸机也能当精准延时用。
核心优势:Cortex-M 把「高性能」和「低功耗」这对矛盾体,硬是揉在了一起。你想想看,一个跑 200MHz 的 M7,功耗才几十毫瓦,这在十年前根本不敢想。
寄存器组:程序员最该记住的 16 个寄存器
Cortex-M 的寄存器组,说白了就是 R0-R15 加上特殊功能寄存器。我刚开始学的时候,总觉得寄存器太多记不住。后来发现,常用的就那几个。
| 寄存器 | 别名 | 用途 | 我的经验 |
|---|---|---|---|
| R0-R12 | 通用寄存器 | 数据运算、地址暂存 | R0-R3 传参数,R4-R11 保存局部变量 |
| R13 | SP(堆栈指针) | 指向当前堆栈 | MSP 和 PSP 切换时容易出错,我吃过亏 |
| R14 | LR(链接寄存器) | 保存函数返回地址 | 中断里改 LR 要小心,否则回不来 |
| R15 | PC(程序计数器) | 指向当前指令 | PC 最低位必须是 1(Thumb 模式) |
| xPSR | 程序状态寄存器 | 标志位、中断状态 | 调试时多看 xPSR,能发现很多问题 |
小技巧:调试时用 IDE 的寄存器窗口,盯着 SP 和 PC 看。程序跑飞了,先看 PC 是不是指向了非法地址。我曾经花了两小时查一个 bug,最后发现是堆栈溢出把 PC 给覆盖了。
工作模式:线程模式 vs 处理模式
Cortex-M 只有两种工作模式,比传统 ARM 简单多了。
- 线程模式(Thread Mode):跑普通代码。可以运行在特权级或用户级。
- 处理模式(Handler Mode):跑异常处理程序。始终在特权级。
为什么会这样设计?说白了,就是为了安全。你想想看,如果用户代码能随便改中断向量表,那系统还怎么稳定?
我记得有个项目,同事把系统时钟配置放在了线程模式的用户级代码里,结果一运行就 HardFault。查了半天才发现,是权限不够。后来我把时钟初始化放到启动代码里,问题就解决了。
异常处理:中断系统的灵魂
Cortex-M 的异常处理,是我最喜欢的部分。它把中断响应时间压缩到了极致。
异常类型
| 异常编号 | 名称 | 优先级 | 触发条件 |
|---|---|---|---|
| 1 | Reset | -3(最高) | 上电或复位 |
| 2 | NMI | -2 | 不可屏蔽中断 |
| 3 | HardFault | -1 | 任何错误 |
| 4-10 | 系统异常 | 可配置 | MemManage、BusFault 等 |
| 11-15 | 保留 | - | - |
| 16+ | 外部中断 | 可配置 | 外设触发 |
避坑指南:我曾经把两个中断的优先级设成了相同值,结果一个中断没处理完,另一个又来了,导致堆栈溢出。记住——同优先级中断不会互相抢占,但会排队。如果处理时间太长,后面的中断可能会丢。
中断响应流程
Cortex-M 的中断响应,硬件自动完成了大部分工作。流程是这样的:
- CPU 检测到中断请求
- 硬件自动压栈:PC、LR、xPSR、R0-R3、R12
- 从向量表取出中断服务函数地址
- 切换到处理模式,执行 ISR
- ISR 执行完毕,硬件自动出栈
- 返回线程模式,继续执行
整个过程只需要 12 个时钟周期。我测过 M4 的中断延迟,从触发到进入 ISR,大概 80ns(以 168MHz 计)。这个速度,做电机控制绰绰有余。
知识体系总览
下面这张图,把本章的核心知识点串起来了。我建议你保存下来,复习时看一眼就全想起来了。
写在最后
ARM Cortex-M 架构,说复杂也复杂,说简单也简单。你只要抓住三个核心:寄存器怎么用、模式怎么切、中断怎么处理。剩下的,都是在这些基础上堆功能。
我个人建议,初学者先拿一块 M4 开发板,点个灯,然后写个定时器中断。等你能让 LED 以精确的 1 秒间隔闪烁时,恭喜你——你已经掌握了 Cortex-M 的精髓。