1. MPU 相关基础

内存保护单元(MPU)是 Cortex-R52 中用于管理内存访问权限和属性的硬件模块。它通过划分内存区域来工作,每个区域最小为 64 字节,并且起始地址必须对齐到其大小的整数倍(例如,一个 64 字节的区域必须从一个能被 64 整除的地址开始)。对齐要求就像整理书架时规定每本书必须从固定的格子开始摆放,这样系统才能快速、准确地找到和管理这些内存区域,否则可能导致硬件错误或性能下降。


1.1. 4.1. R52 内存模型功能支持

Cortex-R52 的内存模型有若干关键特性,这些特性深刻影响着系统设计和编程:

  1. 共享性与缓存的强制规则:为了在无硬件缓存一致性的多核系统中保证数据安全,任何被标记为 Inner Shareable(集群内共享)或 Outer Shareable(集群间共享)的内存区域,其数据访问都会强制绕过缓存,变为不可缓存(Non-cacheable)。这就像在团队协作中,所有需要共享给团队成员的文件都必须放在公共公告板上,而不是个人的抽屉里,确保每个人看到的都是最新版本,避免了数据不一致的风险。

  2. 不支持快速上下文切换(FCSE):Cortex-R52 作为实时处理器,优先考虑确定性和简单性,因此不支持 FCSE 这一用于加速任务切换的功能。这意味着任务切换的延迟可能稍高,但系统行为更可预测。

  3. 辅助寄存器支持:Cortex-R52 提供了一组用于深度调试和系统控制的辅助寄存器,它们是系统工程师的“诊断工具”。

    • Auxiliary Fault Status Registers (AIFSR 和 ADFSR):当处理器遇到指令获取错误(AIFSR)或数据访问错误(ADFSR)时,这些寄存器会记录详细的错误原因。例如,当 DMA 控制器试图访问一个未配置权限的内存区域而触发总线错误时,工程师可以通过读取 ADFSR 来定位问题根源。
    • Auxiliary Control Register (ACTLR):这是一个权限寄存器(通常在 EL1 或 EL3 级别才能访问),用于微架构行为控制,例如调整缓存策略、预取器行为或多核交互。一个典型应用是禁用特定核心的 L2 缓存预取功能,以在特定工作负载下降低功耗
  4. 受限的 PMSA 架构:Cortex-R52 采用受保护的存储器系统架构(PMSA),它不支持虚拟内存(这与 MMU 的 VMSA 不同),而是通过 MPU 实现物理内存的保护,架构更简单,非常适合实时嵌入式系统。

  5. 支持 TCM 及相关 DMA:TCM 是一种紧耦合内存,具有低延迟、高带宽的特性,常用于存储关键代码和数据。Cortex-R52 支持 TCM 并且能够与 DMA 控制器高效协作,例如,DMA 可以将传感器数据直接写入 TCM,然后 CPU 核心能够极速处理这些数据。

  6. 两级共享等级:共享性分为两个层级,Inner Shareable 通常指在一个处理器集群内部(例如,同一芯片上的多个 R52 核心)之间的共享;Outer Shareable 范围更广,指在不同集群之间(例如,系统中多个芯片)的共享。在 R52 中,无论哪个级别的共享,都会触发上述的不可缓存强制规则。


1.2. 4.2. MPU 寄存器详解

