大家好,我是痞子衡,是正经搞技术的痞子。今天痞子衡给大家介绍的是ARM Cortex-M存储保护模块(MPU)

  《ARM Cortex-M内核MCU开发那些事》的内核篇连载最早是 2017 年底开始写的,但只写了 7 篇就停更了,鸽了这么久实在不好意思。最近在支持 i.MXRT 客户的过程中,发现客户对 Cortex-M 的 MPU 功能不太了解,导致项目中出了内存非法访问的问题,借此机会,痞子衡将重启这个 Cortex-M 内核篇连载,为大家系统地讲解下MPU:

备注:本篇是MPU上篇,主要讲述PMSAv6/7架构下的Cortex-M处理器MPU设计,适用Cortex-M0+/M3/M4/M7。

一、MPU是什么?

  MPU 全称"Memory Protection Unit",中文叫“存储保护单元”,它是 Cortex-M 处理器内部的一个模块(注意:并不是所有 Cortex-M 版本都支持 MPU,并且在一些支持 MPU 的 Cortex-M 版本上,MPU 也是可选组件(要看具体MCU厂商是否实现))。

  让我们结合如下 Cortex-M 处理器(以 CM0+ 为例,其他版本类似)模块框图中来解释 MPU 作用,从框图中大家可以看到,MPU 介于 Core 和 Bus matrix 中间。Bus matirx 是 ARM 系统总线大管家,用以实现系统内多主(Core,DMA等)、多从(内部RAM,APB外设,外部总线等)的交联和仲裁,Core 通过 Bus matirx 可以访问到系统空间内的所有存储/外设资源,现在 MPU 挡在了 Core 和 Bus matirx 中间,这意味着从此 Core 对系统存储资源的访问需要经过 MPU 的权限控制与审核。

二、存储空间类型与属性

  MPU 对存储空间的访问权限控制主要包含:Strongly-ordered(是否严格有序)、Shareable(是否共享)、Cacheable(是否缓存)、Execute Never(是否可执行)等方面,不同的访问权限配置造就了系统里不同的存储空间类型与属性,这一切都是为了能够让存储资源被 Core 高效且可靠地访问(RTOS环境下比裸机程序下更需要可靠保证)。

  Shareable/Cacheable/Execute Never 属性大家应该都了解,有必要特别提一下 Strongly-ordered 属性,因为不同属性的存储空间配置会给代码执行时内存访问指令的顺序方面造成了困扰,比如两个内存访问指令A1, A2,假定它们是同一主设备接口发出的,并且 A1 在程序代码里出现在 A2 之前,根据 A1/A2 不同的属性组合其实际执行结果如下,有些时候系统无法保证 A1 操作一定比 A2 操作先完成,这时候需要软件设计里手工插入内存屏障指令(ISB, DSB)来保证最终顺序。

  如果 MPU 模块不存在或者没有被使能,处理器系统 4GB 存储空间默认的属性如下(表中 XN 即 Execute Never;WT 即 Write-Throug;WBWA 即 Write-Back, write allocate):

三、MPU功能配置

  MPU 模块是处理器内核自带的模块,其寄存器定义见 \CMSIS\Include\core_cm0plus/3/4/7.h 文件,具体寄存器功能解释这里就不展开了,可翻阅对应 ARMv6/7-M Architecture RM 或者 Cortex-M0+/3/4/7 Generic UG 手册找到具体解释。

  简单概括一下,MPU 最多支持 8/16 个主空间划分(MPU_RNR[REGION],REGION取值 0-7 或者 0-15),每个主空间可以自由设置其属性(MPU_RASR[XN/AP/TEX/S/C/B]),空间大小是可设的,最小粒度为 32bytes,空间之间也可以重叠(高序号空间属性会覆盖低序号空间属性)。当某个主空间分配的大小超过 256 bytes 时,这个主空间还可以被等分成 8 个子空间,每个子空间有独立的开关控制(MPU_RASR[SRD])。

  MPU 模块最核心的寄存器是 MPU_RASR,其提供了存储空间具体访问权限配置,XN/AP/TEX/S/C/B 位域共同决定了最终权限,用户可根据项目实际需求进行配置。

