第 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->REGION[0].START_ADDR = 0x0E000000;

RIF_RISAF1->REGION[0].END_ADDR = 0x0E03FFFF;

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

相关推荐
BHXDML2 小时前
VMware Workstation Pro 安装详细教程(超详细图文讲解)
linux·虚拟机
一路往蓝-Anbo2 小时前
第 8 章:M33 领航——引导 A35 加载 U-Boot 与 Linux 内核
linux·运维·服务器·stm32·单片机·嵌入式硬件·网络协议
一路往蓝-Anbo3 小时前
第 6 章:GPIO 与外部中断——M33 掌控下的 LED 与按键响应
linux·stm32·单片机·嵌入式硬件
闲人编程4 小时前
任务监控与错误重试
linux·服务器·网络·celery·任务队列·任务监控·错误重试
LCG元4 小时前
直流电机闭环控制:STM32F1 PWM+ADC电流采集,PID调速实战
stm32·单片机·嵌入式硬件
hoududubaba5 小时前
ORAN C平面传输和基本功能——基于DMRS的波束赋形和SINR报告
网络·网络协议
Y1rong6 小时前
STM32之MQTT
stm32
REDcker6 小时前
FTP协议原理及应用精解
linux·后端·计算机网络·互联网·ftp·服务端开发
Zeku6 小时前
TCP交错传输多通道实现原理
stm32·freertos·linux应用开发