fix(net): N34 阶段0 零风险清理 9 条(注释债/死码/三处小逻辑门)

纯注释/死码(零行为变更):
- 0-1 pump 注释 50ms→100ms(宏真值源 100U,net_socket.c)
- 0-2 D10 give-up 文案改"retry budget exhausted, pump takes over"
  (旧文案夸大永久失效语义,pump 100ms 仍周期认领重建)
- 0-7 IP 字节序注释更正:set_ip/gw/mask 实为点分十进制序(调用方
  parse_ip_string 数组直传、芯片按首段接受、台架多年实证);
  set_des_ip 补"与 get_remot_ipp 输出同序"往返注(ch395f.h/.c)
- 0-8 Trap 13 注释降级为"未证实历史观察"(对齐 2026-10-11 Trap 13
  复核注,与手册 §5.34 相左):DMA 定容理由改"接收缓冲 2KB 整缓冲
  单读=Trap 25 排空契约形态";net_socket.c 四处引用改写
- 0-9 删死声明:GET_GLOB_INT_STATUS(0x29)/ENTER_SLEEP/EEPROM×3/
  GPIO×2/SPI_BEGIN_DELAY_MS/GINT_STAT_SOCK0..3(全仓零引用核实)

小逻辑(台架冒烟实证):
- 0-3 U12 对称:TCP_LISTEN 失败补 close 两处(net_relisten_locked /
  net_listen_locked)——防芯片 Socket 卡"OPEN 无监听"、下轮 open
  恒返 USE(U12 同源事故形态)
- 0-4 retry_tick 状态门:仅 LISTENING/CLOSED 才重试;已转 ESTABLISHED
  (新会话抢先)清陈旧登记,防 open→close 摧毁活连接(认领口径同 pump)
- 0-5 FUN_PARA 裸 0x08 → CH395F_FUN_PARA_SOCKET_CLOSE(复用既有宏
  (1UL<<3),注释补 §5.52/版本/红线口径;曾重复定义触发 9 警告,
  已并入原宏块)
- 0-6 版本门控:ver<0x46 拒置 bit3 并 [ERR] 留痕(防芯片批次漂移;
  本台架 ≥0x46 行为不变,fun_para 日志改打实际值)

验证:@build 全量重编 0 错 0 警(Code=209580,RW/ZI 不变);@test
PASS(回读无差异);冒烟 n30 0/20、:21 @0ms 20/20、:7003 20/20、
ftp_regression 11/11。

