用 STM32H750 通过 QSPI 挂载外扩 NOR FLASH、开内存映射模式跑程序,大概率会碰到一个超级隐蔽的坑:常温正常运行,大约 2 小时后必然死机,且死机位置不固定,有时死在定时器入口,有时死在中断赋值语句,怎么查都找不到原因。
这篇 LAT1151 是 ST 官方给出的标准答案,告诉你这不是硬件问题、不是电源问题,而是H750 勘误 + Cache 预取 + QSPI 内存映射共同引发的 BUG。
资料获取:【应用笔记】LAT1151 程序运行在 STM32H750 的外扩 FLASH 上两小时后死机
1. 典型故障现象(完全一致就是同款问题)
- 芯片:STM32H750VBT6
- 外扩:QSPI NOR FLASH(4MB)
- 模式:Memory Map 内存映射(XIP)
- 现象:运行约2 小时左右必死机
- 死机位置不固定:TIM15 入口、中断内赋值语句
- 关闭 I-Cache 或 D-Cache 后,问题消失
- 代码量并没有占满 FLASH
2. 真正根因:H750 勘误 + Cortex-M7 预取机制
LAT1151 明确指出:这是 STM32H750xB/H753xI 官方勘误(ES0396 2.4.4) 问题:QSPI 内存映射模式下,读取 FSIZE 配置区域的最后一个字节,会导致 AXI 总线挂死(stall),CPU 直接卡死。
再加上 Cortex‑M7 指令预取 & 分支预测:即使你的代码没到 FLASH 末尾,CPU 也会提前预读后面的地址,最终触发 “最后一字节读取”,导致总线死锁。
时间随机 = 预取随机 → 2 小时左右命中一次。
3. 官方唯一正确解决方案(直接照做)
3.1 QSPI Flash Size 配置 “放大一倍”
不要配置实际大小,故意设大,留出安全裕量,避开最后一字节。
例:4MB FLASH → 配置成 8MB
QSPIHandle.Init.FlashSize = POSITION_VAL(8*1024*1024) - 1;
3.2 配置 MPU 保护
把实际不存在的空间设为 “禁止访问”,防止 CPU 乱读。
MPU 规则:
- Region0:4GB 空间 → NO_ACCESS
- Region1:0x90000000 4MB → 允许访问、允许 Cache、允许执行
3.3 保持 Cache 开启
不用关 Cache,性能不受影响。
4. 为什么关 Cache 能临时解决?
因为关闭 Cache 后,M7 不再预取指令,不会触发 “读取最后一字节” 动作。
但关 Cache 会让性能暴跌,不能用于量产。
5. 最简总结(工程师记这 3 条)
- H750 QSPI 内存映射不能读配置空间最后 1 字节,否则总线死锁
- M7 会自动预取,所以代码没到末尾也会触发
- 解决方法:
- FlashSize 设大一点
- MPU 保护无效地址
- Cache 正常开
STM32H750 外扩 QSPI FLASH 长时间死机,是勘误导致的读最后一字节 AXI 挂死。通过放大 FlashSize + MPU 保护,即可彻底根治,不需要关 Cache,不影响性能。
89