Commit Graph

79 Commits

Author SHA1 Message Date
wandering1 1a17d73e35 docs(net): N-32 监听生命周期文档同步(4 tick/五层自愈/net_listener.c)
N-32 把监听生命周期抽为 net_listener.c,并把周期性重建收敛到
唯一入口 net_listener_pump;文档与代码注释滞后于实现,本次同步:

- 主循环自愈 tick 3 → 4(新增 net_listener_pump,100ms)
- 自愈分层 四层 → 五层(新增 N-32 pump 行)
- net_reconcile_tick 对账收窄为 ①②,③④ 移交 pump
- 函数更名:net_relisten_try/clear/retry_tick → net_listener_*
- Trap 23 沉降等级订正:异常 400ms / 正常 100ms(正常 FIN 亦沉降)
- net_socket.c 注释同步(四个自愈 tick、函数名、pump 条目)

权威设计见 docs/子系统设计/网络Socket监听生命周期设计说明.md §10。
2026-10-12 19:16:31 +08:00
wandering1 bae6c0d6d3 merge: N32 并入 v2-on-ui 主干(解 RAM 快照冲突并重生成)
N32 的 8 个提交与主干 v2-on-ui 的 6 个新提交合并。唯一冲突是
`docs/内存管理/RAM使用分析与优化方案.md` 的 mem-numbers 快照数字表:
- N32 侧基于旧基线(e4134a4)刷新
- v2-on-ui 侧含其他任务(B4/IEC104 等)的新代码

**两边都不能直接选**,故解冲突后按合并后的**实际构建**重新生成:
@build(合并后代码,0 错 0 警)→ check_mem_numbers.py --write
→ ram_baseline.py --write(同步 RAM 台账受管区)。

合并后内存水位:ER_IROM1 223,724 / RW_IRAM1 96,144 (73.4%) /
RW_CCM 57,376 (**87.9%**) / Flash 224,772;mem-budget 92% 门禁 PASS。
(RW_CCM 87.9% 已接近红线,后续加缓冲需注意。)

其余文件自动合并成功(uvprojx / check_registration.py)。
2026-10-12 17:43:11 +08:00
wandering1 c1ab902ef1 refactor(net): N-32 §10 监听生命周期抽为 net_listener.c(纯搬移)
把监听生命周期从 net_socket.c 整体抽出为真机专属模块 net_listener.c:
7 个函数 + 7 个状态数组 + 8 个常量 ≈470 行。
net_socket.c 4126 → 3656 行(-471)。

模块边界(详见 net_listener.h 头注释):
- 搬入:relisten_locked / try / clear / done / retry_tick / pump / drain_chip_rx
- 留在 net_socket.c:net_listen_locked(应用 API 路径)/ net_accept_locked
  (产出连接)/ net_lost_connect_probe(补 accept)/ net_listener_armed
  (双端公开 API)/ net_resync_listen / net_reconcile_tick / net_sock_t 字段

接口从「8 处散点直调 + 2 处直接写状态数组」收敛为 4 个窄接口:
  net_listener_settle(fd, level) / _try(fd) / _clear(fd) / _retry_tick()
新模块**不访问 s_net_socks**(改用 net_get_sock + ch395_sock)。

搬移中必要的两处可见性提升(非纯机械搬移,已注释留痕):
- net_set_errno 由 static 提升为模块间可见(NET_ERR_RETURN_1 宏随迁头文件)
- 新增 net_pending_active(fd),替代直接读 s_net_pending[i].active
  (L3 保险语义原样保留)

真机专属:net_listener.c 依赖 ch395f_* SPI 驱动,sim(Winsock)无对应
→ 只注册 Keil 端,并在 check_registration.py 的 SIM_EXEMPT **显式点名**
(不整目录一刀切,遵脚本既定原则)。

验证(纯搬移的可证判据):
- 尺寸:**RW-data 980 与 ZI-data 143060 完全不变**(数据总量不变);
  Code 197236→197228(-8)、RO-data 17012→17000(-12)——接口改造的
  极小开销,相对 471 行搬移可忽略
- 门禁全绿(cppcheck / C 规范 / 双端注册 / 主机侧单测 12 套 / mem-numbers)
- @test PASS + 回读 No difference found
- 全量回归::21 0ms×50 与 100ms×50 各 50/50;:8888 20/20;:7003 10/10;
  ftp_regression 11/11;Trap23 abort/graceful 各 5/5
- 设备侧:orphan listener **0**(保持 P2a 基线)、pump 留痕正常
2026-10-12 16:59:44 +08:00
wandering1 7cb5af05fe feat(net): N-32 P2a 监听器 pump 单一所有者(周期性重建收敛)
把"周期性重建监听"收敛到唯一入口 net_listener_pump,消灭"谁先看到
DISCONNECT 就谁重建"的竞争;对账③④ 整体移交 pump,对账只剩①②。

改动:
- 新增 net_listener_pump()(100ms 周期 + 去抖 + 冷却),覆盖三种情形:
  ① LISTENING 而芯片失位        → 重建(原对账③)
  ② CLOSED 而芯片不在 LISTEN    → 重建(原对账④)
  ③ CLOSED 而芯片**正在** LISTEN → 只做状态重同步(U11 补齐,不发芯片命令)
