该篇主要:参考正点原子教程和安富莱教程
目录
[1. 内存保护单元(MPU)介绍(了解)](#1. 内存保护单元(MPU)介绍(了解))
[1.1. 内存保护单元(memory protection unit),简称:MPU](#1.1. 内存保护单元(memory protection unit),简称:MPU)
[1.1.1. MPU的功能:](#1.1.1. MPU的功能:)
[1.1.2. MPU的好处:](#1.1.2. MPU的好处:)
[1.2. MPU的使用:](#1.2. MPU的使用:)
[1.2.1. MPU配置保护内存区域:](#1.2.1. MPU配置保护内存区域:)
[1.2.1.1. 默认配置的保护区域:背景区,序号(-1)](#1.2.1.1. 默认配置的保护区域:背景区,序号(-1))
[1.2.1.2. 可配置的保护内存区域:0-15](#1.2.1.2. 可配置的保护内存区域:0-15)
[1.2.2. MPU设置内存区域的访问权限:MPU_REGION_XX_XX - XXX访问](#1.2.2. MPU设置内存区域的访问权限:MPU_REGION_XX_XX - XXX访问)
[1.2.3. MPU配置内存区域的访问属性:内存类型(Normal/Device/S..o..)](#1.2.3. MPU配置内存区域的访问属性:内存类型(Normal/Device/S..o..))
不同配置下(访问属性:内存类型,是否缓存,是否缓冲,是否共享)的性能情况:
[2. Cache简介(了解)](#2. Cache简介(了解))
[2.1. Cache简介:](#2.1. Cache简介:)
[2.2. Cache使用:对SRAM的-读操作、写操作](#2.2. Cache使用:对SRAM的-读操作、写操作)
[2.2.1. Core读Cache:读操作](#2.2.1. Core读Cache:读操作)
[2.2.2. Core写Cache:写操作](#2.2.2. Core写Cache:写操作)
[2.3. 数据不一致问题解决:](#2.3. 数据不一致问题解决:)
[3. MPU相关寄存器介绍(熟悉)](#3. MPU相关寄存器介绍(熟悉))
[3.1. MPU类型寄存器(MPU_TYPE):是否支持MPU,可配置8(F7)/16(H7)个保护区域](#3.1. MPU类型寄存器(MPU_TYPE):是否支持MPU,可配置8(F7)/16(H7)个保护区域)
[3.2. MPU控制寄存器(MPU_CTRL):设置MPU使能](#3.2. MPU控制寄存器(MPU_CTRL):设置MPU使能)
[3.3. MPU区域编号寄存器(MPU_RNR):选中要配置的(0-7(F7)/0-15(H7))区域](#3.3. MPU区域编号寄存器(MPU_RNR):选中要配置的(0-7(F7)/0-15(H7))区域)
[3.4. MPU基地址寄存器(MPU_RBAR):设置区域的起始地址](#3.4. MPU基地址寄存器(MPU_RBAR):设置区域的起始地址)
[3.5. MPU区域属性和容量寄存器(MPU_RASR):设置每个区域的属性【重点】](#3.5. MPU区域属性和容量寄存器(MPU_RASR):设置每个区域的属性【重点】)
[4. MPU相关HAL库驱动介绍(掌握)](#4. MPU相关HAL库驱动介绍(掌握))
[4.1. void HAL_MPU_Enable(uint32_t MPU_Control)](#4.1. void HAL_MPU_Enable(uint32_t MPU_Control))
[4.2. MPU HAL相关结构体-MPU_Region_InitTypeDef](#4.2. MPU HAL相关结构体-MPU_Region_InitTypeDef)
[5. MPU基本配置步骤(掌握)](#5. MPU基本配置步骤(掌握))
[5.1. 通过配置TEX C B S =>> 来配置内存类型,Cache策略](#5.1. 通过配置TEX C B S =>> 来配置内存类型,Cache策略)
[6. 编程实战------分析总框图!!!(掌握)](#6. 编程实战——分析总框图!!!(掌握))
[6.1. 实战代码](#6.1. 实战代码)
[6.2. 分析总框图(全屏看)](#6.2. 分析总框图(全屏看))
[7. H7的内存模型:H7内存默认映射与属性](#7. H7的内存模型:H7内存默认映射与属性)
[7.1. H7内存默认映射](#7.1. H7内存默认映射)
[8. 通过Keil Debug来查看MPU配置(MDK局限:只能显示8个区域)](#8. 通过Keil Debug来查看MPU配置(MDK局限:只能显示8个区域))
[8.1. 菜单栏打开:](#8.1. 菜单栏打开:)
[8.2. Memory Protection Unit (MPU)工具](#8.2. Memory Protection Unit (MPU)工具)
[8.3. 执行完MPU配置代码后,在工具内查看MPU配置情况](#8.3. 执行完MPU配置代码后,在工具内查看MPU配置情况)
[9. 课堂总结](#9. 课堂总结)
1. 内存保护单元(MPU)介绍(了解)
1.1. 内存保护单元(memory protection unit),简称:MPU
1.1.1. MPU的功能:
- 设置不同存储区域的存储器访问权限(特权级、用户级)
- 设置存储器(内存和外设)属性(可缓存、可缓冲、可共享)
1.1.2. MPU的好处:
MPU可作为管理员:管理权限、管理通行规则和路径
具体好处
1.2. MPU的使用:
1.2.1. MPU配置保护内存区域:
MPU可配置保护 8/16个 内存区域,每个区域 最小要求256字节 ,且每个区域还可配置为 8个子区域 (大小一样)
H7的存储器映射:
- STM32的地址空间共4GB(即有2^32个地址),需要将地址和内存映射起来。
- ST将这些地址划分成块,根据不同芯片中内存大小,映射长度也不同。
- 每个地址映射1个(u8)字节
- F7可配置8个保护内存区域,单个区域>256字节,并且可细分为8个子区域
- H7可配置16个保护内存区域,单个区域>256字节,并且可细分为8个子区域
16(>256,不一致)*8(相同大小)
此处配置内存区域的范围是整个单片机的内核地址
1.2.1.1. 默认配置的保护区域:背景区,序号(-1)
对没有配置保护规则的内存区域统一管理
1.2.1.2. 可配置的保护内存区域:0-15
- 编号为优先级:0~15 优先级越来越高
- (配置)规则:访问属性和权限
- 重叠或嵌套下,重叠部分按着优先级高的内存区配置规则执行
1.2.2. MPU设置内存区域的访问权限:MPU_REGION_XX_XX
- XXX访问
1.2.3. MPU配置内存区域的访问属性:内存类型(Normal/Device/S..o..)
Strongly ordered:强序
三种内存类型对应的情景:可缓存,可缓冲,可共享
三种内存类型的性能体现
- Normal
- Device
- S..o..
可共享:主机(Master)间数据同步
- 适用范围:
-
- 多主机访问单从机时
- 另一个主机的数据可能还在缓存中,未同步到从机上
- 那当前主机访问的从机数据就是有误的
- 共享使能:
-
- 开启共享 ≈ 关闭Cache
- 开关共享: 读操作速度影响大,写操作基本没有影响
不同配置下(访问属性:内存类型,是否缓存,是否缓冲,是否共享)的性能情况:
2. Cache简介(了解)
Cache:高级缓存,结合MPU使用(由MPU来指定内存区域的Cache策略)
F4有MPU但是没有Cache,所以一般不用MPU
2.1. Cache简介:
- Cache:高级缓存(因为处于CPU中,主频与CPU一致)
-
- 可实现
- Cache分为:
-
- 数据缓存D-Cache
-
-
- 可解决CPU加速访问SRAM
-
SRAM主频<CPU主频
-
- 指令缓存I-Cache
- Cache操作:由MPU指定区域的Cache策略
-
- 使能
- 禁止
- 清空
- 无效化
2.2. Cache使用:对SRAM的-读操作、写操作
- 读写命中:Cache hit
- 读写丢失:Cache miss
2.2.1. Core读Cache:读操作
Core可以理解为CPU
RT RA对应处理方式的缩写
2.2.2. Core写Cache:写操作
Core可以理解为CPU
WT WB NWA对应处理方式的缩写
2.3. 数据不一致问题解决:
- 设置共享
浪费了Cache资源
- 软件对Cache进行维护:在读写操作之前,调用解决对应情况的api
Cache配置相关函数:
SCB_EnableICache
SCB_DisableICache
SCB_InvalidateICache
SCB_EnableDCache
SCB_DisableDCache
SCB_InvalidateDCache
SCB_CleanDCache
SCB_CleanInvalidateDCache
SCB_InvalidateDCache_by_addr
SCB_CleanDCache_by_addr
SCB_CleanInvalidateDCache_by_addr
3. MPU相关寄存器介绍(熟悉)
Region:区域
3.1. MPU类型寄存器(MPU_TYPE):是否支持MPU,可配置8(F7)/16(H7)个保护区域
通过对DREGION的配置:MPU支持的区域数量
- 0:不支持MPU
- >0:支持MPU
-
- 0x08
- 0x10
3.2. MPU控制寄存器(MPU_CTRL):设置MPU使能
PRIVDEFENA位的影响:
M3:
H7:
3.3. MPU区域编号寄存器(MPU_RNR):选中要配置的(0-7(F7)/0-15(H7))区域
3.4. MPU基地址寄存器(MPU_RBAR):设置区域的起始地址
3.5. MPU区域属性和容量寄存器(MPU_RASR):设置每个区域的属性【重点】
XN位:指令访问
功能是在该区域能不能执行代码
AP位:访问权限,通常使用全访问
TEX位:设置Cache策略
不同配置下(访问属性:内存类型,是否缓存,是否缓冲,是否共享)的 性能情况 :
注意,性能由TEX,C,B,S等其他共同影响的
SRD位:使能当前区域的子区域
15:8的每一位,给0:子region使能,1:失能
直接给SRD0x00,代表全使能
4. MPU相关HAL库驱动介绍(掌握)
这里仅讲使能、配置(主要讲结构体)函数
4.1. void HAL_MPU_Enable(uint32_t MPU_Control)
MPU_HFNMI_PRIVDEF_NONE
MPU_HARDFAULT_NMI
MPU_PRIVILEGED_DEFAULT
MPU_HFNMI_PRIVDEF
使用:HAL_MPU_Enable(MPU_PRIVILEGED_DEFAULT);
4.2. MPU HAL相关结构体-MPU_Region_InitTypeDef
将配置好的该结构体对象,传入
5. MPU基本配置步骤(掌握)
5.1. 通过配置TEX C B S =>> 来配置内存类型,Cache策略
6. 编程实战------分析总框图!!!(掌握)
解读工程📎H750-实验12 内存保护(MPU)实验.zip
6.1. 实战代码
/**
****************************************************************************************************
* @file mpu.c
* @author 正点原子团队(ALIENTEK)
* @version V1.0
* @date 2020-03-22
* @brief MPU内存保护 驱动代码
* @license Copyright (c) 2020-2032, 广州市星翼电子科技有限公司
****************************************************************************************************
* @attention
*
* 实验平台:正点原子 STM32H750开发板
* 在线视频:www.yuanzige.com
* 技术论坛:www.openedv.com
* 公司网址:www.alientek.com
* 购买地址:openedv.taobao.com
*
* 修改说明
* V1.0 20200322
* 第一次发布
*
****************************************************************************************************
*/
#include "./SYSTEM/usart/usart.h"
#include "./SYSTEM/delay/delay.h"
#include "./BSP/LED/led.h"
#include "./BSP/MPU/mpu.h"
/**
* @brief 设置某个区域的MPU保护
* @param baseaddr: MPU保护区域的基址(首地址)
* @param size:MPU保护区域的大小(必须是32的倍数,单位为字节)
* @param rnum:MPU保护区编号,范围:0~15,最大支持16个保护区域
* @param de:禁止指令访问;0,允许指令访问;1,禁止指令访问
* @param ap:访问权限,访问关系如下:
* @arg 0,无访问(特权&用户都不可访问)
* @arg 1,仅支持特权读写访问
* @arg 2,禁止用户写访问(特权可读写访问)
* @arg 3,全访问(特权&用户都可访问)
* @arg 4,无法预测(禁止设置为4!!!)
* @arg 5,仅支持特权读访问
* @arg 6,只读(特权&用户都不可以写)
* @note 详见:STM32H7编程手册.pdf,4.6.6节,Table 91.
* @param sen:是否允许共用;0,不允许;1,允许
* @param cen:是否允许cache;0,不允许;1,允许
* @param ben:是否允许缓冲;0,不允许;1,允许
* @retval 0, 成功; 1, 错误;
*/
uint8_t mpu_set_protection(uint32_t baseaddr, uint32_t size, uint32_t rnum, uint8_t de, uint8_t ap, uint8_t sen, uint8_t cen, uint8_t ben)
{
MPU_Region_InitTypeDef mpu_region_init_handle; /* MPU初始化句柄 */
HAL_MPU_Disable(); /* 配置MPU之前先关闭MPU,配置完成以后在使能MPU */
mpu_region_init_handle.Enable = MPU_REGION_ENABLE; /* 使能该保护区域 */
mpu_region_init_handle.Number = rnum; /* 设置保护区域 */
mpu_region_init_handle.BaseAddress = baseaddr; /* 设置基址 */
mpu_region_init_handle.Size = size; /* 设置保护区域大小 */
mpu_region_init_handle.SubRegionDisable = 0X00; /* 禁止子区域 */
mpu_region_init_handle.TypeExtField = MPU_TEX_LEVEL0; /* 设置类型扩展域为level0 */
mpu_region_init_handle.AccessPermission = ap; /* 设置访问权限 */
mpu_region_init_handle.DisableExec = de; /* 是否允许指令访问 */
mpu_region_init_handle.IsShareable = sen; /* 是否允许共享 */
mpu_region_init_handle.IsCacheable = cen; /* 是否允许cache */
mpu_region_init_handle.IsBufferable = ben; /* 是否允许缓冲 */
HAL_MPU_ConfigRegion(&mpu_region_init_handle); /* 配置MPU */
HAL_MPU_Enable(MPU_PRIVILEGED_DEFAULT); /* 开启MPU */
return 0;
}
/**
* @brief 设置需要保护的存储块
* @note 必须对部分存储区域进行MPU保护,否则可能导致程序运行异常
* 比如MCU屏不显示,摄像头采集数据出错等等问题
* @param 无
* @retval 无
*/
void mpu_memory_protection(void)
{
/* 保护整个DTCM,共128K字节,允许指令访问,禁止共用,允许cache,允许缓冲 */
mpu_set_protection(0x20000000, MPU_REGION_SIZE_128KB, MPU_REGION_NUMBER1, MPU_INSTRUCTION_ACCESS_ENABLE,
MPU_REGION_FULL_ACCESS, MPU_ACCESS_NOT_SHAREABLE, MPU_ACCESS_CACHEABLE, MPU_ACCESS_BUFFERABLE);
/* 保护整个AXI SRAM,共512K字节,允许指令访问,禁止共用,允许cache,允许缓冲 */
mpu_set_protection(0x24000000, MPU_REGION_SIZE_512KB,MPU_REGION_NUMBER2, MPU_INSTRUCTION_ACCESS_ENABLE,
MPU_REGION_FULL_ACCESS, MPU_ACCESS_NOT_SHAREABLE, MPU_ACCESS_CACHEABLE, MPU_ACCESS_BUFFERABLE);
/* 保护整个SRAM1~SRAM3,共288K字节,允许指令访问,禁止共用,允许cache,允许缓冲 */
mpu_set_protection(0x30000000, MPU_REGION_SIZE_512KB,MPU_REGION_NUMBER3, MPU_INSTRUCTION_ACCESS_ENABLE,
MPU_REGION_FULL_ACCESS, MPU_ACCESS_NOT_SHAREABLE, MPU_ACCESS_CACHEABLE, MPU_ACCESS_BUFFERABLE);
/* 保护整个SRAM4,共64K字节,允许指令访问,禁止共用,允许cache,允许缓冲 */
mpu_set_protection(0x38000000, MPU_REGION_SIZE_64KB, MPU_REGION_NUMBER4, MPU_INSTRUCTION_ACCESS_ENABLE,
MPU_REGION_FULL_ACCESS, MPU_ACCESS_NOT_SHAREABLE, MPU_ACCESS_CACHEABLE, MPU_ACCESS_BUFFERABLE);
/* 保护MCU LCD屏所在的FMC区域,,共64M字节,允许指令访问,禁止共用,禁止cache,禁止缓冲 */
mpu_set_protection(0x60000000, MPU_REGION_SIZE_64MB, MPU_REGION_NUMBER5, MPU_INSTRUCTION_ACCESS_ENABLE,
MPU_REGION_FULL_ACCESS, MPU_ACCESS_NOT_SHAREABLE, MPU_ACCESS_NOT_CACHEABLE, MPU_ACCESS_NOT_BUFFERABLE);
/* 保护SDRAM区域,共64M字节,允许指令访问,禁止共用,允许cache,允许缓冲 */
mpu_set_protection(0XC0000000, MPU_REGION_SIZE_64MB, MPU_REGION_NUMBER6, MPU_INSTRUCTION_ACCESS_ENABLE,
MPU_REGION_FULL_ACCESS, MPU_ACCESS_NOT_SHAREABLE, MPU_ACCESS_CACHEABLE, MPU_ACCESS_BUFFERABLE);
/* 保护整个NAND FLASH区域,共256M字节,禁止指令访问,禁止共用,禁止cache,禁止缓冲 */
mpu_set_protection(0X80000000, MPU_REGION_SIZE_256MB, MPU_REGION_NUMBER7, MPU_INSTRUCTION_ACCESS_DISABLE,
MPU_REGION_FULL_ACCESS, MPU_ACCESS_NOT_SHAREABLE, MPU_ACCESS_NOT_CACHEABLE, MPU_ACCESS_NOT_BUFFERABLE);
}
/**
* @brief MemManage错误处理中断
* @note 进入此中断以后,将无法恢复程序运行!!
*
* @param 无
* @retval 无
*/
void MemManage_Handler(void)
{
LED1(0); /* 点亮LED1(GREEN LED) */
printf("Mem Access Error!!\r\n"); /* 输出错误信息 */
delay_ms(1000);
printf("Soft Reseting...\r\n"); /* 提示软件重启 */
delay_ms(1000);
NVIC_SystemReset(); /* 软复位 */
}
6.2. 分析总框图(全屏看)
可以通过微调整来实现程序高速运行,前提是稳定性
7. H7的内存模型:H7内存默认映射与属性
参考H7的编程手册📎STM32H743勘误手册.pdf📎STM32H7xx参考手册(V3中文版).pdf📎STM32H7xx参考手册.pdf📎STM32H7编程手册.pdf