docs+net: FUN_PARA 定案 0x08——bit0 保留位证伪,Trap18 定案更正 + N-31

CH395F FUN_PARA 的 bit0 之争定案:取 0x08(bit3 SOCKET_CLOSE=1,bit0=0)。

证据(一手,按强度):
- 官方手册 V2.2/V2.3 与旧版 V1C/V1E/2020 版 §5.52 位表:bit0 一律
  「保留,必须为0」,任何版本都不存在「bit0=多 Socket」这一行。
- 官方 SDK CH395INC.H:349-353 位宏只有 bit1/3/4/7/8,无 bit0 宏。
- 官方例程直接反例:EXAM5_TCP_Server 传 0x02(bit0=0)却给 Socket 0~7
  全部配缓冲;EXAM11_FTPClient 直接传 0x08;全 EVT 包无一处 0x09。
- 手册命令章前言:8 Socket 是芯片原生能力,靠 _SN 索引寻址;§5.45
  真正的门槛是缓冲分配(Socket 个数 >4 须重分配缓冲)。
- 概念讹传源是 bit1 FUN_PARA_FLAG_TCP_SERVER(服务器多连接,§9.2.6)。
- 互联网检索无任何出处称 bit0 为单/多 Socket 模式。

Trap 18 的「bit0 决定 Socket 数量」是推论而非实测:无日志、无 TC 号,
且当年 Socket 1~7 未显式配缓冲(Trap 01/02 混淆因子未排除);TC704
40/40 与结论出自同一提交,属自证,不构成 0x08 的对照。

改动:
- net_socket.c:0x09→0x08(原为未提交改动,现已过编译门禁)+ 版本留痕
- ch395f_reuse_bench.c:0x09→0x08,与生产 net_init 同构
- net_test_task.c:TC704 注释纠正(Socket 可用性不依赖 FUN_PARA)
- Trap 18 新增「定案更正」完整证据链;Trap 25 疑点改判为定案
- Test_Guide / 产品需求 / 架构总览 / BSD 调用关系:0x09→0x08 改口径
- 待处理内容.md 登记 N-31:0x08 下多 Socket 台架复测(TC704 降并发
  ≤5 + FTP 回归),补 Trap 25 销项时漏登记的尾巴

