fix(vd960DBN): 联网 SocketSend 0x11 死循环 — 发送退避 + SocketCreat 失败中止
现象: loop_data 606B 发送 0x11(ERR_MEM) → 立即重试10次 → 3次断连 → 重连 SocketCreat 0x1D(ISCONN) 仍继续 Connect → timeout 死循环永久失联 根因: 1. WCHNET_NUM_TCP_SEG=2 (瘦身改小): 重传队列占用即无发送缓冲 → 0x11 瞬时 2. iot_mqtt_send 失败处理过激: 无退避立即重试 + 3次就强制断连 3. WCHNET_CreateTcpMqttSocket: SocketCreat 失败(mStopIfError只打印)仍继续 Connect → 无效 socket 等超时死循环; SocketId_TCP 未置 0xFF 沿用旧 id 修复: - iot_mqtt_send: 0x11 200ms 退避重试(≤10次, 等SEG释放), 不立即断连 - 强制重连: 补 SocketId_TCP=0xFF - WCHNET_CreateTcpMqttSocket: SocketCreat 失败置 0xFF + return 不 Connect, 上层指数退避 验证: 语法 0 错误; 待板级确认重发自动恢复 + 重连退避
This commit is contained in:
@@ -351,19 +351,32 @@ static int iot_mqtt_send(const uint8_t *buf, uint16_t len) {
|
|||||||
uint32_t slen = len - total_sent;
|
uint32_t slen = len - total_sent;
|
||||||
uint8_t ret = WCHNET_SocketSend(g_iot_socket, (uint8_t *)(buf + total_sent), &slen);
|
uint8_t ret = WCHNET_SocketSend(g_iot_socket, (uint8_t *)(buf + total_sent), &slen);
|
||||||
total_sent += (uint16_t)slen;
|
total_sent += (uint16_t)slen;
|
||||||
if (slen == 0 || ret != WCHNET_ERR_SUCCESS || ++retries > 10) {
|
if (slen == 0 || ret != WCHNET_ERR_SUCCESS) {
|
||||||
_iot_send_fail_cnt++;
|
/* 0x11 = WCHNET_ERR_MEM: 瞬时发送缓冲不足 (WCHNET_NUM_TCP_SEG=2 极小,
|
||||||
PRINT("IOT: SocketSend FAIL#%d ret=0x%02X sent=%u/%u\n",
|
重传队列占用即无缓冲)。200ms 退避重试等 WCHNET 释放 SEG —
|
||||||
_iot_send_fail_cnt, ret, total_sent, len);
|
不要立即断连: 断连重连会让 WCHNET socket 表更乱
|
||||||
if (_iot_send_fail_cnt >= 3) {
|
(SocketCreat ISCONN 死循环, 2026-08-20 现场) */
|
||||||
PRINT("IOT: SocketSend 3 consecutive failures, forcing reconnect\n");
|
if (ret == WCHNET_ERR_MEM && retries < 10) {
|
||||||
WCHNET_SocketClose(g_iot_socket, TCP_CLOSE_NORMAL);
|
uint32_t w = mstick();
|
||||||
g_iot_socket = 0xFF;
|
while ((mstick() - w) < 200) { } /* 退避 (IWDG 4s 内安全) */
|
||||||
g_iot_state = IOT_STATE_DISCONNECTED;
|
|
||||||
_iot_send_fail_cnt = 0;
|
|
||||||
_iot_reconnect_deadline = mstick() + 3000; // 3s 后重连, 让 WCHNET 清旧 socket
|
|
||||||
}
|
}
|
||||||
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; // 成功一次就清零
|
_iot_send_fail_cnt = 0; // 成功一次就清零
|
||||||
|
|||||||
@@ -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);
|
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);
|
mStopIfError(i);
|
||||||
i = WCHNET_SocketConnect(SocketId_TCP); //make a TCP connection
|
i = WCHNET_SocketConnect(SocketId_TCP); //make a TCP connection
|
||||||
if(i == WCHNET_ERR_SUCCESS)
|
if(i == WCHNET_ERR_SUCCESS)
|
||||||
|
|||||||
@@ -4,6 +4,33 @@
|
|||||||
>
|
>
|
||||||
> 项目定位: DLD960 通信板 — BLE 配网、TCP JSON 协议服务、Loop MCU 串口桥接
|
> 项目定位: 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 全错)
|
## 2026-08-20 — OTA 下载失败修复:hex 提取不兼容 json.dumps 空格(单片 CRC 全错)
|
||||||
|
|
||||||
### 现象(板级)
|
### 现象(板级)
|
||||||
|
|||||||
Reference in New Issue
Block a user