MPU概述
2026/10/3大约 2 分钟
MPU(内存保护单元)的规矩,完全可以用“势力范围”来理解。它管得宽不宽、让不让进,全看地盘归谁管。


1. 被 MPU 势力范围笼罩(Region 覆盖)
只要这块地盘被 MPU 划进了它的势力范围,访问就要看它定的“规矩”(AP 权限):
- 设成只读:你就只能读,敢写就触发 MemManage Fault。
- 设成只写(如果有这种配置):那就只能写,读就报错。
- 设成读写:随便访问,相安无事。
- 设成禁止访问:一碰就报错。
一句话:在势力范围内,按规矩办事,违规必究。
2. 在 MPU 势力范围之外(Background Region 未覆盖)
如果你想去 MPU 没管的地盘逛逛,那就要看控制寄存器里的“默认后门开关”(PRIVDEFENA 位):
- 开关为 0(严格模式):六亲不认。
不管你是特权内核)还是非特权(任务),只要访问了没被 MPU 笼罩的地方,统统触发 MemManage Fault。 - 开关为 1(默认放行模式):
- 特权(内核/中断):可以去势力范围外的地方随便逛,不会触发异常(相当于有特权通行证)。
- 非特权(用户任务):依然不行! 哪怕开了这个开关,普通任务一旦踏入 MPU 未覆盖的区域,依然会触发 MemManage Fault。

例子
#include <stdio.h>
#include "ARMCM3.h"
void switch_user (void) {
__set_CONTROL(CONTROL_nPRIV_Msk);
}
int main (void) {
// 读取区域的数量
int dregion = (MPU->TYPE & MPU_TYPE_DREGION_Msk) >> MPU_TYPE_DREGION_Pos;
printf("dregion count: %d\n", dregion);
// PRIVDEFENA - 特权等级默认存储器映射使能,即是否允许特权级访问默认的存储映射区域
// 开启MPU同时打开PRIVDEFENA位,特权程序能够访问所有存储
// 如果未打开,则特权级默认不允许访问这些区域
ARM_MPU_Enable(MPU_CTRL_PRIVDEFENA_Msk);
//ARM_MPU_Enable(0); // 未打开,不管是什么权限,都死机
// 切换用户模式将进入HardFault, 因为无权限访问内容
switch_user();
for (;;) {
}
return 0;
}
