第 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 现在拥有了受保护的运行内存和用于跨核交换的共享内存。

相关推荐
Brilliantwxx3 小时前
【STM32】 深度详解总线架构 哈佛总线结构
stm32·嵌入式硬件·架构
Zenova EdgeOS3 小时前
Linux eBPF 工业边缘性能观测实战
linux·服务器·网络
恶魔泡泡糖3 小时前
stm32F103C8T6标准库DWT应用DHT11温湿度传感器数据手册说明
stm32·单片机·嵌入式硬件
深圳市恒锐丰科技杨生3 小时前
EG1192S 10‑100V 高压集成上管降压 DC‑DC|零功耗使能 Buck 电源芯片
嵌入式硬件·硬件工程
单片机仿真设计3 小时前
【Proteus 仿真】基于 STM32 单片机鸡舍环境监控系统设计(仿真 + 源码)
stm32·单片机·嵌入式硬件·proteus·毕设
skywalk81633 小时前
通过下载Ubuntu ova文件在Virtual Box快速安装ubuntu
linux·运维·ubuntu·virtualbox
wuminyu4 小时前
JVM锁膨胀与Futex源码解析
java·linux·c语言·jvm·c++
斑马1394 小时前
Linux软件编程学习笔记(十一)——HTTP协议
linux·笔记·学习
OpenPomeloxCommunity4 小时前
Linux驱动基础(一):模块机制的设计与实现
linux
Shadow(⊙o⊙)4 小时前
Linux网络——文件与网络的连接桥梁struct sock {
linux·运维·网络