目录
一 Memory Protection Unit (MPU) 功能概述:
在ARM Cortex-M3(CM3)微控制器中,实际上并没有传统的内存管理单元(MMU)。但是,CM3提供了Memory Protection Unit(MPU),它是MMU的一个轻量级替代方案,用于实现简单的内存保护和分区功能。
一 Memory Protection Unit (MPU) 功能概述:
-
内存区域划分:MPU允许开发者将系统内存划分为多个不同的区域(Regions),并对每个区域设置不同的访问权限(读/写/执行)。
-
权限控制:每个内存区域可以配置为只读、只写或可读写,也可以完全禁止访问,从而实现对不同任务或中断服务程序访问内存的权限控制,增强系统的安全性。
-
粒度管理:Cortex-M3的MPU支持不同的粒度,可以按照区域大小进行划分,例如可以选择整个内存区域,或者按照较小的区块进行管理。
-
硬件支持内存隔离:通过MPU,可以在不同的任务之间实现内存隔离,防止一个任务无意或恶意修改另一个任务的数据。
实例说明:
; 假设我们想为Cortex-M3设置一个只读的内存区域,该区域从地址0x20000000开始,大小为4KB
; 首先,需要初始化MPU
MPU_Initialize();
; 然后,配置一个新的内存区域
MPU_SetRegionNum(0); ; 选择区域编号
MPU_ConfigRegion(0x20000000, 4*1024, MPU_REGION_READ_ONLY); ; 地址、大小和权限
; 启用MPU
MPU_Enable(MPU_PRIVILEGED_DEFAULT); ; 启用MPU,并设置默认的访问权限(例如,特权模式)
; 之后,当尝试在非特权模式下对0x20000000开始的4KB内存区域进行写操作时,将触发总线错误异常(BusFault)。
这段代码是一个简化的示例,表明了如何使用MPU来保护一段内存区域使其变为只读。在实际应用中,程序员需要使用CMSIS(Cortex Microcontroller Software Interface Standard)或特定微控制器供应商提供的库函数来操作MPU。
由于Cortex-M3并不支持虚拟内存和地址转换,所以MPU并不负责虚拟地址到物理地址的转换,其主要关注的是物理内存的保护和隔离。在更高级别的ARM架构(如Cortex-A系列)中,才会有支持完整地址转换和页面替换机制的MMU。
二 MPU_Initialize函数介绍
`MPU_Initialize` 是一个用于初始化内存保护单元(MPU)的函数。在基于 ARM Cortex-M 处理器的嵌入式系统中,特别是 STM32 系列微控制器中,MPU 可以帮助实现对内存区域的访问权限控制,防止非法或意外的内存访问导致系统不稳定或数据泄露。
`MPU_Initialize` 函数通常由芯片厂商提供的 SDK 或 CMSIS 库提供,其主要作用是:
1. 关闭所有已配置的 MPU 区域,清空所有 MPU 寄存器的设置。
2. 设置 MPU 的基础配置,如启用 MPU、设置异常响应方式等。
3. 为后续对 MPU 区域的配置做好准备。
下面是一个简化的 `MPU_Initialize` 函数调用示例(基于 STM32 Cube HAL 库的风格):
void MPU_Initialize(void) {
HAL_MPU_Disable(); // 关闭 MPU,清除所有之前的配置
// 设置 MPU 控制寄存器的属性,例如是否启用 MPU,异常响应方式等
MPU_CTRL_Type MPU_Ctrl;
MPU_Ctrl.Enable = MPU_ENABLE;
MPU_Ctrl.HFNMIENA = MPU_HFNMI_PRIVDEF_DISABLE; // HFNMI 异常情况下保持特权模式默认内存映射
MPU_Ctrl.PrivilegeDefault = MPU_PRIVILEGED_DEFAULT_DISABLE; // 非特权模式下默认关闭内存访问
MPU_Ctrl.HardFaultNMI = MPU_HARDFAULT_NMI_DISABLE; // 硬故障和 NMI 不影响 MPU
HAL_MPU_ConfigCtrl(&MPU_Ctrl); // 应用 MPU 控制寄存器的设置
HAL_MPU_Enable(MPU_PRIVILEGED_DEFAULT); // 启用 MPU,设置默认的访问权限(例如,特权模式)
}
在实际应用中,调用 `MPU_Initialize` 函数是配置 MPU 的第一步,初始化完成后,就可以通过类似 `MPU_ConfigRegion` 的函数进一步配置内存区域的访问权限。
三 MPU_ConfigRegion函数介绍
`MPU_ConfigRegion` 是一个抽象函数名,通常在基于 ARM Cortex-M 内核的微控制器(如 STM32 系列)中用于配置内存保护单元(MPU)的一个内存区域。这个函数通常由芯片厂商提供的 SDK 或 CMSIS 库提供,用于设置 MPU 的各个区域属性,如基地址、大小、访问权限等。
下面是一个简化的 `MPU_ConfigRegion` 函数调用示例(基于 STM32 Cube HAL 库的风格):
#define REGION_NUMBER 0
#define START_ADDRESS 0x20000000
#define SIZE_BYTES 4096
#define ACCESS_PERMISSION MPU_REGION_FULL_ACCESS
void MPU_ConfigRegion(uint32_t Mem_Rgn, uint32_t BaseAddress, uint32_t Size, uint32_t AccessPermission) {
MPU_Region_InitTypeDef MPU_Init;
MPU_Init.Enable = MPU_REGION_ENABLE;
MPU_Init.Number = Mem_Rgn; // 区域编号
MPU_Init.BaseAddress = BaseAddress; // 区域起始地址
MPU_Init.Size = MPU_REGION_SIZE_4KB; // 区域大小,这里假设为4KB
MPU_Init.AccessPermission = AccessPermission; // 访问权限设置
// 根据实际需求配置其他属性,如缓冲特性、缓存特性、共享属性等
HAL_MPU_ConfigRegion(&MPU_Init); // 调用HAL库函数实际配置MPU区域
}
// 使用示例
void Configure_MPU(void) {
MPU_ConfigRegion(REGION_NUMBER, START_ADDRESS, SIZE_BYTES, ACCESS_PERMISSION);
}
在这个示例中,`MPU_ConfigRegion` 函数接受四个参数:
1. `Mem_Rgn`: 要配置的MPU区域编号。
2. `BaseAddress`: 配置的内存区域的起始地址。
3. `Size`: 配置的内存区域的大小,通常是以字节为单位。
4. `AccessPermission`: 配置的内存区域的访问权限,可以是只读、读写、执行等各种组合。
实际调用该函数时,会根据传入的参数设置对应的 MPU 区域属性,然后通过 HAL 库函数 `HAL_MPU_ConfigRegion` 将这些属性配置到 MPU 控制器中。