存储器保护单元——基于ARM Cortex-M0技术
- UID
- 1029342
- 性别
- 男
|
存储器保护单元——基于ARM Cortex-M0技术
存储器保护单元(MPU)是用来保护存储器的一个元件。Cortex-M0处理器支持标准的ARMv6 PMSA模型,具有以下功能:
(1)保护内存区域。
(2)将保护区域重叠。
(2)控制访问权限。
(3)将存储器属性输出到系统。
内存访问时,如果MPU不匹配或越权访问,将发生“内存管理错误(MemManage Fault Handler)”,激活存储器管理故障处理程序。表7-18所示为MPU相关寄存器。
表7-18 MPU相关寄存器
名 称 | 类 型 | 地 址 | 复 位 值 | MPU类型寄存器 | 只读 | 0xE000ED90 | 0x00000800 | MPU控制寄存器 | 读/写 | 0xE000ED94 | 0x00000000 | MPU区号寄存器 | 读/写 | 0xE000ED98 | - | MPU区域基址寄存器 | 读/写 | 0xE000ED9C | - | MPU区域属性与大小寄存器 | 读/写 | 0xE000EDA0 | - | MPU别名1区基址寄存器 | D9C重叠 | 0xE000EDA4 | - | MPU别名1区属性与大小寄存器 | DA0重叠 | 0xE000EDA8 | - | MPU别名2区基址寄存器 | D9C重叠 | 0xE000EDAC | - | MPU别名2区属性与大小寄存器 | DA0重叠 | 0xE000EDB0 | - | MPU别名3区基址寄存器 | D9C重叠 | 0xE000EDB4 | - | MPU别名3区属性与大小寄存器 | DA0重叠 | 0xE000EDB8 | - | 对MPU区域的编程,可通过对映射到内存的3个字寄存器的编程来实现。3个寄存器相互独立,程序可分开访问。MPU寄存器相互独立的特性,可以使用户方便地移植现有的ARMv6、ARMv7和CP15的代码,使Cortex-M3很容易地实现向后兼容。当移植ARMv6和CP15的现有代码时,只需使用LDRx和STRx操作代替MRC和MCR。
使用CP15等效代码更新MPU区域的代码实例如下:
R1 = region number
R2 = size/enable
R3 = attributes
R4 = address
MOV R0,#NVIC_BASE
ADD R0,#MPU_REG_CTRL
STR R1,[R0,#0] ;
STR R4,[R0,#4] ;
STRH R2,[R0,#8] ;
STRH R3,[R0,#10] ;
值得注意的是,如果中断在这期间可以抢占,那么它会受MPU区域的影响,即必须禁能、写然后再使能该区域。这对于上下文转换器通常没有太大用处,但是如果需要在其他地方进行更新,这就很有必要了。
MPU可以包含关键的数据,这是因为在更新时得花费一个以上的总线处理,通常是两个字,结果就不是“线程安全”了,即中断可以将两个字分离,使得区域包含不连续的信息。此时要注意以下两个问题。
(1)更新MPU通常会产生中断。这不仅是“读—修改—写”的问题,它还会对“保证中断程序不会修改相同区域”的情形造成影响。这是因为编程取决于正写入寄存器的区号,所以它知道要更新哪个区。因而这种情形下每个更新程序周围都必须禁能中断。
(2)使用域操作更新MPU会产生中断,该中断将使正在更新的区域受到影响,因为只有基址或“大小域”被更新。如果新的大小域发生了改变,但是基址没有变,那么基址 +new_size可能会在一个被另外区域正常处理的区域内重叠。
但是对于标准的OS上下文转换代码,将会改变用户区域,因为这些区域会被预设成用户特权和用户区地址,所以没有风险。也就是说即使是中断也不会产生副作用。因此不需要禁能/使能代码,也不需要禁止中断。
最普通的方法是只从两个位置对MPU进行编程:引导代码和上下文转换器。如果以唯一的两个位置进行编程,且上下文转换器仅更新用户区,那么因为上下文转换器已经是一个关键区域,且引导代码在禁能中断时运行,所以不需要禁能。 |
|
|
|
|
|