1. MPU - 内存保护单元
-
MPU:(Memory Protection Unit,内存保护单元),是一种硬件机制,用于保护处理器访问内存时产生的错误或意外情况。
-
MPU的作用:MPU 可以使用一组规则来限制某些内存区域的读、写或执行权限。这些规则被称为“MPU区域”。MPU 可以将内存分成多个区域,并为每个区域分配访问权限。这些权限包括读、写、执行和访问级别等。通过使用MPU,可以实现对特定区域的访问限制,保护系统的重要数据和代码。
-
内存映射:指将STM32H7芯片中的各种硬件资源,如存储器、外设和寄存器等,映射到特定的内存地址空间中,以便CPU可以通过读写内存的方式来访问这些硬件资源。在STM32H7中,所有的硬件资源都被映射到一段连续的内存地址空间中,这段地址空间称为内存映射区域;
在STM32H7内32 位 CM7 内核整体可以寻址的0 到 2^32 -1
共计 4GB 的寻址空间。通过这些地址可以访问 RAM、Flash、外设等。下图是内存映射的轮廓图,IC 厂家使用时,再做细分,添加相应的硬件功能:
-
MPU 的功能实现:MPU 可以独立配置保护 16 个内存区域,每个区域最小要求 256 字节,每个区域还可以配置为 8 个子区域;由于子区域一般都大小相同,这样每个子区域的大小就是 32 字节(256/8=32),正好跟 Cache 的 Cache Line 大小一样;
-
16个内存区的优先级:MPU 可以配置的 16 个内存区的序号范围是 0 到 15,还有默认区 default region,也叫作背景区,序号-1;由于这些内存区可以嵌套和重叠,所以这些区域在嵌套或者重叠时有个优先级的问题。序号15 的优先级最高,以此递减,序号-1,即背景区的优先级最低。这些优先级是固定的;
- 关于内存区的重叠优先级问题:如下所示共有 7 个区,背景区和序号 0-5 的区。内存区 4 跟内存区 0 和 1 有重叠部分,那么重叠部分将按照内存区 4 的配置规则执行(因为内存区 4的优先级更高);内存区 5 被完全包含在内存区3 里面,那么这部分内存区将按照内存区 5 的配置规则执行。
- 三种可配置的内存类型:STM32H7的MPU 提供了三种可配置的内存类型,分别是:
-
Strongly Ordered Memory(强序内存):这种内存类型适用于访问特定的外设寄存器和共享内存区域等,它的访问顺序不能被改变。在这种内存类型下,访问该内存区域的数据会直接被发送到总线上,而不会被缓存。
-
Device Memory(设备内存):这种内存类型适用于访问外设的数据缓冲区和寄存器等,它的访问顺序可以被改变。在这种内存类型下,访问该内存区域的数据会被缓存,但缓存策略不同于普通的数据缓存。
-
Normal Memory(普通内存):这种内存类型适用于访问普通的数据和程序代码等,它的访问顺序可以被改变。在这种内存类型下,访问该内存区域的数据会被缓存,并且可以使用通用的缓存策略,如写回、写直通等。
通过使用这三种可配置的内存类型,STM32H7的MPU可以为不同的内存区域分配不同的访问权限,并控制不同类型的内存访问。例如,对于设备内存和强序内存,MPU可以限制对其的访问权限,防止程序对系统的恶意操作;而对于普通内存,MPU可以使用缓存策略来提高访问速度和效率。
1.1 MPU 的寄存器与对应库参数
1.1.1 MPU_RASR
寄存器
STM32H7的MPU中的MPU_RASR(Region Attribute and Size Register,区域属性和大小寄存器)寄存器用于配置MPU内存区域的属性和大小。MPU_RASR寄存器的位域结构如下:
typedef struct {
uint32_t ENABLE:1; // 区域使能位,最低位
uint32_t SIZE:5; // 区域大小
uint32_t SRD:8; // 禁用子区域位
uint32_t B:1; // 可缓存
uint32_t C:1; // 可写回(Cacheable)
uint32_t S:1; // 可共享
uint32_t TEX:3; // 类型扩展域
uint32_t AP:3; // 访问权限
uint32_t XN:1; // 禁止执行
uint32_t res1:1; // 保留位
uint32_t SBO:1; // 应该为1
uint32_t res2:6; // 保留位,最高位
} MPU_RASR_TypeDef;
-
XN
位:XN=0
表示使能指令提取,即这块内存区可以执行程序代码,XN=1
表示禁止指令提取,即这块内存
区禁止执行程序代码。对应的 HAL 库 MPU 参数如下:
/** @defgroup CORTEX_MPU_Instruction_Access CORTEX MPU Instruction Access
* @{
*/
#define MPU_INSTRUCTION_ACCESS_ENABLE ((uint8_t)0x00)
#define MPU_INSTRUCTION_ACCESS_DISABLE ((uint8_t)0x01)
-
AP
位::其功能如下:
对应的 HAL 库 MPU 参数如下
/** @defgroup CORTEX_MPU_Region_Permission_Attributes CORTEX MPU Region Permission Attributes
* @{
*/
#define MPU_REGION_NO_ACCESS ((uint8_t)0x00)
#define MPU_REGION_PRIV_RW ((uint8_t)0x01)
#define MPU_REGION_PRIV_RW_URO ((uint8_t)0x02)
#define MPU_REGION_FULL_ACCESS ((uint8_t)0x03)
#define MPU_REGION_PRIV_RO ((uint8_t)0x05)
#define MPU_REGION_PRIV_RO_URO ((uint8_t)0x06)
-
TEX
位:这仅关注 TEX = 0b000 和 0b001,其它的 TEX 配置基本用不到,其功能如下:
-
SRD
位:这个位用于控制内存区的子区域,使用的是 bit[15:8],共计 8 个 bit,一个 bit 控制一个子区域,0表示使能此子区域,1 表示禁止此子区域。一般情况,基本不使用子区域的禁止功能,所以配置 HAL 库的 SubRegionDisable 参数时,直接取值 0x00 即可,表示 8 个子区域均使能。
1.1.2 MPU 的配置函数
HAL 库的 stm32h7xx_hal_cortex.c
文件为 MPU 的配置提供了三个函数:HAL_MPU_Disable
、HAL_MPU_Enable
和HAL_MPU_ConfigRegion
:
-
HAL_MPU_Disable
:该函数用于禁用MPU,函数原型如下:
void HAL_MPU_Disable(void);
该函数没有参数,也没有返回值。在函数内部,它会通过清除MPU的控制寄存器中的MPU_CTRL_ENABLE位来禁用MPU,代码如下:
MPU->CTRL &= ~MPU_CTRL_ENABLE_Msk;
-
HAL_MPU_Enable
:该函数用于使能MPU,函数原型如下:
void HAL_MPU_Enable(void);
该函数没有参数,也没有返回值。在函数内部,它会通过设置MPU的控制寄存器中的MPU_CTRL_ENABLE位来使能MPU,代码如下:
MPU->CTRL |= MPU_CTRL_ENABLE_Msk;
-
HAL_MPU_ConfigRegion
:该函数用于配置MPU的某个区域,函数原型如下:
HAL_StatusTypeDef HAL_MPU_ConfigRegion(MPU_Region_InitTypeDef *MPU_Init);
该函数接收一个MPU_Region_InitTypeDef
类型的结构体指针作为参数,该结构体定义了要配置的MPU 区域的各个参数,包括区域编号、起始地址、大小、访问权限等等。
函数返回值为HAL_StatusTypeDef
类型,表示函数执行结果的状态,包括HAL_OK
、HAL_ERROR
等等。
在函数内部,首先会检查传入的参数是否合法,如果不合法则返回HAL_ERROR;否则,根据传入的参数配置MPU的区域,代码如下:
if((MPU_Init->Number < 0U) || (MPU_Init->Number > 7U))
{
return HAL_ERROR;
}
else
{
MPU->RNR = MPU_Init->Number;
MPU->RBAR = MPU_Init->BaseAddress;
MPU->RASR = MPU_Init->Attribute;
return HAL_OK;
}
其中,MPU_Init->Number
表示要配置的MPU区域的编号,MPU_Init->BaseAddress
表示要配置的MPU区域的起始地址,MPU_Init->Attribute
表示要配置的MPU区域的访问属性。
2. Cache - 缓存
-
Cache:Cache,即缓存是一种高速存储器,它可以暂存处理器访问的数据,以提高数据访问的速度和效率。缓存大小越大,系统的执行效率越高,但是也会占用更多的芯片面积和功耗。
当前芯片厂商出的 M7 内核芯片基本都做了一级 Cache 支持, Cache 又分数据缓存 D-Cache 和指令缓冲 I-Cache,这里只看数据缓存D-Cache,其大小是16kB.
STM32H7的主频是 400MHz,除了 TCM 和 Cache 以 400MHz工作,其它 AXI SRAM,SRAM1,SRAM2 等都是以 200MHz 工作。数据缓存 D-Cache 就是解决 CPU加速访问 SRAM. -
对于使能了 Cache 的 SRAM 区,要分读/写两种情况考虑:
- 读操作:如果 CPU 要读取的 SRAM 区数据在 Cache 中已经加载好,这就叫读命中(Cache hit),如果 Cache
里面没有,就是所谓的读 Cache Miss. - 写操作:如果 CPU 要写的 SRAM 区数据在 Cache 中已经开辟了对应的区域(专业词汇叫 Cache Line,以 32
字节为单位),这就叫写命中(Cache hit),如果 Cache 里面没有开辟对应的区域,就是所谓的写 Cache Miss.
- 读操作:如果 CPU 要读取的 SRAM 区数据在 Cache 中已经加载好,这就叫读命中(Cache hit),如果 Cache
2.1 Cache 的配置
Cache 的配置是通过 MPU 来设置的,通常只用到下几种方式:
其中的 TEX
是用来设置 Cache 策略的, C
是 Cache, B
是缓冲用来配合 Cache 设置的,而 S
是共享,
用来解决多总线或者多核访问时的同步问题。
2.2 四种 Cache(MPU) 配 置的读写操作流程
- Cache 支持的策略有如下四种:
M7 内核只要开启了 Cache,read allocate 就是开启的。文章来源:https://www.toymoban.com/news/detail-597513.html
-
Non-cacheable
:正常的读写操作,无 Cache,即关闭Cache. 以下四种 MPU 配置都表示Non-cacheable
:
文章来源地址https://www.toymoban.com/news/detail-597513.html
-
Write back、read allocate、no write allocate
:- 使能了此配置的 SRAM 缓冲区写操作:如果 CPU 要写的 SRAM 区数据在 Cache 中已经开辟了对应的区域,那么会同时写到 Cache 里面和SRAM 里面;如果没有,就用到配置
no write allocate
,意思就是 CPU 会直接往 SRAM 里面写数据,而不再需要在 Cache 里面开辟空间。
在写 Cache 命中的情况下,这个方式的优点是 Cache 和 SRAM 的数据同步更新了,没有多总线访问造成的数据一致性问题。缺点也明显,Cache 在写操作上无法有效发挥性能。 - 使能了此配置的 SRAM 缓冲区读操作:如果 CPU 要读取的 SRAM 区数据在 Cache 中已经加载好,就可以直接从 Cache 里面读取。如果没有,就用到配置
read allocate
,意思就是在 Cache 里面开辟区域,将 SRAM 区数据加载进来,后续的操作,CPU 可以直接从 Cache 里面读取。
- 使能了此配置的 SRAM 缓冲区写操作:如果 CPU 要写的 SRAM 区数据在 Cache 中已经开辟了对应的区域,那么会同时写到 Cache 里面和SRAM 里面;如果没有,就用到配置
到了这里,关于STM32【H7】理论——MPU、Cache的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!