MPU是内核外设,想获取相关资料只能从内核手册查找
MPU功能仅F7/H7系列具备
内存保护单元(MPU介绍)
MPU基本介绍
说白了MPU用来管理内存和外设存储区的访问权限
MPU可配置保护8/16个内存区域(看芯片型号),每个区域最小要求256字节,且每个区域还可配置为8个子区域(大小一样)。
MPU设置内存的访问权限
NO_ACCESS 无访问
PRIV_RW 特权读写
PRIV_RW_URO 特权读写,禁止用户写访问 userReadOnly
FULL_ACCESS 全访问,特权和用户都可访问
PRIV_RO 仅支持特权读访问
PRIV_RO_URO 只读
配置好MPU,不得访问定义外的地址空间,也不得访问未经授权的区域,否则属于非法访问。会触发MemManage异常。
MPU配置内存区域的访问属性
三种内存类型:
普通内存:ROM、FLASH、SRAM, CPU对普通内存的加载或存储的程序代码可优化
外设内存:加载和存储严格次序进行
强顺序内存:严格按照代码执行
Cache是高级缓存,它的速度和CPU主存的速度是一致的。SRAM的速度只有CPU主存的一半,通过Cache缓存做到无差别访问。
普通内存,ROM\SRAM\FLASH这些,从CPU主存读数据,放到高级缓存Cache里面,再经过Buffer缓冲(可选),最后读到内存
设备内存,从CPU读数据,经过缓冲Buffer,读到内存
强顺序内存,直接从CPU读
芯片的总线错综复杂, 每条总线上都有多个主机Master和从机Slave,且同一个Slave可以由多个Master进行访问。比如SRAM,CPU可以访问,DMA也可以访问。
假如现在CPU把数据存放到了Cache里面,但SRAM还没有同步,这时候DMA直接就把SRAM读出来了,就会出现数据不一致。因此出现了数据共享。但开启共享就意味着关闭Cache。开启共享会导致SRAM直接从主存读数据,性能变慢。
C---Cache B---Buffer S---Share
Cache简介
Cache(高级缓存)是提升STM32性能的关键一步。
M7内核芯片做了一级Cache支持,Cache分为数据缓存D-Cache和指令缓存I-Cache。
Cache支持4种基本操作:1,使能;2,禁止; 3,清空; 4,无效化
数据缓存D-Cache是解决CPU加速访问SRAM
这里主频480MHz是针对H7系列来讲的
操作SRAM有三种方式,
- CPU直接读写SRAM、
- CPU操作Cache再读写SRAM、
- DMA读写SRAM
写操作:
CPU要写的SRAM区数据在Cache中已经开辟了对应的区域,这就叫写命中(Cache hit); 如果Cache里面没有开辟对应的区域怎么办,这就是所谓的写丢失(Cache Miss)。
读操作:
CPU要读取的SRAM区数据在Cache中已经加载好,叫读命中(Cache hit); 如果Cache里面没有,这就是读丢失(Cache Miss)。
保证cache有足够高的命中率,尽量少的cache miss,读/写速度会有比较大的提高。
读命中Cache hit 时直接从cache中读出数据即可。
读丢失Cache miss时,有两种处理方式,
一种是直接读 read through,略过Cache直接从内存SRAM读到CPU;
另一种是分配读 read allocate,把数据从内存加载到Cache,再从Cache读取。
写命中 Cache hit 时有两种处理方式:
一种是直接写 write through,直接写到内存SRAM并同时放到Cache 里;
另一种是分配写 write back,数据写到Cache,只有被更改时才写到SRAM里。
写丢失 Cache miss 时有两种处理方式:
一种是分配写 write allocate,先把数据写到Cache,然后更新到SRAM
另一种是不分配写 no write allocate,不经过Cache直接写到SRAM里。
数据不一致问题解决
1)设置共享属性
Cache相当于没有开启,性能优势体现不出来
2)软件进行Cache维护
调用Cache配置相关函数。
Cache支持4种基本操作:1,使能;2,禁止; 3,清空; 4,无效化
清空 Clean 和 无效化 Invalidation 用于处理数据不一致情况
Clean 清空:Cache已变化,SRAM数据未更新。
DMA搬运数据前,将Cache相对应数据更新到SRAM。
Invalidate无效化:SRAM数据已变化,Cache未更新。
DMA搬运数据后,Cache数据无效,需从SRAM获取。
在操作数据前调用一下函数,做一下数据统一。
MPU相关寄存器介绍
TEX用来设置Cache策略
Non-cacheable
正常读写操作,无cache
Write through, read allocated , no write allocate
写操作命中,用到WT;不命中,用到NWA 读操作没有命中,用到RA
Write back, read allocated , no write allocate
写操作命中,用到WB;不命中,用到NWA 读操作没有命中,用到RA
Write back, read allocated , write allocate
写操作命中,用到WB;不命中,用到WA 读操作没有命中,用到RA
MPU相关HAL库驱动介绍
/*MPU HAL库相关结构体*/
typedef struct {
uint8_t Enable; /* 区域使能/禁止 */ MPU_RASR
uint8_t Number; /* 区域编号 */ MPU_RBAR/RNR
uint32_t BaseAddress; /* 配置区域基地址 */ RBAR
uint8_t Size; /* 区域容量 */ RASR 下面都是
uint8_t SubRegionDisable; /* 子region失能位段设置 */
uint8_t TypeExtField; /* 类型扩展级别*/
uint8_t AccessPermission; /* 设置访问权限 */
uint8_t DisableExec; /* 允许/禁止取指*/
uint8_t IsShareable; /* 禁止/允许共享 */
uint8_t IsCacheable; /* 禁止/允许缓存 */
uint8_t IsBufferable; /* 禁止/允许缓冲 */
} MPU_Region_InitTypeDef;
void HAL_MPU_Enable (uint32_t MPU_Control);
设置MPU_CTRL寄存器:
操作PRIVDEFENA位,该位为0,禁止背景区,访问任何未使能MPU区域均会造成内存异常MemFault ;该位为1,使能背景区,特权级下可以正常访问任何未使能MPU区域
操作HFNMIENA位,该位为0,NMI不可屏蔽中断服务程序和硬件异常中断服务程序执行器件会强制关闭MPU ; 该位为1,会继续开启MPU。
MPU基本配置步骤
1、禁止MPU void HAL_MPU_Disable();
2、配置某个区域的MPU保护参数 通过调用HAL_MPU_ConfigRegion()函数去设置
3、使能MPU void HAL_MPU_Enable();
4、编写MemManage中断服务函数 void MemManage_Handler(void);