STM32F7读文本文件分段POST提交时Web服务随机冻结问题
问题核心诱因
- 你用
setInterval+同步form.submit()的发送逻辑完全没有和STM32端的处理节奏对齐。STM32上运行的轻量Web服务器(一般基于lwip实现)TCP接收缓存极小,同步表单提交不会等待上一个请求的响应返回就触发下一次发送,非常容易打满接收缓存造成内存溢出,触发硬错误导致服务器冻结。测试用固定短字符串AAAA单包payload仅150字节左右,STM32接收、处理速度快,刚好能赶上你设置的发送间隔才不会出错;实际文件单包长度达1200+字节,加上STM32写Flash的耗时,随机出现缓存溢出就会导致20~200次请求后随机失败。 - 切片逻辑缺失边界校验。你固定按每行41字节、每次30行切片,没有判断偏移是否超出文件总长度,当发送接近文件末尾时,很容易切出空值、
undefined或者长度和HTTP头Content-Length不匹配的残缺请求,STM32端的HTTP解析器会一直等待不存在的后续字节,直接进入死锁状态。 - 收发和Flash操作时序冲突。STM32擦写内部Flash时需要关闭全局中断,如果你在HTTP数据还没接收/发送完成时就触发Flash写操作,会直接丢TCP包,若重传逻辑异常就会导致连接断开、服务器挂死。
可行解决建议
- 前端替换同步表单提交为异步请求,严格按“等上一包收到200响应再发下一包”的节奏传输,彻底弃用
setInterval盲发逻辑。不要用application/x-www-form-urlencoded表单格式,直接发原始文本减少STM32解析开销,参考实现如下:
let offset = 0; const CHUNK_LINES = 20; // 可以先调小包大小,稳定后再加大 const LINE_BYTES = 41; // 先确认你的文件实际是\n(40字节/行)还是\r\n(41字节/行)换行 async function startUpload() { while (offset < fich.length) { const endPos = Math.min(offset + CHUNK_LINES * LINE_BYTES, fich.length); const chunk = fich.slice(offset, endPos); // 等待请求响应再继续 const res = await fetch('/api/write_flash', { method: 'POST', headers: {'Content-Type': 'text/plain'}, body: chunk }); if (!res.ok) throw new Error(`传输失败,偏移${offset}`); offset = endPos; // 这里可以加进度条更新逻辑 } // 全量传输完成后,再发请求触发bootloader跳转 await fetch('/api/run_bootloader', {method: 'POST'}); }
- STM32端做时序和稳定性适配:
- 每收完一整包数据(按HTTP头的
Content-Length判断收全),先给浏览器回完HTTP 200响应,再执行Flash擦写操作,不要边收数据边写Flash,避免关中断导致丢包。 - 固定HTTP接收缓存大小,不要用动态内存分配;单包大小建议先控制在1KB以内(对应20行左右数据),适配STM32F7以太网MAC的帧缓存上限,稳定后再尝试调大包长提升速度。
- 加连接超时机制:如果超过5秒没收到完整的HTTP请求,直接复位当前TCP连接、清空接收缓存,不要死等字节导致服务器卡死。
- 每收完一整包数据(按HTTP头的
- 修复切片逻辑:每次切片前判断偏移是否超出文件总长度,最后一包不足整行时按实际长度发送,不要拼接
undefined或者无效内容。
内容的提问来源于stack exchange,提问作者ced74
相关产品推荐
相关产品推荐

