为一块内存区域开启只读保护
2026/10/3大约 2 分钟
接下来就是要对mpu的覆盖范围进行设置,并且设置访问的权限

设置的话,只会涉及到两个寄存器

首先是基地址的设置寄存器

然后配置基地址处内存保护单元的大小,

这里主要看size字段就行了
不同的二进制字段代表不同的含义,具体看代码吧

AP字段我们对它进行设置的话,可以设置权限的访问,在特权级与非特权级情况下,是访问可读还是可写,只读还是只写

下面就实现了对一段内存保护的特权级下的只读权限访问
#include <stdio.h>
#include "ARMCM3.h"
void switch_user (void) {
__set_CONTROL(CONTROL_nPRIV_Msk);
}
#define MEM32(addr) *(volatile unsigned int *)(addr)
int main (void) {
// 读取区域的数量
int dregion = (MPU->TYPE & MPU_TYPE_DREGION_Msk) >> MPU_TYPE_DREGION_Pos;
printf("dregion count: %d\n", dregion);
// 没有保护,可以先设置好数据
MEM32(0x20010000) = 0x12345678;
// 0x20010000 + 16KB,特权程序只读
ARM_MPU_SetRegion(
ARM_MPU_RBAR(0, 0x20010000), // 注意这个地址要对齐到16KB
ARM_MPU_RASR(
0, // DisableExec,是否允许取指
ARM_MPU_AP_PRO, // AccessPermission,特权程序只读
0, // TypeExtField
0, // IsShareable
0, // IsCacheable
0, // IsBufferable
0, // SubRegionDisable
ARM_MPU_REGION_SIZE_16KB // 区域大小为16KB
)
);
// PRIVDEFENA - 特权等级默认存储器映射使能,即是否允许特权级访问默认的存储映射区域
// 开启MPU同时打开PRIVDEFENA位,特权程序能够访问所有存储
// 如果未打开,则特权级默认不允许访问这些区域
ARM_MPU_Enable(MPU_CTRL_PRIVDEFENA_Msk);
//ARM_MPU_Enable(0); // 未打开,不管是什么权限,都死机
// 超过16KB,0x20014000使用缺省的设置,可以读写
MEM32(0x20010000 + 16 * 1024) = 0x87654321;
// 设置保护模式后,特权级模式下只读,如果写,则进入fault
MEM32(0x20010000) = 0x87654321;
// switch_user();
for (;;) {
}
return 0;
}在调试的时候,可以通过这个调试窗口来看见寄存器的值,这里面可视化了mpu的8个区域,还有权限的访问。P是特权级,U是非特权级


