这个问题抓得非常关键!STM32H7 运行 LWIP 时的死机故障,大多源于 MPU 配置缺失或不当 —— 默认 MPU 配置仅适配简单应用,LWIP+ETH 的复杂场景需针对性配置存储域、内存类型和地址分配,核心是将 ETH 缓存放在 D2 域 SRAM、设为 Device 类型,同时合理分配 LWIP 堆栈地址。
资料获取:开发经验 | LAT1510 STM32H7xx运行LWIP时的MPU配置介绍
1. 问题背景:为什么 LWIP 场景必须配置 MPU?
STM32H7 的 CubeMX 默认会启用 MPU 并配置基础规则(4GB 地址范围,特权访问),简单应用(无 ETH、USB)可正常运行,但运行 LWIP 时会因三个核心矛盾触发死机:
- 缓存存储域错误:ETH 专用 DMA 无法访问 DTCM RAM,但默认配置可能将 LWIP 缓存分配到 DTCM;
- 内存类型冲突:Cortex-M7 对 Normal 类型内存乱序访问,直接写入 ETH 寄存器会导致数据错乱;
- 总线访问限制:ETH_MAC 仅能访问 D2 域 SRAM,默认缓存分配可能超出该范围。
2. 核心诱因:LWIP+ETH 的 MPU 配置三大关键诉求
2.1 存储域要求:缓存必须放在 D2 域 SRAM
STM32H7 的 D2 域 SRAM(如 SRAM1/2,地址 0x30000000 起)是 ETH_MAC 可访问的唯一区域,需将以下 LWIP 核心缓存分配至此:
- 接收 / 发送描述符(DMARxDscrTab、DMATxDscrTab);
- 接收内存池(memp_memory_RX_POOL_base);
- LWIP 堆(LwIP heap)。
2.2 内存类型要求:ETH 缓存需设为 Device 类型
- Normal 类型:适用于 LWIP 堆栈(无外设交互,允许乱序访问);
- Device 类型:适用于 ETH TX/RX 缓存(强顺序访问,匹配外设寄存器操作);
- 禁用 Cache:LWIP 未实现 Cache 一致性操作,缓存区需关闭 Cache。
2.3 地址分配要求:遵循官方推荐地址映射
不同 STM32H7 系列的推荐地址不同,以常用型号为例:
| 型号系列 | 缓存变量 | 起始地址 | 大小 | 源文件 |
|---|---|---|---|---|
| STM32H723/733/725/735/730 | DMARxDscrTab | 0x30000000 | 96B(最大 256B) | ethernetif.c |
| DMATxDscrTab | 0x30000100 | 96B(最大 256B) | ethernetif.c | |
| memp_memory_RX_POOL_base | 0x24000000 | 12*(1536+24)B | ethernetif.c | |
| LwIP heap | 0x30000200 | 32232B(32KB-512B-24B) | lwipopts.h | |
| STM32H742/743/753/750 | LwIP heap | 0x30020000 | 131048B(128KB-24B) | lwipopts.h |
3. MPU 配置实操:以 STM32H723ZG 为例
需配置 2 个 MPU 区域,分别对应 LWIP 堆栈和 ETH 缓存,配合 ETH 与 LWIP 参数设置,步骤如下:
3.1 区域 1:LWIP 堆栈区配置(Normal 类型)
用于 LWIP 堆和内存池,属性为 Non-cacheable Normal 内存:
| 配置项 | 取值 | 说明 |
|---|---|---|
| MPU Region | Enabled | 启用该区域 |
| 基地址 | 0x30000000 | 对应 D2 域 SRAM1 起始地址 |
| 区域大小 | 32KB | 覆盖 LWIP 堆和部分缓存 |
| 子区域禁用 | 0x0 | 全部子区域启用 |
| TEX 字段等级 | level1(TEX=001) | 配合 C/B 设置内存类型 |
| 访问权限 | ALL ACCESS PERMITTED | 允许所有权限访问 |
| 指令访问 | DISABLE | 仅数据访问,禁用指令执行 |
| 可共享性 | DISABLE | 私有数据区域,无需共享 |
| Cacheable(C) | DISABLE | 禁用 Cache(LWIP 无 Cache 一致性) |
| Bufferable(B) | DISABLE | 禁用缓冲 |
| 内存类型 | Normal(Non-cacheable) | 匹配堆栈数据访问需求 |
3.2 区域 2:ETH TX/RX 缓存区配置(Device 类型)
用于描述符和接收缓冲区,属性为 Shared Device 内存:
| 配置项 | 取值 | 说明 |
|---|---|---|
| MPU Region | Enabled | 启用该区域 |
| 基地址 | 0x30000000 | 与堆栈区同起始,大小隔离 |
| 区域大小 | 512B | 覆盖 2 个描述符(共 192B) |
| 子区域禁用 | 0x0 | 全部子区域启用 |
| TEX 字段等级 | level0(TEX=000) | 配合 C/B 设置内存类型 |
| 访问权限 | ALL ACCESS PERMITTED | 允许所有权限访问 |
| 指令访问 | DISABLE | 仅数据访问 |
| 可共享性 | ENABLE | 外设(ETH DMA)与 CPU 共享 |
| Cacheable(C) | DISABLE | 禁用 Cache |
| Bufferable(B) | ENABLE | 启用缓冲,匹配外设访问 |
| 内存类型 | Device(Shared) | 强顺序访问,避免数据错乱 |
3.3 ETH 与 LWIP 参数补充配置
(1)ETH 配置(CubeMX)
- 发送描述符起始地址:0x30000100(DMATxDscrTab);
- 接收描述符起始地址:0x30000000(DMARxDscrTab);
- 接收缓冲区地址:0x30000200;
- 接收缓冲区长度:1536B(以太网 MTU 值)。
(2)LWIP 配置(lwipopts.h)
- 堆内存大小(MEM_SIZE):32232B;
- 堆内存起始地址(LWP_RAM_HEAP_POINTER):0x30000200;
- 启用内存保护(SYS_LIGHTWEIGHT_PROT):Enabled。
4. 关键参数解读:TEX、C、B 的组合逻辑
MPU 的内存类型由 TEX(存储类型扩展)、C(Cacheable)、B(Bufferable)三者组合决定,LWIP 场景核心组合如下:
| TEX(二进制) | C | B | 内存类型 | 适用场景 |
|---|---|---|---|---|
| 001 | 0 | 0 | Normal(Non-cacheable) | LWIP 堆栈、内存池 |
| 000 | 0 | 1 | Device(Shared) | ETH TX/RX 缓存、描述符 |
- TEX=001+C=0+B=0:禁止 Cache 和缓冲,Normal 类型保证数据访问稳定性;
- TEX=000+C=0+B=1:Shared Device 类型,强顺序访问,适配 ETH 外设交互。
5. 验证方法:确认配置生效
- 编译验证:无内存访问报错,链接时无地址重叠警告;
- 运行验证:LWIP 正常初始化,ETH 能收发数据,系统无死机、无数据丢包;
- 调试验证:通过调试器查看 MPU 寄存器(MPU_RNR、MPU_RBAR、MPU_RASR),确认配置参数与预期一致。
STM32H7 运行 LWIP 的 MPU 配置核心逻辑:“分区域定义内存属性,精准匹配存储域和访问需求”。无需复杂配置,只需聚焦两个关键区域 ——LWIP 堆栈(Normal 类型 + D2 域 SRAM)和 ETH 缓存(Device 类型 + 共享属性),再配合官方推荐的地址分配,即可彻底解决死机问题。
143