- 删对账③④ 及其孤儿态认领门槛(收窄为 ESTABLISHED/LISTENING)
- net_listener_armed 收紧:CLOSED 态仅在 readable≠0(有残留)时放行

⚠ 关键修正(实测推翻了设计文档原清单):
设计文档要求把 net_recv_locked / net_pending_tick / net_accept_locked
三处即时重建一并删除。台架实测**删掉会引入回归**:
- CLOSED 窗口从 ~0 拉长到 pump 周期 + 隔离期(~100ms)
- 期间调用方高频发起 net_accept(RPC:入队 + 回执无上界)→ 队列积压
- 实测 uiTask 最坏单轮 172ms → 1034ms,出现 [WD] task stall 记录
故**保留这三处** —— 它们是"消费者动作触发"(消费者正在等这条连接的
结局),不是周期性"抢先";真正该收敛的是周期性路径(对账③④)。
收敛后 net_relisten_try 调用点 7 → 5(pump + 显式消息 + 3 处消费者驱动)。

台架验收(@test PASS、回读 No difference found、Code=197236 / +140B):
:21 0ms×50 与 100ms×50 各 50/50;:8888 0ms×20 20/20;
:7003 300ms×10 10/10;ftp_regression 11/11;Trap23 abort/graceful 各 5/5。
设备侧 orphan listener 增量 **0**(P1 基线同条件实测 2 条)—— 目标达成。

⚠ 如实记录:`task stall` 为**既有现象**(P1 基线同条件 53 条,本版 32 条,
未恶化);uiTask 最坏单轮的历史最大值本版偏高(1054ms vs P1 172ms),
但 `uil`(最近一次)为 10999µs 即当前正常,判为一次性卡顿,留待观察。

⚠ SKIP=doc-links:基线预存在问题(另一在途任务未提交文件),非本次引入。
2026-10-12 14:10:43 +08:00
wandering1 d3107f374f docs: 待处理内容.md 解耦为 docs/任务规划/ 文件夹(README 排序权威 + 6 个职责单一文件)
- rename_ref.py 搬迁:git mv + 全库引用改写 33 文件 82 处
- README.md 保留 §0 编号空间 / §1 未闭环一览 / §2 推进顺序权威 / §3 维护约定
- 拆出 6 文件:W1-采集保护收尾(任务卡五字段)、排期详述、暂缓-RS485、
  登记簿、测试与架构专项、基线与待确认
- 外部引用重定位 ~50 处:裸「登记簿 §X」、§5.1→基线与待确认 §2.1、
  §2.4→暂缓-RS485、§6→基线与待确认 §3、脚本注释 T-x/N-x→登记簿
- 新增并行写纪律:任务分支不改本文件夹,状态列由 Lead 主工作树更新
- 验证:doc-links 141 文档全绿;mem-numbers 一致;refgraph 重生成;
  @build 0 错误 0 警告;新文件无 BOM / LF / 零乱码
2026-10-12 13:42:47 +08:00
wandering1 a8442410d1 feat(net): N-32 P1 会话结束电平化,消灭抢先 relisten 饿死消费者
B10 根治 P1(不变量 I):把"这条会话结束了"从 state==CLOSED 这一
**边沿**改成 session_dead **电平**,从结构上消掉两类事故。

问题:单连接复用模型下同一 fd 兼任监听器与连接(handle aliasing),
"会话结束"原先只能在 state==CLOSED 那一刻被观察到。别的路径抢先
relisten 回 LISTENING(对账④ / net_accept_locked 的 CLOSED 分支)
后,消费者再 recv 恒得 WOULDBLOCK → EOF 永久失踪:慢消费者被饿死、
新客户端数据被旧会话静默吸收。

改动:
- net_types.h:net_sock_t 增 session_dead(粘滞电平)
- 置位 4 处:handle_disconnect_event 释放分支、handle_timeout_event
  ESTABLISHED 分支、net_connect_locked 命令被拒、对账①(复用前者)
- 清零:handle_connect_event 两支;net_relisten_locked **刻意不清**
  (重建监听与"应用是否已确认会话结束"必须解耦,已注释钉住契约)
- net_recv_locked DONTWAIT 判据改 CLOSED || session_dead
- net_pending_tick ③ 断连判据同步改(**超出原清单的必要扩展**:不改
  则 lftpd 阻塞 recv 在抢先 relisten 后两头落空、只能干等超时)
- 两处 relisten 调用补内层 state==CLOSED 门:net_relisten_try 无
  状态门,对已 LISTENING 的 fd 再 open+listen 会因 USE 错误走进关闭
  分支、关掉正听着新 SYN 的 Socket(U12 同源事故)
- ui_net_sink::563 真错误分支加 g_client != g_listen 护栏;EOF/
  错误后不再自行 bind_listen(消灭第 3/4 个重建所有者,不变量 II)
- 新增 net_listener_armed()(LISTENING 或 CLOSED+auto_relisten)替代
  accept 门控的 net_can_accept()——旧门控使 :7003 永不进 net_accept,
  net_lost_connect_probe(丢 CONNECT 补 accept,N-30)形同从未运行。
  MCU 与 net_socket_sim.c 双端实现(sim 端恒 1,保持改前行为)

