【单片机外设】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

相关推荐
单片机社区3 小时前
随笔十七、eth0单网卡绑定双ip的问题
网络·嵌入式硬件·网络协议·udp·智能路由器
梦云澜3 小时前
论文阅读(五):乳腺癌中的高斯图模型和扩展网络推理
论文阅读·人工智能·深度学习·学习
王磊鑫3 小时前
计算机组成原理(2)王道学习笔记
笔记·学习
LS_learner4 小时前
0.91英寸OLED显示屏一种具有小尺寸、高分辨率、低功耗特性的显示器件
嵌入式硬件
漫无目的行走的月亮4 小时前
51单片机开发:独立键盘实验
嵌入式硬件·51单片机
汉克老师4 小时前
GESP2024年3月认证C++六级( 第三部分编程题(1)游戏)
c++·学习·算法·游戏·动态规划·gesp6级
东京老树根5 小时前
Excel 技巧21 - Excel中整理美化数据实例,Ctrl+T 超级表格(★★★)
笔记·学习·excel
CPU NULL6 小时前
新版IDEA创建数据库表
java·数据库·spring boot·sql·学习·mysql·intellij-idea
jacob~7 小时前
c++学习第十二天
学习
_Eden_7 小时前
Ansible入门学习之Playbook快速入门
学习·ansible