【单片机外设】MPU及Cache学习与开发

该篇主要:参考正点原子教程和安富莱教程

安富莱_STM32-V7_MPU及Cache部分.pdf


目录

[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的好处:)

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..))

三种内存类型对应的情景:可缓存,可缓冲,可共享

可共享:主机(Master)间数据同步

不同配置下(访问属性:内存类型,是否缓存,是否缓冲,是否共享)的性能情况:

[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使能)

PRIVDEFENA位的影响:

M3:

H7:

[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):设置每个区域的属性【重点】)

XN位:指令访问

AP位:访问权限,通常使用全访问

TEX位:设置Cache策略

SRD位:使能当前区域的子区域

[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:区域

📎Cortex M3权威指南(中文).pdf

📎STM32H7编程手册.pdf

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

7.1. H7内存默认映射

8. 通过Keil Debug来查看MPU配置(MDK局限:只能显示8个区域)

8.1. 菜单栏打开:

8.2. Memory Protection Unit (MPU)工具

8.3. 执行完MPU配置代码后,在工具内查看MPU配置情况

9. 课堂总结

内存保护(MPU)实验(课堂总结).pdf

相关推荐
机智的叉烧37 分钟前
前沿重器[57] | sigir24:大模型推荐系统的文本ID对齐学习
人工智能·学习·机器学习
量子-Alex2 小时前
【多模态聚类】用于无标记视频自监督学习的多模态聚类网络
学习·音视频·聚类
吉大一菜鸡2 小时前
FPGA学习(基于小梅哥Xilinx FPGA)学习笔记
笔记·学习·fpga开发
森旺电子2 小时前
51单片机仿真摇号抽奖机源程序 12864液晶显示
单片机·嵌入式硬件·51单片机
爱吃西瓜的小菜鸡4 小时前
【C语言】判断回文
c语言·学习·算法
不过四级不改名6774 小时前
蓝桥杯嵌入式备赛教程(1、led,2、lcd,3、key)
stm32·嵌入式硬件·蓝桥杯
小A1595 小时前
STM32完全学习——SPI接口的FLASH(DMA模式)
stm32·嵌入式硬件·学习
Rorsion5 小时前
各种电机原理介绍
单片机·嵌入式硬件
岁岁岁平安5 小时前
spring学习(spring-DI(字符串或对象引用注入、集合注入)(XML配置))
java·学习·spring·依赖注入·集合注入·基本数据类型注入·引用数据类型注入
武昌库里写JAVA5 小时前
Java成长之路(一)--SpringBoot基础学习--SpringBoot代码测试
java·开发语言·spring boot·学习·课程设计