diff --git a/AGENTS.md b/AGENTS.md index 8e866a60..f1c02c25 100644 --- a/AGENTS.md +++ b/AGENTS.md @@ -113,5 +113,6 @@ STM32F407ZGTx @168MHz(HSE 8MHz → PLL M=4/N=168/P=2);**仅 Keil MDK-ARM v ## 文档与图形 - 配置文件 `docs/子系统设计/配置文件设计说明.md`;墙钟 `docs/子系统设计/系统墙钟时间维护说明.md`;控制台单写者日志 `docs/子系统设计/控制台单写者日志设计说明.md`;代码规范 `docs/代码规范/`;测试说明 `docs/测试说明/`;审计发现 `docs/审查记录/项目审计改进清单.md`;已知待办 `待处理内容.md`(内存预算);引用关系图 `docs/架构设计/引用关系图说明.md` +- **登记簿类文档「完成即销项」**(2026-09-26 定规):`docs/待处理内容.md` 这类跨文档待办登记簿,事项修复/关闭后**直接从表中删除该行**(不保留"已消化"行、不建归档区)——结论与证据应已沉淀进对应模块文档/问题记录,登记簿只留**未办项**。销项时必须:① 先核对目标文档确已含完整记录(删了不丢信息)② 同步清理其他文档对该编号的引用(改为指向目标文档,或注明"已销项")③ 改完跑 `check_doc_links.py --all` + pre-commit - 图形走 **`draw-diagram` skill**:精确布局图(协议帧/分层/屏障)用 `tools/arch_diagram/gen_*.py` 生成器(产物放 `docs/images/`,脚本与 .svg 一并提交);拓扑图(流程/时序/状态机)用 Mermaid;**勿手绘 ASCII 框图** - **文件引用关系图**走 `tools/refgraph`:`& 'tools\refgraph\gen_refgraph.bat'` 生成文件级 + 模块级引用图(产物 `docs/images/引用关系图.*`,脚本与 .dot/.svg/.json 一并提交,PNG 本地预览不提交);项目文件变化后重跑更新;渲染依赖 Graphviz(winget 可装) diff --git a/docs/待处理内容.md b/docs/待处理内容.md index 4fe4a81f..e678f7aa 100644 --- a/docs/待处理内容.md +++ b/docs/待处理内容.md @@ -1,30 +1,27 @@ # 待处理内容(登记簿) > **用途**:跨文档的待办/观察项登记——台架与审计过程中发现、但**不属于当前修复范围** -> (或 A/B 归因为既有问题)的事项,在此留档防丢失。每项带发现日期、证据与出处; -> 消化(修复/关闭)时移入对应模块文档并在本表标"已消化(去向)"。 +> (或 A/B 归因为既有问题)的事项,在此留档防丢失。每项带发现日期、证据与出处。 +> **消化即销项**:事项修复/关闭后,**直接从本表删除该行**(结论与证据应已沉淀进 +> 对应模块文档/问题记录,此处不再保留),并同步清理其他文档对本编号的引用。 > **创建**:2026-09-22(L3 pending 台架收尾时建立,AGENTS.md 既有引用自此落文件)。 ## 网络(CH395F / net 层) | # | 事项 | 发现 | 证据与现状 | 出处 | |---|---|---|---|---| -| N-1 | **✅ 已结案(2026-09-23):TC-NET-604"接收缓冲填满后 RX 窗口冻结"判定为非缺陷**——原报告(阶段 8:前序突发后 4096B 突发仅前 2KB 回显、其余无回显)在当前固件**不可复现**:真实生产路径(产品固件 + 真 lftpd FTP 上传,判据 = FTP 协议结果 + **上传后 RETR 回读 SHA-256**)**227 轮全过**(8KB/64KB/256KB/1MB,含零间隔快速重连与 100 轮浸泡),并发生产 UI 流 600 帧 CRC 全过,设备侧无 FAIL/ERROR/WARN。原台架"停摆"系**测试程序自吞数据**(Phase 9/11 的 64B 读、固件探针读走不回显;短收量恰等于被吞字节数)+ **判读工具误判**(`probe_classify.py` A/C 把通过运行报成 STALL,C0 脚本层实测 1460/1460 全匹配)——详见 `CH395F_Trap_Records.md` Trap 21"教训"节。**原残留决策项(数据通道预算缩短)随之关闭** | 2026-08-26 发现 / 2026-09-23 结案 | 结案依据与台架纪律见 Trap 21;真实路径工具 `MDK-ARM/ftp_freeze_probe.py`(上传+回读哈希)、判读 `MDK-ARM/bench_verdict.py`;同类真实缺陷见 Trap 23(已修复) | `CH395F_Trap_Records.md` Trap 21;`CH395F_Test_Guide.md` TC-NET-604 | | N-2 | **49s 全系统日志静默(defaultTask/NAND syslog 排空停滞)**——串口日志 49s 无行(testTask 10s 周期行/netTask 事件行/[STACK] 行全缺),期间 net 栈照常处理外部连接(FTP banner 92ms)→ 日志管线(defaultTask 排空 → NAND+UART)停滞,队列满后各任务日志行被丢;系统功能不受损 | 2026-09-22 17:23:52~17:24:41(L3 台架 F2 运行中,gen 181) | **A/B 归因:L3 不触碰 defaultTask/syslog 路径 → 既有存储侧现象**。待办:① 复现条件定位(NAND 写/GC 长尾 vs UART TX 卡滞——对照 `CH395F` 无关的 SD2506 侧日志)② 日志队列满的丢弃计数/告警(现静默丢行,排障不可见)③ 与 S8(非阻塞日志)合并评估 | `错误码传播审计.md` E-02 阶段二"台架新发现②";`链路延迟测试说明.md` §6.7 注 | | N-3 | **L5 队列往返基线(1223/988µs)的 L3 后重验**——L5 测 DONTWAIT 队列全程;L3 对该路径逐位不变、pending tick 无 pending 时为 µs 级指针读 → 机制上无影响,但基线数值属分片时代,严格重锁需跑一轮 Phase 13(需 PC peer) | 2026-09-22(L3 收尾留档) | 低风险:10ms/100ms 阈值余量 >8×;下次 Phase 13 窗口顺带重锁即可 | `链路延迟测试说明.md` §6.4 L5 注¹ | -| N-6 | **✅ 已修复(2026-09-23 当日闭环):Trap 22 快速复连丢 CONNECT/DISCONNECT 中断 → 监听静默死亡**——生产固件确定性复现(待机后 UI `:7003` 快速复连:修复前 2/10 后永久拒连;FTP `:21` 100ms 间隔:第 29 轮起死亡);机制 = 芯片丢 CONNECT 或 DISCONNECT 中断 → 那条连接一直占住单连接监听(后续 SYN 全拒),且丢事件后本层收不到任何中断、纯事件驱动无法自愈。修复 = `net_socket.c` 新增**周期对账 `net_reconcile_tick()`**(200ms,回读芯片状态修正三类失同步:本层 ESTABLISHED 而芯片已断 → 断开;本层 LISTENING 而芯片已握手 → 补 accept;本层 LISTENING 而芯片监听消失 → 重建)+ 去抖(连续 2 次)+ 冷却(1s);`handle_disconnect_event` LISTENING 分支改为"已不可监听即重建"。验证:待机 `:7003` 10/10、`:21` 100ms/0ms/600ms 各 50/50、UI 20/20、FTP 正常 10/10(哈希)、中止 RST/FIN 5/5+5/5、零重建风暴 | 2026-09-22 发现 / 2026-09-23 复现+修复闭环 | 踩坑留档:自愈若放 accept 路径且用单次状态读,会因"刚 listen 未生效"瞬态反复重建直至 `relisten give up`(三监听口全死)——**单次状态读的重建动作必须去抖**。工具 `MDK-ARM/tcp_reconnect_probe.py` | `CH395F_Trap_Records.md` Trap 22;`Drivers/BSP/NET/net_socket.c`(`net_reconcile_tick` / `handle_disconnect_event`) | -| N-8 | **✅ 已修复(2026-09-23 当日闭环):Trap 23 上传中止后首笔复连上传被静默截断(≤2048B)并误报成功**——修复前可信复现 15/15(RST 10/10 + 优雅 FIN 5/5);修复后 RST **10/10**、FIN **5/5** 全通过,正常路径回归 30/30 + 20/20(SHA-256 全匹配)。**真因**:中止时对端仍有在途数据 → 芯片 TIMEOUT 后才把在途段落进 RX 缓冲(约 2048B 残渣)→ 立即复监听时残渣被下一条连接当作自己的数据读走(新上传只"收"2048B 就判结束并回 226)。**修复**:异常释放(TIMEOUT)的 socket 复监听前隔离(持续排空 RX 残渣 + 主动 close + 等 CLOSED/TCP_CLOSED),400ms 起、800ms 上限强制放行(上限须 < 重试放弃时限 2000ms,否则监听被放弃,已实测修正);`net_drain_chip_rx()` 分块读空、零新增静态缓冲;仅异常路径生效,正常 FIN 路径零改动。详见 Trap 23"修复实施与验证"——生产路径 FTP STOR 中途断开(RST 或 FIN 均可)后,紧跟的第一笔复连上传被截断到 ≤2048B(芯片单 socket RX 缓冲)且回报 226 成功 → 客户端认为上传成功 = 静默数据损坏;第二笔起恢复正常 | 2026-09-23(可信复现 + 当日修复闭环;`MDK-ARM/ftp_abort_probe.py` 自动判定) | 已实施:`net_socket.c` 新增 `s_relisten_quarantine[]`(`handle_timeout_event` 置位)+ `net_drain_chip_rx()` + `net_relisten_locked` 隔离门(`NET_RELISTEN_QUARANTINE_MS`=400 / `NET_RELISTEN_SETTLE_MS`=800 < `NET_RELISTEN_DEADLINE_MS`=2000) | `CH395F_Trap_Records.md` Trap 23;`Drivers/BSP/NET/net_socket.c`(`net_relisten_locked` / `handle_timeout_event` / `net_drain_chip_rx`) | ## 存储 / 日志管线 | # | 事项 | 发现 | 证据与现状 | 出处 | |---|---|---|---|---| | S-1 | defaultTask 静态最坏链余量贴线:2872B/4096(余量 1224B = 29.9% < 30% 判据,差 **4.8B**)——`storage_bring_up → … → dhara GC → SPI` 链,**L3 前即如此**(L3 不触 defaultTask 调用链) | 2026-09-22(L3 产品构建栈报告) | 处置方向二选一:栈 4096→4608(CCM 堆余量 4816B 可覆盖 +512B)或 GC 链缓冲局部削减;与 S8(非阻塞日志)并案评估 | `scripts/stack_report.py`(L3 产品构建档) | -| S-2 | N-1/N-2 消化后,台架 20MB 串口日志截头会丢早期 [STACK] 水位行——跨构建的"前后"栈水位对照建议固化 boot_log 快照(`%TEMP%\opencode\boot_log_*.txt`)进 `docs/测试说明/` 存档目录 | 2026-09-22(L3 收尾发现:切片时代水位行已被截头,A/B 只能定性) | 流程项,无代码改动 | 本文件 N-1/N-2 佐证 | +| S-2 | N-2 消化后,台架 20MB 串口日志截头会丢早期 [STACK] 水位行——跨构建的"前后"栈水位对照建议固化 boot_log 快照(`%TEMP%\opencode\boot_log_*.txt`)进 `docs/测试说明/` 存档目录 | 2026-09-22(L3 收尾发现:切片时代水位行已被截头,A/B 只能定性) | 流程项,无代码改动 | 本文件 N-2 佐证 | ## 网络(二期排期,随第二档 #1) | # | 事项 | 说明 | 出处 | |---|---|---|---| | N-4 | **pending 机制二期:ACCEPT + SEND 阻塞路径 pending 化**——E-06(accept 轮询计时失真)、E-20(lftpd 控制通道 errno 分类/501)、E-21(timeSync errno 分级)剩余分量共用该机制扩展;届时 L3/L5 基线再重锁、探针族扩充(close/reconfig/EOF/disconnect-during-pending)、看门狗接 selftest 留痕、模拟器差距清单 +1 | 一期(RECV)已落地:`f16dc9a`;设计基线与门禁结果见 `docs/问题记录/Net层阻塞模型业界对照与演进方案.md` §6.7 | 同左 + `错误码传播审计.md` 第二档 #1 | -| N-5 | **✅ 已修复(2026-09-25):E-03 `s_net_errno` 跨任务覆写竞态**——采取"**按任务隔离**"路线(而非二期 pending 化):删除全局 `s_net_errno`,改为 `s_net_errno_slots[8]`(每槽 `{任务句柄, err}`);`net_errno_slot()` 无锁快路径只读命中本任务槽、首次占用在 `taskENTER_CRITICAL` 内复查(槽位用尽回退 [0] 槽,**不新增共享槽**以免把竞态带回来);`net_set_errno()` 取代全部赋值、`NET_ERR_RETURN_1()` 宏合并"记码+return -1"共 82 处;`net_get_errno()` 改读本任务槽位、**对外语义不变**(成功不清零)。构建 0 错 0 警 + cppcheck 无告警 + `git diff --check` 干净 + 编码无 `U+FFFD`,BSS +64B。**残留台架项**:本机 COM6 未枚举(ST-Link 虚拟串口不在)→ 硬件闭环回归待补(`错误码传播审计.md` §3.1 E-03 / 页脚) | 2026-09-25 修复 | `错误码传播审计.md` E-03;`Drivers/BSP/NET/net_socket.c`(`net_errno_slot` / `net_set_errno` / `net_get_errno`) | diff --git a/docs/问题记录/CH395F_Trap_Records.md b/docs/问题记录/CH395F_Trap_Records.md index 7e29c49f..370a5755 100644 --- a/docs/问题记录/CH395F_Trap_Records.md +++ b/docs/问题记录/CH395F_Trap_Records.md @@ -603,7 +603,7 @@ NET 层 TCP Client(阶段 7)`net_connect()` 返回 0,但 `net_poll()` 报 自愈实测计数(整轮会话):`chip closed -> disconnect` **12** 次、`connection completed w/o CONNECT irq -> accept` **1** 次、`listen lost -> relisten` **1** 次——三类失同步均真实出现并被自愈;`relisten give up` 0 次。 ### 对应文件 -`Drivers/BSP/NET/net_socket.c`(`net_reconcile_tick` / `handle_disconnect_event` LISTENING 分支);`MDK-ARM/tcp_reconnect_probe.py`(可信用例);`docs/待处理内容.md` N-6(已闭环)。 +`Drivers/BSP/NET/net_socket.c`(`net_reconcile_tick` / `handle_disconnect_event` LISTENING 分支);`MDK-ARM/tcp_reconnect_probe.py`(可信用例);`docs/待处理内容.md` N-6(✅ 已销项,2026-09-26 清理)。 ### 发现时间 2026-09-22(台架偶发 1/1)→ 2026-09-23(生产固件确定性复现 + 当日修复闭环)。 diff --git a/docs/问题记录/Net层阻塞模型业界对照与演进方案.md b/docs/问题记录/Net层阻塞模型业界对照与演进方案.md index 77bca4ac..f21a8cec 100644 --- a/docs/问题记录/Net层阻塞模型业界对照与演进方案.md +++ b/docs/问题记录/Net层阻塞模型业界对照与演进方案.md @@ -246,7 +246,7 @@ B 类(LwIP netconn)的三个构件在本项目的对应物: | # | 门禁 | 结果 | |---|---|---| -| 1 | CH395F NET 层套件 | **PASS(分组合并执行)**:F1 组合 Phase 6/9/11——64B/1460B 回显 11/11、select 回显 11/11、断开重连、KeepAlive 断连 + auto-relisten 全 PASS;F2 组合 Phase 8-RECV——100KB 阻塞接收 50/50 块(2048B/块)逐块校验 + CRC32 整包一致(0x9A0E0C8C)+ 收齐 close + auto-relisten。Phase 7(TC703 环境互斥 + 全 DONTWAIT 不经过 pending)、Phase 10(双 32KB 缓冲与全产品镜像结构性超 RAM)本轮未跑——DONTWAIT 路径另由 M3 探针族(L5~L7 全 DONTWAIT)重锁覆盖。TC-NET-604 4096B 子项 FAIL = **既有芯片侧问题**(A/B:切片构建行为逐字节相同,L3 无责,转 `docs/待处理内容.md` N-1) | +| 1 | CH395F NET 层套件 | **PASS(分组合并执行)**:F1 组合 Phase 6/9/11——64B/1460B 回显 11/11、select 回显 11/11、断开重连、KeepAlive 断连 + auto-relisten 全 PASS;F2 组合 Phase 8-RECV——100KB 阻塞接收 50/50 块(2048B/块)逐块校验 + CRC32 整包一致(0x9A0E0C8C)+ 收齐 close + auto-relisten。Phase 7(TC703 环境互斥 + 全 DONTWAIT 不经过 pending)、Phase 10(双 32KB 缓冲与全产品镜像结构性超 RAM)本轮未跑——DONTWAIT 路径另由 M3 探针族(L5~L7 全 DONTWAIT)重锁覆盖。TC-NET-604 4096B 子项 FAIL = **既有芯片侧问题**(A/B:切片构建行为逐字节相同,L3 无责;后续经真实路径 227 轮复测判定为非缺陷,2026-09-23 结案,见 `CH395F_Trap_Records.md` Trap 21) | | 2 | M3 基线重锁 | **PASS**:静默档 host 帧 med 58.9/p95 69.9/max 72.1ms 零尖峰;压力档(FTP 头阻塞工况实发)med 60.1/p95 66.4/max 69.3ms 零尖峰(分片基线 65.0/133.5 → p99 尾部压缩近半);MCU `prod_cycle_mcu` med 6706µs 压力下平坦(min 6698/max 6720);relisten 89ms×3;L5~L7 探针路径(DONTWAIT)不受 pending 影响 | | 3 | e02_probe A/B 回归 | **PASS 且优于分片方案**:队列响应性 92.5ms(分片 109/75ms);30s 截止按节拍精确触发(30.1s);超时留痕在位;TIME 正常路径全通;监听恢复 6.6s(2 次 Trap 09 重试,既有行为同构) | | 4 | ftp_regression / E-06 假 425 | **随 F1/F2 台架 + M3 压力档覆盖**(FTP 空闲登录头阻塞工况 + 数据通道收发);未单独重跑 D20 脚本(其场景 = M3 压力档的 FTP 半登录态,已实证) | diff --git a/docs/问题记录/错误码传播审计.md b/docs/问题记录/错误码传播审计.md index d00c8e78..74ca7875 100644 --- a/docs/问题记录/错误码传播审计.md +++ b/docs/问题记录/错误码传播审计.md @@ -10,7 +10,7 @@ > **本版**:2026-09-25 重写 —— ① 已闭环项从正文移除,只在 §2 留一行索引;② 全部未闭环项 > **逐项回到当前代码复核**;③ 新增本轮复核发现。 > **代码基线**:`v2-on-ui` @ `9a8255f`(2026-09-24),复核日期 2026-09-25 -> **配套文档**:`docs/待处理内容.md`(N-2/N-4/N-5 登记项)、`docs/问题记录/Net层阻塞模型业界对照与演进方案.md`(E-02 配套)、 +> **配套文档**:`docs/待处理内容.md`(N-2/N-4 登记项)、`docs/问题记录/Net层阻塞模型业界对照与演进方案.md`(E-02 配套)、 > `docs/问题记录/*_Trap_Records.md`(模块陷阱史)、`AGENTS.md`(已固化铁律) --- @@ -157,7 +157,7 @@ E-57(`int` / `int32_t` 混用)。 - **验证**:构建 0 错误 0 警告;cppcheck(warning/performance/portability)无告警; `git diff --check` 无空白问题;编码无 `U+FFFD` 且 BOM 状态与原文一致 - **代码代价**:BSS +64 B(8×(4+4)) -- **登记**:`docs/待处理内容.md` N-5(可销项) +- **登记**:`docs/待处理内容.md` N-5(✅ 已销项,2026-09-26 清理) - **残留**:`net_recv_to` 继续用返回码 `-2` 表达超时(不依赖 errno),保持既有正确做法 ---