一、STM32H7 系列 MCU 的 MPU 介绍**
参考资料:PM0253 STM32F7 Series and STM32H7 Series Cortex®-M7 processor programming manualV5.0
1.1 MPU 的作用
防止不受信任的应用程序访问受保护的内存区域; 防止用户应用程序破坏操作系统使用的数据;通过阻止任务访问其它任务的数据区;允许将内存区域定义为只读,以便保护重要数据;检测意外的内存访问。 简单的说就是内存保护、外设保护和代码访问保护。
1.2 MPU 可配置的三种内存类型
1)Normal memory
CPU 以最高效的方式加载和存储字节、半字和字,对于这种内存区,CPU 的加载或存储不一定要按照程序列出的顺序执行。
2)Device memory
对于这种类型的内存区,加载和存储要严格按照次序进行,这样是为了确保寄存器按照正确顺序设置。
3)Strongly ordered memory
程序完全按照代码顺序执行,CPU 需要等待当前的加载/存储指令执行完毕后才执行下一条指令。这样会导致性能下降。
1.3 MPU 的使用
MPU 可以配置保护 16 个内存区域(这 16 个内存域是独立配置的),每个区域最小要求 256 字节,每个区域还可以配置为 8 个子区域。由于子区域一般都相同大小,这样每个子区域的大小就是 32 字节,正好跟 Cache 的 Cache Line 大小一样。
使用时把一段连续的内存区配置为一个 MPU 保护区域,然后再配置这个 MPU 保护区域的特性。比如 128KB 的 DTCM、64KB 的 SRAM4、32MB 的 SDRAM。MPU 保护区域的特性使用 MPU_RASR 寄存器来配置(PM0253.Rev 5, page227),描述如图 1 所示。
1)XN:用于控制这个 MPU 保护区域能否执行程序代码。
2)AP:用于控制这个 MPU 保护区域的特权级和非特权级的读写访问权限,具体如图 2 所示。
3)TEX、C、B、S:H7 支持 4 种 Cache 策略,这几位就是用来控制这个 MPU 保护区域使用哪一种,如图 3 所示。
S 位用于解决多总线或者多核访问的共享问题,一般不要开启。
4)SRD:这个位用于控制内存区的子区域 ,使用的是 bit[15:8],共计 8 个 bit,一个 bit 控制一个子区域, 0 表示使能此子区域, 1 表示禁止。一般情况下,取值 0x00,表示 8 个子区域都使能。
5)SIZE:配置这个 MPU 保护区域的大小。
二、STM32H7 系列 MCU 的 Cache 介绍
Cache 又分数据缓存 D-Cache 和指令缓冲 I-Cache,STM32H7 的数据缓存和指令缓存大小都是 16KB。STM32H7 最高主频是 480MHz,除了 TCM 和 Cache 以 480MHz 工作,其它 AXI SRAM,SRAM1,SRAM2 等都是以 240MHz 工作。数据缓存 D-Cache 就是解决 CPU 加速访问 SRAM。
如果每次 CPU 要读写 SRAM 区的数据,都能够在 Cache 里面进行,自然是最好的,实现了 240MHz 到 480MHz 的飞跃,实际是做不到的,因为数据 Cache 只有 16KB 大小,总有用完的时候。
2.1 Cache 的操作
读操作: 如果 CPU 要读取的 SRAM 区数据在 Cache 中已经加载好,这就叫读命中(Cache hit),如果 Cache 里面没有怎么办,这就是所谓的读 Cache Miss。
写操作: 如果 CPU 要写的 SRAM 区数据在 Cache 中已经开辟了对应的区域(专业词汇叫 Cache Line,以 32 字节为单位),这就叫写命中(Cache hit),如果 Cache 里面没有开辟对应的区域怎么办,这就是所谓的写 Cache Miss。
2.2 H7 支持的 Cache 策略
<回写:如果 Cache 中有,写数据只写到 Cache,不写到 RAM。>
<透写:如果 Cache 中有,写数据也要同时写到 Cache 和 RAM。>
<write allocate:写数据时,如果 Cache 中没有,那么就要在 Cache 中开辟一个空间,把数据写入 Cache,同时把 RAM 中的相邻数据加载进来填充 Cache。>
<no write allocate:写数据时,如果 Cache 中没有,那么把数据直接写入 RAM。>
<read allocate:读数据时,如果 Cache 中没有,那么就要在 Cache 中开辟一个空间,把数据从 RAM 中加载进来,后续的读操作,就可以直接从 Cache 中读取了。>
<no read allocate:读数据时,如果 Cache 中没有,那么直接从 RAM 中读。>
2.3 Cache 引入的风险
从上面的图就看出来使用 Cache 的风险,因为 DMA 是直接与 SRAM 交换数据的,而 CPU 与 SRAM 之间隔了一个 Cache,如果 DMA 更新了某个数据到 SRAM,CPU 要去访问,而恰好 Cache 中有,那么 CPU 就不会去 SRAM 中拿,就会拿到 Cache 中已经过时的数据。因此使用了 DMA 的内存区要配置为无 Cache 或者拿数据前清一次 Cache。
2.4 相关函数
CMSIS 软件包的 core_cm7.h 文件为 Cache 的配置提供了 11 个函数:
SCB_EnableICache(void) :用于使能指令 Cache,系统上电后优先初始化即可。
SCB_DisableICache(void) :用于禁止指令 Cache。
SCB_InvalidateICache(void) :用于将指令 Cache 无效化,无效化的意思是将 Cache Line 标记为无效,等同于删除操作。这样 Cache 空间就都腾出来了,可以加载新的指令。
SCB_EnableDCache(void) :用于使能数据 Cache,系统上电后优先初始化即可。
SCB_DisableDCache(void) :用于禁止数据 Cache。
SCB_InvalidateDCache(void) :用于将数据 Cache 无效化,无效化的意思是将 Cache Line 标记为无效,等同于删除操作。这样 Cache 空间就都腾出来了,可以加载新的数据。
SCB_CleanDCache(void):用于将数据 Cache 清除,清除的意思是将 Cache Line 中标记为 dirty 的数据写入到相应的存储区。
SCB_CleanInvalidateDCache(void) :此函数是前面两个函数 SCB_InvalidateDCache 和 SCB_CleanDCache 的二合一。将 Cache Line 中标记为 dirty 的数据写入到相应的存储区后,再将 Cache Line 标记为无效,表示删除。这样 Cache 空间就都腾出来了,可以加载新的数据。
SCB_InvalidateDCache_by_Addr(uint32_t *addr,int32_t dsize):可以指定地址和存储区大小,地址要 32 字节对齐,大小要是 32 字节的整数倍。用于将数据 Cache 无效化,无效化的意思是将 Cache Line 标记为无效,等同于删除操作。这样 Cache 空间就都腾出来了,可以加载新的数据。
SCB_CleanDCache_by_Addr(uint32_t *addr,int32_t dsize):可以指定地址和存储区大小,地址要 32 字节对齐,大小要是 32 字节的整数倍。用于将数据 Cache 清除,清除的意思是将 Cache Line 中标记为 dirty 的数据写入到相应的存储区。
SCB_CleanInvalidateDCache_by_Addr(uint32_t *addr,int32_t dsize):可以指定地址和存储区大小,地址要 32 字节对齐,大小要是 32 字节的整数倍。将 Cache Line 中标记为 dirty 的数据写入到相应的存储区后,再将 Cache Line 标记为无效,表示删除。这样 Cache 空间就都腾出来了,可以加载新的数据。
三、MPU 和 Cache 的 HAL 配置例程
//设置某个区域的 MPU 保护
//baseaddr:MPU 保护区域的基址(首地址)
//size:MPU 保护区域的大小(必须是 32 的倍数,单位为字节),可设置的值参考:CORTEX_MPU_Region_Size
//rnum:MPU 保护区编号,范围:0~7,最大支持 8 个保护区域,可设置的值参考:CORTEX_MPU_Region_Number
//ap:访问权限,访问关系如下:可设置的值参考:CORTEX_MPU_Region_Permission_Attributes
//0,无访问(特权&用户都不可访问)
//1,仅支持特权读写访问
//2,禁止用户写访问(特权可读写访问)
//3,全访问(特权&用户都可访问)
//4,无法预测(禁止设置为 4!!!)
//5,仅支持特权读访问
//6,只读(特权&用户都不可以写)
//详见:STM32F7 Series Cortex-M7 processor programming manual.pdf,4.6 节,Table 89.
//sen:是否允许共用;0,不允许;1,允许
//cen:是否允许 catch;0,不允许;1,允许
//返回值;0,成功.
// 其他,错误.
u8 MPU_Set_Protection(u32 baseaddr,u32 size,u32 rnum,u32 ap,u8 sen,u8 cen,u8 ben,u8 Tex)
{
MPU_Region_InitTypeDef MPU_Initure;
HAL_MPU_Disable(); //配置 MPU 之前先关闭 MPU,配置完成以后在使能 MPU
MPU_Initure.Enable=MPU_REGION_ENABLE; //使能该保护区域
MPU_Initure.Number=rnum; //设置保护区域
MPU_Initure.BaseAddress=baseaddr; //设置基址
MPU_Initure.Size=size; //设置保护区域大小
MPU_Initure.SubRegionDisable=0X00; //禁止子区域
MPU_Initure.TypeExtField=Tex; //设置类型扩展域
MPU_Initure.AccessPermission=(u8)ap; //设置访问权限,
MPU_Initure.DisableExec=MPU_INSTRUCTION_ACCESS_ENABLE; //允许指令访问(允许读取指令)
MPU_Initure.IsShareable=sen; //是否允许共用
MPU_Initure.IsCacheable=cen; //是否允许 cache
MPU_Initure.IsBufferable=ben; //是否允许缓冲
HAL_MPU_ConfigRegion(&MPU_Initure); //配置 MPU
HAL_MPU_Enable(MPU_PRIVILEGED_DEFAULT); //开启 MPU
return 0;
}
//设置需要保护的存储块
//必须对部分存储区域进行 MPU 保护,否则可能导致程序运行异常
//比如 MCU 屏不显示,摄像头采集数据出错等等问题...
void MPU_Memory_Protection(void) //特意把 SRAM4 设置为不允许 cache,使用 DMA 的变量可以放在这里。但要注意相应 DMA 能否访问 SRAM4
{
MPU_Set_Protection(0x20000000,MPU_REGION_SIZE_128KB,MPU_REGION_NUMBER1,MPU_REGION_FULL_ACCESS,0,1,1,MPU_TEX_LEVEL0); //保护整个 DTCM,共 128K 字节,禁止共用,允许 cache,允许缓冲
MPU_Set_Protection(0x24000000,MPU_REGION_SIZE_512KB,MPU_REGION_NUMBER2,MPU_REGION_FULL_ACCESS,0,1,1,MPU_TEX_LEVEL0); //保护整个内部 SRAM,包括 SRAM1,SRAM2 和 DTCM,共 512K 字节
MPU_Set_Protection(0x30000000,MPU_REGION_SIZE_512KB,MPU_REGION_NUMBER3,MPU_REGION_FULL_ACCESS,0,1,1,MPU_TEX_LEVEL0); //保护整个 SRAM1~SRAM3,共 288K 字节,禁止共用,允许 cache,允许缓冲
MPU_Set_Protection(0x38000000,MPU_REGION_SIZE_64KB ,MPU_REGION_NUMBER4,MPU_REGION_FULL_ACCESS,0,0,1,MPU_TEX_LEVEL0); //保护整个 SRAM4,共 64K 字节,禁止共用,不允许 cache,允许缓冲
MPU_Set_Protection(0x60000000,MPU_REGION_SIZE_64MB ,MPU_REGION_NUMBER5,MPU_REGION_FULL_ACCESS,0,0,0,MPU_TEX_LEVEL0); //保护 MCU LCD 屏所在的 FMC 区域,,共 64M 字节,禁止共用,禁止 cache,禁止缓冲
MPU_Set_Protection(0xC0000000,MPU_REGION_SIZE_64MB ,MPU_REGION_NUMBER6,MPU_REGION_FULL_ACCESS,0,1,1,MPU_TEX_LEVEL0); //保护 SDRAM 区域,共 32M 字节,禁止共用,允许 cache,允许缓冲
}
四、其他说明
值得一提的是,LTDC 也是直接从 RAM 拿数据的,如果使用了 GUI(比如 EMWIN),显示数据可能会暂存在 Cache,而 LTDC 直接从 RAM 拿数据,就可能造成画面撕裂、重影、斑点之类的问题。解决方法是,把显存设置成透写。
从上面的图可以看到,Cache 是在 M7 那个框里面的。而框外面的外设都可以直接与 RAM 交换数据,因此使用外设操作数据时都要考虑一下 Cache 的影响,不然异常可能难以预料。
以上即是 STM32H7 系列 MCU 的 MPU 和 Cache 的简单介绍文章来源:https://www.toymoban.com/news/detail-789606.html
文章转载https://www.sunev.cn/embedded/934.html文章来源地址https://www.toymoban.com/news/detail-789606.html
到了这里,关于STM32H7系列MCU的MPU和Cache功能介绍的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!