From d758d5cd7b28f5c796ae62661097a472dbeba890 Mon Sep 17 00:00:00 2001 From: Wanderingss <1624155937@qq.com> Date: Sun, 11 Oct 2026 20:05:22 +0800 Subject: [PATCH] =?UTF-8?q?docs+net:=20FUN=5FPARA=20=E5=AE=9A=E6=A1=88=200?= =?UTF-8?q?x08=E2=80=94=E2=80=94bit0=20=E4=BF=9D=E7=95=99=E4=BD=8D?= =?UTF-8?q?=E8=AF=81=E4=BC=AA=EF=BC=8CTrap18=20=E5=AE=9A=E6=A1=88=E6=9B=B4?= =?UTF-8?q?=E6=AD=A3=20+=20N-31?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit 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。 --- Drivers/BSP/NET/net_socket.c | 19 +++++++++++---- docs/产品需求/产品需求设计文档.md | 2 +- docs/待处理内容.md | 5 ++-- docs/架构设计/项目架构总览.md | 2 +- docs/测试说明/CH395F_Test_Guide.md | 6 ++--- docs/网络/BSD_Socket_API_函数调用关系.md | 6 ++--- docs/问题记录/CH395F_Trap_Records.md | 30 ++++++++++++++++++++---- test/board/ch395f_reuse_bench.c | 3 ++- test/board/net_test_task.c | 3 ++- 9 files changed, 55 insertions(+), 21 deletions(-) diff --git a/Drivers/BSP/NET/net_socket.c b/Drivers/BSP/NET/net_socket.c index 30ec7414..108a8212 100644 --- a/Drivers/BSP/NET/net_socket.c +++ b/Drivers/BSP/NET/net_socket.c @@ -259,11 +259,20 @@ static bool s_mac_is_zero(const uint8_t *p_mac) { /* 复位芯片 */ ch395f_reset(); - /* 多 Socket 模式 + TCP Server 单连接 + 手动关闭 Socket(bit0=1, bit1=0, bit3=1) - * bit0=1: 多 Socket 模式,启用 Socket 0~7(单 Socket 模式下 1~7 被禁用) - * bit1=0: TCP Server 单连接,监听 Socket 0 仅接受 1 个客户端(连接停留在 Socket 0 本身) - * bit3=1: DISCONNECT/TIMEOUT 时不自动清空缓冲区,由软件排空数据后手动关闭 */ - ch395f_set_fun_para(0x09); + /* 芯片版本留痕:SOCKET_CLOSE 需 ≥0x46、TCP_SERVER 需 ≥0x44(§5.52 表), + * 版本门槛排查曾是盲区(Trap 25 定案过程确认本芯片 SOCKET_CLOSE 实际生效) */ + DBG_INFO("ch395f ver=0x%02X fun_para=0x08", ch395f_get_version()); + + /* 功能参数(§5.52 表):bit3=1 SOCKET_CLOSE——DISCONNECT/TIMEOUT 后芯片 + * 不清缓冲,由 MCU 读出残留数据后再关 Socket(Trap 25 三次定案的排空契约); + * bit1=0 TCP_SERVER 多连接模式不用(本项目单连接模型:每监听器独占一个 + * Socket,监听转数据通道);bit0 保留必须为 0——旧注释"bit0=1 多 Socket + * 模式"手册与网络资料均无出处(多 Socket 由 SN 命令族寻址实现,与 FUN_PARA + * 无关),且违反保留位规定 → 0x09 改 0x08(2026-10-11 定案:官方手册 + * 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); /* 设置 TCP MSS:维持 1024(512 裕量方案未采纳,当年支撑它的台架判据不可信, * 已随 TC-NET-604 结案为非缺陷一并撤回(2026-09-23,见 Trap 21)) */ diff --git a/docs/产品需求/产品需求设计文档.md b/docs/产品需求/产品需求设计文档.md index 595f9ad3..bb97b3ec 100644 --- a/docs/产品需求/产品需求设计文档.md +++ b/docs/产品需求/产品需求设计文档.md @@ -315,7 +315,7 @@ sequenceDiagram - 判据:三个 TCP 服务(FTP / 对时 / 远程显示)均经同一 API 工作;单连接模型下连接断开自动回到 LISTEN。 **FR-NET-3 单连接模型与自愈** -- 需求:CH395F 配置为多 Socket + TCP Server 单连接(`set_fun_para(0x09)`),Socket 0 复用监听与数据通道;网络重建后服务自动重连。 +- 需求:CH395F 配置为 8 Socket(索引寻址)+ TCP Server 单连接(`set_fun_para(0x08)`,bit3 SOCKET_CLOSE;bit0 为保留位必须为 0),Socket 0 复用监听与数据通道;网络重建后服务自动重连。 - 实现:三个 TCP 服务**串行**占用连接,断开自动重听;代次号(`net_get_generation()`)驱动服务自愈。 - 判据:FTP 旧会话异常断开后约 30 s 恢复监听;网络重建(改 IP)后服务自动重建监听。 diff --git a/docs/待处理内容.md b/docs/待处理内容.md index 0da7e442..272ab5b9 100644 --- a/docs/待处理内容.md +++ b/docs/待处理内容.md @@ -40,7 +40,7 @@ |---|---|---| | **安全** | 0 | — | | **P1** | 0 (+1 收尾) | P1-10 测试固件构建实测闭环(主体已闭环,见 §3.1);~~N-30~~ 已销项(2026-10-11 三连定案修复,回归 4 轮 11/11,见 `问题记录/CH395F_Trap_Records.md` Trap 25) | -| 登记簿 | 20 | 网络:N-2(49s 日志静默,**低风险观察项**)、N-3(L5 基线重验)、N-4(pending 二期)、N-16(A2/A4 专项负向验证)、N-17(探针窗口心跳缺口);存储/日志:**S-3(USART1 TX-only 根治)**、S-4(dhara 重试自旋)、S-5(可选全序列卷锁)、N-22(写回 flush)、N-24(日志逐条开关);数据正确性:**N-21(dhara is_free/copy,报告 N-12/13)**;结构:**N-20(Error_Handler 死循环)、N-23(注册反向校验)、N-26(NAND DMA 断言)**;预算:**N-27(内存优化簇)、N-28(Flash 死代码簇)**;仓库:**N-29(.git 149 MB,需用户决策)**;硬件:**N-18(V0.2 改版项)** | +| 登记簿 | 21 | 网络:N-2(49s 日志静默,**低风险观察项**)、N-3(L5 基线重验)、N-4(pending 二期)、N-16(A2/A4 专项负向验证)、N-17(探针窗口心跳缺口)、N-31(FUN_PARA=0x08 下多 Socket 台架复测);存储/日志:**S-3(USART1 TX-only 根治)**、S-4(dhara 重试自旋)、S-5(可选全序列卷锁)、N-22(写回 flush)、N-24(日志逐条开关);数据正确性:**N-21(dhara is_free/copy,报告 N-12/13)**;结构:**N-20(Error_Handler 死循环)、N-23(注册反向校验)、N-26(NAND DMA 断言)**;预算:**N-27(内存优化簇)、N-28(Flash 死代码簇)**;仓库:**N-29(.git 149 MB,需用户决策)**;硬件:**N-18(V0.2 改版项)** | | 测试/基础设施 | 6 | T-7(CI runner 未就绪 + 推送后两 job 闭环 + 第二机交叉验证)+ **S12**(断言宏)、**S1-c**(可选单测)、**A-4**(采集链路测试约束)、**A-5 残余**(CI 体积门禁盲区)、**D7**(串口助手 A6/A7 待 CH340) | > **网络侧另有 E-xx 未闭环项**(E-12/15/16/23/24/25/26/27/28/30/47/48/49/50/58/59/61,共 17 项) @@ -70,7 +70,7 @@ | **W2 功能主线** | **修 E-50/E-49 → B2** RS-485(ModBus RTU)∥ **B4** IEC104 上行 → **B5** protectTask 立项 | DTU 核心职责"采集与转发"仅剩两环:RS-485 侧被 E-59 挡、上行侧未动工;B4 数据源(ADC ✅)已具备,**可与 B2 并行**。**已定(2026-10-11):B2 先行(先修 E-50/E-49 驱动契约)、B4 并行开工** | | **W3 数据正确性** | **N-21** dhara `is_free`/`copy`(报告 N-12/13) | 低概率、后果重(数据丢失);修复须配主机侧移植层测试,一并补报告"覆盖率"缺口 | | **W4 预算与内存** | **N-27**:`docs/问题记录/项目审查与优化建议报告.md` §5.5 台账三件套 → R-9 池 40→16 KB → R-2 后半(54 KB→CCM) | CCM 只剩 16,304 B,R-2 后半被堵死;三件套是排期前提且工作量小 | -| **W5 结构债** | C1 pending 二期 · C3 日志管线(N-2 + N-24)· C5 收口 · C6 USART1(S-3)· N-20 `Error_Handler` · N-23 注册反向校验 · N-22/N-25/N-26/N-28 | 二期/健壮性/评估类,无紧急;N-23 是唯一"1 小时工作量"的一条;~~N-30~~ 已销项(Trap 25 定案修复,2026-10-11 回归 4 轮 11/11) | +| **W5 结构债** | C1 pending 二期 · C3 日志管线(N-2 + N-24)· C5 收口 · C6 USART1(S-3)· N-20 `Error_Handler` · N-23 注册反向校验 · N-22/N-25/N-26/N-28 · N-31 复测 | 二期/健壮性/评估类,无紧急;N-23 是唯一"1 小时工作量"的一条;~~N-30~~ 已销项(Trap 25 定案修复,2026-10-11 回归 4 轮 11/11) | | **W6 验证常态** | P1-10 收尾 · T-7 CI · D2 N-3 · D5 N-16 · D6 N-17 · **D7 串口助手 A6/A7** · S12 · S1-c · A-5 | 窗口性,逢机顺带,不单独排期 | | **W7 UI 扩展** | U4 残余(golden + 字符集差集挂门禁)→ U1 令牌层 → U2/U3 → **27 页**落地 | 产品驱动、体量大,需单独立项(顺序按 `docs/问题记录/项目审查与优化建议报告.md` §6.5) | | **W8 仓库决策** | **N-29** `.git` 149 MB + 图片 36.3 MB | `git filter-repo` 历史重写影响未推送提交与协作者 → **需用户决策** | @@ -183,6 +183,7 @@ W8 仓库 N-29 .git 149MB(用户决策) 硬件:N-18 V0.2 | N-27 | **内存优化簇**:LVGL 池 + UI 两份缓冲 54,146 B 仍在 SRAM1,CCM 只剩 16,304 B;`ram_baseline.tsv` / `RAM预算台账.md` / 92% 阈值门禁**均未建** | R-2 后半段(迁 CCM)被堵死 → B2/B4/B5 的功能预算看不清 | **前置 §5.5 台账三件套** → R-9(`LV_MEM_SIZE` 40→16 KB,池水位门禁数据已具备)→ R-2 后半;R-3/R-4/R-5/R-6 逐项评估(R-6 前置已满足) | **W4** | 报告 R-2 剩余/R-3~R-6/R-9/§5.5 | | N-28 | Flash 死代码评估簇:剩余 ≈10 KB(`box_shadow` 3,246 / `draw_sw_img` 2,960 / `bin_decoder` 1,972 / `image_decoder` 952 / `triangle` 930)+ 双精度 `dadd` 等 ≈1 KB;uvprojx 仍挂 201 个空 LVGL TU(F-1/F-2/F-3 已闭环,省的是编译时长) | 编译时长 + 文档噪音 | 逐项实测再关;⚠ `mask`/`mask_rect`/`grad` 是文字与矩形绘制必经路径,**不可盲关** | W5 | 报告 F-4/F-5/F-6 | | N-29 | **仓库膨胀**:`.git` 149 MB + 图片 36.3 MB | clone/备份慢,且持续恶化 | 降采样 / 拆 submodule / LFS 三选一 **+ 一次 `git filter-repo` 历史重写**。**已决策(2026-10-11):暂不处理、登记观察**——推送/协作前重评(届时未推送提交更少、重写代价最低) | **W8** | 报告 D-1 | +| N-31 | **FUN_PARA=0x08 下的多 Socket 台架复测**:bit0 保留位已定案(`net_init` 与 `test/board/ch395f_reuse_bench.c` 均改 0x08,`@build` 0 错 0 警),但"0x08 下 Socket 1~7 仍可用"**至今零实测** | 结论有官方手册(V1C/V1E/V2.2/V2.3 bit0 均为保留)+ 官方例程(bit0=0 下 Socket 0~7 配缓冲)一手支撑,风险低;判错则 FTP 数据通道 / 对时 / 远显**静默失效** | 跑 TC-NET-704(开 `ENABLE_PHASE7_TESTS`,`PHASE7_MULTI_COUNT` 降到 ≤5 绕开 E-23 的 fd 池上限)+ FTP 回归(数据通道实测落 sock4);判据:全路 ESTABLISHED + 回显字节级比对通过 | W5 | `问题记录/CH395F_Trap_Records.md` Trap 18「定案更正」+ Trap 25 | | U 簇 | UI 标准化:无令牌层/组件库/页注册表(手写 `case` 仍在),**27 页**未落地;golden 未挂 pre-commit、字符集差集检查仍是约定 | 新增一页成本仍是 8 处手工改动 | 按 `docs/问题记录/项目审查与优化建议报告.md` §6.5:U4 残余(两脚本入门禁,可逢窗口顺带)→ U1 令牌层 → U2/U3 → 页面落地;U4 golden 可直接当 U1 验收工具。**已确认(2026-10-11):本轮不排期**,等功能主线出结果后按产品需求启动 | W7 | 报告 U1~U5 | ### 3.3 测试与架构改进专项(S1x / A-x) diff --git a/docs/架构设计/项目架构总览.md b/docs/架构设计/项目架构总览.md index 29819828..0798379f 100644 --- a/docs/架构设计/项目架构总览.md +++ b/docs/架构设计/项目架构总览.md @@ -187,7 +187,7 @@ flowchart TB style NT fill:#efe,stroke:#484 ``` -**单连接约束**:CH395F 配置为多 Socket + TCP Server 单连接(`set_fun_para(0x09)`),Socket 0 复用监听与数据通道;FTP / 对时 / 远程显示三个 TCP 服务**串行**占用连接,连接断开后自动回到 LISTEN。 +**单连接约束**:CH395F 配置为 8 Socket(索引寻址)+ TCP Server 单连接(`set_fun_para(0x08)`,bit3 SOCKET_CLOSE;bit0 保留必须为 0),Socket 0 复用监听与数据通道;FTP / 对时 / 远程显示三个 TCP 服务**串行**占用连接,连接断开后自动回到 LISTEN。 > **FTP 启动门(2026-09-21 修复)**:`ftpTask` 必须等 `NET_READY` **且** `STORAGE_READY`(两位均 `NoClear`)才 `lftpd_start`——此前就绪位被其它等待者消费,FTP **静默不监听**(详见 §2.2 与 `docs/测试说明/FTP_Test_Guide.md` §8.6)。 > **单客户端实测注意**:同一时刻只服务 1 个会话,旧会话异常断开后约 30s 才恢复监听。测试脚本必须内置连接重试(`test/host/ftp_up_dl_test.py`、`test/host/ftp_speed_test.py` 已内置),且**不要用裸 TCP 工具探测 21 端口**(探测会占掉唯一会话,见 `docs/测试说明/FTP_Test_Guide.md` §8.7)。 diff --git a/docs/测试说明/CH395F_Test_Guide.md b/docs/测试说明/CH395F_Test_Guide.md index 45100203..b0efe76e 100644 --- a/docs/测试说明/CH395F_Test_Guide.md +++ b/docs/测试说明/CH395F_Test_Guide.md @@ -2,7 +2,7 @@ ## 1. 概述 -本文档定义 CH395F 以太网驱动(STM32F407ZGTx,SPI2 接口)的测试规范。当前固件运行于**多 Socket 模式**(`FUN_PARA=0x09`:8 个 Socket 0~7 全部可用,Socket 0 作 TCP Server 单连接),覆盖单连接与多并发客户端场景。测试按阶段(TM-PHY-NN)组织,每个阶段包含独立测试用例(TC-NET-NNN)。 +本文档定义 CH395F 以太网驱动(STM32F407ZGTx,SPI2 接口)的测试规范。当前固件 `FUN_PARA=0x08`(bit3 SOCKET_CLOSE=1,bit0/bit1 均为 0):8 个 Socket 0~7 全部可用(**由 Socket 索引 `_SN` 命令族 + 缓冲显式分配实现,与 FUN_PARA 无关**,见 `问题记录/CH395F_Trap_Records.md` Trap 18「定案更正」),Socket 0 作 TCP Server 单连接,覆盖单连接与多并发客户端场景。测试按阶段(TM-PHY-NN)组织,每个阶段包含独立测试用例(TC-NET-NNN)。 ### 设计原则 @@ -29,7 +29,7 @@ ### 多 Socket / 8 端口并发分配 -`net_init` 中 `ch395f_set_fun_para(0x09)` 启用 8 个 Socket 后,循环 0~7 调用 `SET_RECV_BUF` / `SET_SEND_BUF` 重分配(必须在 `OPEN_SOCKET` 之前,顺序遵循 Trap 01:先数据 Socket 1~7 再监听 Socket 0): +`net_init` 中 `ch395f_set_fun_para(0x08)` 之后,循环 0~7 调用 `SET_RECV_BUF` / `SET_SEND_BUF` 重分配(**这一步才是 Socket 1~7 可用的前提**,见 `问题记录/CH395F_Trap_Records.md` Trap 18「定案更正」;必须在 `OPEN_SOCKET` 之前,顺序遵循 Trap 01:先数据 Socket 1~7 再监听 Socket 0): | Socket | 接收起始块 | 接收块数 | 接收大小 | 发送起始块 | 发送块数 | 发送大小 | |--------|-----------|---------|---------|-----------|---------|---------| @@ -834,7 +834,7 @@ sequenceDiagram | **优先级** | P0 | | **类型** | 功能测试 / 并发测试(NET 层) | | **标题** | 同时打开 8 个 Socket 连接 PC Server,各自 64B 收发 | -| **前置条件** | 1. PC: `python ./test/host/ch395f_socket_test.py tcp_server --port 8081 --max-conn 8`(并发回显,`--max-conn` 为并发计数)
2. `net_init()` 已置 `FUN_PARA=0x09`(8 Socket 模式),8 个 Socket 缓冲按「CH395F 缓冲架构」分配(每 Socket 接收 2KB + 发送 1KB,MSS=1024)
3. `ENABLE_PHASE7_TESTS` 已定义 | +| **前置条件** | 1. PC: `python ./test/host/ch395f_socket_test.py tcp_server --port 8081 --max-conn 8`(并发回显,`--max-conn` 为并发计数)
2. `net_init()` 已置 `FUN_PARA=0x08`,8 个 Socket 缓冲按「CH395F 缓冲架构」分配(每 Socket 接收 2KB + 发送 1KB,MSS=1024)——**缓冲显式分配是本用例的前提**(Socket 可用性不依赖 FUN_PARA)
3. `ENABLE_PHASE7_TESTS` 已定义 | **测试步骤与判定标准**: diff --git a/docs/网络/BSD_Socket_API_函数调用关系.md b/docs/网络/BSD_Socket_API_函数调用关系.md index 9f92ec0a..2100e955 100644 --- a/docs/网络/BSD_Socket_API_函数调用关系.md +++ b/docs/网络/BSD_Socket_API_函数调用关系.md @@ -103,7 +103,7 @@ flowchart TB | 函数 | 设计作用 | 主要调用 | 意图 / 注意 | |---|---|---|---| -| `net_init(ip,mask,gw,mac)` | 芯片一次性配置:探测/复位 → 参数 → MAC → 协议栈初始化 → 8 Socket 缓冲布局 → 使能 PING | `net_pending_cancel_all` → `ch395f_check_exist` / `ch395f_reset` / `set_fun_para(0x09)` / `set_tcp_mss` / `set_retrans_count+period` / `set_keepalive_idle+intvl+cnt` → `set_mac_addr` → `parse_ip_string` + `set_ip_addr` / `set_gwip_addr` / `set_mask_addr`(或 `set_dhcp`)→ `ch395f_init` → `set_send_buf` / `set_recv_buf` ×8 → `ping_enable` | ① **重建前**先取消全部挂起 recv 并逐一通知(不通知 = 调用方永久挂死),且必须早于控制块清零与芯片复位;② 重传/KeepAlive/**MAC**/IP/GW/MASK 参数**必须**在 `ch395f_init` 之前下发(`docs/芯片手册/CH395F.md` §9.2.1:SET_MAC 为步骤①,INIT_CH395 加载 MAC——顺序反了本次上电不生效,P1-7);③ `fun_para=0x09`:多 Socket 模式 + TCP Server 单连接 + DISCONNECT/TIMEOUT 不清缓冲(软件排空后手动关);④ 缓冲布局每 Socket 6 块(收 4 + 发 2)×8 = 48 块恰好用尽,Socket 0~7 必须显式重分配(Trap 01/02);⑤ 捕获 `xTaskGetCurrentTaskHandle` 存入 `s_net_task_handle`(防自通知死锁的判据) | +| `net_init(ip,mask,gw,mac)` | 芯片一次性配置:探测/复位 → 参数 → MAC → 协议栈初始化 → 8 Socket 缓冲布局 → 使能 PING | `net_pending_cancel_all` → `ch395f_check_exist` / `ch395f_reset` / `set_fun_para(0x08)` / `set_tcp_mss` / `set_retrans_count+period` / `set_keepalive_idle+intvl+cnt` → `set_mac_addr` → `parse_ip_string` + `set_ip_addr` / `set_gwip_addr` / `set_mask_addr`(或 `set_dhcp`)→ `ch395f_init` → `set_send_buf` / `set_recv_buf` ×8 → `ping_enable` | ① **重建前**先取消全部挂起 recv 并逐一通知(不通知 = 调用方永久挂死),且必须早于控制块清零与芯片复位;② 重传/KeepAlive/**MAC**/IP/GW/MASK 参数**必须**在 `ch395f_init` 之前下发(`docs/芯片手册/CH395F.md` §9.2.1:SET_MAC 为步骤①,INIT_CH395 加载 MAC——顺序反了本次上电不生效,P1-7);③ `fun_para=0x08`:bit3 SOCKET_CLOSE(DISCONNECT/TIMEOUT 后不清缓冲,软件排空后手动关);bit0/bit1 保持 0——8 个 Socket 由索引 `_SN` 寻址 + 缓冲显式分配实现,与 FUN_PARA 无关(bit0 是保留位,必须为 0);④ 缓冲布局每 Socket 6 块(收 4 + 发 2)×8 = 48 块恰好用尽,Socket 0~7 必须显式重分配(Trap 01/02);⑤ 捕获 `xTaskGetCurrentTaskHandle` 存入 `s_net_task_handle`(防自通知死锁的判据) | | `net_get_generation()` | 读网络代次号(纯 RAM) | 无 | FTP/UI/对时服务据此感知"网络已重建"→ 放弃旧监听并重建 | | `net_generation_inc()` | 代次号 +1 | 无 | 唯一合法递增点 = `net_stack_bring_up()` 末尾(PHY/链路就绪后)——太早递增会让服务在网络不可用时抢跑重建;模拟器端恒为 0(无重建概念,上层自愈逻辑空转) | @@ -318,7 +318,7 @@ sequenceDiagram N->>A: net_init 开头:net_pending_cancel_all(CONNRESET)——逐一取消并通知 N->>N: 控制块全部清零 - N->>C: check_exist → reset → fun_para(0x09)/MSS/重传/KeepAlive + N->>C: check_exist → reset → fun_para(0x08)/MSS/重传/KeepAlive N->>C: IP·GW·掩码(或 DHCP)→ ch395f_init → MAC → 8 Socket 缓冲布局 Note over N,A: net_stack_bring_up:PHY/链路就绪 → net_generation_inc
FTP/UI/对时据**代次变化**放弃旧监听并重建(见 docs/子系统设计/网络配置说明.md §4) ``` @@ -347,7 +347,7 @@ sequenceDiagram | 芯片命令 | 使用处 | 说明 | |---|---|---| | `ch395f_check_exist` / `ch395f_reset` | `net_init` | 上电探测与复位 | -| `ch395f_set_fun_para(0x09)` | `net_init` | 多 Socket + TCP 单连接 + 手动关缓冲 | +| `ch395f_set_fun_para(0x08)` | `net_init` | bit3 手动关缓冲(SOCKET_CLOSE);bit0/1=0,Socket 个数与 FUN_PARA 无关 | | `ch395f_set_tcp_mss` / `set_retrans_count` / `set_retrans_period` / `set_keepalive_idle+intvl+cnt` | `net_init`(**均须在 `ch395f_init` 之前**) | 值见 `net_config.h` | | `ch395f_set_mac_addr` | `net_init`(**须在 `ch395f_init` 之前**) | 写芯片 EEPROM;INIT_CH395 加载 MAC(`docs/芯片手册/CH395F.md` §9.2.1 步骤①,P1-7) | | `ch395f_set_ip_addr` / `set_gwip_addr` / `set_mask_addr` / `set_dhcp` | `net_init`(**均须在 `ch395f_init` 之前**) | 固定 IP 或 DHCP | diff --git a/docs/问题记录/CH395F_Trap_Records.md b/docs/问题记录/CH395F_Trap_Records.md index 74a55f2a..84e9e00a 100644 --- a/docs/问题记录/CH395F_Trap_Records.md +++ b/docs/问题记录/CH395F_Trap_Records.md @@ -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`)。 diff --git a/test/board/ch395f_reuse_bench.c b/test/board/ch395f_reuse_bench.c index d13cfb4a..1aa9540c 100644 --- a/test/board/ch395f_reuse_bench.c +++ b/test/board/ch395f_reuse_bench.c @@ -96,7 +96,8 @@ static int bench_chip_init(void) { } HAL_Delay(100); } - ch395f_set_fun_para(0x09); + /* bit3=1 SOCKET_CLOSE;bit0 保留必须为 0(§5.52)→ 与生产 net_init 同构 */ + ch395f_set_fun_para(0x08); ch395f_set_tcp_mss(CH395F_TCP_MSS); ch395f_set_retrans_count(3); ch395f_set_retrans_period(200); diff --git a/test/board/net_test_task.c b/test/board/net_test_task.c index 556fcaa6..de50a61f 100644 --- a/test/board/net_test_task.c +++ b/test/board/net_test_task.c @@ -291,7 +291,8 @@ static void phase7_test_timeout(void) } /* TC 704:多 Socket 并发 TCP Client。 - * 多 Socket 模式下 Socket 1~7 才可用;本用例同时打开 Socket 0~7, + * Socket 0~7 由索引寻址 + 缓冲显式分配即可全部使用(FUN_PARA bit0 是保留位, + * 与 Socket 个数无关,见 Trap 18「定案更正」);本用例同时打开 Socket 0~7, * 各自连 PC echo server,每路独立收发 PHASE7_EXCH_SIZE 字节回显并比对, * 验证 8 个 Socket 均能独立工作。依赖 PC 端 tcp_server 支持并发连接。 */ #ifndef PHASE7_MULTI_COUNT