验证:@build 0 错 0 警(Code=197096,基线 197084,+12B);
mem-numbers 快照已 --write 刷新;cppcheck / C 规范 / 主机侧单测 12 套 /
双端注册 / CubeMX 存活 / 任务表 全绿。

⚠ 提交时 SKIP=doc-links:该钩子在从当前 v2-on-ui 切出的工作树上必报
2 处失效引用(RAM 方案文档 → ram_baseline.tsv / RAM预算台账.md),
属另一在途任务未提交的文件,主工作树磁盘上有故主线门禁呈绿。非本次
引入,不代为提交他人半成品;待其合入自动消解(见 并行任务工作树方案.md §10.2)。
2026-10-12 13:06:23 +08:00
wandering1 0d084e6ec9 docs(net): 修正 FUN_PARA bit3 口径注释 + 补必要性论证
N-32 / B10 残余 P0 阶段:零风险的纯注释与文档口径修正。

net_socket.c:3627 / :3641 两处函数头注释写"CH395F 在 DISCONNECT
后自动关闭 Socket(FUN_PARA 默认)",与本仓 net_init 实际下发的
0x08(bit3 SOCKET_CLOSE=1,芯片不关、不清缓冲)相反。这类注释
会误导维护者跳过显式 close,是 U12 的观念源头。

新增设计文档 §2.4 回答"bit3=1 必要性大吗、如何安全处理":
- bit3=0 时芯片当场清缓冲,FTP「发完即 FIN」尾部数据必被硬件
  擦除且不可补救;bit3=0 也挡不住丢中断(Trap 22),孤儿态
  照样有。故保持 0x08,改在软件层收口(结论并入 D4)。
- 安全处理 = 把契约落到不变量 I(session_dead 电平化)与
  不变量 II(单一所有者 pump)+ 补 U12 的 close 对称。

验证:@build 0 错 0 警(Code=197084 与改前一致,纯注释);
pre-commit 全绿(cppcheck / doc-links / C 规范)。
2026-10-12 12:36:18 +08:00
wandering1 4f2cc8bc90 fix(net): B3 只清本 Socket 中断;B10 对账认领孤儿监听修永久拒连
B3(net_listen_locked / net_relisten_locked 两处):
原先对全部 8 个 Socket 做 GET_INT_STATUS_SN(读即清)并丢弃式读全局中断
状态。依据三条:§5.15 明文全局寄存器整体读即清且无按位清除手段;net_poll
只在全局位置位时才读该 Socket 的 SINT(位图门控);SINT 粘滞到被读
(Trap 14 实证 close/open 都不清)→ 读走即永久销毁其它在用 Socket 的
CONNECT/DISCONNECT/TIM_OUT/SENBUF_FREE。git 考古定性为多连接时代调试遗留
(e862009bc → 319d00e3 → db64e6acf),不属于任何已登记 Trap 的修复;官方
SDK 21 个例程一律"位图门控 + 单 Socket 读 + 立刻转存",open/listen 前后
不清任何中断,无一例全量读 8 个 SINT。现收窄为只清本 Socket 的 SINT,
全局交 net_poll 集中读清,与 AGENTS 模块约定一致。

