fix(tcp): MUX模式网口失联 — 对端关闭时用tcp_abort替代tcp_close避免TIME_WAIT耗尽pcb池

根因: tcp_close()将对端关闭的pcb推入TIME_WAIT(120s), 占用MEMP_TCP_PCB池(仅4个),
多连接同时断开后pcb池耗尽, tcp_new()返回NULL, 新连接无法建立直到120s超时释放。

核心修复:
- tcp_server/client: 对端关闭(p=NULL)时tcp_abort替代tcp_close, pcb立即释放
- ch390_runtime: PKT_ERR恢复强制OR上RCR_RXEN(与WCH官方一致)
- ch390_runtime: TX连续超时3次自动emergency reset
- ch390_runtime: 每5秒health_check读VID验证芯片存活
- main: App_StartLinksIfNeeded失败时不标记g_links_started, 允许重试
- main: MUX逐帧RTT printf改为#if DEBUG门控, 减少主循环延迟
- uart_trans: MUX帧解析改为先搜0x7E再消费header, 非法帧只丢1字节
This commit is contained in:
2026-04-14 03:44:26 +08:00
parent efb88ea367
commit 31a3da48fa
7 changed files with 151 additions and 19 deletions
+28 -1
View File
@@ -417,10 +417,37 @@ python .\tools\tcp_debug_server.py --host 0.0.0.0 --port 8081 --no-stdin
1. PHY 访问无超时,导致永久卡死
2. 刷新未初始化的 IWDG 句柄导致 HardFault
3. 在长耗时 SPI 路径中错误扩大临界区,导致看似系统假死
3. 在长耗时 SPI 路径中错误扩大临界区,导致看似"系统假死"
4. 在多个层次同时触达 CH390 / SPI,导致运行时边界混乱
5. 配置口命令结束方式不对,导致误判为 parser 无响应
### 9.4 2026-04-14 MUX 模式网口失联修复记录
#### 现象
MUX 模式启动后,一段时间后网口失联。重新插拔网线无法恢复,重启后恢复正常。对端主动关闭 TCP 连接后,120 秒内无法重新建立连接。
#### 根因
对端主动关闭 TCP 连接时,`tcp_server_on_recv(p=NULL)``tcp_client_on_recv(p=NULL)` 调用 `tcp_close()` 关闭本地 pcb。`tcp_close()` 发送 FIN 后将 pcb 推入 TIME_WAIT 状态,持续 `2 × TCP_MSL = 120 秒`。在此期间 pcb 占用 `MEMP_TCP_PCB` 池(总量仅 4 个)。当多条连接同时断开后,pcb 池耗尽,新连接的 `tcp_new()` 返回 NULL。
#### 修复内容
| 文件 | 修改 | 说明 |
|------|------|------|
| `App/tcp_server.c` | `tcp_close(pcb)``tcp_abort(pcb)` | 对端关闭时立即释放 pcb,不进入 TIME_WAIT |
| `App/tcp_client.c` | `tcp_close(pcb)``tcp_abort(pcb)` | 同上 |
| `Drivers/CH390/ch390_runtime.c` | PKT_ERR 恢复时 `rcr``rcr \| RCR_RXEN` | 确保 RX 重新使能,与 WCH 官方参考一致 |
| `Drivers/CH390/ch390_runtime.c` | TX 连续超时 3 次触发 `ch390_runtime_emergency_reset()` | CH390 TX 引擎卡死时自动复位芯片 |
| `Drivers/CH390/ch390_runtime.c` | 新增 `ch390_runtime_health_check()` | 每 5 秒读 VID 验证芯片存活 |
| `Core/Src/main.c` | `App_StartLinksIfNeeded` 失败时不标记 `g_links_started` | 允许下次 poll 自动重试 |
| `Core/Src/main.c` | MUX 逐帧 RTT printf 改为 `#if DEBUG` 门控 | 生产固件不输出,减少主循环延迟 |
| `App/uart_trans.c` | `uart_mux_try_extract_frame` 先搜 0x7E 再消费 header | 非法帧只丢 1 字节而非 5 字节 |
#### 构建验证
Keil MDK-ARM 构建 0 Error(s), 0 Warning(s)。Flash 52.7 KB / 64.0 KB (82.5%)RAM 20.0 KB / 20.0 KB (100%)。
---
## 10. 常见误区