第 7 章:内存地图 (Memory Map) 深度设计——DDR 与 SRAM

如果说 RIF 是外设所有权的"物权法",那么 Memory Map (内存地图) 就是多核系统的"领土疆域图"。在 STM32MP257 这种异构系统中,M33 核和 A35 核共享物理内存地址空间,但如果不划清界限,就会发生"踩踏事件",导致系统随机崩溃或内核死锁。

本章我们将手把手编写链接脚本(Linker Script),并在物理层面上彻底完成内存的割裂。


7.1 STM32MP257 内存布局解析

STM32MP257 拥有多层级的存储结构,我们需要对其进行战术分配:

  1. SYSRAM (SRAM1/2/3):位于 SoC 内部,低延迟,掉电丢失。适合存放 M33 的关键代码和实时栈。

  2. RETRAM (Retained SRAM):低功耗域内存,适合存放跨核通讯的握手信号。

  3. DDR4/LPDDR4:外部大容量内存(通常 1GB~4GB)。A35 的主战场,但我们要从中"割"出一块给 M33 存放非关键大数据。

推荐实战分配表:
物理地址区间 长度 分配目标 备注
0x0E000000 256KB M33 Code/Data 存放 M33 的 ELF 运行镜像
0x90000000 2MB Shared Memory M33 与 A35 的 IPC 缓冲区
0x90200000 -- Linux Kernel A35 Linux 系统起始

7.2 深度实战:编写 M33 链接脚本 (.ld)

我们需要告诉编译器,把 .text(代码)和 .data(变量)放到正确的地方。

/* STM32MP257F_M33_FLASH.ld */

MEMORY

{

/* M33 运行的主内存:SRAM1 */

RAM (xrw) : ORIGIN = 0x0E000000, LENGTH = 256K

/* 预留给 IPC 的共享内存 */

SHM (rw) : ORIGIN = 0x90000000, LENGTH = 2M

}

SECTIONS

{

/* 向量表必须放在起始位置 */

.isr_vector :

{

. = ALIGN(8);

KEEP(*(.isr_vector))

. = ALIGN(8);

} > RAM

/* 代码段 */

.text :

{

. = ALIGN(8);

*(.text)

*(.text*)

. = ALIGN(8);

} > RAM

/* 共享内存段:用于定义跨核通讯变量 */

.shared_data (NOLOAD) :

{

. = ALIGN(4096);

*(.ipc_shm)

. = ALIGN(4096);

} > SHM

/* 堆栈空间定义 */

._user_stack :

{

. = ALIGN(8);

. = . + 0x2000; /* 8KB Stack */

. = ALIGN(8);

} > RAM

}

7.3 Cache 一致性:不可忽视的幽灵

这是多核开发中最难抓的 Bug。A35 拥有强大的 L1/L2 Cache,M33 也有 D-Cache。

  • 场景 :M33 把 IMU 数据写到了 0x90000000

  • 问题:A35 读取该地址时,可能直接从自己的 Cache 里读到了旧数据,而没有去 DDR 物理地址读。

实战解决方案:

  1. 针对 M33 :使用 MPU (Memory Protection Unit) 将共享内存区域配置为 DeviceStrongly-ordered 属性,禁用 Cache。

  2. 针对 A35 :在 Linux 设备树中将该区域标记为 no-map 或在驱动中使用 dma_alloc_coherent


7.4 内存隔离保护 (RISAF) 代码实现

RIF_Init 中,我们要通过 RISAF 锁定这块地盘,防止 Linux 启动后"越界"。

void RIF_Memory_Protection_Init(void) {

// 配置 RISAF:将 0x0E000000 区域锁定给 CID1 (M33)

// 这样即便 A35 侧出现指针跑飞,也无法修改 M33 的代码

RIF_RISAF1->REGION0.START_ADDR = 0x0E000000;

RIF_RISAF1->REGION0.END_ADDR = 0x0E03FFFF;

RIF_RISAF1->REGION0.CIDCFGR = (1 << RIF_RISCF_CIDCFGR_SCID_Pos) | RIF_RISCF_CIDCFGR_CONF;

}

7.5 引导 Linux 的前哨战:预留内存

在 M33 引导 Linux 之前,我们必须在 M33 侧定义好 Linux 的入口地址。通常我们将 U-Boot 加载到 DDR 的某个固定偏移(如 0x80800000)。

在本章的实验中,我们先不启动 A35,但要确保 M33 能够成功读写 DDR 空间。 实验验证:

  • 编写一个循环,M33 往 0x90000000 写入一个递增序列。

  • 使用调试器(J-Link/ST-Link)查看该内存地址,确认写入成功。


7.6 避坑指南 (Debug Tips)

  • 对齐问题:MP257 的资源隔离通常以 4KB 或 64KB 为最小页单位。如果你的内存分配没有对齐到页边界,RIF 配置会失效。

  • 地址重映射 :注意 M33 看到的地址与 A35 看到的地址在某些总线视角下可能存在偏移(虽然在 MP257 中大部分是统一编址),务必对照参考手册确认 Bus Matrix


章节小结

通过本章,我们完成了 M33 的"深挖洞、广积粮"。M33 现在拥有了受保护的运行内存和用于跨核交换的共享内存。

相关推荐
戴为沐1 天前
Linux内存扩容指南
linux
zylyehuo1 天前
Linux 彻底且安全地删除文件
linux
明月_清风2 天前
开发者网络概念全扫盲:一篇搞定
后端·网络协议
刘马想放假2 天前
Modbus 全栈技术解析:TCP、RTU、ASCII、RTU over TCP
数据结构·网络协议
用户805533698032 天前
主线 U-Boot 上 RK3506:和闭源 rkbin 拔河的三个隐性契约
linux·嵌入式
用户034095297912 天前
linux fcitx 5 雾凇拼音 设置在中文输入法下仍然输入英文标点
linux
王二端茶倒水3 天前
一套可落地的无线运营方案,不能只管 AP,还要管用户、计费和运维
网络协议
162723816083 天前
EtherCAT 分布式时钟(DC)原理与配置实战:把多轴真正"对齐到同一时刻"
网络协议
王二端茶倒水4 天前
宽带无线项目,怎么从一次性交付变成长期运营收入?
网络协议
Web3探索者4 天前
可视化服务器管理和传统命令行区别是什么?新手教程:Linux 运维到底该用图形界面还是 SSH 命令行?
linux·ssh