fix(net): B2 不再丢弃 TCP_CONNECT 命令状态,命令级被拒立即回滚返 -1

问题:net_connect_locked() 调 ch395f_tcp_connect() 后直接丢弃返回值,
而同函数内 open/listen 都查了状态。§9.2.2 ⑧ 明文:发完
CMD_TCP_CONNECT_SN 后须轮询 GET_CMD_STATUS,返回 SUCCESS 仅表示
**命令**执行成功(不代表 TCP 连接成功),其他值表示命令执行失败。
丢弃它 = 命令级被拒时本层停在 CONNECTING,要等 30 s recv 超时才暴露。

修法(不能一刀切):只拦"非 SUCCESS 且非 BUSY"。因为
ch395f_poll_cmd_status() 超时返回的就是 CH395F_ERR_BUSY(= 4 s 内
芯片仍在执行,命令并未被拒绝),把它当失败会误杀慢芯片。明确失败
→ 打 [ERR] rejected by chip: 0xNN 留痕 + 按 §9.2.2 ⑧"再次连接需从
⑤ 重开"关掉 Socket、状态回滚 CLOSED、返 -1(NET_ERR_INVAL)。

顺带修一处错注释:原写"发起 TCP 连接(异步:芯片立即返回)",实际
驱动内部已按 §9.2.2 ⑧ 轮询 GET_CMD_STATUS 最多 4 s,并非立即返回。

硬件回归(Phase 7,NET 层 TCP Client 主动连接):
- TC701 连接 + 64 B 回显逐字节比对 PASS(cksum=0x000007E0)
- TC702 关闭重连 x3 全 PASS → 正常连接路径无误杀
- 不可达对端时芯片回的是 SUCCESS、ret=0 且不打 rejected by chip
  → 失败仍由 CONNECT TIMEOUT(~1.6 s) 裁定,行为未变;新分支只在
  芯片明确说"命令执行失败"时才走
- TC704 socket create #5 FAIL = E-23 既有(NET_MAX_SOCKETS=8 减 3
  个常驻监听 → 并发上限 5,而 PHASE7_MULTI_COUNT 仍是 8),与本次无关
- TC703 要求 PC 服务器离线,与 701/702/704 环境互斥,同轮连跑必有
  一侧失真;其 rc==0 断言等于把"返回值被丢弃"写进判据,真发生命令
  级被拒时它会 FAIL(属正确告警)

前两轮 Phase 7 全灭不是改动问题,已登记为台架坑:本机对
C:\programdata\anaconda3\python.exe 有两条 Public 入站 Block 规则,
而 .venv 的基座解释器正是 Anaconda python;Windows 防火墙块规则优先
于放行规则,故中途加的 8081 端口级 Allow 完全无效,只有临时关 Public
才通。症状极具误导性(芯片 1.6 s 报 CONNECT TIMEOUT、net_connect 仍
返 0、openOK 照常打印),看着像芯片/驱动故障。

残余(登记未动):net_reconcile_tick 仍只裁 ESTABLISHED/LISTENING,
CONNECTING 丢中断无人收口——产品不走出向连接、无法实测,按 Trap 25
"不加未证明的复杂度"只登记不实现。

验证:构建 0 错 0 警、Code=197032;内存快照已刷新;doc-links EXIT=0、
无 U+FFFD;@test 闭环 PASS(戳 fw build: Oct 12 2026 08:03:29
suite=NONE、回读无差异、548 ms)。测试宏已复原,两个测试头文件与
HEAD 字节一致;临时防火墙规则已删除、Public 已重新启用。
This commit is contained in:
2026-10-12 08:17:36 +08:00
parent 9a45be1700
commit 794a688a3c
3 changed files with 27 additions and 6 deletions
+22 -3
View File
@@ -1526,7 +1526,8 @@ int net_connect(int sockfd, const struct net_sockaddr *addr, int addrlen) {
* 函数说明:1. 校验控制块(in_use、TCP 类型、地址参数)并保存对端地址
* 2. 芯片侧 OPEN(失败重试 3 次、间隔 500ms,见 Trap 09)+ 配置源/目的端口与目的 IP
* 3. 清本 Socket 残留中断状态(丢弃上一条连接遗留的 DISCONNECT)
* 4. 发起 TCP_CONNECT 并置 CONNECTING;成败由 net_poll() 的 CONNECT/TIMEOUT 中断裁定
* 4. 发起 TCP_CONNECT(驱动内已轮询 CMD_STATUS)并置 CONNECTING;
* 命令级被拒立即关 Socket 返 -1,TCP 层成败仍由 CONNECT/TIMEOUT 裁定
*/
static int net_connect_locked(int sockfd, const struct net_sockaddr *addr, int addrlen) {
/* Socket 控制块指针 */
@@ -1634,8 +1635,26 @@ static int net_connect_locked(int sockfd, const struct net_sockaddr *addr, int a
(dip >> 8) & 0xFF, dip & 0xFF, dp, st[0], st[1]);
}
/* 发起 TCP 连接(异步:芯片立即返回) */
ch395f_tcp_connect(sockfd);
/* 发起 TCP 连接:驱动内部已按 §9.2.2 ⑧ 轮询 GET_CMD_STATUS(4 s 上限),
* 并非"立即返回"。⚠ §9.2.2 ⑧ 明文:返回 SUCCESS 仅表示**命令**执行成功,
* 不代表 TCP 连接成功;连接结果仍由 CONNECT/TIM_OUT 中断裁定。 */
status = ch395f_tcp_connect(sockfd);
/* BUSY 是 poll 超时的返回值 = 芯片仍在执行,命令并未被拒绝 → 维持原行为,
* 交给 CONNECT/TIM_OUT 裁定,不得当成失败(否则慢芯片会被误杀)。
* 其余非 SUCCESS 均为明确的命令级失败(VAL/ARG/USE/OPEN/IF/MEM/BUF/RTE…):
* 此前返回值被直接丢弃 → 本层停在 CONNECTING 干等 recv 30 s 超时才暴露
* (2026-10-12 审计 B2)。按 §9.2.2 ⑧"再次连接需从 ⑤ 重开"回滚。 */
if ((status != CH395F_ERR_SUCCESS) && (status != CH395F_ERR_BUSY)) {
DBG_ERROR("[CONN] sock%d TCP_CONNECT rejected by chip: 0x%02X", sockfd, status);
(void)ch395f_close_socket((uint8_t)sockfd);
p_sock->state = NET_SOCK_STATE_CLOSED;
return NET_ERR_RETURN_1(NET_ERR_INVAL);
}
if (status == CH395F_ERR_BUSY) {
DBG_INFO("[CONN] sock%d TCP_CONNECT still BUSY after poll, await irq", sockfd);
}
/* 状态 → CONNECTING(等待 CONNECT/TIMEOUT 中断裁定) */
p_sock->state = NET_SOCK_STATE_CONNECTING;