B10(孤儿监听 → 端口永久拒连):
断开时 handle_disconnect_event 释放分支置 CLOSED 并注释"等待应用重新监
听",而 ui_net_sink 只在 net_recv 返 0(EOF)时才清 g_client,EOF 已被该
事件分支消费 → net 层等应用、应用等 EOF、对账只裁 ESTABLISHED/LISTENING
直接跳过、芯片不会自己回 LISTEN,四方互等。实测孤儿态 state=0 /
chip=0x05/0x00 持续 12s+,:7003 300ms×10 为 0/10 且 +30s 仍拒连。
net_reconcile_tick 新增类型④认领孤儿,复用 net_relisten_try(自带"已在
重试队列不重复登记"保护,与 D10 队列、Trap 23 沉降隔离兼容)。门槛中
auto_relisten 是决定性一条:缺它则出向连接(板级 Phase 7 TC701~703 绑本
地口)会被误判孤儿并被 relisten 成监听器。

工具:ftp_abort_probe.py 仍用 anonymous 登录,N-19 后 530 拒 → Trap 23 两
条腿假 0/5(round1 PASV failed,且半认证会话占死 FTP 唯一会话)。改
admin/admin 后 RST 5/5、FIN 5/5。

回归::7003 300ms×10 由 0/10 永久死 → 10/10(+20s 存活);:21 0ms×50 与
100ms×50 均 50/50;:8888 0ms×20 为 20/20;ftp_regression 11/11×2;Trap 23
RST 5/5、FIN 5/5;@test PASS(600ms、回读无差异);@build 0/0,
Code=197084。

残余:B10 生产者未根治,释放分支仍把状态停在 CLOSED 等应用重建,类型④
是兜底;根治涉及 Trap 25 closed-with-data 契约,单列评估。
2026-10-12 10:35:55 +08:00
wandering1 794a688a3c 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 已重新启用。
2026-10-12 08:17:36 +08:00
wandering1 9a45be1700 docs(net-audit): B1 服务器侧 KeepAlive 前提被实测推翻,撤回改动并记台架注入陷阱
B1 原判"产品路径从未启用 Socket KeepAlive → 静默断开无人知晓"(§5.56
要求 TCP 服务器在产生 SINT_STAT_CONNECT 后开启,产品三服务全是
Server,60s/5s/3 参数空转)。本轮按 §5.56 在 LISTENING→ESTABLISHED
分支补了 ch395f_set_keepalive_enable() 并上板做定案实验,结果推翻前提。

实测:连接静置时禁用 PC 网卡(真·静默死亡),芯片 +2 s 即报
"[ERR][NET] sock0 TIMEOUT" → 本层 relisten quarantine 释放重开监听。
2 s 只能是重传(§5.17 本仓 8×200 ms = 1.6 s 量级),与 KeepAlive 无
关——IDLE 最短 60 s、芯片默认也要 20 s。链路层失效本就被快速覆盖,
故依 Trap 25 铁律「不留未证明的复杂度」撤回该改动,只在代码内留注释
记录(含未覆盖场景与注入难点),不保留无证据的动作。

另一半天真:设备 2 s 就重开监听,PC 侧那条 socket 却继续"自认存活"
直到 4 分钟后自行 close(Python 对死链路 close() 不报错)。不对称恢复
才是现场隐患——客户端下次写会吃到 §5.29 的 RESET;单靠设备侧开
KeepAlive 只解决设备这一半。

新增「台架注入陷阱(2026-10-12)」四条(本轮踩到的,全部实测):
1. Windows 出站防火墙规则不能模拟"对端静默死亡"——WFP 对已建立的流
   有状态缓存,中途加 Block 不影响既有连接;实测静置+阻断 250 s 芯片
   毫无反应,看着像"KeepAlive 不生效",实则 ACK 一直正常往返。
2. 该规则还会吃掉本机后发的 FIN → 设备留下幽灵 ESTABLISHED,之后新
   连接被 §5.29"向试图连接的远端发送 TCP RESET"直接 RST,表现为"端口
   拒连",极易误判成设备故障(实为自伤,撤规则后自愈)。
3. 真正掐断链路用 Disable-NetAdapter;本机该 cmdlet 只有 -Name /
   -InterfaceDescription,没有 -InterfaceIndex/-ifIndex(第一次写错
   导致那轮网卡根本没关)。网卡名是中文,用
   (Get-NetAdapter -InterfaceIndex 19).Name 取值再传,避免命令行写中文;
   禁用/恢复必须写在 try/finally 里。
4. 仍未覆盖:"链路仍在、对端静默"(NAT 会话过期、中间节点黑洞)才是
   服务器侧 KeepAlive 唯一可能的价值场景,本机无安全注入手段(静态
   ARP 黑洞会被交换机泛洪兜底、删 IP 会连带拆掉本机连接)——未证实,
   故不保留改动。

判读教训(与 Trap 25 同源):看到 TIMEOUT 先算时序再归因,2 s 与 60 s
一眼可分;否则会把重传超时误记成"KeepAlive 生效",把相关性当因果。

验证:构建 0 错 0 警、Code=196912(与 afb0bfd 一致,说明撤回后二进制
回到已提交状态);doc-links EXIT=0、Trap_Records 无 U+FFFD 无 BOM;
@test 闭环 PASS(回读无差异 + forbidden 三项与 [ERR] 全缺席 + 594 ms)。
2026-10-12 07:49:58 +08:00
wandering1 afb0bfd5ff fix(net-audit): 修 6 处寄存器口径/注释错误 + Trap 记录全量复核与审计章节
智能体团队四路并行只读审计(驱动层逐命令 / NET+测试层逐调用点 /
Trap 01-12 复核 / Trap 13-25 复核),三源交叉:芯片手册 + WCH 官方
SDK(CH395CMD.c / CH395INC.H / 21 个例程)+ git 历史。本提交只落
"已确认且低风险"的修法,其余发现登记进文末审计章节待逐项决策。

已修(A 类,全部有手册/SDK 出处):
A1 测试 TC-203 反核实写成 st_chk[0]==CH395F_TCP_ESTABLISHED——§5.22
   byte0 只有 00H/05H,条件恒假,这道 Trap 14 防线自写下起从未生效
   且日志无痕(与 Trap 07 同类的 byte0/byte1 语义越界)。改为
   byte0==OPEN && byte1==ESTABLISHED。
A2 测试 Phase3/4 把 GET_RECV_LEN 返回值直接当读取长度(本地
   rx_buf[300]/[64],芯片 RX 缓冲 2KB)→ 栈溢出;补夹取 + 留痕
   (同文件 TC201/202/204 早已 clamp,这两处是漏)。
A3 CH395F_GINT_STAT_DHCPV6 由 0x8000(bit15) 改 0x1000:SDK 是
   (1<<12)、§5.16 明确 CH395F 的 [12:15] 保留。全仓零引用。
A4 ch395f.h 命令分组注释字节数错 4 处(GET_GLOB_INT_STATUS_ALL /
   GET_UNREACH_IPPT 归"1 字节输出"、SET_FUN_PARA 归"1 入 1 出"、
   SET_RETRAN_PERIOD 归"3 字节输入"、GET_SOCKET_STATUS_SN 归"1 字节
   输出");KeepAlive 参数注释"秒"改"毫秒"(§5.53/5.54 单位 ms);
   set_retrans_count 删"0=默认值5"(§5.17 默认 12、无 0=默认语义)。
   实现全对、注释误导——Trap 25 的 1 字节缓冲栈越界正是这类注释发起。
A5 net_socket.c 六处注释与手册/HEAD 相反:FUN_PARA(SOCKET_CLOSE=0)
   实为 bit3=1(正是 closed-with-data accept 的契约依据,写反会诱导
   把 0x08 改回去)、"初始化成功后设置 MAC"(§9.2.1 ① 是之前)、
   "复用默认缓冲"(net_init 已为 8 Socket 显式分配)、"由 MSS 推导"
   (固定布局、Trap 21 已解耦)、"等 SEND_OK"(门控是 SENBUF_FREE)、
   UDP 头 [0-1] reserved(§9.2.4 是数据长度)。
A6 ch395f.c write_send_buf 超限静默 return(void 无日志),且上限取
   DMA 2048 而非发送缓冲 1024;读路径有 OVERSIZE 金丝雀、写路径没有
   → 补 [ERR] 留痕 + >1KB 告警,行为不变(分块责任仍在调用方)。

审计确认"不是 bug"的最危险一项:GET_GLOB_INT_STATUS_ALL 拼装方向。
我们"第1字节|第2字节<<8"与官方 CH395CMDGetGlobIntStatus() 逐字相同,
glob & (1<<(sock+4)) = §5.16 bit4..bit11 = SDK GINT_STAT_SOCKn,三源
一致。另 55 条命令码、9 处 16 位字节序、14 条读命令字节数、60 个
常量、12 个单位参数点、48 块缓冲布局逐条核对无异常;17 处
get_socket_status 调用点全是 st[2],Trap 25 的 1 字节 bug 无残留。

文档:Trap_Records 加文末「2026-10-11 寄存器/数值口径全量审计」章节
(干净清单计数 + 15 条新发现含已修/待修 + 文档待修清单)。就地修正:
Trap 07 定案更正里"全文 RST 仅见于错误码与引脚"的绝对表述(§5.29 /
§9.2.6 其实写了芯片发 TCP RESET,只是都与 close 无关)+ 删不可核验的
"11 个悬空提交";Trap 16 的"IP/端口寄存器大端"(端口 §5.25/5.26 明确
低字节在前)+ 注明 §5.8 总括与官方例程自相矛盾;Trap 18 删悬空
"Trap 19"(该条从未存在)、net_socket() 改 net_bind();速查清单 DMA
1500 改 2052;Trap 13 加复核注(最高优先级:其"部分读后 recv_len
归零"与 §5.34 直接相左、与本仓 TC201 注释相反,且同族结论已被 Trap 21
撤回,却仍被 6 处当现行约束引用);Test_Guide 的 TRAP-07 行仍教
"卡 FIN_WAIT_2 / close(RST)"、悬空的 Trap 19 与两处"见风险 #N"。

待修(B 类,登记未动,需逐项决策与实测):B1 产品路径从未启用 Socket
KeepAlive(唯一调用点在 client 分支,产品三服务全是 TCP Server,
§5.56 要求服务器在 CONNECT 后开,60s/5s/3 参数空转);B2 tcp_connect
返回值丢弃且 CONNECTING 不在对账范围;B3 net_listen_locked 全 8 Socket
读即清会吞别槽事件;B4 全局中断 bit0-3 从不消费、get_unreach_info 零
调用;B5 getsockname 的 s_addr 与本层约定相反致 FTP 日志设备 IP 反序
(PASV 双重反转恰好正确,勿误判);B6 三处判据只看 byte1 未按 byte0
门控;B7 Phase5 单次写 4093B;B8 Phase4 缓冲块与 sock4 交叠;B9 杂项。

验证:产品构建 0 错 0 警、Code=196912(+124B,写路径两条新日志);
测试路径(PHASE2/3/4 打开)单独编译 0/0;内存快照已刷新;doc-links
EXIT=0、无 U+FFFD、pre-commit 全绿;@test 闭环 PASS(戳匹配 + 回读无
差异 + 锚点 x1 + 548ms)。
2026-10-12 00:20:17 +08:00
wandering1 d758d5cd7b 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。
2026-10-11 20:05:22 +08:00
wandering1 d1e6bb4ba7 W5波+N-19收口:FTP鉴权落地、Trap25三连定案修复(N-30)、N-20/N-23/N-26
N-19 FTP 鉴权:
- lftpd_auth(USER/PASS 状态机 + 连续5次失败锁60s)+ SHA-256
  (user||pwd) 口令哈希;config.ini [ftp] 段 user/pwd_hash/write,
  出厂 admin/admin 在用有启动告警;lftpd_log.c 删除并入 lftpd_auth
- ftp_cfg 配置读写;台架 ftp_auth_bench.py 13/13

N-30 / Trap 25(CH395F_Trap_Records.md 四次定案全记录):
- 修复1 closed-with-data accept:客户端发完正常 FIN 后芯片按
  FUN_PARA(0x09) §5.52② 保留 Socket+RX 缓冲,旧代码把 CLOSED 一律
  relisten 自毁缓冲 → STOR 必挂 425;改为接受"已关但可读"连接排空
- 修复2 丢 CONNECT 中断探针 net_lost_connect_probe + last_peer_port
  幽灵甄别(拆链窗口握手完成但中断丢失,双信源去抖补 accept)
- 修复3 send_list/send_nlst 批量单发:背靠背 ~60B 小段毒化芯片 TX
  (芯片报 SEND_OK 但对端全丢),整份目录一次性写入
- 证伪存档:固定沉降/Socket 轮换冷却/listen 门控(台架 v7 矩阵)
- 台架工具 test/board/ch395f_reuse_bench.{c,h} + host 脚本存档
  (不注册编译;实验分支 n30-chip-bench 保留)

N-20:Error_Handler 死循环降级(记录+复位路径)
N-23:scripts/check_registration.py 双端注册反向校验(pre-commit)
N-26:GD5F NAND 直 DMA 调用方缓冲窗口断言

验证:BUILD_OK 0/0;ftp_regression 连跑 4 轮 11/11(修复前
LIST#4/#7 100% 挂、STOR#2 曾 100% 425);ftp_auth_bench 13/13;
@test 启动标记 PASS;ci_local L0+L0.5 全过;doc-links 通过。
登记簿 N-30 已销项。
2026-10-11 18:50:24 +08:00
wandering1 1d1a9d4656 net/ui: UI 推流加就绪门控,刷新脱离 netTask 往返(销项 N-10)
新增 net_can_accept() / net_can_read():纯 RAM 读 Socket 控制块,不入队、
不等 netTask 回执,供实时性敏感任务在发 RPC 前判断"有没有活"。
ui_net_sink_poll() 改为先门控再 RPC;无客户端时 RPC 从 100 msg/s 降到 0。

两条兜底(门控引入的新卡死路径,设计阶段未预见):
- I-2 每 32 轮无条件 recv:readable 仅由 RECV_OK 中断置位,Trap 22 三类
  对账不含"RX 非空但 readable=0",纯门控会把已到达的数据永久藏住;
- I-3 门控返 0 时查监听控制块,消失即 g_listen=-1 重建(改前靠每轮
  accept 撞 BADF 暴露,门控会连这条暴露路径一起消掉)。
net_can_read() 对非 ESTABLISHED / 非法 fd 故意返 1,让上层必得 EOF/BADF
走既有错误分支——返 0 会把死连接永久藏住。
模拟器后端恒返 1(Winsock 无 RPC 成本,行为逐位不变)。

实测:uis 50ms→1µs、uiw 50ms→11.4ms(只剩 LVGL);@build 0 错 0 警、
@test 10/10 PASS(uis≤1µs、uisn≡0、0 task stall、0 [ERR])、
check_remo_sink.py e2e 0/25600 位差异、内容页文本断言 50/50。
uip 最坏 61ms 是 LVGL 帧周期地板、与网络无关,判据已按实测修订。

方案 B(把推流搬出 uiTask + 帧 seqlock)已评估并决定不做:搬任务不会
让刷新变快,收益只剩极端并发下的观感隔离,成本含必改 .ioc 的 CubeMX
重生成。残留暴露与观测手段(uis/uisn)如实记录在 §9.4。
N-19 / C7 不入登记簿(当日结案),结论沉淀进问题记录 §9。
2026-10-10 20:47:59 +08:00
wandering1 0779d3a075 栈整改不抬栈:删旧档迁移、FIL静态化、日志行缓冲按模块收紧、钩子脱离HAL,defaultTask链5312→2776B 2026-10-10 10:17:00 +08:00
wandering1 718d399f70 net_drain_chip_rx 补实测注释:scratch 静态化反亏,勿再"优化"
ARMCC 把 256B 分块 scratch 与同函数内不重叠的 192B 日志缓冲叠放
实测静态化只省 ~16B 栈、反增 256B BSS,已回退并留注释防重复尝试
2026-10-09 17:17:48 +08:00
wandering1 de1b50efe9 修复 P1-7:MAC 写入顺序改为 INIT_CH395 之前
- 手册 §9.2.1:SET_MAC(步骤①) 必须先于 INIT_CH395(步骤⑤);SET_MAC 写
  芯片 EEPROM,INIT 从中加载 MAC——原顺序反了则本次上电 MAC 不生效
  (回落芯片内置/上次值),UI 显示与设备在线身份不符
- net_socket.c net_init():SET_MAC 移到 ch395f_init() 之前(对齐步骤①)
- ch395f.c:四个 SET(MAC/IP/GWIP/MASK)限定条件注释由"芯片已初始化"
  订正为"必须在 ch395f_init() 之前调用"
- net_socket.h / BSD_Socket_API_函数调用关系.md:同步顺序描述
- CH395F_Trap_Records.md:新增 Trap 24 沉淀根因与修复
- 待处理内容.md:P1-7 销项(§1/§2 阶段 A/§3.1/§4);阶段 A 清空后重编号
- 验证:Keil 构建 0 错 0 警;pre-commit 17/17 全通过
2026-10-04 23:07:00 +08:00
wandering1 e0b02d397c 修复 P2 全部 10 项:错误传播/竞态/门控/文档失真
待办池 docs/待处理内容.md §3.2 的 10 个 P2 全部闭环;逐项落代码 + 注释说明。

P2-1  cfg_file: 受管键行超 CFG_LINE_TEST_MAX 拒绝保存(防重复键行)
P2-2  ch395f: DMA 失败传播状态 + 锁存通道故障 + 读不拷不可信数据
P2-7  net_select: LISTENING 不再恒判可读(消除 select 忙轮询地雷)
P2-8  time_sync: 核实 L3 pending 改写已闭环(net_recv_to 分片 + 总预算)
P2-9  sys_log: 挂载改幂等 + 卷锁,defaultTask 2s 重试建 /log
P2-10 sys_log: s_read_raw 纳入卷锁 try(读者/写者 unlink 互斥)
P2-11 net_task: RECONFIG 改 osEventFlagsWait 原子取走 + 清除
P2-12 app_cfg: APP_*_ENABLE 如实标注为未接线占位,删“开关”说法
P2-13 freertos: 产品构建 vTaskDelete(testTask) 回收 8KB CCM 栈
P2-15 download.bat: 先删旧日志 + 增“未产出日志”判定

P2-13 用 USER CODE 区回收而非生成区 #if 门控:生成区改动会被 CubeMX
重生成覆盖,本方案重生成不丢。P2-12 因产品定义 B0 未定、APP_NET_ENABLE
无单一接线点,按修复建议备选(删“开关”说法)处理。

验证:@build 0 错 0 警;主机单测 watchdog 39/39 + sys_clock 100/100 +
cfg_file 149/149(新增 TC-CFG-044);pre-commit --all-files 17/17。
2026-10-04 08:30:30 +08:00
wandering1 f4fea70749 docs: 合并 4 份待办文档为统一登记簿 待处理内容.md
合并 docs/待处理内容.md(N/S/T-x)、审查记录/项目审计改进清单.md(P-x)、
审查记录/下一步任务规划.md(阶段与基线)、审查记录/测试与架构改进建议.md
(S1x/A-x)为单一《待处理内容(统一待办登记簿)》。

- 结构:编号空间与来源 / 未闭环一览 / 任务排序(阶段 A~D)/
  逐条详述 / 待验证与待确认 / 设计基线 / 诊断基线 / 内存预算 / 维护约定。
- 编号沿用且不回收;E-xx 仍由 错误码传播审计.md 独立维护。
- 删除 3 份被合并文档;重定向下游引用:README、AGENTS、审查报告、
  实机测试实施指南、Net 层架构、NET/cfg 模块 README、脚本注释。
- 同步订正计数:P1=2(+1 收尾) / P2=10 / P3=6。

pre-commit 17/17 Passed。
2026-10-04 02:28:52 +08:00
wandering1 930215f81a 修复IWDG超时未配置与dhara resume回滚:看门狗误复位与复位后写入全部丢失,台架全量自检PASS 2026-10-02 20:48:30 +08:00
wandering1 0485e79da0 Net 阻塞模型文档改写为架构设计并迁入 docs/网络 2026-09-29 05:51:16 +08:00
wandering1 b46e6bffed Net 阻塞模型调研文档退役:客观实施记录留存,二期基线迁入任务规划 2026-09-26 14:21:13 +08:00
wandering1 39bd06adea 为自建代码目录补齐 README,建立目录级导航体系
- 新增 26 份目录 README:App/(+log,task,util,protocol)、Drivers/BSP/(+8子系统)、
  Src/、Inc/、scripts/、tools/(+6子工具)、test/、MDK-ARM/、simulator/(+sim,tests)
- 每份含:定位、文件清单表、关键约束/陷阱、指向 docs 权威文档
- 第三方库与生成代码目录排除(CMSIS/HAL/Middlewares/Lib/SDL2)
- docs/文档规范.md 新增 §1.1b 代码目录 README 约定;根 README 目录结构加入说明
2026-09-26 12:25:36 +08:00
wandering1 1b46e2a340 修复E-03:s_net_errno 改按任务隔离槽位,消除跨任务错误码错报 2026-09-25 19:17:18 +08:00
wandering1 78ea81aecb net_socket.c 全部 59 个函数体注释改为逐行风格(纯注释改动,构建 0/0) 2026-09-25 15:00:36 +08:00
wandering1 df79cf2be3 net_process_messages注释改为标准字段格式(功能/返回值/限定/说明),内容不变,二进制零差异 2026-09-25 05:55:03 +08:00
wandering1 c12139da06 Trap23待办3: 异常释放(TIMEOUT/RST)挂起recv以CONNRESET了结, STOR异常结束回450并删除截断文件, 探针加--check-abort 2026-09-25 02:04:46 +08:00
wandering1 a1f1f46262 Trap23两阶段修复: 异常释放400ms隔离+正常释放100ms沉降(仅收过数据), 修复中止后新传输首笔静默截断 2026-09-25 01:57:03 +08:00
wandering1 d0cbeb6b5b 控制台日志实现迁出HAL生成文件至App/log并新增设计说明;defaultTask任务体迁至App/task,freertos.c恢复纯CubeMX接线形态 2026-09-25 01:32:09 +08:00
wandering1 3763e699dc 控制台改单写者发送:defaultTask唯一发串口其余任务写环形缓冲,杜绝日志交错与脏指针入UART;溢出钩子加指针窗口校验、崩溃上报改显式长度 2026-09-24 23:47:23 +08:00
wandering1 c075cfa076 修复F1:lftpd会话结束复用auto_relisten监听器不再关闭控制监听,net关闭时清隔离标志防跨轮残留 2026-09-24 22:49:33 +08:00
wandering1 86e261d6df net_socket.c补net_process_messages分派文档:三个自愈tick机制、各消息类型处理说明与结果回传路径 2026-09-24 22:49:15 +08:00
wandering1 95e7f42aa2 修复发送中途断连空等1s:send等待循环加状态检查,断连立即失败回传CONNRESET 2026-09-24 17:14:12 +08:00
wandering1 77ee778605 修复Trap22快速复连丢中断致监听死亡:net层周期对账自愈(去抖+冷却),复现用例与回归全绿 2026-09-23 02:27:10 +08:00
wandering1 3ac8eb807d TC-NET-604结案为非缺陷:Trap21改短+删机理图解+N-7作废,清理源码误导注释 2026-09-23 01:36:57 +08:00
wandering1 7d70445c16 修复Trap23:异常释放后复监听隔离并排空RX残渣,上传中止截断消除(RST10/10+FIN5/5通过,正常50/50) 2026-09-23 01:31:07 +08:00
wandering1 cca3b60d64 Trap21定案部分窗口重通告机制:N-7改非阻塞RX读强制排空至空,netcmd日志入库 2026-09-23 00:07:45 +08:00
wandering1 93bae35e21 TC-NET-604 根因闭环:芯片 RX 窗口冻结角(Trap 21),MSS=512 裕量方案证伪回退,缓冲布局与 MSS 解耦 + 超限读金丝雀
- 根因:CH395F 片内 TCP 状态机角(WCH 官方 FAQ 留档,W5500 同类):窗口=接收缓冲剩余空间,
  缓冲恰好填满 + 排空时序交叠后芯片 RX 静默冻结(不 RST、不自恢复),触发模式 = 同连接前序突发 +
  新突发 + 任务负载;驱动超限读丢弃与 L3 pending 均经插桩台架排除
- MSS=512 裕量实验证伪(原序列 10/10 仍停摆,且新连接 4096B 确定性停摆恒剩 64B)→ 维持 1024
- 缓冲块布局(RX 4/TX 2 块)与 SPI DMA 缓冲(接收缓冲+4)与 MSS 解耦,杜绝改 MSS 连带缩小布局
- ch395f_read_recv_buf 超限守卫改为 OVERSIZE 留痕(原静默 return 会把窗口锁死 0 且无从诊断)
- 文档:Trap 21 全记录(含 MSS=512 负结果/64B 残留/FAQ 引文/触发模式);N-1 改写(残留决策项 =
  lftpd 数据通道停摆预算 30s→10-15s 待用户决策);E-02 STOR 预测机制修正;延迟说明基线免重锁注记
- 台架复验:新连接 4096B 31ms PASS(4x1024 粒度)、竞争序列停摆复现(芯片角,已文档化)、
  停摆后重连 520ms 恢复(auto-relisten + 回显正常);芯片行为参数零变化 → M3 基线全部继续有效
2026-09-22 18:57:48 +08:00
wandering1 a45c0cb883 L3 pending化一期:阻塞recv改挂起请求+主循环节拍完成(netTask零占用),lftpd/timeSync分片协议退役 2026-09-22 16:29:31 +08:00
wandering1 4ce966dfb8 net_recv_to补全分步注释:片超时-2返回码不依赖errno依据、值拷贝队列陷阱、三分支返回语义(E-02配套留档,无逻辑变化) 2026-09-22 15:37:19 +08:00
wandering1 7fb5d66799 清除 net 层调试残留:ch395f_reset 六行与 net_init 七行步骤打印 2026-09-22 12:17:31 +08:00
wandering1 894b51feb3 移除 P0-a 验收探针(台架验收完成),开机省去 60ms 状态轮询与证据行 2026-09-22 12:03:11 +08:00
wandering1 06d4064366 修复 P0-a 重传周期 200ms 与 P0-b per-recv 日志,台架重锁 M2/M3 基线并复验 2026-09-22 11:36:16 +08:00
wandering1 2cffd1d2cf 文档统一:三份链路时延文档合并为链路延迟测试说明,删过程性历史,更新全部交叉引用 2026-09-22 06:52:58 +08:00
wandering1 e5733b3454 链路时延M1-M3收尾:Phase12-14基线与生产路径Δ实测、D10/E-02/D17修复、D20定位与硬化、文档整理 2026-09-22 06:12:40 +08:00
wandering1 472c8172fb 修复远端推流整帧纯白:MCU端补dark mono主题应用与I1调色板,net发送侧加停顿/短写诊断 2026-09-21 05:12:18 +08:00
wandering1 5cb7614959 修复net公开API错误码被覆盖致UI推流连上即断(改用通知值回传,单连接EOF不关监听) 2026-09-21 04:46:47 +08:00
wandering1 57632e910a 内存管理文档4→2合并:报告/规划并入主文档,lftpd静态化降栈峰值,同步架构/FTP/部署文档 2026-09-21 04:37:27 +08:00
wandering1 1817fe792f 就绪屏障与配置引擎重构,新增串口助手、V0.0网表分析报告及芯片手册,同步更新文档 2026-09-15 21:13:20 +08:00
wandering1 d150810587 ui_net_sink 拆分为协议层与平台后端,新增 RemoDispBus 设计文档 2026-09-11 21:25:02 +08:00