这一部分描述在一些stm32微控制器应用的内存保护单元。参看相应的设备手册检查在我们使用的stm32类型中是否存在。
内存保护单元划分内存地图为许多区域,而且定义了每一区域的定位、大小、访问权限和内存属性。它支持:每一区域独立属性设置;重叠区;将内存属性导出到系统。
内存属性影响到区域内存访问的行为。Cortex-M3内存管理单元定义:8个独立的内存区域,0-7;一个背景区域。
当内存区域重叠时,区域编号最高的区域属性影响内存访问。例如,区域7的属性优先于任何与区域7重叠区域的属性。
背景区域和默认内存地图有相同的内存访问属性,但它只能由特权代码访问。
Cortex-M3内存管理单元内存地图是统一的,这意味着指令访问和数据访问有相同的区域设置。
如果一个程序访问一个被MPU禁止的内存地址,处理器将会产生一个内存管理错误。这导致一个错误异常,可能导致一个操作系统环境中的进程中止。
在一个操作系统环境中,内核可以根据要执行的进程动态的更新MPU区域设置。典型的,一个嵌入式操作系统使用MPU进行内存保护。
MPU区域的配置基于内存类型,以下列出了可能的MPU区域属性。
MPU访问许可属性,MPU_RASR寄存器的访问许可位TEX,C,B,S,AP和XN,控制相应内存区域的访问。如果一个内存区域的访问没有需要的许可,MPU产生一个权限错误。
当一个访问违反了MPU许可,处理器产生一个内存管理错误,MMFSR指示错误的原因。
为了更新一个MPU区域的属性,更新MPU_RNR,MPU_RBAR和MPU_RASR寄存器。我们可以单独地编写每一个寄存器,或者使用多字写编程所有的这些寄存器。我们可以使用MPU_RBAR和MPU_RASR别名,使用一个STM指令同时编写最多4个区域。
使用单独的字更新MPU区域:
如果在先前已启用要修改的区域,在向MPU写入新区域设置前先失能这个区域。
软件必须使用内存障碍指令:在MPU设置前,如果那里有未解决的内存传送,如缓冲写,它们可能在MPU设置变化时收到影响;在MPU设置后,如果包含必须使用新MPU设置的内存传输。
然而,如果MPU设置处理在进入一个异常处理时开始或后边紧跟一个异常返回,不需要内存障碍指令,因为异常进入和异常返回机制导致内存障碍行为。
软件在MPU设置中不需要内存屏障指令,因为它通过PPB访问MPU,PPB是一个强有序内存区域。
例如,如果你想所有的内存访问行为在编程顺序后迅速见效,使用一个DSB指令和一个ISB指令。在改变MPU设置后需要使用一个DSB指令,例如在上下文切换的结尾。如果编程MPU区域的代码使用分支或调用进入,一个ISB指令需要使用。如果使用异常返回或采用一个异常输入编程序列,我们不再需要一个ISB指令。
使用多字写更新MPU区域:
我们可以根据信息如何分离,直接使用多字节写。
子区域:
256或更多字节的区域被分为8个大小相等的子区域。设置RASR中的SRD区域的相应位失能子区。SRD的最低有效位控制第一个子区域,SRD的最高有效位控制最后一个子区域。失能一个子区域意味着另一个重叠失能范围的区域匹配代替。如果没有其它的使能区域重叠这个失能这个子区域,MPU发行一个错误。
32,64,128字节的区域不支持子区域,对于这些区域,我们必须设置SRD域为0x00,否则,MPU的行为是不可预测的。
SRD的例子,两个区域有相同的地址重叠。区域1是128KB,区域2是512KB。为了确保区域1的属性应用于第一个128KB区域,设置区域2的SRD域为b00000011,失能前两个子区域。如图所示;
MPU设计提示和技巧
为了避免意外的行为,在更新一个中断处理可能访问的区域属性前失能中断。
确保软件使用正确大小的对齐访问方式访问MPU寄存器:除了RASR,必须使用对齐字访问;对于RASR,可以使用字节或半字对齐或字访问。
处理器不支持对MPU寄存器的不对齐访问。
在设置MPU时,如果MPU在先前已经被编程,失能不用的区域避免任何先前区域设置影响新的MPU设置。
建议的MPU配置,STM32微控制系统只有一个处理器,所以我们应该编程MPU如下,
在stm32实现,共享性和缓冲策略属性不影响系统的行为。但是,对MPU使用那些设置可以使应用代码更有移植性。给出的值可用于典型的场景。
MPU属性不影响DMA对内存/外设地址空间的数据访问。因此,为了保护内存区域免受无意的DMA访问,MPU必须控制SW/CPU访问DMA寄存器。
MPU典型寄存器 (MPU_TYPER)
地址偏移:0x00
复位值:0x00000800
需要的特权:特权的
MPU典型寄存器指示MPU是否存在,如果存在,它支持多少区域。
位31:24 保留,硬件强制为0
位23:16 IREGION[7:0] MPU指令区域的数量。这些位指示支持的MPU指令区域的数量,一致含0x00.MPU内存地图由DREGION域描述和统一。
位15:8 DREGION[7:0] MPU数据区域的数量
位7:1 保留,硬件强制为0
为0 SEPARATE:分开标志。这一位指示支持统一的或单独的指令和数据内存地图:0,统一的;1,单独的。
MPU控制寄存器(MPU_CR)
地址偏移0x04
复位值 0x0000 0000
需要的特权 特权的
MPU_CR寄存器,使能MPU,使能默认内存地图背景区域,在硬件错误,不可屏蔽中断和错误屏蔽升级处理时使能MPU的使用。
当ENABLE和PRIVDEFENA都设置为1:对于特权访问,默认的内存地图,任何特权程序的访问在没有定位任何使能内存区域的行为将会当作默认的内存地图。
任何非特权程序的访问没有定位任何使能的地址区域将会导致一个内存管理错误。
不可执行和强有序规则同样适用于系统控制空间不管ENABLE位的值。
当使能位设置为1时,除非PRIVDEFENA位设置为1,至少内存地图的一个区域必须使能为了系统正常工作。如果PRIVDEFENA位设置为1而且没有区域被使能,那么仅有特权程序可以运行。
当使能为设置为0,系统使用默认的内存地图。这和当MPU没有被执行时有相同的内存属性。默认的内存地图应用于特权和不特权程序访问。
当MPU被使能,系统控制空间和向量表的访问总是被允许的。其它区域的访问性基于区域和PRIVDEFENA是否设置为1。
除非HFNMIENA设置为1,否则在处理去执行优先级为-1或-2异常处理时MPU不被使能。这些优先级仅仅可能在处理一个硬件错误或NIM异常或FAULTMASK被使能时。设置HFNMIENA位为1使能在两种优先级运行时的MPU。
位31:3 保留,硬件强制为0
位2 PRIVDEFENA 使能特权程序访问默认内存地图。
0如果MPU被使能,失能默认内存地图的使用。任何对一位置的内存访问没有覆盖任何使能的区域导致一个错误。
1如果MPU使能,使能默认内存地图的使用对特权程序访问作为背景区域。
注意:当使能时,背景区域行为好像它的区域编号为-1,任何被定义和使能的区域有超过默认地图的优先级。如果MPU未使能,处理器忽略这一位。
位1 HFNMIENA 在硬件错误、NMI和错误屏蔽处理时使能MPU的操作。
当MPU使能时,
0,在硬件错误、NMI和错误屏蔽处理时,不管ENABLE位的值MPU失能
1, 在硬件错误、NMI和错误屏蔽处理时,使能MPU
注意:当MPU被使能,如果这一位被设置为1,行为是不可预测的。
位0 ENABLE 使能MPU
0MPU失能
1MPU使能
MPU区域编号寄存器(MPU_RNR)
地址偏移0x08
复位值 0x0000 0000
需要的特权 特权的
MPU_RNR寄存器选择哪一个内存区域被MPU_RBAR和MPU_RASR寄存器引用。
位31:8 保留,硬件强制为0.
位7:0 REGION[7:0] MPU区域。这些位表明被MPU_RBAR和MPU_RASR寄存器应用的MPU区域。MPU支持8个内存区域,所以这一域允许的值为0-7。通常地,在访问MPU_RBAR或MPU_RASR之前,我们写需要的区域编号到这一寄存器。然而,你可以通过写MPU_RBAR寄存器的VALID位为1,改变区域的编号,这个写操作将会更新REGION域。
MPU区域基地址寄存器(MPU_RBAR)
地址偏移0x0C
复位值 0x0000 0000
需要的特权 特权的
MPU_RBAR寄存器定义了被MPU_RNR寄存器选中的MPU区域基地址,而且可以更新MPU_RNR寄存器的值·。将VALID位设置为1写入MPU_RBAR寄存器改变当前区域的编号和更新MPU_RNR寄存器。
位31:N 区域基地址域。N的值依赖于区域的大小。区域的大小,由RASR中的SIZE域明确,定义N=log2(区域的大小字节)。如果在MPU_RASR寄存器中区域的大小配置为4GB,则没有有效的ADDR域。在这种情况下,区域占据全部的内存地图,基地址为0x0000 0000。基地址对齐为区域的大小。例如,一个64KB区域必须对齐64KB的倍数,例如,在0x0001 0000或0x0002 0000。
位N-1:5 保留,硬件强制为0
位4 VALID MPU寄存器编号生效
写:
0 MPU_RNR寄存器不发生变化,处理器更新在RNR中明确的区域基地址,忽略REGION域的值。
1 处理器更新RNR的值为REGION域的值,更新区域基地址的值为REGION域明确的区域。
读:一直读为0
位3:0 REGION[3:0] MPU区域域。对于写的行为,看VAILD域的描述。在读时,返回由MPU_RNR寄存器明确的当前区域编号。
MPU区域属性和大小寄存器(MPU_RASR)
地址偏移:0x10
复位值 0x0000 0000
需要的特权 特权的
MPU_RASR寄存器定义了由MPU_RNR明确的MPU区域的区域的大小和内存属性,和使能区域及子区域。MPU_RASR可以使用字或半字访问。高有效位的半字保存区域的属性;低有效位的半字保存区域的大小和区域及子区域的使能位。
位31:29 保留,硬件强制为0
位28 XN:指令获取失能位
0, 指令获取使能
1, 指令获取失能
位27 保留,硬件强制为0
位26:24 AP[2:0] 访问许可
位23:22 保留,硬件强制为0
位21:19 TEX[2:0] 内存属性
位18 S:可分享内存属性
位17 C:内存属性
位16 B:内存属性
位15:8 SRD 子区域失能位。对于域中的每一位,0,相应的子区域使能;1,相应的子区域失能。区域大小128字节和更少的不支持子区域,当对这样的区域写入属性时,写入SRD域为0x00。
位7:6 保留,硬件强制为0
位5:1 SIZE MPU保护区域的大小。最小的许可值为3。
SIZE域的值,SIZE域的值定义了由MPU_RNR明确的MPU内存区域大小,区域字节大小=2(SIZE+1)。最小的许可区域大小为32B,相应你给的SIZE值为4。
位0 ENABLE 区域使能位。