IT数码 购物 网址 头条 软件 日历 阅读 图书馆
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
图片批量下载器
↓批量下载图片,美女图库↓
图片自动播放器
↓图片自动播放器↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁
 
   -> 嵌入式 -> 痞子衡嵌入式:ARM Cortex-M内核那些事(9.1)- 存储保护(MPU - PMSAv6/7) -> 正文阅读

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


  大家好,我是痞子衡,是正经搞技术的痞子。今天痞子衡给大家介绍的是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-cacheable
    01 Write-back, write and read allocate
    10 Write-through, no write allocate
    11 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;
#endif
    volatile 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/1N/AN/AN/AN/A
Cortex-M0+8个支持k*8个不支持
Cortex-M3/48个支持k*8个支持
Cortex-M78/16个支持k*8个支持
Cortex-M238个不支持不支持不支持
Cortex-M33/35P8个不支持不支持支持
Cortex-M554/8/12/16个不支持不支持支持

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

欢迎订阅

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

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

  嵌入式 最新文章
基于高精度单片机开发红外测温仪方案
89C51单片机与DAC0832
基于51单片机宠物自动投料喂食器控制系统仿
《痞子衡嵌入式半月刊》 第 68 期
多思计组实验实验七 简单模型机实验
CSC7720
启明智显分享| ESP32学习笔记参考--PWM(脉冲
STM32初探
STM32 总结
【STM32】CubeMX例程四---定时器中断(附工
上一篇文章      下一篇文章      查看所有文章
加:2021-08-09 10:23:46  更:2021-08-09 10:25:43 
 
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁

360图书馆 购物 三丰科技 阅读网 日历 万年历 2024年11日历 -2024/11/25 20:39:58-

图片自动播放器
↓图片自动播放器↓
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
图片批量下载器
↓批量下载图片,美女图库↓
  网站联系: qq:121756557 email:121756557@qq.com  IT数码