内存保护单元 (MPU)
概述
内存保护单元 (Memory Protection Unit,MPU) 是 Arm Cortex-M 系列 MCU 提供的一个组件,用于通过软件定义来实现硬件保护。各个 CPU 的 MPU 条目数量不同,具体如下表所示:
API 参考
SDK 中提供了 mpu_region_config 结构体,用于设置 MPU 的区域内存属性。下表列出了 mpu_region_config 结构体的成员变量:
名称 |
类型 |
描述 |
---|---|---|
region_base |
uint32_t |
MPU 区域基地址,32 字节对齐 |
region_size |
uint32_t |
MPU 区域大小,32 字节对齐 |
xn |
uint8_t |
执行禁止属性 (Execute Never)
|
ap |
uint8_t |
访问权限
|
sh |
uint8_t |
普通内存的共享属性
|
attr_idx |
uint8_t |
内存属性间接索引 取值范围为 0 ~ 7,具体属性在 mpu_init() 中定义且支持自定义。典型定义如下:
|
mpu_init
void mpu_init(void)
初始化 MPU 区域内存属性为典型值
参数:无
返回值:无
mpu_set_mem_attr
void mpu_set_mem_attr(uint8_t attr_idx, uint8_t mem_attr)
修改 MPU 区域内存属性
参数:
attr_idx
: 内存属性间接索引,取值范围为 0 ~ 7mem_attr
: MPU_MEM_ATTR0 ~ MPU_MEM_ATTR7,也可以自定义
返回值:无
mpu_region_cfg
void mpu_region_cfg(uint8_t region_num, mpu_region_config *pmpu_cfg)
依据给定参数配置 MPU 区域内存属性
参数:
region_num
: MPU条目索引pmpu_cfg
: 指向已配置的 mpu_region_config 结构体
返回值:无
mpu_entry_free
void mpu_entry_free(u32 entry_index)
释放 MPU 条目对应的软件标记,此时 MPU 条目将被标记为可用
参数:
entry_index
: MPU条目索引
返回值:无
mpu_entry_alloc
char mpu_entry_alloc(void)
分配一个空闲的 MPU 条目
参数:无
返回值:MPU条目索引,如果分配失败则返回 -1
使用说明
系统启动时,在 ameba_app_start.c
的 app_start()
函数中,会调用 mpu_init()
函数来初始化 MPU。
MPU 初始化完成后,函数 app_mpu_nocache_init()
依据 已定义的非缓存数据缓冲区 来配置非缓存数据缓冲区。
备注
不管是 I-Cache 还是 D-Cache,均不会缓存 MCU 内部 ROM 的地址。
如果运行过程中代码或数据被误踩,想要借助 MPU 区域只读属性来辅助分析,可以按照以下步骤设置 MPU 区域:
定义新变量和结构体
定义一个变量
char mpu_entry;
用于存储 MPU 实体索引;定义一个结构体
mpu_region_config mpu_cfg;
用于存储区域内存属性;
调用
mpu_entry = mpu_entry_alloc();
分配一个空闲的 MPU 实体,-1表示分配失败;设置区域内存属性的结构体;
mpu_cfg.region_base = start_addr; // 需要保护的起始地址,32 字节对齐 mpu_cfg.region_size = size_bytes; // 需要保护的大小,32 字节对齐 mpu_cfg.xn = MPU_EXEC_ALLOW; mpu_cfg.ap = MPU_UN_PRIV_RO; // 只读属性可以避免误踩 mpu_cfg.sh = MPU_NON_SHAREABLE; mpu_cfg.attr_idx = MPU_MEM_ATTR_IDX_WT_T_RA;
调用
mpu_region_cfg(mpu_entry,&mpu_cfg);
配置 MPU 区域内存属性。