门禁说明:doc-links 工作树 junction 伪影按既定口径 SKIP;mem-budget
分支 .map 漂移同前;cppcheck/coding-standard 手跑 Passed。
This commit is contained in:
2026-10-13 05:54:42 +08:00
parent ae17d36f5a
commit 4c0a0af9f8
5 changed files with 80 additions and 38 deletions
+23 -3
View File
@@ -230,6 +230,10 @@ static int net_relisten_locked(int sockfd) {
status = ch395f_tcp_listen((uint8_t)sockfd);
/* LISTEN 失败 → BUSY(同样交重试) */
if (status != CH395F_ERR_SUCCESS) {
/* 0-3(N34 阶段0,U12 对称):open 已成而 LISTEN 失败——不 close 会把
* 芯片 Socket 卡在"OPEN 无监听",下一轮 open 返 USE 又进失败分支
* (U12 同源事故形态)。close 交重试轮,与 open 失败分支同形 */
ch395f_close_socket((uint8_t)sockfd);
/* 置 BUSY(结果回传调用方) */
return NET_ERR_RETURN_1(NET_ERR_BUSY);
}
@@ -394,7 +398,8 @@ int net_listener_try(int sockfd) {
* 函数说明:1. 到点重试待办的重监听;成功即报告探针样本
* 2. 本 fd 有在途挂起 recv 时跳过(net_pending_active,L3 保险:
* 重开 Socket 会摧毁在途连接)
* 3. 超过 NET_RELISTEN_DEADLINE_MS 放弃并记错误日志(防监听器永久失效)
* 3. 超过 NET_RELISTEN_DEADLINE_MS 停止 D10 快速重试并留痕
* (监听不永久失效——pump 100ms 周期仍按"芯片不在听"认领重建)
*/
void net_listener_retry_tick(void) {
/* 当前 tick */
@@ -407,6 +412,20 @@ void net_listener_retry_tick(void) {
if (s_relisten_wait[i] == 0U) {
continue;
}
/* 0-4(N34 阶段0)状态门:仅本层仍 LISTENING/CLOSED 才重试。若已转
* ESTABLISHED(新会话抢先到达),在途重试登记即陈旧——继续跑会
* open→close 摧毁活连接(认领口径与 pump 一致,见 net_listener_pump) */
{
/* 取控制块 */
const net_sock_t *p_sock = net_get_sock(i);
if ((p_sock == NULL) ||
((p_sock->state != NET_SOCK_STATE_LISTENING) &&
(p_sock->state != NET_SOCK_STATE_CLOSED))) {
/* 陈旧登记:清重试状态让位 */
net_listener_clear(i);
continue;
}
}
/* 本 fd 有在途挂起 recv:重开 Socket 会摧毁在途连接(L3 保险) */
if (net_pending_active(i) != 0U) {
continue;
@@ -419,8 +438,9 @@ void net_listener_retry_tick(void) {
if ((int32_t)(now - s_relisten_dead[i]) >= 0) {
/* 清重试状态 */
net_listener_clear(i);
/* 放弃并记错误日志 */
DBG_ERROR("sock%d relisten give up (Trap 09 not cleared)", i);
/* D10 快速重试预算耗尽留痕:后续交 pump 周期接管(N-32 单一重建
* 入口),监听不会永久失效——旧文案"give up"夸大了失效语义 */
DBG_ERROR("sock%d relisten retry budget exhausted, pump takes over", i);
continue;
}
/* 重试成功 */
+28 -9
View File
@@ -254,9 +254,21 @@ static bool s_mac_is_zero(const uint8_t *p_mac) {
/* 复位芯片 */
ch395f_reset();
/* 芯片版本留痕:SOCKET_CLOSE 需 ≥0x46、TCP_SERVER 需 ≥0x44(§5.52 表),
* 版本门槛排查曾是盲区(Trap 25 定案过程确认本芯片 SOCKET_CLOSE 实际生效) */
DBG_INFO("ch395f ver=0x%02X fun_para=0x08", ch395f_get_version());
/* 芯片版本留痕 + 0-6 版本门控(N34 阶段0,§5.52 表):bit3 SOCKET_CLOSE
* 需芯片 ≥0x46、TCP_SERVER 需 ≥0x44。本台架芯片实测 ≥0x46(Trap 25 定案
* SOCKET_CLOSE 实际生效);门控防批次漂移——版本不足则**拒置 bit3**
* (退回芯片自动关断语义)并 [ERR] 留痕,不静默带病运行 */
uint8_t chip_ver = ch395f_get_version();
/* FUN_PARA 实际下发值(版本不足 = 0,bit3 拒置) */
uint8_t fun_para = 0x00U;
if (chip_ver >= 0x46U) {
fun_para = CH395F_FUN_PARA_SOCKET_CLOSE;
} else {
DBG_ERROR("ch395f ver=0x%02X < 0x46: SOCKET_CLOSE(bit3) unsupported, cleared",
chip_ver);
}
/* 版本 + 实际生效 FUN_PARA 留痕(旧日志硬编码 0x08 改为实际值) */
DBG_INFO("ch395f ver=0x%02X fun_para=0x%02X", chip_ver, fun_para);
/* 功能参数(§5.52 表):bit3=1 SOCKET_CLOSE——DISCONNECT/TIMEOUT 后芯片
* 不清缓冲,由 MCU 读出残留数据后再关 Socket(Trap 25 三次定案的排空契约);
@@ -267,7 +279,7 @@ static bool s_mac_is_zero(const uint8_t *p_mac) {
* V1C/V1E/V2.2/V2.3 的 bit0 全是保留位,官方例程 bit0=0 下 Socket 0~7 照常
* 可用、FTP 例程本身就传 0x08;证据链见 Trap 18「定案更正」,
* 0x08 下的多 Socket 台架复测登记 N-31) */
ch395f_set_fun_para(0x08);
ch395f_set_fun_para(fun_para);
/* 设置 TCP MSS:维持 1024(512 裕量方案未采纳,当年支撑它的台架判据不可信,
* 已随 TC-NET-604 结案为非缺陷一并撤回(2026-09-23,见 Trap 21)) */
@@ -1110,6 +1122,10 @@ int net_listen_locked(int sockfd) {
status = ch395f_tcp_listen(sockfd);
/* LISTEN 失败 → BUSY */
if (status != CH395F_ERR_SUCCESS) {
/* 0-3(N34 阶段0,U12 对称):open 已成而 LISTEN 失败必须 close,
* 否则芯片 Socket 卡"OPEN 无监听"、后续 open 恒返 USE(同
* net_relisten_locked 对应分支) */
ch395f_close_socket(sockfd);
return NET_ERR_RETURN_1(NET_ERR_BUSY);
}
@@ -1905,7 +1921,8 @@ static int net_recv_locked(net_sock_t *p_sock, void *buf, int len, int flags,
ch395f_read_recv_buf(sockfd, (uint8_t *)buf, (uint16_t)read_len);
/* 累计接收字节统计 */
p_sock->recv_bytes += (uint32_t)read_len;
/* 已消费数据(注:部分读受 Trap 13 限制,下一次 RECV_OK 会重新置位) */
/* 已消费数据(部分读安全:手册 §5.34 未读数据保留可续读,旧"Trap 13
* 部分读归零"已降级为未证实历史观察;下一次 RECV_OK 重新置 readable) */
p_sock->readable = 0;
/* 返回本次读出字节数 */
return read_len;
@@ -1966,7 +1983,8 @@ static int net_recv_locked(net_sock_t *p_sock, void *buf, int len, int flags,
* ① 数据通道(ESTABLISHED/UDP_OPEN)内 readable 门控 SPI 读——常见无数据路径零额外 SPI 事务
* (INT# 电平触发链保证缓冲有数据时每轮重读 SINT 重位置位)
* ② 到点(与状态无关,旧自旋亦在任何状态下检查超时)→ NET_ERR_TIMEDOUT
* ③ CLOSED:先排空(Trap 13:FIN 可能先于数据)→ 有数据按数据完成,否则 EOF(0) + 自动重监听
* ③ CLOSED:先排空(bit3=1 芯片断连后残数据留缓冲待 MCU 读——Trap 25 排空契约;
* 旧注归 Trap 13 已随其复核注降级)→ 有数据按数据完成,否则 EOF(0) + 自动重监听
* 其他状态(CONNECTING/LISTENING/…)保持等待状态迁移(CONNECT→ESTABLISHED 是合法路径;
* 陈旧 resync 由显式取消处理)——不做状态推断取消,避免误杀正在建链的等待
* 看门狗兜底:到点后仍未了结 = 完成逻辑缺位 → 强制了结留痕
@@ -3386,7 +3404,7 @@ static void handle_disconnect_event(net_sock_t *p_sock) {
/* Trap 22 / N-6:监听态收到 DISCONNECT——bit3=1(0x08)下芯片**不**关该 Socket(停 0x05/0x00,芯片 TCP 侧已 CLOSED);不重开则此后所有 SYN 全被拒 = 监听永久死亡;
* 触发 = 断连后 <~1s 快速复连时 CONNECT 中断未上报(控制块滞留 LISTENING)后该连接断开(2026-09-23 生产固件复现);
* N-32 P2:本分支**只回读留痕、不再 relisten** —— 重建统一交
* net_listener_pump(每 50 ms 回读芯片状态,监听失位即重建)。原处直接
* net_listener_pump(每 100 ms 回读芯片状态,监听失位即重建)。原处直接
* relisten 是 12 个所有者之一,且位于 DISCONNECT 事件路径,可能"抢先"
* 于消费者 recv(P1 已消除其后果,P2 消除其可能) */
/* 回读缓冲(芯片状态 2 字节) */
@@ -3499,11 +3517,12 @@ static void handle_disconnect_event(net_sock_t *p_sock) {
* 返回值:无
* 限定条件:net_poll() 检测到 RECV_OK 中断后调用;netTask 上下文
* 函数说明:1. 仅触发 NET_EVENT_DATA_RECEIVED 回调通知上层
* 2. 不在此读取 recv_len,避免与 net_recv_locked 中的读取冲突(Trap 13)
* 2. 不在此读取 recv_len:单一读取点归 net_recv_locked(省一次 SPI
* 查询;Trap 13 时代的"读取冲突"顾虑已随复核注降级,结构保留)
*/
static void handle_recv_event(net_sock_t *p_sock) {
/* RECV_OK 中断已触发,直接通知上层。不在此读 recv_len,
* 避免和 net_recv_locked 里面的 ch395f_get_recv_len 冲突(Trap 13) */
* 单一读取点在 net_recv_locked(省 SPI;原 Trap 13 顾虑已降级) */
/* 置可读标志,供 net_select 在无 SPI 访问下判读 */
p_sock->readable = 1;
/* 触发数据到达事件回调 */