第1章:ARM Cortex-M MPU基础
大家好,我是你们的讲师。今天咱们聊聊MPU——内存保护单元。说实话,我刚入行那会儿,总觉得MPU是个可有可无的东西。直到有一次,一个野指针把整个系统搞崩了,我才意识到:没有MPU,你的代码就像在悬崖边跳舞。
1.1 MPU架构概览
ARM Cortex-M的MPU,说白了就是一个硬件级的保镖。它帮你盯着内存访问,谁越界了,它就立刻叫停。我个人习惯把MPU看作一个「门禁系统」——每个内存区域都有对应的访问权限,不是谁都能随便进的。
MPU在Cortex-M3/M4/M7上都有支持,M0/M0+没有。嗯,这里要注意:如果你的芯片是M0系列,那MPU这块内容可以跳过,但原理还是值得了解的。
核心要点:MPU位于处理器核心和总线系统之间,所有内存访问都要经过它检查。它不参与数据运算,只负责「看门」。
1.2 MPU寄存器介绍
MPU的寄存器不多,但每个都很关键。我列个表,大家先混个脸熟:
| 寄存器名称 | 功能描述 | 我踩过的坑 |
|---|---|---|
| MPU_TYPE | 读取MPU支持的region数量 | 别直接写,它是只读的 |
| MPU_CTRL | 使能/禁用MPU,控制特权模式访问 | 使能前一定要先配好region |
| MPU_RNR | 选择当前要配置的region编号 | 记得先选region再写寄存器 |
| MPU_RBAR | 设置region的基地址 | 地址要对齐,不然配置无效 |
| MPU_RASR | 设置region的大小、权限、属性 | 大小必须是2的幂次 |
为什么说这些寄存器重要?因为配置MPU就是跟它们打交道。我曾经在项目里因为忘记设置MPU_RNR,结果写到了错误的region上,排查了整整两天。
1.3 Region概念
Region,就是MPU管理的基本单位。每个region定义了一块连续的内存区域,以及它的访问规则。Cortex-M3/M4最多支持8个region,M7最多支持16个。
你想想看,8个region够用吗?我个人的经验是:大多数场景下够用。一般我们会这样分配:
- Region 0:Flash代码区(只读,可执行)
- Region 1:SRAM数据区(读写,不可执行)
- Region 2:外设寄存器区(读写,不可执行,强序)
- Region 3:堆栈区(读写,不可执行)
小技巧:我习惯把最常用的region放在编号小的位置,因为有些芯片对低编号region有优先级优势。
1.4 Region配置实战
光说不练假把式。咱们直接看代码,配置一个保护Flash的region:
// 配置Region 0:保护Flash区域
// 基地址:0x08000000,大小:512KB
MPU->RNR = 0; // 选择Region 0
MPU->RBAR = 0x08000000; // 基地址
MPU->RASR = (0x1A << 1) | // 大小:512KB (2^19)
(0x3 << 24) | // 权限:全读,特权写
(0x1 << 28); // 使能该region
// 使能MPU
MPU->CTRL = (0x1 << 0) | // 使能MPU
(0x1 << 2); // 使能默认region映射
这段代码看起来简单,但有几个坑:
- 基地址必须对齐到region大小。512KB的region,基地址必须是512KB的整数倍
- 大小编码用的是2的幂次,0x1A表示2^19 = 512KB
- 使能MPU前,最好先关掉中断,防止配置过程中发生异常
警告:我曾经在配置MPU时没关中断,结果配置到一半,一个中断进来访问了未保护的区域,直接触发MemManage Fault。所以,配置MPU前一定要关中断!
1.5 默认Region映射
MPU有个特性叫「默认region映射」。使能后,所有未配置region的内存区域都采用默认权限:特权模式全访问,用户模式不可访问。
这个特性很有用。比如你只想保护几个关键区域,其他区域让系统自己管。我个人习惯是:使能默认映射,然后只配置需要特殊保护的region。
但要注意:默认映射下,用户模式代码访问任何未配置region都会触发异常。所以如果你的系统有用户态任务,记得给它们分配好region。
1.6 避坑指南
最后,分享几个我这些年踩过的坑:
- region重叠:两个region不能重叠,否则行为未定义。我曾经不小心把两个region设成了同一个地址范围,结果MPU直接罢工
- 大小限制:region最小128字节,最大4GB。但实际芯片可能有限制,查手册为准
- 对齐要求:基地址必须对齐到region大小。128字节的region,基地址最后7位必须是0
- 使能顺序:先配region,再使能MPU。顺序反了,系统直接崩
好了,这一章就到这里。MPU的基础概念和寄存器配置,说白了就是这些内容。下一章咱们聊聊「内存访问权限的精细控制」,到时候会讲怎么用MPU实现任务隔离。
记住:MPU不是万能的,但没有MPU是万万不能的。尤其是在做安全关键系统时,MPU就是你的最后一道防线。
课后思考:如果你的系统有8个region,你会怎么分配?试着画一张内存布局图,标出每个region的用途和权限。
公众号:蓝海资料掘金营,微信deep3321