验证:@build 0 错误 0 警告;check_doc_links --all 通过;无 U+FFFD。
This commit is contained in:
2026-10-11 20:05:22 +08:00
parent d1e6bb4ba7
commit d758d5cd7b
9 changed files with 55 additions and 21 deletions
+26 -4
View File
@@ -489,13 +489,17 @@ NET 层 TCP Client(阶段 7)`net_connect()` 返回 0,但 `net_poll()` 报
## Trap 18:多 Socket 模式切换 + 8 个 Socket 缓冲分配
### 现象
阶段 7 仅测了 Socket 0(单连接模式只有 Socket 0 可用)。要验证 Socket 1~7 也能作为 client,必须把 `FUN_PARA` 从单 Socket 模式切到多 Socket 模式,否则 `open_socket(1~7)` 被芯片拒绝/无响应,1~7 完全不可用。
阶段 7 仅测了 Socket 0。要验证 Socket 1~7 也能作为 client,当时**推论**必须把 `FUN_PARA` 从"单 Socket 模式"切到"多 Socket 模式",否则 `open_socket(1~7)` 被芯片拒绝/无响应,1~7 完全不可用。
⚠ **2026-10-11 复核:这句"必须切多 Socket 模式"是当时的前置推论,不是实测记录**——本段无串口日志摘录、无 TC 编号、无主机侧独立证据;且当年 Socket 1~7 **根本没有显式分配缓冲**(`net_init` 注释"先不配置 buffer"、MSS=1460),按 Trap 01/02 未配缓冲的 Socket 中断不触发,混淆因子未被排除。bit0 语义见本节末「定案更正」。
### 根因
`CMD_SET_FUN_PARA` 的 **bit0** 决定 Socket 数量模式:`0`=单 Socket 模式(仅 Socket 0,8KB 缓冲全归它);`1`=多 Socket 模式(Socket 0~7 全部可用,缓冲需自行分配)。之前 `net_init` 用 `0x08`(bit0=0)即单 Socket 模式,故 1~7 不存在。注意 bit1(TCP Server 单/多连接)与 bit0 是两回事:本方案只翻 bit0(多 Socket),bit1 保持 0(TCP Server 单连接),即"8 个 Socket 可用,但 Socket 0 作服务端时只接 1 客户端"。
⚠ **此"根因"已于 2026-10-11 证伪**(bit0 在所有版本官方手册里都是「保留,必须为0」;官方例程 bit0=0 下 8 个 Socket 照常可用)。当年真正起作用的是下面第 2 条的**缓冲显式分配**,不是 bit0。完整证据见本节末「定案更正」。
### 解决
1. `net_init`:`ch395f_set_fun_para(0x09)`(bit0=1, bit1=0, bit3=1)。
1. `net_init`:`ch395f_set_fun_para(0x09)`(bit0=1, bit1=0, bit3=1)。⚠ **2026-10-11 已改回 `0x08`**(bit0 保留必须为 0,见「定案更正」)。
2. `ch395f_init()` 之后,循环 0~7 用 `ch395f_set_send_buf(sock, i*6+4, 2)` / `ch395f_set_recv_buf(sock, i*6, 4)` 给每个 Socket 分配独立收发缓冲。按`docs/芯片手册/CH395F.md` §5.45(48 块 × 512B = 24KB)+ §9.2.8 最优分配:每 Socket 6 块 = 接收 4 块(2KB) + 发送 2 块(1KB),`ch395f_set_tcp_mss(1024)`,恰好用尽 0~47 块、互不重叠。
3. MSS 选取依据 §9.2.8:接收缓冲(2KB) ≥ 2×MSS(1024) 满足建议、≥ MSS 满足必须;发送缓冲(1KB) ≤ 8KB 满足必须。MSS 取 1024 为 8-Socket 共享 24KB 时的最大值。
4. `net_init` 缓冲分配顺序遵循 Trap 01:先配数据 Socket,再配监听 Socket 0(本 Net 层 Socket 按需 open,故统一在 init 一次性配好)。UDP 路径 `net_socket()` 中对 Socket 4~7 的兜底重设也同步为同一布局。
@@ -510,6 +514,24 @@ NET 层 TCP Client(阶段 7)`net_connect()` 返回 0,但 `net_poll()` 报
### 对应文件
`Drivers/BSP/NET/net_socket.c`(`net_init` FUN_PARA + 缓冲分配 + MSS);`test/board/net_test_task.c`(新增 TC704 八 Socket 并发回显);`test/host/ch395f_socket_test.py`(`tcp_server` 并发 + `--max-conn`)。
### 定案更正(2026-10-11):`FUN_PARA` 取 **0x08**,bit0 与 Socket 个数无关
**结论**:`net_init` 用 `ch395f_set_fun_para(0x08)`(bit3 SOCKET_CLOSE=1、bit0=0)。本节"bit0=单/多 Socket 模式"的说法**无任何出处,已撤回**;当年让 Socket 1~7 真正可用的是上面第 2 条的**缓冲显式分配**,不是 bit0。
**证据(一手,按强度排序)**:
1. **官方手册位表**:本机 `D:\Code\DTU\使用的芯片手册\以太网控制器_CH395F(1).pdf`(WCH《CH395 手册 1》V2.2,页眉 `https://wch.cn`)§5.52 表跨 PDF 第 21→22 页,bit0 行原文 `0 - - 保留,必须为0`;bit2、`[5:6]`、`[31:8]` 同为保留;注释①~⑥ 无一处提 Socket 数量。官方现行版 V2.3 逐位一致。旧版(V1C、英文 V1E、2020 版 CH395L/Q)bit0 **同样是保留**(旧版多出的位是 bit2=LOW_PWR,V2.2 起收回为保留)→ **任何版本都不存在"bit0=多 Socket"这一行**。
2. **官方 SDK 位宏**:`CH395EVT\EVT\EXAM\PUB\CH395INC.H:349-353` 只定义 bit1/3/4/7/8,**没有 bit0 宏**。
3. **官方例程直接反例**:`EXAM5_TCP_Server\main.c:296` 传 `0x02`(bit0=0),同文件 `:337-359` 给 Socket 0~7 全部配缓冲 → **bit0=0 下 8 个 Socket 照常可用**;`EXAM11_FTPClient\FTP\CH395.C:319` 官方直接传 `0x08, 0x00, 0x00, 0x00`(与本仓取值逐字节相同);全 EVT 包 grep `SetFunPapr` 仅 3 处(0x02 / 0x02 / 0x08),**无一处 0x09**。
4. **8 Socket 是芯片原生能力**:`docs/芯片手册/CH395F.md` 命令章前言「CH395 内部可以同时提供 8 个 Socket,其索引值分别为 0、1、2、3、4、5、6、7」;Socket 类命令一律 `_SN`(Socket 索引)寻址。
5. **真正的门槛是缓冲**:`docs/芯片手册/CH395F.md` §5.45「如果单片机需要用到的 Socket 个数大于 4,需要重新对缓冲区进行分配」——正是本节第 2 条措施。
6. **概念讹传源**:手册里唯一的"多"字样是 bit1 `FUN_PARA_FLAG_TCP_SERVER`(TCP 服务器**多连接**,全局配置),`docs/芯片手册/CH395F.md` §9.2.6「默认的设置下,服务器多连接功能被关闭……每个 Socket 只可以建立一个 TCP 连接」——单/多之分指**一个服务器能接几个客户端**,不是"能用几个 Socket"。
7. **互联网侧**:多轮检索无任何来源称 bit0 为单/多 Socket 模式,无公开代码传 0x09;CH390/CH392/CH397 同族也无此位可串源。
**为什么 0x09 当年"看起来有效"**:芯片忽略了保留位(Trap 25 旁证:bit0=1 下 sock1/2/3 并行正常)。TC704 40/40 PASS 只证明"0x09 + 缓冲布局"通过,**不构成"0x08 下不通过"的对照**(与 bit0 结论出自同一提交,属自证)。留着 bit0=1 的代价是违反保留位规定——后续固件版本一旦启用该位,现网设备静默失效。
**待补实测**(登记 `docs/待处理内容.md` N-31):0x08 下跑 TC-NET-704(须降并发 ≤5:E-23 未修,`NET_MAX_SOCKETS=8` 而三个监听常驻占 3 个 fd)+ FTP 回归(数据通道实测落在 sock4,比 TC704 更贴生产)。
### 发现时间
阶段 7 扩展 8 Socket 测试,2026-08-25。
@@ -823,7 +845,7 @@ Trap 22 的周期对账(200ms 节拍 + 400ms 去抖 + 1s 冷却)设计目标
**寄存器读数本身全部正确**(`GET_SOCKET_STATUS_SN` §5.22:`05H=SOCKET_OPEN/00H=SOCKET_CLOSED`;第二字节 TCP 态 `00H=CLOSED/04H=ESTABLISHED`,与 WCH 官方数据手册表 5-8/5-9 一致;`GET_RECV_LEN_SN` §5.33 低字节在前,驱动实现一致)。**错在对 DISCONNECT 事件语义的解读**:
1. `net_init` 的 `ch395f_set_fun_para(0x09)` 置 **FUN_PARA_FLAG_SOCKET_CLOSE=1**(§5.52 ②):产生 DISCONNECT/TIMEOUT 后芯片**不关 Socket、不清缓冲**,就是留给单片机把残留数据读出后再关 Socket。
1. `net_init` 的 `ch395f_set_fun_para(0x08)` 置 **FUN_PARA_FLAG_SOCKET_CLOSE=1**(§5.52 ②):产生 DISCONNECT/TIMEOUT 后芯片**不关 Socket、不清缓冲**,就是留给单片机把残留数据读出后再关 Socket。
2. 判别探针现场:`kill-check recv_len=1027 re-read st=0x05/0x00`——Socket 仍 OPEN、TCP 已 CLOSED、**RX 缓冲 1027 字节 = STOR 载荷一个不少全在**。这是芯片按 §5.52 规格**保留现场**,不是杀连接。
3. 那个 DISCONNECT 是**客户端的正常 FIN**:Python ftplib `storbinary` 语义 = `sendall` 发完立即关数据连接,然后回控制通道等 226——标准 FTP 行为。局域网小文件下"连接→发完→关闭"在 ~5 ms 内完成。
@@ -851,7 +873,7 @@ Trap 22 的周期对账(200ms 节拍 + 400ms 去抖 + 1s 冷却)设计目标
**教训(Trap 25 总纲)**:本轮先后误读三次——把客户端正常 FIN 读成"芯片杀连接"、把 open 重试读成"拆链窗口"、把芯片假 SEND_OK 读成"数据已上线"。铁律:**CH395F 的"成功"(中断位/状态码)只代表芯片本地动作完成,不代表对端收到;判定必须回到对端可见证据(主机侧收发)+ 手册语义(FUN_PARA §5.52、状态码 §5.22)**。
**顺带发现的疑点(存疑,暂不动)**:`set_fun_para(0x09)` 的 bit0——§5.52 表明确写 **bit0 保留、必须为 0**,而 `net_init` 注释声称"bit0=1 多 Socket 模式"(手册与网络资料均无此说法,CH395 的 8 Socket 是芯片原生能力,单/多 Socket 之分在手册中只关联 SCS0 引脚硬件形态)。现固件 bit0=1 下 sock1/2/3 多路并行正常 → 该位大概率被芯片忽略。**本轮不改**(若真为多 Socket 使能,改 0x08 会毁掉全部 1~7 号 Socket);后续单独台架验证"0x08 下多 Socket 是否仍正常"再定。
**顺带发现的疑点(2026-10-11 已定案)**:`set_fun_para(0x09)` 的 bit0——§5.52 表明确写 **bit0 保留、必须为 0**,而 `net_init` 注释声称"bit0=1 多 Socket 模式"(手册与网络资料均无此说法,CH395 的 8 Socket 是芯片原生能力,靠 Socket 索引 `_SN` 寻址)。现固件 bit0=1 下 sock1/2/3 多路并行正常 → 该位被芯片忽略。**定案:改回 `0x08`**——官方手册 V1C/V1E/V2.2/V2.3 的 bit0 全是保留位,官方例程 bit0=0 下 8 个 Socket 照常可用(`EXAM5_TCP_Server` 传 0x02 却给 Socket 0~7 配缓冲),官方 FTP 例程本身就传 0x08。完整证据链见 Trap 18「定案更正」;**0x08 下的多 Socket 台架复测尚未做**(登记 `docs/待处理内容.md` N-31)。
### 发现时间
2026-10-11(登记簿 N-30;裸机芯片台架定案实验见本节,实验分支 `n30-chip-bench`)。