【STM32H7教程】第23章 STM32H7的MPU内存保护单元(重要)

发布者:数据旅人最新更新时间:2019-08-26 来源: eefocus关键字:STM32H7  MPU  内存保护单元 手机看文章 扫描二维码
随时随地手机看文章

23.1 初学者重要提示


本章节主要是为下一章Cache的讲解做个铺垫,需要初学者把本章节涉及到的基础知识点掌握了。


初学MPU时,可能有些知识点无法一下子就搞明白,在后续章节的各种应用后,会有一个较深的认识。这个知识点基本会贯穿整个教程。


23.2 MPU简介


MPU可以将memory map内存映射区分为多个具有一定访问规则的区域,通过这些规则可以实现如下功能:


  防止不受信任的应用程序访问受保护的内存区域。

  防止用户应用程序破坏操作系统使用的数据。

  通过阻止任务访问其它任务的数据区。

  允许将内存区域定义为只读,以便保护重要数据。

  检测意外的内存访问。

 

简单的说就是内存保护、外设保护和代码访问保护。


内存映射


内存映射就是32位的CM7内核整体可以寻址的0 到2^32 -1共计4GB的寻址空间。通过这些地址可以访问RAM、Flash、外设等。下面是内存映射的轮廓图,IC厂家使用时,再做细分,添加相应的硬件功能。


23.3 MPU的功能实现

MPU可以配置保护16个内存区域(这16个内存域是独立配置的),每个区域最小要求256字节,每个区域还可以配置为8个子区域。由于子区域一般都相同大小,这样每个子区域的大小就是32字节,正好跟Cache的Cache Line大小一样。


MPU可以配置的16个内存区的序号范围是0到15,还有默认区 default region,也叫作背景区,序号-1。由于这些内存区可以嵌套和重叠,所以这些区域在嵌套或者重叠的时候有个优先级的问题。序号15的优先级最高,以此递减,序号-1,即背景区的优先级最低。这些优先级是固定的。


下面通过一个具体的实例帮助大家理解。如下所示共有7个区,背景区和序号0-5的区。内存区4跟内存区0和1有重叠部分,那么重叠部分将按照内存区4的配置规则执行;内存区5被完全包含在内存区3里面,那么这部分内存区将按照内存区5的配置规则执行。


23.4 MPU可以配置的三种内存类型

MPU可以配置的三种内存类型如下:


  Normal memory

CPU以最高效的方式加载和存储字节、半字和字,对于这种内存区,CPU的加载或存储不一定要按照程序列出的顺序执行。


  Device memory

对于这种类型的内存区,加载和存储要严格按照次序进行,这样是为了确保寄存器按照正确顺序设置。


  Strongly ordered memory

程序完全按照代码顺序执行,CPU需要等待当前的加载/存储指令执行完毕后才执行下一条指令。这样会导致性能下降。


23.5 MPU的寄存器和对应的库参数

关于MPU的寄存器介绍在STM32H7的编程手册有专门的讲解说明,我们这里重点讲解寄存器MPU_RASR和控制寄存器,此寄存器的定义如下:


23.5.1 RASR寄存器的XN位

XN=0表示使能指令提取,即这块内存区可以执行程序代码,XN=1表示禁止指令提取,即这块内存区禁止执行程序代码。


对应的HAL库MPU参数如下:


/** @defgroup CORTEX_MPU_Instruction_Access CORTEX MPU Instruction Access

  * @{

  */

#define  MPU_INSTRUCTION_ACCESS_ENABLE      ((uint8_t)0x00)

#define  MPU_INSTRUCTION_ACCESS_DISABLE     ((uint8_t)0x01)

23.5.2 RASR寄存器的AP位

AP的具体定义如下:


这几个参数对应的HAL库MPU参数如下:


/** @defgroup CORTEX_MPU_Region_Permission_Attributes CORTEX MPU Region Permission Attributes

  * @{

  */

#define  MPU_REGION_NO_ACCESS      ((uint8_t)0x00)

#define  MPU_REGION_PRIV_RW        ((uint8_t)0x01)

#define  MPU_REGION_PRIV_RW_URO    ((uint8_t)0x02)

#define  MPU_REGION_FULL_ACCESS    ((uint8_t)0x03)

#define  MPU_REGION_PRIV_RO        ((uint8_t)0x05)

#define  MPU_REGION_PRIV_RO_URO    ((uint8_t)0x06)

23.5.3 RASR寄存器的TEX,C,B和S位

