diff --git a/vd960DBN/BLE/OnlyUpdateApp_Peripheral/APP/iot_mqtt_srv.c b/vd960DBN/BLE/OnlyUpdateApp_Peripheral/APP/iot_mqtt_srv.c index 359f034..05c91fa 100644 --- a/vd960DBN/BLE/OnlyUpdateApp_Peripheral/APP/iot_mqtt_srv.c +++ b/vd960DBN/BLE/OnlyUpdateApp_Peripheral/APP/iot_mqtt_srv.c @@ -351,19 +351,32 @@ static int iot_mqtt_send(const uint8_t *buf, uint16_t len) { uint32_t slen = len - total_sent; uint8_t ret = WCHNET_SocketSend(g_iot_socket, (uint8_t *)(buf + total_sent), &slen); total_sent += (uint16_t)slen; - if (slen == 0 || ret != WCHNET_ERR_SUCCESS || ++retries > 10) { - _iot_send_fail_cnt++; - PRINT("IOT: SocketSend FAIL#%d ret=0x%02X sent=%u/%u\n", - _iot_send_fail_cnt, ret, total_sent, len); - if (_iot_send_fail_cnt >= 3) { - PRINT("IOT: SocketSend 3 consecutive failures, forcing reconnect\n"); - WCHNET_SocketClose(g_iot_socket, TCP_CLOSE_NORMAL); - g_iot_socket = 0xFF; - g_iot_state = IOT_STATE_DISCONNECTED; - _iot_send_fail_cnt = 0; - _iot_reconnect_deadline = mstick() + 3000; // 3s 后重连, 让 WCHNET 清旧 socket + if (slen == 0 || ret != WCHNET_ERR_SUCCESS) { + /* 0x11 = WCHNET_ERR_MEM: 瞬时发送缓冲不足 (WCHNET_NUM_TCP_SEG=2 极小, + 重传队列占用即无缓冲)。200ms 退避重试等 WCHNET 释放 SEG — + 不要立即断连: 断连重连会让 WCHNET socket 表更乱 + (SocketCreat ISCONN 死循环, 2026-08-20 现场) */ + if (ret == WCHNET_ERR_MEM && retries < 10) { + uint32_t w = mstick(); + while ((mstick() - w) < 200) { } /* 退避 (IWDG 4s 内安全) */ } - return -1; + retries++; + if (retries > 10) { + _iot_send_fail_cnt++; + PRINT("IOT: SocketSend FAIL#%d ret=0x%02X sent=%u/%u\n", + _iot_send_fail_cnt, ret, total_sent, len); + if (_iot_send_fail_cnt >= 3) { + PRINT("IOT: SocketSend 3 consecutive failures, forcing reconnect\n"); + WCHNET_SocketClose(g_iot_socket, TCP_CLOSE_NORMAL); + g_iot_socket = 0xFF; + SocketId_TCP = 0xFF; /* 防重连 SocketCreat 沿用旧 id (2026-08-20) */ + g_iot_state = IOT_STATE_DISCONNECTED; + _iot_send_fail_cnt = 0; + _iot_reconnect_deadline = mstick() + 3000; // 3s 后重连, 让 WCHNET 清旧 socket + } + return -1; + } + continue; /* 重试 (MEM 已退避 200ms, 其他错误立即重试) */ } } _iot_send_fail_cnt = 0; // 成功一次就清零 diff --git a/vd960DBN/BLE/OnlyUpdateApp_Peripheral/APP/net_srv.c b/vd960DBN/BLE/OnlyUpdateApp_Peripheral/APP/net_srv.c index 3acfb03..5e6cb90 100644 --- a/vd960DBN/BLE/OnlyUpdateApp_Peripheral/APP/net_srv.c +++ b/vd960DBN/BLE/OnlyUpdateApp_Peripheral/APP/net_srv.c @@ -346,6 +346,13 @@ void WCHNET_CreateTcpMqttSocket(void) { PRINT("WCHNET_MQTT_SocketCreate %d,desIP:%d.%d.%d.%d, des_port:%d, srcport:%d\r\n", SocketId_TCP, RemoteIP[0],RemoteIP[1],RemoteIP[2],RemoteIP[3], iot_net_info.mqtt_port, TmpSocketInf.SourPort); } + if (i != WCHNET_ERR_SUCCESS) { + /* 2026-08-20: SocketCreat 失败 (0x1D ISCONN 等, 旧 socket 未清干净) + 置无效并返回, 由上层退避重试 — 继续 Connect 只会等超时死循环 */ + PRINT("MQTT: SocketCreat failed 0x%02X, abort connect\r\n", i); + SocketId_TCP = 0xFF; + return; + } mStopIfError(i); i = WCHNET_SocketConnect(SocketId_TCP); //make a TCP connection if(i == WCHNET_ERR_SUCCESS) diff --git a/vd960DBN/docs/devlog.md b/vd960DBN/docs/devlog.md index ae90aa9..59f6822 100644 --- a/vd960DBN/docs/devlog.md +++ b/vd960DBN/docs/devlog.md @@ -4,6 +4,33 @@ > > 项目定位: DLD960 通信板 — BLE 配网、TCP JSON 协议服务、Loop MCU 串口桥接 +## 2026-08-20 — 联网 SocketSend 0x11 死循环修复:发送退避 + SocketCreat 失败中止 + +### 现象(板级) + +收 report_config 后 loop_data(606B)发送失败:`SocketSend FAIL ret=0x11 sent=0/606` → 立即重试 10 次无效 → 3 次强制断连 → 重连 SocketCreat 返回 **0x1D(ISCONN)** + Connect 0x17(CLSD) → TCP connect timeout 死循环,永久失联。 + +### 根因 + +1. **WCHNET_NUM_TCP_SEG = WCHNET_NUM_TCP×2 = 2**(RAM 瘦身改小):TCP 发送段缓冲仅 2 个,重传队列占用即无缓冲 → 606B 发送 `WCHNET_ERR_MEM(0x11)` +2. **iot_mqtt_send 失败处理过激**:0x11 是瞬时(SEG 被占),却立即重试 10 次(无退避,WCHNET 没时间释放)+ 3 次就强制断连 +3. **重连缺陷**:`WCHNET_CreateTcpMqttSocket` 里 SocketCreat 失败(0x1D ISCONN,旧 socket 未清干净)后**仍继续 Connect**(mStopIfError 只打印不中止)→ 无效 socket 等超时 → 死循环;且强制重连时 `SocketId_TCP` 未置 0xFF,SocketCreat 沿用旧 id + +### 修复 + +| 位置 | 改动 | +|------|------| +| `iot_mqtt_srv.c` iot_mqtt_send | 0x11 时 **200ms 退避重试**(等 WCHNET 释放 SEG,最多 10 次×200ms≈2s),不立即断连;非 MEM 错误立即重试 | +| `iot_mqtt_srv.c` 强制重连 | 补 `SocketId_TCP = 0xFF`(防 SocketCreat 沿用旧 id) | +| `net_srv.c` WCHNET_CreateTcpMqttSocket | SocketCreat 失败 → 打印 + `SocketId_TCP=0xFF` + **return 不 Connect**,由上层指数退避重试 | + +### 验证 + +- 语法 0 错误 +- **待板级确认**:重发场景(瞬时 0x11)应自动恢复不断连;真断连重连失败应退避而非死循环 + +--- + ## 2026-08-20 — OTA 下载失败修复:hex 提取不兼容 json.dumps 空格(单片 CRC 全错) ### 现象(板级)