MPU 的功能通过一系列寄存器进行配置,理解它们是进行内存保护编程的关键。

  • MPU 的启用与背景区域:MPU 的全局开关由系统控制寄存器(SCTLR)的 M 位控制。当 SCTLR.M=0,MPU 被禁用,此时系统会使用 EL1 控制的 MPU 背景区域作为默认内存映射,这相当于一个“安全网”,定义了未受 MPU 明确管理的内存区域的属性。当 MPU 启用(SCTLR.M=1) 后,还可以通过设置 SCTLR.BR 位来单独启用或禁用这个背景区域。

  • MPU 区域数量:系统支持的 MPU 区域数量(即可配置的内存保护区块数)是一个硬件特性,可以从 MPU Type 寄存器中读取。

  • EL2 Hypervisor 支持:对于支持虚拟化的场景,EL2 级别的 MPU 是可选的。如果实现,其相关配置寄存器为 HPRBAR(Hypervisor Physical Region Base Address Register)和 HPRLAR(Hypervisor Physical Region Limit Address Register)。在 Hypervisor 模式下,一次内存访问会同时检查 EL1 和 EL2 的 MPU 区域设置,两者共同决定最终的访问权限和内存属性。

  • 区域配置寄存器(以 EL1 为例):每个 MPU 区域通过一对寄存器定义:

    • PRBAR(区域基址寄存器)
      • SH 字段:控制内存区域的共享性(Shareable)。对于普通内存,一旦设置为共享,该区域即被强制为不可缓存。
      • AP 字段:控制访问权限(Access Permission),定义在 EL1(操作系统)和 EL0(应用程序)特权等级下是否可读、可写。
      • XN 字段:控制是否可执行(eXecute Never)。设置为 1 可防止在该区域执行代码,有效抵御某些代码注入攻击。
    • PRLAR(区域限界寄存器)
      • AttrIndx 字段:这是一个索引值,用于选择 MAIR(Memory Attribute Indirection Register) 寄存器中的属性配置。MAIR 寄存器可以看作一个“属性模板库”,提供了 8 个(attr0 到 attr7)可编程的内存属性槽。
      • EN 位:区域启用位。只有设为 1,该 MPU 区域的配置才生效。

1.3. 4.3. 内存属性深度解析

内存属性决定了处理器访问内存时的微观行为,如缓存策略、排序要求等。Cortex-R52 在此有特殊规定。

2. 4.3.1. Cortex-R52+ 内存属性核心行为要点

  1. 数据缓存策略强制为 Write-Through(直写):这是 R52 的一个关键特性。无论软件在属性中配置为 Write-Back(回写)还是其他,实际的内存访问行为都是 Write-Through。这意味着数据写入时会同时更新缓存和主内存,保证了数据的实时一致性,简化了多核数据共享的处理,但可能比 Write-Back 模式性能稍低。
  2. Shareable 属性强制为 Non-cacheable:如前所述,标记为 Inner 或 Outer Shareable 的内存区域会被强制当作 Non-cacheable 处理,所有访问直接到达内存,这是保证多核数据一致性的核心机制。
  3. Transient 提示被忽略:Transient 属性用于提示某次访问是临时的、可能不会重用,但 Cortex-R52 忽略所有 Transient 提示,统一按 Non-transient 处理。
  4. 非一致性架构:Cortex-R52 的各个核心的缓存之间没有硬件自动维护一致性,因此对共享数据的软件管理要求更高。

3. 4.3.2. 属性编码与实际行为

内存属性编码分为外层(Outer)和内层(Inner)属性,但对于 Cortex-R52 的实时应用场景,许多配置的实际行为被简化或强制改变。

3.1. Device 内存类型(用于访问外设寄存器)

当外层属性编码为 0000 时,内存类型为 Device。其内层编码决定了访问设备的严格程度,这对于外设的正确操作至关重要。

内层编码 Device 类型 严格程度 实际行为(对寄存器的操作) 典型使用场景
0b0000 nGnRnE 最严格 合并、重排序、提前写确认 中断控制器、系统关键控制寄存器
0b0100 nGnRE 较严格 合并、重排序、提前写确认 UART、SPI、定时器等普通外设
0b1000 nGRE 较宽松 合并、重排序、提前写确认 帧缓冲区、DMA 描述符表
0b1100 GRE 最宽松 合并、重排序、提前写确认 大块内存映射 IO 区域
  • 名词解释
    • 聚集(Gathering):将多个小访问合并成一次大访问。
    • 重排序(Reordering):改变内存访问的先后顺序。
    • 提前写确认(Early-acknowledge):在写入操作实际完成前就通知处理器完成。

3.2. Normal 内存类型(用于普通数据内存)

当外层属性编码不为 0000 时,内存类型为 Normal。下表展示了配置值与 Cortex-R52 实际行为的差异。

外层/内层属性编码与实际行为对照