上表中关于 Cache 策略的设置 AA/BB 定义如下:00 Non-cacheable01 Write-back, write and read allocate10 Write-through, no write allocate11 Write-back, no write allocate

四、MPU配置代码示例

  ARM 官方为 MPU 模块预实现了一些功能函数/宏定义,见 \CMSIS\Include\mpu_armv6/7.h 文件,其中最常用的是 ARM_MPU_RBAR 和 ARM_MPU_RASR 宏。

  如下是恩智浦 i.MXRT1170 的 MPU 示例配置代码,这是颗 Cortex-M7 内核的 MCU,内部有 2MB RAM,官方 MIMXRT1170-EVK 板卡为其外挂了 16MB 的 NOR Flash 和 64MB 的 SDRAM。

  代码中 Region2/3/4/5/6/8/9 是实际用户存储空间的配置,其他 Region0/1/7 是基本系统空间的配置,未定义空间的非法访问会产生 MemManage 或者 BusFault。

void BOARD_ConfigMPU(void)
{/* Disable I cache and D cache */SCB_DisableICache();SCB_DisableDCache();/* Disable MPU */ARM_MPU_Disable();//// 系统全部 4GB 空间先配置成 XN 属性的 Device/* Region 0 setting: Instruction access disabled, No data access permission. */MPU->RBAR = ARM_MPU_RBAR(0, 0x00000000U);MPU->RASR = ARM_MPU_RASR(1, ARM_MPU_AP_NONE, 2, 0, 0, 0, 0, ARM_MPU_REGION_SIZE_4GB);//// 0x00000000 之后的1GB 空间配置成非 XN 属性的 Device/* Region 1 setting: Memory with Device type, not shareable, non-cacheable. */MPU->RBAR = ARM_MPU_RBAR(1, 0x00000000U);MPU->RASR = ARM_MPU_RASR(0, ARM_MPU_AP_FULL, 2, 0, 0, 0, 0, ARM_MPU_REGION_SIZE_1GB);//// 0x00000000 之后的内部 RAM 空间配置(实际 2MB)/* Region 2 setting: Memory with Normal type, not shareable, outer/inner write back */MPU->RBAR = ARM_MPU_RBAR(2, 0x00000000U);MPU->RASR = ARM_MPU_RASR(0, ARM_MPU_AP_FULL, 0, 0, 1, 1, 0, ARM_MPU_REGION_SIZE_256KB);/* Region 3 setting: Memory with Normal type, not shareable, outer/inner write back */MPU->RBAR = ARM_MPU_RBAR(3, 0x20000000U);MPU->RASR = ARM_MPU_RASR(0, ARM_MPU_AP_FULL, 0, 0, 1, 1, 0, ARM_MPU_REGION_SIZE_256KB);/* Region 4 setting: Memory with Normal type, not shareable, outer/inner write back */MPU->RBAR = ARM_MPU_RBAR(4, 0x20200000U);MPU->RASR = ARM_MPU_RASR(0, ARM_MPU_AP_FULL, 0, 0, 1, 1, 0, ARM_MPU_REGION_SIZE_1MB);/* Region 5 setting: Memory with Normal type, not shareable, outer/inner write back */MPU->RBAR = ARM_MPU_RBAR(5, 0x20300000U);MPU->RASR = ARM_MPU_RASR(0, ARM_MPU_AP_FULL, 0, 0, 1, 1, 0, ARM_MPU_REGION_SIZE_512KB);//// 0x30000000 之后的外部 NOR Flash 空间配置(实际 16MB)
#if defined(XIP_EXTERNAL_FLASH) && (XIP_EXTERNAL_FLASH == 1)/* Region 6 setting: Memory with Normal type, not shareable, outer/inner write back. */MPU->RBAR = ARM_MPU_RBAR(6, 0x30000000U);MPU->RASR = ARM_MPU_RASR(0, ARM_MPU_AP_RO, 0, 0, 1, 1, 0, ARM_MPU_REGION_SIZE_16MB);
#endif//// 0x80000000 之后的外部 SDRAM 空间配置(最大 512MB,实际 64MB)/* Region 7 setting: Memory with Device type, not shareable, non-cacheable. */MPU->RBAR = ARM_MPU_RBAR(7, 0x80000000U);MPU->RASR = ARM_MPU_RASR(0, ARM_MPU_AP_FULL, 2, 0, 0, 0, 0, ARM_MPU_REGION_SIZE_512MB);
#ifdef USE_SDRAM/* Region 8 setting: Memory with Normal type, not shareable, outer/inner write back */MPU->RBAR = ARM_MPU_RBAR(8, 0x80000000U);MPU->RASR = ARM_MPU_RASR(0, ARM_MPU_AP_FULL, 0, 0, 1, 1, 0, ARM_MPU_REGION_SIZE_64MB);
#endif
#if defined(__ICCARM__) || defined(__GNUC__)extern uint32_t __NCACHE_REGION_START[];  // 来自链接文件里的定义extern uint32_t __NCACHE_REGION_SIZE[];   // 来自链接文件里的定义uint32_t nonCacheStart = (uint32_t)__NCACHE_REGION_START;uint32_t size          = (uint32_t)__NCACHE_REGION_SIZE;
#endifvolatile uint32_t i = 0;while ((size >> i) > 0x1U){i++;}if (i != 0){/* The MPU region size should be 2^N, 5<=N<=32, region base should be multiples of size. */assert(!(nonCacheStart % size));assert(size == (uint32_t)(1 << i));assert(i >= 5);/* Region 9 setting: Memory with Normal type, not shareable, non-cacheable */MPU->RBAR = ARM_MPU_RBAR(9, nonCacheStart);MPU->RASR = ARM_MPU_RASR(0, ARM_MPU_AP_FULL, 1, 0, 0, 0, 0, i - 1);}/* Enable MPU */ARM_MPU_Enable(MPU_CTRL_PRIVDEFENA_Msk);/* Enable I cache and D cache */SCB_EnableDCache();SCB_EnableICache();
}

