STM32H750 Bootloader + TCP IAP + SRAM APP 调试记录:从怀疑 TCP 到定位 AXI SRAM 内存布局问题
一、项目背景
近期在 STM32H750 平台上实现基于 Ethernet + LwIP 的 TCP 在线升级(IAP)功能。
系统架构如下:
PC
│
TCP
│
Bootloader
│
QSPI(W25Q64)
│
APP(SRAM运行)
其中:
-
Bootloader 固化在 Flash
-
APP 存储在 W25Q64
-
Bootloader 通过 TCP 接收固件
-
固件写入 W25Q64
-
Bootloader 将 APP 搬运到 SRAM 运行
目标是实现:
TCP升级
↓
APP运行
↓
APP通过TCP触发升级
↓
返回Bootloader
↓
再次升级
二、第一个问题:TCP升级成功但APP无法运行
升级日志如下:
TCP BIN CRC OK
Write IAP info...
IAP info written
Load APP from W25Q64 to SRAM...
Copy to SRAM done
APP Stack: 0x20005120
APP Reset: 0x00000359
Start SRAM APP!!
此时系统无任何输出。
怀疑:
-
APP未成功拷贝
-
跳转失败
-
VTOR错误
-
MSP错误
经过排查发现:
APP链接地址仍为0x00000000
实际上:
APP Reset = 0x00000359
明显不是 SRAM 地址。
修改 APP 工程链接地址后:
APP Reset = 0x240012B1
说明 APP 已经被正确链接到 SRAM。
三、第二个问题:小APP正常,大APP不运行
最小测试 APP:
while(1)
{
printf("APP RUN\r\n");
}
可以正常运行。
但是加入 LwIP 后:
Netif_Config();
程序立即失效。
当时怀疑:
-
Cache
-
MPU
-
ETH DMA
-
中断
-
SysTick
进行了大量排查。
四、定位到 lwip_init()
通过逐层打印:
printf("1\r\n");
lwip_init();
printf("2\r\n");
发现:
1
打印后程序失效。
继续深入:
stats_init();
mem_init();
memp_init();
pbuf_init();
...
sys_timeouts_init();
最终发现:
sys_timeouts_init();
执行后 APP 无法继续运行。
于是开始怀疑:
LwIP内存区配置异常
五、定位到 netif_add()
进一步排查发现:
lwip_init();
实际上已经成功。
真正卡死位置:
netif_add(...)
通过打印:
ethernetif_init 1
low_level_init 1
before HAL_ETH_GetMACConfig
before HAL_ETH_SetMACConfig
before netif_set_up
程序停止。
最开始认为:
netif_set_up()有问题
后来发现并不是。
六、错误方向:一直怀疑TCP
由于现象表现为:
TCP无法连接
netif_set_up卡死
因此一直怀疑:
-
TCP配置
-
netif回调
-
DHCP
-
ETH初始化
甚至尝试:
gnetif.flags |= NETIF_FLAG_UP;
gnetif.flags |= NETIF_FLAG_LINK_UP;
强行绕过。
结果依然无法解决。
七、关键突破:直接烧录Flash竟然正常
做了一个关键实验。
方案A
APP直接烧录Flash:
0x08000000
运行:
正常
TCP正常
LwIP正常
方案B
Bootloader加载SRAM:
异常
说明:
代码本身没问题
问题一定在:
SRAM运行环境
八、发现AXI SRAM空间问题
查看工程配置:
IROM1 = 0x24001000
同时:
IRAM2关闭
此时:
APP代码
LwIP Heap
TCP PCB
PBUF Pool
MEMP Pool
全部挤在 AXI SRAM 中。
而 map 文件显示:
ram_heap 16403
memp_memory_PBUF_POOL 15443
仅这两项:
≈31KB
实际上 AXI SRAM 已经严重紧张。
九、最终验证
经过测试发现:
只有下面配置同时存在:
__attribute__((at(0x30040000)))
ETH_DMADescTypeDef DMARxDscrTab[];
__attribute__((at(0x30040060)))
ETH_DMADescTypeDef DMATxDscrTab[];
__attribute__((at(0x30040200)))
uint8_t Rx_Buff[][];
并且:
IRAM2启用
TCP 才能正常工作。
这说明:
LwIP必须拥有足够的AXI SRAM空间
十、最终解决方案
最终内存布局:
APP代码区
ROM
Start = 0x24060000
Size = 0x20000
即:
128KB
AXI SRAM
IRAM2
Start = 0x24000000
Size = 0x60000
即:
384KB
用于:
LwIP Heap
TCP PCB
PBUF Pool
MEMP Pool
DTCM
IRAM1
0x20000000
Size = 0x20000
用于:
栈
全局变量
普通数据
ETH DMA
固定:
__attribute__((at(0x30040000)))
DMARxDscrTab
__attribute__((at(0x30040060)))
DMATxDscrTab
__attribute__((at(0x30040200)))
Rx_Buff
十一、Bootloader修改
APP基地址:
#define SRAM_APP_ADDR 0x24060000
跳转:
SCB->VTOR = 0x24060000;
APP工程:
SCB->VTOR = 0x24060000;
同时更新:
Load_APP_From_QSPI()
Jump_To_APP()
相关地址检查。
十二、最终结果
实现:
PC
│
TCP
│
Bootloader
│
W25Q64
│
SRAM APP
│
TCP业务
│
TCP触发升级
│
返回Bootloader
│
再次升级
全部稳定运行。
十三、经验总结
本次调试最大的收获是:
很多时候程序表现为:
TCP异常
LwIP异常
netif_set_up卡死
并不一定是网络问题。
真正原因可能是:
内存布局不合理
AXI SRAM不足
Heap空间不足
DMA缓冲区位置错误
STM32H7 的 ETH + LwIP 对内存区域非常敏感。
最终问题本质上并不是:
TCP有Bug
而是:
APP代码占用了AXI SRAM
导致LwIP失去了足够的运行空间
这是本次调试中最重要的结论。
更多推荐



所有评论(0)