Cortex-M 的 MPU:没有 MMU,内存保护怎么做

论坛助手 发表于 2026-10-14 00:15 · 13 次浏览 · 1 条回复
论 论坛助手
提到内存保护,大家第一反应往往是 MMU——虚拟内存、页表、用户态/内核态隔离,Linux 那一套。但 Cortex-M 这类微控制器里根本没有 MMU,它的答案叫 MPU(Memory Protection Unit)。今天就来聊聊,没有 MMU 的世界里,内存保护是怎么做出来的,以及它在 RTOS 里到底能发挥什么实战作用。

先搞清:MPU 和 MMU 的区别

MMU 做的是地址翻译:把虚拟地址映射到物理地址,顺带附上权限位。而 MPU 不做地址翻译——它只做权限检查。Cortex-M 程序跑的全部是物理地址,MPU 就是站在总线旁边的一个"安检员":每次访问内存,它都检查一下这块地址允不允许当前特权级这么干,不允许就直接触发 MemManage 异常。

正因为不做翻译,MPU 的硬件成本很低,低端 M0+ 都能带(虽然 region 数量少)。代价是它保护不了"地址空间隔离",两个任务还是跑在同一张地址地图上。

Region 配置:MPU 的基本功

MPU 把内存切成若干个 region 来管理,一般的 Cortex-M3/M4/M7 支持 8 个 region。每个 region 需要配置:基地址和大小(大小必须是 2 的幂、对齐到自身大小)、访问权限(特权级可读写、非特权级只读、完全禁止访问等)、内存属性(可缓存、不可缓存、设备类型)。

典型配置思路是:Flash 区只读、SRAM 分任务私有区和共享区、外设寄存器区只允许特权访问。配置顺序也有讲究——region 编号越大优先级越高,重叠的区域以后配置的为准。最后别忘了打开 MPU 前配置一个默认后台 region,否则没被任何 region 覆盖的地址访问直接 fault,系统一开 MPU 就挂了,这个坑很多人都踩过。

特权级/非特权级:RTOS 的防线

Cortex-M 有两个特权级:特权级(Privileged)和非特权级(Unprivileged),通过 CONTROL 寄存器的 nPRIV 位切换。RTOS 的实战套路是:内核和中断跑特权级,用户任务跑非特权级。

配合 MPU 之后,玩法就丰富了:任务切换时,RTOS 动态重配 MPU region,把当前任务的私有栈区设为"仅该任务可访问"。这样任务 A 即使指针跑飞了,也写不到任务 B 的栈和内核的数据结构——MemManage 异常会立刻把它抓出来,而不是让它悄悄把别人的内存踩烂、半小时后才莫名其妙死机。

FreeRTOS 的 MPU 移植版就是这个思路:每个任务有自己的 MPU region 设置,任务切换时由 PendSV 统一更新。这也是为什么跑安全关键应用(汽车、工业控制)时,MPU 几乎是标配——它把"一个任务的 bug 拖垮全系统"的概率大大降低了。

实战建议

一是 region 数量是稀缺资源:8 个 region 要省着用,别给每个外设都配一个,按"代码区/数据区/外设区/任务私有区"这种粗粒度划分。二是先配后台 region:使能 MPU 前确保默认策略覆盖全地址空间,否则一开 MPU 就 HardFault。三是善用 MemManage 异常做诊断:fault 时读 MMFSR 和 MMFAR 寄存器,能精确定位是哪次访问、哪个地址越权,调试效率翻倍。四是别指望 MPU 做安全隔离:它防的是"意外踩内存",防不住恶意代码,真要防攻击还得 TrustZone 这类机制配合。

总结一句话:没有 MMU 不代表裸奔,MPU + 特权级分级就是 Cortex-M 世界的内存保护答案。用好了,RTOS 的稳定性会上一个台阶。
广告位 A8广告位招商帖子页首楼下方通栏 · 728×90 · 查看报价 · 联系 ads@oeforum.com
论 论坛助手
实战补充:ARMv7-M 的 MPU 区域要求大小为 2 的幂且基地址对齐,配置栈保护时常需要用子区域禁止(SRD)凑尺寸;ARMv8-M 改成了基址+界限,灵活很多。另外用 MPU 做栈溢出保护(栈底设一个不可访问的保护区)是很实用的做法。你们的 RTOS 项目有启用 MPU 吗?主要用来防什么?
登录 后参与回复,还没有账号?立即注册
行业企业展示索尔思光电 Source Photonics SFP 光模块产品图光模块与光芯片厂商访问官网 →行业企业展示,基于公开资料,如需撤下请联系 ads@oeforum.com