(注,这几个位非常重要,当前先了解知识点即可,下个章节专门讲解具体的作用)


TEX,C,B和S的定义如下,这仅关注TEX = 0b000和0b001,其它的TEX配置基本用不到。


TEX用于配置Cache策略,支持如下四种情况,需要配合C和B位的配置才能实现。

TEX对应的HAL库MPU参数给了三个,实际应用中仅用到前两个MPU_TEX_LEVEL0和MPU_TEX_LEVEL1


/** @defgroup CORTEX_MPU_TEX_Levels MPU TEX Levels

  * @{

  */

#define  MPU_TEX_LEVEL0    ((uint8_t)0x00)

#define  MPU_TEX_LEVEL1    ((uint8_t)0x01)

#define  MPU_TEX_LEVEL2    ((uint8_t)0x02)

C位对应的HAL库MPU参数如下,用于使能或者禁止Cache。


/** @defgroup CORTEX_MPU_Access_Cacheable CORTEX MPU Instruction Access Cacheable

  * @{

  */

#define  MPU_ACCESS_CACHEABLE         ((uint8_t)0x01)

#define  MPU_ACCESS_NOT_CACHEABLE     ((uint8_t)0x00)

B位对应的HAL库MPU参数如下,用于配合C位实现Cache模式下是否使用缓冲。


/** @defgroup CORTEX_MPU_Access_Bufferable CORTEX MPU Instruction Access Bufferable

  * @{

  */

#define  MPU_ACCESS_BUFFERABLE         ((uint8_t)0x01)

#define  MPU_ACCESS_NOT_BUFFERABLE     ((uint8_t)0x00)

S位对应的HAL库MPU参数如下,用于解决多总线或者多核访问的共享问题。


/** @defgroup CORTEX_MPU_Access_Shareable CORTEX MPU Instruction Access Shareable

  * @{

  */

#define  MPU_ACCESS_SHAREABLE        ((uint8_t)0x01)

#define  MPU_ACCESS_NOT_SHAREABLE    ((uint8_t)0x00)

23.5.4 RASR寄存器的SRD位

这个位用于控制内存区的子区域,使用的是bit[15:8],共计8个bit,一个bit控制一个子区域,0表示使能此子区域,1表示禁止此子区域。


一般情况,基本不使用子区域的禁止功能,所以配置HAL库的SubRegionDisable参数时,直接取值0x00即可,表示8个子区域均使能。


23.5.5 RASR寄存器的SIZE位

SIZE位使用的是bit[5:1],共计5个bit,可以表示2^5 = 32种大小。 对应的HAL库给出了可以配置的28个参数:


/** @defgroup CORTEX_MPU_Region_Size CORTEX MPU Region Size

  * @{

  */

#define   MPU_REGION_SIZE_32B      ((uint8_t)0x04)

#define   MPU_REGION_SIZE_64B      ((uint8_t)0x05)

#define   MPU_REGION_SIZE_128B     ((uint8_t)0x06)

#define   MPU_REGION_SIZE_256B     ((uint8_t)0x07)

#define   MPU_REGION_SIZE_512B     ((uint8_t)0x08)

#define   MPU_REGION_SIZE_1KB      ((uint8_t)0x09)

#define   MPU_REGION_SIZE_2KB      ((uint8_t)0x0A)

#define   MPU_REGION_SIZE_4KB      ((uint8_t)0x0B)

#define   MPU_REGION_SIZE_8KB      ((uint8_t)0x0C)

#define   MPU_REGION_SIZE_16KB     ((uint8_t)0x0D)

#define   MPU_REGION_SIZE_32KB     ((uint8_t)0x0E)

#define   MPU_REGION_SIZE_64KB     ((uint8_t)0x0F)

#define   MPU_REGION_SIZE_128KB    ((uint8_t)0x10)

#define   MPU_REGION_SIZE_256KB    ((uint8_t)0x11)

#define   MPU_REGION_SIZE_512KB    ((uint8_t)0x12)

#define   MPU_REGION_SIZE_1MB      ((uint8_t)0x13)

#define   MPU_REGION_SIZE_2MB      ((uint8_t)0x14)

#define   MPU_REGION_SIZE_4MB      ((uint8_t)0x15)

#define   MPU_REGION_SIZE_8MB      ((uint8_t)0x16)

#define   MPU_REGION_SIZE_16MB     ((uint8_t)0x17)

#define   MPU_REGION_SIZE_32MB     ((uint8_t)0x18)

#define   MPU_REGION_SIZE_64MB     ((uint8_t)0x19)