配置的编码 软件配置的类型 Cortex-R52+ 实际行为 说明
0b00RW (RW≠00) Write-Through Transient 实际为 Write-Through,Transient 被忽略
0b0100 Non-Cacheable Non-Cacheable
0b01RW (RW≠00) Write-Back Transient 实际为 Write-Through,Transient 被忽略 Write-Back 配置被强制转换
0b10RW Write-Through Non-transient Write-Through Non-transient
0b11RW Write-Back Non-transient 实际为 Write-Through Non-transient Write-Back 配置被强制转换

R/W 分配策略编码 此策略控制当缓存未命中时,是否为读(R)或写(W)操作分配缓存行。

R/W 值 含义 实际效果
R=0, W=0 读写都不分配 直接访问内存,不占用缓存空间
R=0, W=1 读不分配,写分配 仅当写入数据且不在缓存时,才将其载入缓存
R=1, W=0 读分配,写不分配 仅当读取数据且不在缓存时,才将其载入缓存
R=1, W=1 读写都分配 只要访问的数据不在缓存,就将其载入缓存

4. 4.3.3. 配置指南与决策流程

4.1. 推荐配置场景

  1. 私有数据(单核心访问)

    • 配置:Non-Shareable + Write-Through + 合适的 R/W 分配。
    • 场景:核心内部的局部变量、临时计算数据。
    • 策略建议:频繁读写的小数据用 R=1, W=1;读多写少的数据用 R=1, W=0
  2. 共享数据(多核心/DMA 访问)

    • 配置:Shareable(自动变为 Non-cacheable)。
    • 场景:核心间通信缓冲区、DMA 数据区。
    • 说明:这是最简单且安全地保证数据一致性的方法。
  3. 设备寄存器

    • 配置:Device 内存类型(根据外设要求选择 nGnRnE, nGnRE 等)。
    • 场景:外设控制/状态寄存器。
    • 原则:对顺序敏感的关键寄存器用 nGnRnE;对顺序要求不高的普通外设可用 nGnRE。
  4. 代码段

    • 配置:Non-Shareable + Write-Through + R=1, W=0。
    • 场景:程序代码、常量数据。
    • 说明:利用缓存加速指令读取(R=1),由于代码通常不写入,故 W=0。
  5. 流式数据处理

    • 配置:Non-Shareable + Write-Through + R=0, W=0。
    • 场景:处理大型数据块、一次性 DMA 传输缓冲区。
    • 说明:避免被只使用一次的数据“污染”缓存,提升缓存效率。

4.2. 配置决策流程

初学者可以遵循以下步骤来配置内存属性:

  1. 是否需要共享? 如果该内存区域会被多个核心或 DMA 访问 → 标记为 Shareable(它将自动变为 Non-cacheable,一致性得到保证)。如果否 → 进入下一步。
  2. 是否是设备内存? 如果该区域是映射的外设寄存器 → 选择合适严格程度的 Device 类型。如果否 → 配置为 Normal 内存。
  3. 选择分配策略:根据对该 Normal 内存区域的访问模式(读多还是写多)来选择合适的 R/W 位。请记住:Transient 属性可忽略,且任何 Write-Back 配置都无效。

5. 4.3.4. nGnRnE 深度解读

nGnRnE 是 ARM 架构中用于描述设备内存行为的最严格类型,其名称中的每个字母都代表一个限制:

  • nG (No Gathering)不允许事务合并。多个对同一设备的访问不能合并为一次更大的传输。
  • nR (No Reordering)不允许事务重排序。对该设备的访问必须严格按照程序代码的顺序执行。
  • nE (No Early-acknowledge)不允许提前确认。写操作必须在该操作确实在设备端完成之后,才能向处理器发送“完成”信号。

应用场景nGnRnE 用于访问那些对操作顺序极其敏感的设备寄存器,例如中断控制器系统关键控制寄存器。确保一个“开启”指令绝对在“配置”指令之后执行,是系统稳定性的基石。在 ARMv7 架构中,它对应于 Strongly Ordered 内存类型。

Logo

有“AI”的1024 = 2048,欢迎大家加入2048 AI社区

更多推荐