附录一、MPU特性差异

处理器版本 存在MPU 最大主保护区域(k) 主保护区域可重叠 子保护区域 三组Alias空间
Cortex-M0/1 N/A N/A N/A N/A
Cortex-M0+ 8个 支持 k*8个 不支持
Cortex-M3/4 8个 支持 k*8个 支持
Cortex-M7 8/16个 支持 k*8个 支持
Cortex-M23 8个 不支持 不支持 不支持
Cortex-M33/35P 8个 不支持 不支持 支持
Cortex-M55 4/8/12/16个 不支持 不支持 支持

  至此,ARM Cortex-M存储保护模块(MPU)痞子衡便介绍完毕了,掌声在哪里~~~

欢迎订阅

文章会同时发布到我的 博客园主页、CSDN主页、知乎主页、微信公众号 平台上。

微信搜索"痞子衡嵌入式"或者扫描下面二维码,就可以在手机上第一时间看了哦。

痞子衡嵌入式:ARM Cortex-M内核那些事(9.1)- 存储保护(MPU - PMSAv6/7)相关推荐

  1. 痞子衡嵌入式:ARM Cortex-M内核那些事(5)- 一表搜罗指令集

    大家好,我是痞子衡,是正经搞技术的痞子.今天痞子衡给大家介绍的是ARM Cortex-M指令集. 指令集 指令长度 (bits) 包含指令 Cortex M0 Cortex M0+ Cortex M1 ...

  2. 痞子衡嵌入式:ARM Cortex-M内核那些事(6)- 系统堆栈机制

    大家好,我是痞子衡,是正经搞技术的痞子.今天痞子衡给大家介绍的是ARM Cortex-M堆栈机制. 今天给大家分享的这篇依旧是2016年之前痞子衡写的技术文档,花了点时间重新编排了一下格式.前面痞子衡 ...

  3. 痞子衡嵌入式:盘点国内Cortex-M内核MCU厂商高性能产品

    大家好,我是痞子衡,是正经搞技术的痞子.今天痞子衡给大家介绍的是国内Cortex-M内核MCU厂商高性能产品. 在8/16位中低端MCU领域,国内厂商的本土化产品设计以及超低价特点,使得其与国外大厂竞 ...

  4. 痞子衡嵌入式:单片机AI的春天已来,ARM Cortex-M55发布了

    大家好,我是痞子衡,是正经搞技术的痞子.今天痞子衡给大家介绍的是ARM Cortex-M55. 鼠年春节,大家都在时刻关心 2019nCoV 疫情发展,没太多心思搞技术,就在这个时候,ARM 不声不响 ...

  5. 痞子衡嵌入式:盘点国内Cortex-M内核MCU厂商高主频产品(2023)

    大家好,我是痞子衡,是正经搞技术的痞子.今天痞子衡给大家介绍的是国内Cortex-M内核MCU厂商高主频产品. 在 2021 年初痞子衡写了篇 <盘点国内Cortex-M内核MCU厂商高性能产品 ...

  6. 痞子衡嵌入式:盘点国内RISC-V内核MCU厂商(2018年发布产品)

    大家好,我是痞子衡,是正经搞技术的痞子.今天痞子衡给大家介绍的是国内RISC-V内核MCU厂商(2018). 虽然RISC-V风潮已经吹了好几年,但2019年才是其真正进入主流市场的元年,最近国内大量 ...

  7. 痞子衡嵌入式:ARM Cortex-M文件那些事(3)- 工程文件(.ewp)

    大家好,我是痞子衡,是正经搞技术的痞子.今天痞子衡给大家讲的是嵌入式开发里的project文件. 前面两节课里,痞子衡分别给大家介绍了嵌入式开发中的两种典型input文件:源文件(.c/.h/.s). ...

  8. 痞子衡嵌入式:盘点国内MCU级RISC-V内核IP厂商

    大家好,我是痞子衡,是正经搞技术的痞子.今天痞子衡给大家介绍的是国内MCU级RISC-V内核IP厂商. 自RISC-V指令集2010年诞生以来,业界普遍认为,RISC-V将会改变现有的由Arm和Int ...

  9. 痞子衡嵌入式:盘点国内RISC-V内核MCU厂商(2019年发布产品)

    大家好,我是痞子衡,是正经搞技术的痞子.今天痞子衡给大家介绍的是国内RISC-V内核MCU厂商(2019). 虽然RISC-V风潮已经吹了好几年,但2019年才是其真正进入主流市场的元年,最近国内大量 ...