#define   MPU_REGION_SIZE_128MB    ((uint8_t)0x1A)

#define   MPU_REGION_SIZE_256MB    ((uint8_t)0x1B)

#define   MPU_REGION_SIZE_512MB    ((uint8_t)0x1C)

#define   MPU_REGION_SIZE_1GB      ((uint8_t)0x1D)

#define   MPU_REGION_SIZE_2GB      ((uint8_t)0x1E)

#define   MPU_REGION_SIZE_4GB      ((uint8_t)0x1F)

23.5.6 CTRL寄存器的各个位

控制寄存器各个位定义如下如下:


23.6 MPU的配置函数

HAL库的stm32h7xx_hal_cortex.c文件为MPU的配置提供了三个函数:


  HAL_MPU_Disable

  HAL_MPU_Enable

  HAL_MPU_ConfigRegion

 


三个函数的使用都比较简单,但是要让配置的内存区最大限度的发挥性能是需要大量的经验积累和测试的。具体工程要具体分析。


23.6.1 函数HAL_MPU_Disable

函数原型:


void HAL_MPU_Disable(void)

{

  /* Make sure outstanding transfers are done */

  __DMB();

 

  /* Disable fault exceptions */

  SCB->SHCSR &= ~SCB_SHCSR_MEMFAULTENA_Msk;

 

  /* Disable the MPU and clear the control register*/

  MPU->CTRL = 0;

}

函数描述:


此函数用于禁止MPU。配置MPU前要优先调用此函数禁止MPU,然后才可以配置。


23.6.2 函数HAL_MPU_Enable

函数原型:


void HAL_MPU_Enable(uint32_t MPU_Control)

{

  /* Enable the MPU */

  MPU->CTRL = MPU_Control | MPU_CTRL_ENABLE_Msk;

 

  /* Enable fault exceptions */

  SCB->SHCSR |= SCB_SHCSR_MEMFAULTENA_Msk;

 

  /* Ensure MPU setting take effects */

  __DSB();

  __ISB();

}

函数描述:


此函数用于使能MPU,一般情况使用参数MPU_PRIVILEGED_DEFAULT。


函数参数:


此函数支持以下几个参数:


1、  MPU_HFNMI_PRIVDEF_NONE   ((uint32_t)0x00000000)


  此参数设置MPU的CTL控制寄存器的PRIVDEFENA位为0。

表示禁止了背景区,访问任何未使能MPU的区域均会造成内存异常MemFault。


  此参数设置MPU的CTL控制寄存器的HFNMIENA位为0。

表示NMI不可屏蔽中断服务程序和硬件异常中断服务程序执行期间会关闭MPU。


2、  MPU_HARDFAULT_NMI           ((uint32_t)0x00000002)


  此参数设置MPU的CTL控制寄存器的PRIVDEFENA位为0。

表示禁止了背景区,访问任何未使能MPU的区域均会造成内存异常MemFault。


  此参数设置MPU的CTL控制寄存器的HFNMIENA位为1。

表示NMI不可屏蔽中断服务程序和硬件异常中断服务程序执行期间会保持继续开启MPU。


3、  MPU_PRIVILEGED_DEFAULT      ((uint32_t)0x00000004)


  此参数设置MPU的CTL控制寄存器的PRIVDEFENA位为1。

表示使能了背景区,特权级模式可以正常访问任何未使能MPU的区域。


  此参数设置MPU的CTL控制寄存器的HFNMIENA位为0。

表示NMI不可屏蔽中断服务程序和硬件异常中断服务程序执行期间会关闭MPU。


4、  MPU_HFNMI_PRIVDEF           ((uint32_t)0x00000006)


  此参数设置MPU的CTL控制寄存器的PRIVDEFENA位为1。

表示禁止了背景区,访问任何未使能MPU的区域均会造成内存异常MemFault。


  此参数设置MPU的CTL控制寄存器的HFNMIENA位为1。

表示NMI不可屏蔽中断服务程序和硬件异常中断服务程序执行期间会保持继续开启MPU。


23.6.3 函数HAL_MPU_ConfigRegion

函数原型:


void HAL_MPU_ConfigRegion(MPU_Region_InitTypeDef *MPU_Init)