最新文章

  1. Netty源码解析8-ChannelHandler实例之CodecHandler
  2. js 获取最近几天的时间字符串
  3. Detectron:Pytorch-Caffe2-Detectron的一些跟进
  4. 关于python测试webservice接口的视频分享
  5. (需求实战_进阶_06)SSM集成RabbitMQ 订阅模式 关键代码讲解、开发、测试
  6. vim 强制保存只读文件
  7. upper_bound()与lower_bound()
  8. python遇到的问题-Python常见问题
  9. 大道至简 7、8、读后感
  10. 服务器和硬盘如何区分,服务器硬盘和普通硬盘区别介绍
  11. silverlight寻奇
  12. 2022年熔化焊接与热切割操作证考试题库及答案
  13. 幂运算的O(lgn)算法
  14. XSepConv: Extremely Separated Convolution
  15. 毫秒转换成对应到达时间
  16. 五分钟学GIS | BIM与三维GIS的融合
  17. 洛谷P1162 填涂颜色(Python搜索)
  18. FreeRtos--队列
  19. 知识产权保护可列入常识教育
  20. UFC/k1 VS中国散打!!!!!!!

热门文章

  1. denoiser插件_最新版红巨人调色降噪插件合集 Magic Bullet Suite 13.0.9 Win/Mac
  2. 药一点医药软件供应商——医疗器械管理系统
  3. 实景三维建设背景下,三维GIS面临哪些挑战?
  4. SDCC讲师预热专访:淘宝岑文初谈开放平台架构
  5. 加密的rar文件不知道密码怎么解压
  6. iis不能启动站点,端口被占用.(解决办法)
  7. 基于Abaqus的umat子程序实现三维编织复合材料疲劳性能预测
  8. 《测试架构师的修炼之道》七—测试策略实战
  9. 人工智能——主观贝叶斯方法(主要是公式)
  10. 为什么x86不叫x32?