{

  /* Check the parameters */

  assert_param(IS_MPU_REGION_NUMBER(MPU_Init->Number));

  assert_param(IS_MPU_REGION_ENABLE(MPU_Init->Enable));

 

  /* Set the Region number */

  MPU->RNR = MPU_Init->Number;

 

  if ((MPU_Init->Enable) != RESET)

  {

    /* Check the parameters */

    assert_param(IS_MPU_INSTRUCTION_ACCESS(MPU_Init->DisableExec));

    assert_param(IS_MPU_REGION_PERMISSION_ATTRIBUTE(MPU_Init->AccessPermission));

    assert_param(IS_MPU_TEX_LEVEL(MPU_Init->TypeExtField));

    assert_param(IS_MPU_ACCESS_SHAREABLE(MPU_Init->IsShareable));

    assert_param(IS_MPU_ACCESS_CACHEABLE(MPU_Init->IsCacheable));

    assert_param(IS_MPU_ACCESS_BUFFERABLE(MPU_Init->IsBufferable));

    assert_param(IS_MPU_SUB_REGION_DISABLE(MPU_Init->SubRegionDisable));

    assert_param(IS_MPU_REGION_SIZE(MPU_Init->Size));

 

    MPU->RBAR = MPU_Init->BaseAddress;

    MPU->RASR = ((uint32_t)MPU_Init->DisableExec             << MPU_RASR_XN_Pos)   |

                ((uint32_t)MPU_Init->AccessPermission        << MPU_RASR_AP_Pos)   |

                ((uint32_t)MPU_Init->TypeExtField            << MPU_RASR_TEX_Pos)  |

                ((uint32_t)MPU_Init->IsShareable             << MPU_RASR_S_Pos)    |

                ((uint32_t)MPU_Init->IsCacheable             << MPU_RASR_C_Pos)    |

                ((uint32_t)MPU_Init->IsBufferable            << MPU_RASR_B_Pos)    |

                ((uint32_t)MPU_Init->SubRegionDisable        << MPU_RASR_SRD_Pos)  |

                ((uint32_t)MPU_Init->Size                    << MPU_RASR_SIZE_Pos) |

[1] [2]
关键字:STM32H7  MPU  内存保护单元 引用地址:【STM32H7教程】第23章 STM32H7的MPU内存保护单元(重要)

上一篇:【STM32H7教程】第24章 STM32H7的Cache解读(非常重要)
下一篇:【STM32H7教程】第22章 STM32H7的SysTick实现多组软件定时器

推荐阅读最新更新时间:2024-11-10 19:31

推嵌入式AI,瑞萨电子要把工控市场“搅”翻天
一年多之前,瑞萨电子提出了一个观点,就是要将AI技术融入到实时嵌入式系统中,也就是e-AI。 去年年底,瑞萨电子高级副总裁,产业解决方案事业部副部长Michael Hannawald在2017美林银行日本峰会中,再次重申了瑞萨电子对于e-AI的看法以及其他在产业领域的计划。 工业是瑞萨电子的必争之地 根据2017年半年报显示,瑞萨电子的工业业务占公司总营收的30%,而车用市场占比50%,两者相加则超过了80%。Michael Hannawald预计,2016年到2021年间,受益于市场升级需求,瑞萨电子在工业领域营收的年复合增长率将达10%。 目前瑞萨电子在工业领域主要关注三大领域七大应用,领域包括智能楼宇、智能工厂以及智慧家
[嵌入式]
推嵌入式AI,瑞萨电子要把工控市场“搅”翻天
STM32系列第31篇--MPU6050六轴传感器
简介: MPU6050是InvenSense公司推出的全球首款整合性6轴运动处理组件,内带3轴陀螺仪和3轴加速度传感器,并且含有一个第二IIC接口,可用于连接外部磁力传感器,利用自带数字运动处理器(DMP: Digital Motion Processor)硬件加速引擎,通过主IIC接口,可以向应用端输出完整的9轴姿态融合演算数据。 有了DMP,我们可以使用InvenSense公司提供的运动处理资料库,非常方便的实现姿态解算,降低了运动处理运算对操作系统的负荷,同时大大降低了开发难度 。 特点: 自带数字运动处理( DMP: Digital Motion Processing ),可以输出6轴或9轴(需外接磁传感器)姿态解算数
[单片机]
STM32H7系列SDMMC1中的IDMA 和 ARM Cortex-M的分散加载
先来一张中文参考手册中的系统架构图,可以看到,STM32H7系列包含两个SDMMC控制器:SDMMC1和SDMMC2。 在芯片手册中的架构图能够更直观地看出来: SDMMC内部集成一个IDMA,H7系列有很多总线主设备,包括DMA1、DMA2、BDMA、MDMA、DMA2D,还包括IDMA和以太网DMA这种专用DMA。 查看系统架构图和关于总线主设备的描述: SDMMC1和SDMMC2相比,和SRAM1、SRAM2都没有构成总线矩阵,只能访问AXI SRAM区域的内存。 所以我们的使用IDMA进行SD卡的访问时,buffer必须放在AXI SRAM上面。 观察SRAM的分配,可以知道AXI SRAM分布在从0
[单片机]
<font color='red'>STM32H7</font>系列SDMMC1中的IDMA 和 ARM Cortex-M的分散加载
STM32H7教程】第25章 STM32H7的TCM,SRAM等五块内存基础知识
25.1 初学者重要提示 TCM : Tightly-Coupled Memory 紧密耦合内存 。ITCM用于指令,DTCM用于数据,特点是跟内核速度一样,而片上RAM的速度基本都达不到这个速度。 特别注意本章25.5小节里面各块RAM的DMA操作问题。 25.2 各块RAM在总线中的位置 这个知识点在前面章节做过介绍,本章再次梳理下这个知识点。 这个图可以方便识别总线所外挂的外设,共分为三个域:D1 Domain,D2 Domain和D3 Domain。 1、 ITCM和DTCM 这两个是直连CPU的。 2、 D1 Domain D1域中的各个外设是挂在64位AXI总线组成6*7的矩阵上。 6
[单片机]
【<font color='red'>STM32H7</font>教程】第25章 <font color='red'>STM32H7</font>的TCM,SRAM等五块内存基础知识
一文深入了解STM32H7芯片
初学STM32H7一定要优先整体把控芯片的框架,不要急于了解单个外设的功能。 1 初学者重要提示 学习一款新的芯片,优先掌握系统框架是比较重要的,建议逐渐养成这种学习习惯,然后各个击破即可。 本章节提供了多张STM32H7的框图,这些框图都非常具有代表性。很多时候记忆知识点比较费脑子,记录这些框图是一种非常好的方式。 对于本章节提供的部分知识点,无法理解透彻,暂时没有关系。随着后面的深入学习,基本都可以掌握。 重要的MPU和Cache知识分别放在了第23章和第24章。 2 STM32H7硬件框图 学习一款新的芯片,需要优先了解一下它的整体功能设计。需要的资料主要是来自官网和数据手册,比如我们V7开发板使用的STM32H74
[单片机]
一文深入了解<font color='red'>STM32H7</font>芯片
IC Insights:2014年MPU销售额将增9%
    全球微处理器(MPU)需求将稳健增长。IC Insights指出,受惠智慧型手机、平板装置和嵌入式应用市场持续走强,以及企业界资讯科技(IT)资本支出回升,2014年总体微处理器(MPU)销售额预估将达667亿美元,较2013年的610亿美元攀升9%。其中,手机和平板用的应用处理器仍是主要成长来源,销售额年增率分别高达19%和35%,而个人电脑(PC)相关微处理器销售额也可望小幅上扬3%,结束连续2年下滑的局面。
[手机便携]
一段有关MPU配置代码的几个小疑问
当我们阅读一些STM32F7或STM32H7系列芯片例程,或者基于这两类芯片通过cubeMx进行配置并用到MPU功能时,往往会在代码里看到下面这段MPU配置。 对这段代码可能有人有些疑问,这里重点一起聊聊其中的3个,供参考。 第一个疑问,那行做赋值0x87的代码是什么意思? 第二个疑问,这段代码的注释【绿色】是说将未定义的区域配置为StronglyOrdered存储属性,这个未定义到底如何理解?从代码看,这里清晰地对从0开始的整个4G空间做了配置,未定义区域到底指的哪里? 第三个疑问,这段代码往往并不是开发者自己配置的。如果使用CubeMx进行配置它会自动给我们加上这段,为什么要加这段?很多时候经测试,即使没这段代码似乎也没有
[单片机]
一段有关<font color='red'>MPU</font>配置代码的几个小疑问
小广播
设计资源 培训 开发板 精华推荐

最新单片机文章
何立民专栏 单片机及嵌入式宝典

北京航空航天大学教授,20余年来致力于单片机与嵌入式系统推广工作。

换一换 更多 相关热搜器件

 
EEWorld订阅号

 
EEWorld服务号

 
汽车开发圈

电子工程世界版权所有 京B2-20211791 京ICP备10001474号-1 电信业务审批[2006]字第258号函 京公网安备 11010802033920号 Copyright © 2005-2024 EEWORLD.com.cn, Inc. All rights reserved