diff --git a/docs/待处理内容.md b/docs/待处理内容.md new file mode 100644 index 00000000..e32eb88c --- /dev/null +++ b/docs/待处理内容.md @@ -0,0 +1,28 @@ +# 待处理内容(登记簿) + +> **用途**:跨文档的待办/观察项登记——台架与审计过程中发现、但**不属于当前修复范围** +> (或 A/B 归因为既有问题)的事项,在此留档防丢失。每项带发现日期、证据与出处; +> 消化(修复/关闭)时移入对应模块文档并在本表标"已消化(去向)"。 +> **创建**:2026-09-22(L3 pending 台架收尾时建立,AGENTS.md 既有引用自此落文件)。 + +## 网络(CH395F / net 层) + +| # | 事项 | 发现 | 证据与现状 | 出处 | +|---|---|---|---|---| +| N-1 | **TC-NET-604:4096B 经 2KB 芯片缓冲的回显残留停滞**——4096B 单段(2×2KB,芯片 socket RX 缓冲=2KB)回显:前半 2048B 正常回显,后半在 10s 内未被再读/回显,连接停摆至对端超时拆连。**前置 1460B 全 MSS 交换后触发(2/2 复现);独立 4096B(无前置交换)正常(117.8ms 全匹配)**→ 芯片 TCP 层"缓冲满时段的交付/重交付"路径问题,方向性触发条件 = 前序满 MSS 段 | 2026-09-22 17:00/17:03(L3 台架 F1 组合) | **A/B 归因:切片构建(2438de8,L3 前)同一序列逐字节同现**(11 回显 PASS、4096B 10s 超时、Phase 11 级联 FAIL,时序差 2ms)→ 既有芯片侧问题,**L3 pending 无责**(DONTWAIT 快速路径逐位未变)。复现探针(本地未跟踪工件,MDK-ARM/ 下):完整序列 = `test/ch395f_socket_test.py tcp_client --ip 192.168.1.100 --port 8080 --count 10`(F1 组合构建);独立 4096B = `MDK-ARM/probe_4096.py`。规避:Phase 6/8 同建时避免 4096B 子项紧随满 MSS 段;根治待芯片侧定位(`CMD_GET_SOCKET_STATUS_SN`/SINT 序列 + 缓冲水位观测) | `错误码传播审计.md` E-02 阶段二"台架新发现①";`链路延迟测试说明.md` §6.3 | +| 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,窗口与 N-1 定位可并案) | 2026-09-22(L3 收尾留档) | 低风险:10ms/100ms 阈值余量 >8×;下次 Phase 13 窗口顺带重锁即可 | `链路延迟测试说明.md` §6.4 L5 注¹ | + +## 存储 / 日志管线 + +| # | 事项 | 发现 | 证据与现状 | 出处 | +|---|---|---|---|---| +| 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 佐证 | + +## 网络(二期排期,随第二档 #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 | E-03(`s_net_errno` 跨任务覆写竞态)——pending 化不改变 errno 通道现状;与 N-4 二期或独立小修(错误码经通知值直回,包装器去全局) | 既有 P1 | `错误码传播审计.md` E-03 | diff --git a/docs/测试说明/m3_data/m3_pending_quiet.json b/docs/测试说明/m3_data/m3_pending_quiet.json new file mode 100644 index 00000000..f031c5cd --- /dev/null +++ b/docs/测试说明/m3_data/m3_pending_quiet.json @@ -0,0 +1,1783 @@ +{ + "mode": "remo", + "host": "192.168.1.100", + "port": 7003, + "ts_start": "2026-09-22 16:42:24", + "ts_end": "2026-09-22 16:42:36", + "duration_s": 12.48, + "samples": 50, + "cadence_ms": 100.0, + "tcp_nodelay": false, + "immediate_ack": null, + "in_band_ack_probe": false, + "stress_from": null, + "connect_ms": 20.959, + "reconnect_ms": 19.412, + "reconnect_list_ms": [ + 22.588, + 32.645, + 19.412 + ], + "reconnect_stat": { + "n": 3, + "min_ms": 19.412, + "med_ms": 22.588, + "p95_ms": 32.645, + "max_ms": 32.645, + "spikes500": 0 + }, + "init": { + "rtt_ms": 7.826, + "geom": { + "w": 160, + "h": 160, + "framebytes": 3200, + "payload_len": 8 + } + }, + "cycle_all": { + "n": 50, + "min_ms": 47.666, + "med_ms": 58.859, + "p95_ms": 69.871, + "max_ms": 72.065, + "spikes500": 0 + }, + "cycle_quiet": { + "n": 50, + "min_ms": 47.666, + "med_ms": 58.859, + "p95_ms": 69.871, + "max_ms": 72.065, + "spikes500": 0 + }, + "cycle_stress": { + "n": 0 + }, + "first_byte_all": { + "n": 50, + "min_ms": 3.706, + "med_ms": 9.164, + "p95_ms": 14.191, + "max_ms": 16.72, + "spikes500": 0 + }, + "tail_lag_all": { + "n": 50, + "min_ms": 43.371, + "med_ms": 50.444, + "p95_ms": 57.668, + "max_ms": 58.609, + "spikes500": 0 + }, + "crc": { + "ok": 50, + "fail": 0 + }, + "bitmap": { + "nontrivial_ok": 50, + "nontrivial_fail": 0 + }, + "frames": [ + { + "cycle": 0, + "stress": false, + "first_ms": 13.554, + "total_ms": 58.852, + "tail_lag_ms": 45.233, + "batches": [ + [ + 13.554, + 8 + ], + [ + 13.591, + 1016 + ], + [ + 15.364, + 1024 + ], + [ + 17.188, + 1024 + ], + [ + 58.786, + 137 + ] + ], + "bytes": 3209, + "tag": 187, + "cmd": 3, + "crc_ok": true, + "nontrivial": true + }, + { + "cycle": 1, + "stress": false, + "first_ms": 14.191, + "total_ms": 69.871, + "tail_lag_ms": 55.603, + "batches": [ + [ + 14.191, + 8 + ], + [ + 14.292, + 1016 + ], + [ + 16.097, + 1024 + ], + [ + 17.626, + 1024 + ], + [ + 69.794, + 137 + ] + ], + "bytes": 3209, + "tag": 187, + "cmd": 3, + "crc_ok": true, + "nontrivial": true + }, + { + "cycle": 2, + "stress": false, + "first_ms": 14.783, + "total_ms": 68.944, + "tail_lag_ms": 54.102, + "batches": [ + [ + 14.783, + 8 + ], + [ + 14.82, + 1016 + ], + [ + 16.573, + 1024 + ], + [ + 18.429, + 1024 + ], + [ + 68.885, + 137 + ] + ], + "bytes": 3209, + "tag": 187, + "cmd": 3, + "crc_ok": true, + "nontrivial": true + }, + { + "cycle": 3, + "stress": false, + "first_ms": 5.515, + "total_ms": 53.88, + "tail_lag_ms": 48.229, + "batches": [ + [ + 5.515, + 8 + ], + [ + 5.569, + 1016 + ], + [ + 7.34, + 1024 + ], + [ + 9.209, + 1024 + ], + [ + 53.744, + 137 + ] + ], + "bytes": 3209, + "tag": 187, + "cmd": 3, + "crc_ok": true, + "nontrivial": true + }, + { + "cycle": 4, + "stress": false, + "first_ms": 10.79, + "total_ms": 54.964, + "tail_lag_ms": 44.11, + "batches": [ + [ + 10.79, + 8 + ], + [ + 10.823, + 1016 + ], + [ + 12.63, + 1024 + ], + [ + 14.492, + 1024 + ], + [ + 54.9, + 137 + ] + ], + "bytes": 3209, + "tag": 187, + "cmd": 3, + "crc_ok": true, + "nontrivial": true + }, + { + "cycle": 5, + "stress": false, + "first_ms": 12.733, + "total_ms": 61.871, + "tail_lag_ms": 49.076, + "batches": [ + [ + 12.733, + 8 + ], + [ + 12.773, + 1016 + ], + [ + 14.441, + 1024 + ], + [ + 16.283, + 1024 + ], + [ + 61.809, + 137 + ] + ], + "bytes": 3209, + "tag": 187, + "cmd": 3, + "crc_ok": true, + "nontrivial": true + }, + { + "cycle": 6, + "stress": false, + "first_ms": 10.424, + "total_ms": 65.658, + "tail_lag_ms": 55.175, + "batches": [ + [ + 10.424, + 8 + ], + [ + 10.466, + 1016 + ], + [ + 12.217, + 1024 + ], + [ + 14.114, + 1024 + ], + [ + 65.599, + 137 + ] + ], + "bytes": 3209, + "tag": 187, + "cmd": 3, + "crc_ok": true, + "nontrivial": true + }, + { + "cycle": 7, + "stress": false, + "first_ms": 4.303, + "total_ms": 55.095, + "tail_lag_ms": 50.731, + "batches": [ + [ + 4.303, + 8 + ], + [ + 4.33, + 1016 + ], + [ + 6.11, + 1024 + ], + [ + 7.97, + 1024 + ], + [ + 55.034, + 137 + ] + ], + "bytes": 3209, + "tag": 187, + "cmd": 3, + "crc_ok": true, + "nontrivial": true + }, + { + "cycle": 8, + "stress": false, + "first_ms": 8.944, + "total_ms": 61.936, + "tail_lag_ms": 52.92, + "batches": [ + [ + 8.944, + 8 + ], + [ + 8.974, + 1016 + ], + [ + 10.761, + 1024 + ], + [ + 12.617, + 1024 + ], + [ + 61.863, + 137 + ] + ], + "bytes": 3209, + "tag": 187, + "cmd": 3, + "crc_ok": true, + "nontrivial": true + }, + { + "cycle": 9, + "stress": false, + "first_ms": 6.556, + "total_ms": 59.583, + "tail_lag_ms": 52.963, + "batches": [ + [ + 6.556, + 8 + ], + [ + 6.583, + 1016 + ], + [ + 8.374, + 1024 + ], + [ + 10.277, + 1024 + ], + [ + 59.52, + 137 + ] + ], + "bytes": 3209, + "tag": 187, + "cmd": 3, + "crc_ok": true, + "nontrivial": true + }, + { + "cycle": 10, + "stress": false, + "first_ms": 6.88, + "total_ms": 62.415, + "tail_lag_ms": 55.461, + "batches": [ + [ + 6.88, + 8 + ], + [ + 6.91, + 1016 + ], + [ + 8.675, + 1024 + ], + [ + 10.53, + 1024 + ], + [ + 62.341, + 137 + ] + ], + "bytes": 3209, + "tag": 187, + "cmd": 3, + "crc_ok": true, + "nontrivial": true + }, + { + "cycle": 11, + "stress": false, + "first_ms": 4.299, + "total_ms": 57.419, + "tail_lag_ms": 53.059, + "batches": [ + [ + 4.299, + 8 + ], + [ + 4.342, + 1016 + ], + [ + 6.133, + 1024 + ], + [ + 7.985, + 1024 + ], + [ + 57.358, + 137 + ] + ], + "bytes": 3209, + "tag": 187, + "cmd": 3, + "crc_ok": true, + "nontrivial": true + }, + { + "cycle": 12, + "stress": false, + "first_ms": 3.706, + "total_ms": 49.28, + "tail_lag_ms": 45.514, + "batches": [ + [ + 3.706, + 8 + ], + [ + 3.758, + 1016 + ], + [ + 5.5, + 1024 + ], + [ + 7.374, + 1024 + ], + [ + 49.22, + 137 + ] + ], + "bytes": 3209, + "tag": 187, + "cmd": 3, + "crc_ok": true, + "nontrivial": true + }, + { + "cycle": 13, + "stress": false, + "first_ms": 14.143, + "total_ms": 62.435, + "tail_lag_ms": 48.212, + "batches": [ + [ + 14.143, + 8 + ], + [ + 14.178, + 1016 + ], + [ + 15.975, + 1024 + ], + [ + 17.792, + 1024 + ], + [ + 62.356, + 137 + ] + ], + "bytes": 3209, + "tag": 187, + "cmd": 3, + "crc_ok": true, + "nontrivial": true + }, + { + "cycle": 14, + "stress": false, + "first_ms": 11.579, + "total_ms": 69.308, + "tail_lag_ms": 57.668, + "batches": [ + [ + 11.579, + 8 + ], + [ + 11.629, + 1016 + ], + [ + 13.394, + 1024 + ], + [ + 15.228, + 1024 + ], + [ + 69.247, + 137 + ] + ], + "bytes": 3209, + "tag": 187, + "cmd": 3, + "crc_ok": true, + "nontrivial": true + }, + { + "cycle": 15, + "stress": false, + "first_ms": 12.941, + "total_ms": 56.618, + "tail_lag_ms": 43.606, + "batches": [ + [ + 12.941, + 8 + ], + [ + 12.976, + 1016 + ], + [ + 14.777, + 1024 + ], + [ + 16.61, + 1024 + ], + [ + 56.547, + 137 + ] + ], + "bytes": 3209, + "tag": 187, + "cmd": 3, + "crc_ok": true, + "nontrivial": true + }, + { + "cycle": 16, + "stress": false, + "first_ms": 4.982, + "total_ms": 49.009, + "tail_lag_ms": 43.916, + "batches": [ + [ + 4.982, + 8 + ], + [ + 5.003, + 1016 + ], + [ + 6.783, + 1024 + ], + [ + 8.639, + 1024 + ], + [ + 48.898, + 137 + ] + ], + "bytes": 3209, + "tag": 187, + "cmd": 3, + "crc_ok": true, + "nontrivial": true + }, + { + "cycle": 17, + "stress": false, + "first_ms": 5.254, + "total_ms": 49.188, + "tail_lag_ms": 43.79, + "batches": [ + [ + 5.254, + 8 + ], + [ + 5.278, + 1016 + ], + [ + 7.129, + 1024 + ], + [ + 8.928, + 1024 + ], + [ + 49.044, + 137 + ] + ], + "bytes": 3209, + "tag": 187, + "cmd": 3, + "crc_ok": true, + "nontrivial": true + }, + { + "cycle": 18, + "stress": false, + "first_ms": 4.85, + "total_ms": 55.361, + "tail_lag_ms": 50.444, + "batches": [ + [ + 4.85, + 8 + ], + [ + 4.898, + 1016 + ], + [ + 6.708, + 1024 + ], + [ + 8.495, + 1024 + ], + [ + 55.294, + 137 + ] + ], + "bytes": 3209, + "tag": 187, + "cmd": 3, + "crc_ok": true, + "nontrivial": true + }, + { + "cycle": 19, + "stress": false, + "first_ms": 16.72, + "total_ms": 60.732, + "tail_lag_ms": 43.935, + "batches": [ + [ + 16.72, + 8 + ], + [ + 16.791, + 1016 + ], + [ + 18.567, + 1024 + ], + [ + 20.39, + 1024 + ], + [ + 60.655, + 137 + ] + ], + "bytes": 3209, + "tag": 187, + "cmd": 3, + "crc_ok": true, + "nontrivial": true + }, + { + "cycle": 20, + "stress": false, + "first_ms": 4.696, + "total_ms": 54.384, + "tail_lag_ms": 49.592, + "batches": [ + [ + 4.696, + 8 + ], + [ + 4.744, + 1016 + ], + [ + 6.411, + 1024 + ], + [ + 8.354, + 1024 + ], + [ + 54.288, + 137 + ] + ], + "bytes": 3209, + "tag": 187, + "cmd": 3, + "crc_ok": true, + "nontrivial": true + }, + { + "cycle": 21, + "stress": false, + "first_ms": 9.844, + "total_ms": 58.859, + "tail_lag_ms": 48.844, + "batches": [ + [ + 9.844, + 8 + ], + [ + 9.898, + 1016 + ], + [ + 11.642, + 1024 + ], + [ + 13.358, + 1024 + ], + [ + 58.689, + 137 + ] + ], + "bytes": 3209, + "tag": 187, + "cmd": 3, + "crc_ok": true, + "nontrivial": true + }, + { + "cycle": 22, + "stress": false, + "first_ms": 10.167, + "total_ms": 63.007, + "tail_lag_ms": 52.687, + "batches": [ + [ + 10.167, + 8 + ], + [ + 10.227, + 1016 + ], + [ + 11.982, + 1024 + ], + [ + 13.831, + 1024 + ], + [ + 62.855, + 137 + ] + ], + "bytes": 3209, + "tag": 187, + "cmd": 3, + "crc_ok": true, + "nontrivial": true + }, + { + "cycle": 23, + "stress": false, + "first_ms": 7.13, + "total_ms": 58.554, + "tail_lag_ms": 51.266, + "batches": [ + [ + 7.13, + 8 + ], + [ + 7.16, + 1016 + ], + [ + 8.934, + 1024 + ], + [ + 10.864, + 1024 + ], + [ + 58.395, + 137 + ] + ], + "bytes": 3209, + "tag": 187, + "cmd": 3, + "crc_ok": true, + "nontrivial": true + }, + { + "cycle": 24, + "stress": false, + "first_ms": 8.272, + "total_ms": 57.406, + "tail_lag_ms": 49.065, + "batches": [ + [ + 8.272, + 8 + ], + [ + 8.311, + 1016 + ], + [ + 10.113, + 1024 + ], + [ + 11.975, + 1024 + ], + [ + 57.337, + 137 + ] + ], + "bytes": 3209, + "tag": 187, + "cmd": 3, + "crc_ok": true, + "nontrivial": true + }, + { + "cycle": 25, + "stress": false, + "first_ms": 10.216, + "total_ms": 67.616, + "tail_lag_ms": 57.251, + "batches": [ + [ + 10.216, + 8 + ], + [ + 10.259, + 1016 + ], + [ + 12.108, + 1024 + ], + [ + 13.908, + 1024 + ], + [ + 67.467, + 137 + ] + ], + "bytes": 3209, + "tag": 187, + "cmd": 3, + "crc_ok": true, + "nontrivial": true + }, + { + "cycle": 26, + "stress": false, + "first_ms": 12.685, + "total_ms": 70.759, + "tail_lag_ms": 57.985, + "batches": [ + [ + 12.685, + 8 + ], + [ + 12.743, + 1016 + ], + [ + 14.495, + 1024 + ], + [ + 16.344, + 1024 + ], + [ + 70.67, + 137 + ] + ], + "bytes": 3209, + "tag": 187, + "cmd": 3, + "crc_ok": true, + "nontrivial": true + }, + { + "cycle": 27, + "stress": false, + "first_ms": 9.722, + "total_ms": 60.906, + "tail_lag_ms": 50.995, + "batches": [ + [ + 9.722, + 8 + ], + [ + 9.776, + 1016 + ], + [ + 11.57, + 1024 + ], + [ + 13.373, + 1024 + ], + [ + 60.717, + 137 + ] + ], + "bytes": 3209, + "tag": 187, + "cmd": 3, + "crc_ok": true, + "nontrivial": true + }, + { + "cycle": 28, + "stress": false, + "first_ms": 8.214, + "total_ms": 60.55, + "tail_lag_ms": 52.258, + "batches": [ + [ + 8.214, + 8 + ], + [ + 8.265, + 1016 + ], + [ + 10.026, + 1024 + ], + [ + 11.946, + 1024 + ], + [ + 60.471, + 137 + ] + ], + "bytes": 3209, + "tag": 187, + "cmd": 3, + "crc_ok": true, + "nontrivial": true + }, + { + "cycle": 29, + "stress": false, + "first_ms": 6.813, + "total_ms": 57.326, + "tail_lag_ms": 50.454, + "batches": [ + [ + 6.813, + 8 + ], + [ + 6.854, + 1016 + ], + [ + 8.647, + 1024 + ], + [ + 10.687, + 1024 + ], + [ + 57.266, + 137 + ] + ], + "bytes": 3209, + "tag": 187, + "cmd": 3, + "crc_ok": true, + "nontrivial": true + }, + { + "cycle": 30, + "stress": false, + "first_ms": 9.164, + "total_ms": 59.855, + "tail_lag_ms": 50.61, + "batches": [ + [ + 9.164, + 8 + ], + [ + 9.195, + 1016 + ], + [ + 11.09, + 1024 + ], + [ + 12.894, + 1024 + ], + [ + 59.774, + 137 + ] + ], + "bytes": 3209, + "tag": 187, + "cmd": 3, + "crc_ok": true, + "nontrivial": true + }, + { + "cycle": 31, + "stress": false, + "first_ms": 9.12, + "total_ms": 61.005, + "tail_lag_ms": 51.788, + "batches": [ + [ + 9.12, + 8 + ], + [ + 9.182, + 1016 + ], + [ + 10.89, + 1024 + ], + [ + 12.757, + 1024 + ], + [ + 60.908, + 137 + ] + ], + "bytes": 3209, + "tag": 187, + "cmd": 3, + "crc_ok": true, + "nontrivial": true + }, + { + "cycle": 32, + "stress": false, + "first_ms": 7.497, + "total_ms": 56.441, + "tail_lag_ms": 48.766, + "batches": [ + [ + 7.497, + 8 + ], + [ + 7.573, + 1016 + ], + [ + 9.269, + 1024 + ], + [ + 11.204, + 1024 + ], + [ + 56.263, + 137 + ] + ], + "bytes": 3209, + "tag": 187, + "cmd": 3, + "crc_ok": true, + "nontrivial": true + }, + { + "cycle": 33, + "stress": false, + "first_ms": 9.956, + "total_ms": 54.481, + "tail_lag_ms": 44.38, + "batches": [ + [ + 9.956, + 8 + ], + [ + 10.018, + 1016 + ], + [ + 11.868, + 1024 + ], + [ + 13.773, + 1024 + ], + [ + 54.336, + 137 + ] + ], + "bytes": 3209, + "tag": 187, + "cmd": 3, + "crc_ok": true, + "nontrivial": true + }, + { + "cycle": 34, + "stress": false, + "first_ms": 12.081, + "total_ms": 57.487, + "tail_lag_ms": 45.239, + "batches": [ + [ + 12.081, + 8 + ], + [ + 12.137, + 1016 + ], + [ + 13.736, + 1024 + ], + [ + 15.764, + 1024 + ], + [ + 57.32, + 137 + ] + ], + "bytes": 3209, + "tag": 187, + "cmd": 3, + "crc_ok": true, + "nontrivial": true + }, + { + "cycle": 35, + "stress": false, + "first_ms": 14.061, + "total_ms": 59.715, + "tail_lag_ms": 45.58, + "batches": [ + [ + 14.061, + 8 + ], + [ + 14.104, + 1016 + ], + [ + 15.826, + 1024 + ], + [ + 17.807, + 1024 + ], + [ + 59.641, + 137 + ] + ], + "bytes": 3209, + "tag": 187, + "cmd": 3, + "crc_ok": true, + "nontrivial": true + }, + { + "cycle": 36, + "stress": false, + "first_ms": 14.124, + "total_ms": 67.309, + "tail_lag_ms": 53.025, + "batches": [ + [ + 14.124, + 8 + ], + [ + 14.19, + 1016 + ], + [ + 15.929, + 1024 + ], + [ + 17.772, + 1024 + ], + [ + 67.15, + 137 + ] + ], + "bytes": 3209, + "tag": 187, + "cmd": 3, + "crc_ok": true, + "nontrivial": true + }, + { + "cycle": 37, + "stress": false, + "first_ms": 6.23, + "total_ms": 52.326, + "tail_lag_ms": 46.001, + "batches": [ + [ + 6.23, + 8 + ], + [ + 6.271, + 1016 + ], + [ + 7.966, + 1024 + ], + [ + 9.8, + 1024 + ], + [ + 52.231, + 137 + ] + ], + "bytes": 3209, + "tag": 187, + "cmd": 3, + "crc_ok": true, + "nontrivial": true + }, + { + "cycle": 38, + "stress": false, + "first_ms": 13.495, + "total_ms": 64.171, + "tail_lag_ms": 50.566, + "batches": [ + [ + 13.495, + 8 + ], + [ + 13.543, + 1016 + ], + [ + 15.316, + 1024 + ], + [ + 17.127, + 1024 + ], + [ + 64.061, + 137 + ] + ], + "bytes": 3209, + "tag": 187, + "cmd": 3, + "crc_ok": true, + "nontrivial": true + }, + { + "cycle": 39, + "stress": false, + "first_ms": 8.713, + "total_ms": 63.142, + "tail_lag_ms": 54.335, + "batches": [ + [ + 8.713, + 8 + ], + [ + 8.762, + 1016 + ], + [ + 10.545, + 1024 + ], + [ + 12.374, + 1024 + ], + [ + 63.048, + 137 + ] + ], + "bytes": 3209, + "tag": 187, + "cmd": 3, + "crc_ok": true, + "nontrivial": true + }, + { + "cycle": 40, + "stress": false, + "first_ms": 4.882, + "total_ms": 48.943, + "tail_lag_ms": 43.922, + "batches": [ + [ + 4.882, + 8 + ], + [ + 4.923, + 1016 + ], + [ + 6.616, + 1024 + ], + [ + 8.653, + 1024 + ], + [ + 48.804, + 137 + ] + ], + "bytes": 3209, + "tag": 187, + "cmd": 3, + "crc_ok": true, + "nontrivial": true + }, + { + "cycle": 41, + "stress": false, + "first_ms": 12.641, + "total_ms": 66.603, + "tail_lag_ms": 53.864, + "batches": [ + [ + 12.641, + 8 + ], + [ + 12.695, + 1016 + ], + [ + 14.316, + 1024 + ], + [ + 16.234, + 1024 + ], + [ + 66.504, + 137 + ] + ], + "bytes": 3209, + "tag": 187, + "cmd": 3, + "crc_ok": true, + "nontrivial": true + }, + { + "cycle": 42, + "stress": false, + "first_ms": 5.721, + "total_ms": 54.852, + "tail_lag_ms": 49.051, + "batches": [ + [ + 5.721, + 8 + ], + [ + 5.756, + 1016 + ], + [ + 7.603, + 1024 + ], + [ + 9.412, + 1024 + ], + [ + 54.772, + 137 + ] + ], + "bytes": 3209, + "tag": 187, + "cmd": 3, + "crc_ok": true, + "nontrivial": true + }, + { + "cycle": 43, + "stress": false, + "first_ms": 10.578, + "total_ms": 55.102, + "tail_lag_ms": 44.453, + "batches": [ + [ + 10.578, + 8 + ], + [ + 10.623, + 1016 + ], + [ + 12.392, + 1024 + ], + [ + 14.227, + 1024 + ], + [ + 55.031, + 137 + ] + ], + "bytes": 3209, + "tag": 187, + "cmd": 3, + "crc_ok": true, + "nontrivial": true + }, + { + "cycle": 44, + "stress": false, + "first_ms": 4.144, + "total_ms": 47.666, + "tail_lag_ms": 43.371, + "batches": [ + [ + 4.144, + 8 + ], + [ + 4.171, + 1016 + ], + [ + 6.054, + 1024 + ], + [ + 7.795, + 1024 + ], + [ + 47.515, + 137 + ] + ], + "bytes": 3209, + "tag": 187, + "cmd": 3, + "crc_ok": true, + "nontrivial": true + }, + { + "cycle": 45, + "stress": false, + "first_ms": 4.774, + "total_ms": 58.008, + "tail_lag_ms": 53.071, + "batches": [ + [ + 4.774, + 8 + ], + [ + 4.802, + 1016 + ], + [ + 6.655, + 1024 + ], + [ + 8.582, + 1024 + ], + [ + 57.846, + 137 + ] + ], + "bytes": 3209, + "tag": 187, + "cmd": 3, + "crc_ok": true, + "nontrivial": true + }, + { + "cycle": 46, + "stress": false, + "first_ms": 6.364, + "total_ms": 53.901, + "tail_lag_ms": 47.409, + "batches": [ + [ + 6.364, + 8 + ], + [ + 6.417, + 1016 + ], + [ + 8.192, + 1024 + ], + [ + 10.023, + 1024 + ], + [ + 53.773, + 137 + ] + ], + "bytes": 3209, + "tag": 187, + "cmd": 3, + "crc_ok": true, + "nontrivial": true + }, + { + "cycle": 47, + "stress": false, + "first_ms": 12.04, + "total_ms": 61.46, + "tail_lag_ms": 49.351, + "batches": [ + [ + 12.04, + 8 + ], + [ + 12.103, + 1016 + ], + [ + 13.838, + 1024 + ], + [ + 15.604, + 1024 + ], + [ + 61.392, + 137 + ] + ], + "bytes": 3209, + "tag": 187, + "cmd": 3, + "crc_ok": true, + "nontrivial": true + }, + { + "cycle": 48, + "stress": false, + "first_ms": 6.801, + "total_ms": 52.84, + "tail_lag_ms": 45.921, + "batches": [ + [ + 6.801, + 8 + ], + [ + 6.833, + 1016 + ], + [ + 8.6, + 1024 + ], + [ + 10.362, + 1024 + ], + [ + 52.722, + 137 + ] + ], + "bytes": 3209, + "tag": 187, + "cmd": 3, + "crc_ok": true, + "nontrivial": true + }, + { + "cycle": 49, + "stress": false, + "first_ms": 13.393, + "total_ms": 72.065, + "tail_lag_ms": 58.609, + "batches": [ + [ + 13.393, + 8 + ], + [ + 13.463, + 1016 + ], + [ + 15.14, + 1024 + ], + [ + 16.841, + 1024 + ], + [ + 72.002, + 137 + ] + ], + "bytes": 3209, + "tag": 187, + "cmd": 3, + "crc_ok": true, + "nontrivial": true + } + ] +} diff --git a/docs/测试说明/m3_data/m3_pending_stress.json b/docs/测试说明/m3_data/m3_pending_stress.json new file mode 100644 index 00000000..a68159d0 --- /dev/null +++ b/docs/测试说明/m3_data/m3_pending_stress.json @@ -0,0 +1,1788 @@ +{ + "mode": "remo", + "host": "192.168.1.100", + "port": 7003, + "ts_start": "2026-09-22 16:43:51", + "ts_end": "2026-09-22 16:44:04", + "duration_s": 13.01, + "samples": 50, + "cadence_ms": 100.0, + "tcp_nodelay": false, + "immediate_ack": null, + "in_band_ack_probe": false, + "stress_from": 25, + "connect_ms": 26.384, + "reconnect_ms": 30.495, + "reconnect_list_ms": [ + 18.951, + 30.743, + 30.495 + ], + "reconnect_stat": { + "n": 3, + "min_ms": 18.951, + "med_ms": 30.495, + "p95_ms": 30.743, + "max_ms": 30.743, + "spikes500": 0 + }, + "init": { + "rtt_ms": 12.12, + "geom": { + "w": 160, + "h": 160, + "framebytes": 3200, + "payload_len": 8 + } + }, + "cycle_all": { + "n": 50, + "min_ms": 48.238, + "med_ms": 59.168, + "p95_ms": 68.996, + "max_ms": 69.834, + "spikes500": 0 + }, + "cycle_quiet": { + "n": 25, + "min_ms": 48.238, + "med_ms": 58.39, + "p95_ms": 68.996, + "max_ms": 69.834, + "spikes500": 0 + }, + "cycle_stress": { + "n": 25, + "min_ms": 48.863, + "med_ms": 60.103, + "p95_ms": 66.416, + "max_ms": 69.304, + "spikes500": 0 + }, + "first_byte_all": { + "n": 50, + "min_ms": 3.519, + "med_ms": 10.183, + "p95_ms": 13.534, + "max_ms": 14.409, + "spikes500": 0 + }, + "tail_lag_all": { + "n": 50, + "min_ms": 43.623, + "med_ms": 49.477, + "p95_ms": 58.325, + "max_ms": 59.355, + "spikes500": 0 + }, + "crc": { + "ok": 50, + "fail": 0 + }, + "bitmap": { + "nontrivial_ok": 50, + "nontrivial_fail": 0 + }, + "frames": [ + { + "cycle": 0, + "stress": false, + "first_ms": 12.874, + "total_ms": 69.834, + "tail_lag_ms": 56.887, + "batches": [ + [ + 12.874, + 8 + ], + [ + 12.909, + 1016 + ], + [ + 14.69, + 1024 + ], + [ + 16.543, + 1024 + ], + [ + 69.761, + 137 + ] + ], + "bytes": 3209, + "tag": 187, + "cmd": 3, + "crc_ok": true, + "nontrivial": true + }, + { + "cycle": 1, + "stress": false, + "first_ms": 13.482, + "total_ms": 66.345, + "tail_lag_ms": 52.803, + "batches": [ + [ + 13.482, + 8 + ], + [ + 13.54, + 1016 + ], + [ + 15.314, + 1024 + ], + [ + 17.164, + 1024 + ], + [ + 66.284, + 137 + ] + ], + "bytes": 3209, + "tag": 187, + "cmd": 3, + "crc_ok": true, + "nontrivial": true + }, + { + "cycle": 2, + "stress": false, + "first_ms": 6.615, + "total_ms": 50.626, + "tail_lag_ms": 43.946, + "batches": [ + [ + 6.615, + 8 + ], + [ + 6.643, + 1016 + ], + [ + 8.482, + 1024 + ], + [ + 10.243, + 1024 + ], + [ + 50.561, + 137 + ] + ], + "bytes": 3209, + "tag": 187, + "cmd": 3, + "crc_ok": true, + "nontrivial": true + }, + { + "cycle": 3, + "stress": false, + "first_ms": 5.414, + "total_ms": 52.305, + "tail_lag_ms": 46.83, + "batches": [ + [ + 5.414, + 8 + ], + [ + 5.435, + 1016 + ], + [ + 6.631, + 1024 + ], + [ + 8.418, + 1024 + ], + [ + 52.244, + 137 + ] + ], + "bytes": 3209, + "tag": 187, + "cmd": 3, + "crc_ok": true, + "nontrivial": true + }, + { + "cycle": 4, + "stress": false, + "first_ms": 11.575, + "total_ms": 65.064, + "tail_lag_ms": 53.418, + "batches": [ + [ + 11.575, + 8 + ], + [ + 11.647, + 1016 + ], + [ + 13.36, + 1024 + ], + [ + 15.236, + 1024 + ], + [ + 64.993, + 137 + ] + ], + "bytes": 3209, + "tag": 187, + "cmd": 3, + "crc_ok": true, + "nontrivial": true + }, + { + "cycle": 5, + "stress": false, + "first_ms": 5.989, + "total_ms": 55.526, + "tail_lag_ms": 49.477, + "batches": [ + [ + 5.989, + 8 + ], + [ + 6.024, + 1016 + ], + [ + 7.821, + 1024 + ], + [ + 9.671, + 1024 + ], + [ + 55.467, + 137 + ] + ], + "bytes": 3209, + "tag": 187, + "cmd": 3, + "crc_ok": true, + "nontrivial": true + }, + { + "cycle": 6, + "stress": false, + "first_ms": 10.229, + "total_ms": 56.865, + "tail_lag_ms": 46.566, + "batches": [ + [ + 10.229, + 8 + ], + [ + 10.27, + 1016 + ], + [ + 12.031, + 1024 + ], + [ + 14.019, + 1024 + ], + [ + 56.795, + 137 + ] + ], + "bytes": 3209, + "tag": 187, + "cmd": 3, + "crc_ok": true, + "nontrivial": true + }, + { + "cycle": 7, + "stress": false, + "first_ms": 12.958, + "total_ms": 63.482, + "tail_lag_ms": 50.467, + "batches": [ + [ + 12.958, + 8 + ], + [ + 12.993, + 1016 + ], + [ + 14.723, + 1024 + ], + [ + 16.615, + 1024 + ], + [ + 63.425, + 137 + ] + ], + "bytes": 3209, + "tag": 187, + "cmd": 3, + "crc_ok": true, + "nontrivial": true + }, + { + "cycle": 8, + "stress": false, + "first_ms": 9.31, + "total_ms": 58.39, + "tail_lag_ms": 49.013, + "batches": [ + [ + 9.31, + 8 + ], + [ + 9.377, + 1016 + ], + [ + 11.108, + 1024 + ], + [ + 12.973, + 1024 + ], + [ + 58.322, + 137 + ] + ], + "bytes": 3209, + "tag": 187, + "cmd": 3, + "crc_ok": true, + "nontrivial": true + }, + { + "cycle": 9, + "stress": false, + "first_ms": 10.601, + "total_ms": 54.605, + "tail_lag_ms": 43.94, + "batches": [ + [ + 10.601, + 8 + ], + [ + 10.667, + 1016 + ], + [ + 12.383, + 1024 + ], + [ + 14.225, + 1024 + ], + [ + 54.54, + 137 + ] + ], + "bytes": 3209, + "tag": 187, + "cmd": 3, + "crc_ok": true, + "nontrivial": true + }, + { + "cycle": 10, + "stress": false, + "first_ms": 4.446, + "total_ms": 53.747, + "tail_lag_ms": 49.239, + "batches": [ + [ + 4.446, + 8 + ], + [ + 4.494, + 1016 + ], + [ + 6.281, + 1024 + ], + [ + 8.128, + 1024 + ], + [ + 53.686, + 137 + ] + ], + "bytes": 3209, + "tag": 187, + "cmd": 3, + "crc_ok": true, + "nontrivial": true + }, + { + "cycle": 11, + "stress": false, + "first_ms": 10.065, + "total_ms": 66.434, + "tail_lag_ms": 56.309, + "batches": [ + [ + 10.065, + 8 + ], + [ + 10.098, + 1016 + ], + [ + 11.934, + 1024 + ], + [ + 13.721, + 1024 + ], + [ + 66.374, + 137 + ] + ], + "bytes": 3209, + "tag": 187, + "cmd": 3, + "crc_ok": true, + "nontrivial": true + }, + { + "cycle": 12, + "stress": false, + "first_ms": 3.519, + "total_ms": 50.343, + "tail_lag_ms": 46.761, + "batches": [ + [ + 3.519, + 8 + ], + [ + 3.559, + 1016 + ], + [ + 5.344, + 1024 + ], + [ + 7.199, + 1024 + ], + [ + 50.281, + 137 + ] + ], + "bytes": 3209, + "tag": 187, + "cmd": 3, + "crc_ok": true, + "nontrivial": true + }, + { + "cycle": 13, + "stress": false, + "first_ms": 12.72, + "total_ms": 62.989, + "tail_lag_ms": 50.195, + "batches": [ + [ + 12.72, + 8 + ], + [ + 12.758, + 1016 + ], + [ + 14.531, + 1024 + ], + [ + 16.399, + 1024 + ], + [ + 62.915, + 137 + ] + ], + "bytes": 3209, + "tag": 187, + "cmd": 3, + "crc_ok": true, + "nontrivial": true + }, + { + "cycle": 14, + "stress": false, + "first_ms": 9.579, + "total_ms": 68.996, + "tail_lag_ms": 59.355, + "batches": [ + [ + 9.579, + 8 + ], + [ + 9.614, + 1016 + ], + [ + 11.43, + 1024 + ], + [ + 13.268, + 1024 + ], + [ + 68.934, + 137 + ] + ], + "bytes": 3209, + "tag": 187, + "cmd": 3, + "crc_ok": true, + "nontrivial": true + }, + { + "cycle": 15, + "stress": false, + "first_ms": 11.084, + "total_ms": 57.362, + "tail_lag_ms": 46.219, + "batches": [ + [ + 11.084, + 8 + ], + [ + 11.136, + 1016 + ], + [ + 12.894, + 1024 + ], + [ + 14.711, + 1024 + ], + [ + 57.303, + 137 + ] + ], + "bytes": 3209, + "tag": 187, + "cmd": 3, + "crc_ok": true, + "nontrivial": true + }, + { + "cycle": 16, + "stress": false, + "first_ms": 13.255, + "total_ms": 61.991, + "tail_lag_ms": 48.675, + "batches": [ + [ + 13.255, + 8 + ], + [ + 13.286, + 1016 + ], + [ + 15.067, + 1024 + ], + [ + 16.94, + 1024 + ], + [ + 61.93, + 137 + ] + ], + "bytes": 3209, + "tag": 187, + "cmd": 3, + "crc_ok": true, + "nontrivial": true + }, + { + "cycle": 17, + "stress": false, + "first_ms": 10.972, + "total_ms": 54.666, + "tail_lag_ms": 43.623, + "batches": [ + [ + 10.972, + 8 + ], + [ + 11.008, + 1016 + ], + [ + 12.825, + 1024 + ], + [ + 14.659, + 1024 + ], + [ + 54.595, + 137 + ] + ], + "bytes": 3209, + "tag": 187, + "cmd": 3, + "crc_ok": true, + "nontrivial": true + }, + { + "cycle": 18, + "stress": false, + "first_ms": 4.714, + "total_ms": 59.168, + "tail_lag_ms": 54.382, + "batches": [ + [ + 4.714, + 8 + ], + [ + 4.744, + 1016 + ], + [ + 6.564, + 1024 + ], + [ + 8.386, + 1024 + ], + [ + 59.095, + 137 + ] + ], + "bytes": 3209, + "tag": 187, + "cmd": 3, + "crc_ok": true, + "nontrivial": true + }, + { + "cycle": 19, + "stress": false, + "first_ms": 4.96, + "total_ms": 63.356, + "tail_lag_ms": 58.325, + "batches": [ + [ + 4.96, + 8 + ], + [ + 5.016, + 1016 + ], + [ + 6.908, + 1024 + ], + [ + 8.801, + 1024 + ], + [ + 63.285, + 137 + ] + ], + "bytes": 3209, + "tag": 187, + "cmd": 3, + "crc_ok": true, + "nontrivial": true + }, + { + "cycle": 20, + "stress": false, + "first_ms": 12.517, + "total_ms": 63.787, + "tail_lag_ms": 51.202, + "batches": [ + [ + 12.517, + 8 + ], + [ + 12.564, + 1016 + ], + [ + 14.358, + 1024 + ], + [ + 16.172, + 1024 + ], + [ + 63.718, + 137 + ] + ], + "bytes": 3209, + "tag": 187, + "cmd": 3, + "crc_ok": true, + "nontrivial": true + }, + { + "cycle": 21, + "stress": false, + "first_ms": 8.315, + "total_ms": 57.987, + "tail_lag_ms": 49.551, + "batches": [ + [ + 8.315, + 8 + ], + [ + 8.357, + 1016 + ], + [ + 10.254, + 1024 + ], + [ + 12.116, + 1024 + ], + [ + 57.866, + 137 + ] + ], + "bytes": 3209, + "tag": 187, + "cmd": 3, + "crc_ok": true, + "nontrivial": true + }, + { + "cycle": 22, + "stress": false, + "first_ms": 10.183, + "total_ms": 66.312, + "tail_lag_ms": 56.05, + "batches": [ + [ + 10.183, + 8 + ], + [ + 10.228, + 1016 + ], + [ + 12.053, + 1024 + ], + [ + 13.833, + 1024 + ], + [ + 66.233, + 137 + ] + ], + "bytes": 3209, + "tag": 187, + "cmd": 3, + "crc_ok": true, + "nontrivial": true + }, + { + "cycle": 23, + "stress": false, + "first_ms": 3.567, + "total_ms": 48.238, + "tail_lag_ms": 44.502, + "batches": [ + [ + 3.567, + 8 + ], + [ + 3.615, + 1016 + ], + [ + 5.442, + 1024 + ], + [ + 7.128, + 1024 + ], + [ + 48.069, + 137 + ] + ], + "bytes": 3209, + "tag": 187, + "cmd": 3, + "crc_ok": true, + "nontrivial": true + }, + { + "cycle": 24, + "stress": false, + "first_ms": 3.974, + "total_ms": 57.473, + "tail_lag_ms": 53.353, + "batches": [ + [ + 3.974, + 8 + ], + [ + 4.014, + 1016 + ], + [ + 5.825, + 1024 + ], + [ + 7.534, + 1024 + ], + [ + 57.326, + 137 + ] + ], + "bytes": 3209, + "tag": 187, + "cmd": 3, + "crc_ok": true, + "nontrivial": true + }, + { + "cycle": 25, + "stress": true, + "first_ms": 6.523, + "total_ms": 53.406, + "tail_lag_ms": 46.736, + "batches": [ + [ + 6.523, + 8 + ], + [ + 6.573, + 1016 + ], + [ + 8.306, + 1024 + ], + [ + 10.135, + 1024 + ], + [ + 53.259, + 137 + ] + ], + "bytes": 3209, + "tag": 187, + "cmd": 3, + "crc_ok": true, + "nontrivial": true + }, + { + "cycle": 26, + "stress": true, + "first_ms": 12.607, + "total_ms": 62.841, + "tail_lag_ms": 50.163, + "batches": [ + [ + 12.607, + 8 + ], + [ + 12.675, + 1016 + ], + [ + 14.482, + 1024 + ], + [ + 16.352, + 1024 + ], + [ + 62.77, + 137 + ] + ], + "bytes": 3209, + "tag": 187, + "cmd": 3, + "crc_ok": true, + "nontrivial": true + }, + { + "cycle": 27, + "stress": true, + "first_ms": 9.527, + "total_ms": 58.497, + "tail_lag_ms": 48.863, + "batches": [ + [ + 9.527, + 8 + ], + [ + 9.568, + 1016 + ], + [ + 11.349, + 1024 + ], + [ + 13.3, + 1024 + ], + [ + 58.389, + 137 + ] + ], + "bytes": 3209, + "tag": 187, + "cmd": 3, + "crc_ok": true, + "nontrivial": true + }, + { + "cycle": 28, + "stress": true, + "first_ms": 10.701, + "total_ms": 66.416, + "tail_lag_ms": 55.548, + "batches": [ + [ + 10.701, + 8 + ], + [ + 10.781, + 1016 + ], + [ + 12.559, + 1024 + ], + [ + 14.376, + 1024 + ], + [ + 66.249, + 137 + ] + ], + "bytes": 3209, + "tag": 187, + "cmd": 3, + "crc_ok": true, + "nontrivial": true + }, + { + "cycle": 29, + "stress": true, + "first_ms": 3.671, + "total_ms": 48.863, + "tail_lag_ms": 45.115, + "batches": [ + [ + 3.671, + 8 + ], + [ + 3.707, + 1016 + ], + [ + 5.481, + 1024 + ], + [ + 7.366, + 1024 + ], + [ + 48.786, + 137 + ] + ], + "bytes": 3209, + "tag": 187, + "cmd": 3, + "crc_ok": true, + "nontrivial": true + }, + { + "cycle": 30, + "stress": true, + "first_ms": 14.304, + "total_ms": 64.54, + "tail_lag_ms": 50.154, + "batches": [ + [ + 14.304, + 8 + ], + [ + 14.354, + 1016 + ], + [ + 16.156, + 1024 + ], + [ + 17.932, + 1024 + ], + [ + 64.458, + 137 + ] + ], + "bytes": 3209, + "tag": 187, + "cmd": 3, + "crc_ok": true, + "nontrivial": true + }, + { + "cycle": 31, + "stress": true, + "first_ms": 9.697, + "total_ms": 55.705, + "tail_lag_ms": 45.866, + "batches": [ + [ + 9.697, + 8 + ], + [ + 9.77, + 1016 + ], + [ + 11.441, + 1024 + ], + [ + 13.396, + 1024 + ], + [ + 55.563, + 137 + ] + ], + "bytes": 3209, + "tag": 187, + "cmd": 3, + "crc_ok": true, + "nontrivial": true + }, + { + "cycle": 32, + "stress": true, + "first_ms": 13.534, + "total_ms": 62.334, + "tail_lag_ms": 48.674, + "batches": [ + [ + 13.534, + 8 + ], + [ + 13.585, + 1016 + ], + [ + 15.266, + 1024 + ], + [ + 17.249, + 1024 + ], + [ + 62.208, + 137 + ] + ], + "bytes": 3209, + "tag": 187, + "cmd": 3, + "crc_ok": true, + "nontrivial": true + }, + { + "cycle": 33, + "stress": true, + "first_ms": 10.409, + "total_ms": 60.103, + "tail_lag_ms": 49.59, + "batches": [ + [ + 10.409, + 8 + ], + [ + 10.463, + 1016 + ], + [ + 12.185, + 1024 + ], + [ + 14.061, + 1024 + ], + [ + 59.999, + 137 + ] + ], + "bytes": 3209, + "tag": 187, + "cmd": 3, + "crc_ok": true, + "nontrivial": true + }, + { + "cycle": 34, + "stress": true, + "first_ms": 13.412, + "total_ms": 60.287, + "tail_lag_ms": 46.687, + "batches": [ + [ + 13.412, + 8 + ], + [ + 13.464, + 1016 + ], + [ + 15.257, + 1024 + ], + [ + 17.077, + 1024 + ], + [ + 60.1, + 137 + ] + ], + "bytes": 3209, + "tag": 187, + "cmd": 3, + "crc_ok": true, + "nontrivial": true + }, + { + "cycle": 35, + "stress": true, + "first_ms": 12.195, + "total_ms": 61.268, + "tail_lag_ms": 48.992, + "batches": [ + [ + 12.195, + 8 + ], + [ + 12.231, + 1016 + ], + [ + 14.149, + 1024 + ], + [ + 15.919, + 1024 + ], + [ + 61.186, + 137 + ] + ], + "bytes": 3209, + "tag": 187, + "cmd": 3, + "crc_ok": true, + "nontrivial": true + }, + { + "cycle": 36, + "stress": true, + "first_ms": 10.547, + "total_ms": 69.304, + "tail_lag_ms": 58.58, + "batches": [ + [ + 10.547, + 8 + ], + [ + 10.617, + 1016 + ], + [ + 12.437, + 1024 + ], + [ + 14.241, + 1024 + ], + [ + 69.126, + 137 + ] + ], + "bytes": 3209, + "tag": 187, + "cmd": 3, + "crc_ok": true, + "nontrivial": true + }, + { + "cycle": 37, + "stress": true, + "first_ms": 11.565, + "total_ms": 58.986, + "tail_lag_ms": 47.322, + "batches": [ + [ + 11.565, + 8 + ], + [ + 11.631, + 1016 + ], + [ + 13.478, + 1024 + ], + [ + 15.353, + 1024 + ], + [ + 58.886, + 137 + ] + ], + "bytes": 3209, + "tag": 187, + "cmd": 3, + "crc_ok": true, + "nontrivial": true + }, + { + "cycle": 38, + "stress": true, + "first_ms": 11.895, + "total_ms": 56.281, + "tail_lag_ms": 44.177, + "batches": [ + [ + 11.895, + 8 + ], + [ + 11.945, + 1016 + ], + [ + 13.722, + 1024 + ], + [ + 15.574, + 1024 + ], + [ + 56.072, + 137 + ] + ], + "bytes": 3209, + "tag": 187, + "cmd": 3, + "crc_ok": true, + "nontrivial": true + }, + { + "cycle": 39, + "stress": true, + "first_ms": 4.221, + "total_ms": 61.49, + "tail_lag_ms": 57.207, + "batches": [ + [ + 4.221, + 8 + ], + [ + 4.271, + 1016 + ], + [ + 6.217, + 1024 + ], + [ + 8.048, + 1024 + ], + [ + 61.428, + 137 + ] + ], + "bytes": 3209, + "tag": 187, + "cmd": 3, + "crc_ok": true, + "nontrivial": true + }, + { + "cycle": 40, + "stress": true, + "first_ms": 13.135, + "total_ms": 57.92, + "tail_lag_ms": 44.592, + "batches": [ + [ + 13.135, + 8 + ], + [ + 13.201, + 1016 + ], + [ + 14.911, + 1024 + ], + [ + 16.789, + 1024 + ], + [ + 57.727, + 137 + ] + ], + "bytes": 3209, + "tag": 187, + "cmd": 3, + "crc_ok": true, + "nontrivial": true + }, + { + "cycle": 41, + "stress": true, + "first_ms": 3.539, + "total_ms": 57.304, + "tail_lag_ms": 53.596, + "batches": [ + [ + 3.539, + 8 + ], + [ + 3.589, + 1016 + ], + [ + 5.37, + 1024 + ], + [ + 7.062, + 1024 + ], + [ + 57.135, + 137 + ] + ], + "bytes": 3209, + "tag": 187, + "cmd": 3, + "crc_ok": true, + "nontrivial": true + }, + { + "cycle": 42, + "stress": true, + "first_ms": 5.53, + "total_ms": 57.699, + "tail_lag_ms": 52.108, + "batches": [ + [ + 5.53, + 8 + ], + [ + 5.577, + 1016 + ], + [ + 7.395, + 1024 + ], + [ + 9.292, + 1024 + ], + [ + 57.638, + 137 + ] + ], + "bytes": 3209, + "tag": 187, + "cmd": 3, + "crc_ok": true, + "nontrivial": true + }, + { + "cycle": 43, + "stress": true, + "first_ms": 6.916, + "total_ms": 53.306, + "tail_lag_ms": 46.214, + "batches": [ + [ + 6.916, + 8 + ], + [ + 6.967, + 1016 + ], + [ + 8.73, + 1024 + ], + [ + 10.597, + 1024 + ], + [ + 53.13, + 137 + ] + ], + "bytes": 3209, + "tag": 187, + "cmd": 3, + "crc_ok": true, + "nontrivial": true + }, + { + "cycle": 44, + "stress": true, + "first_ms": 12.963, + "total_ms": 66.06, + "tail_lag_ms": 53.019, + "batches": [ + [ + 12.963, + 8 + ], + [ + 13.011, + 1016 + ], + [ + 14.954, + 1024 + ], + [ + 16.808, + 1024 + ], + [ + 65.981, + 137 + ] + ], + "bytes": 3209, + "tag": 187, + "cmd": 3, + "crc_ok": true, + "nontrivial": true + }, + { + "cycle": 45, + "stress": true, + "first_ms": 6.393, + "total_ms": 55.772, + "tail_lag_ms": 49.299, + "batches": [ + [ + 6.393, + 8 + ], + [ + 6.443, + 1016 + ], + [ + 8.186, + 1024 + ], + [ + 9.937, + 1024 + ], + [ + 55.692, + 137 + ] + ], + "bytes": 3209, + "tag": 187, + "cmd": 3, + "crc_ok": true, + "nontrivial": true + }, + { + "cycle": 46, + "stress": true, + "first_ms": 10.129, + "total_ms": 61.494, + "tail_lag_ms": 51.287, + "batches": [ + [ + 10.129, + 8 + ], + [ + 10.181, + 1016 + ], + [ + 11.943, + 1024 + ], + [ + 13.764, + 1024 + ], + [ + 61.416, + 137 + ] + ], + "bytes": 3209, + "tag": 187, + "cmd": 3, + "crc_ok": true, + "nontrivial": true + }, + { + "cycle": 47, + "stress": true, + "first_ms": 8.364, + "total_ms": 63.044, + "tail_lag_ms": 54.611, + "batches": [ + [ + 8.364, + 8 + ], + [ + 8.419, + 1016 + ], + [ + 10.278, + 1024 + ], + [ + 12.095, + 1024 + ], + [ + 62.975, + 137 + ] + ], + "bytes": 3209, + "tag": 187, + "cmd": 3, + "crc_ok": true, + "nontrivial": true + }, + { + "cycle": 48, + "stress": true, + "first_ms": 4.713, + "total_ms": 49.842, + "tail_lag_ms": 44.999, + "batches": [ + [ + 4.713, + 8 + ], + [ + 4.763, + 1016 + ], + [ + 6.65, + 1024 + ], + [ + 8.405, + 1024 + ], + [ + 49.712, + 137 + ] + ], + "bytes": 3209, + "tag": 187, + "cmd": 3, + "crc_ok": true, + "nontrivial": true + }, + { + "cycle": 49, + "stress": true, + "first_ms": 14.409, + "total_ms": 61.269, + "tail_lag_ms": 46.794, + "batches": [ + [ + 14.409, + 8 + ], + [ + 14.485, + 1016 + ], + [ + 16.14, + 1024 + ], + [ + 18.033, + 1024 + ], + [ + 61.203, + 137 + ] + ], + "bytes": 3209, + "tag": 187, + "cmd": 3, + "crc_ok": true, + "nontrivial": true + } + ] +} diff --git a/docs/测试说明/链路延迟测试说明.md b/docs/测试说明/链路延迟测试说明.md index 59113b93..8f04b0a7 100644 --- a/docs/测试说明/链路延迟测试说明.md +++ b/docs/测试说明/链路延迟测试说明.md @@ -61,7 +61,7 @@ sequenceDiagram Note over F: D8 最多等 100ms 才轮到下一次 fetch_screen F->>C: LCDMEM 请求 10B C-->>N: RECV 中断 → net_poll - Note over N: D3 netMsgQueue 头阻塞窗口(已修复:5ms 分片+让出) + Note over N: D3 netMsgQueue 头阻塞窗口(已两阶段修复:分片 → L3 pending 零占用) U->>N: net_recv(64B)(队列 + TaskNotify) Note over U: D5 最多 10ms 相位 + LVGL 渲染占时(渲染实测 ~1ms) N-->>U: 按键注入 UI @@ -114,7 +114,7 @@ sequenceDiagram | **L2** | SPI DMA | `ch395f_read_recv_buf(N)` 完整 DMA 事务(含 CS 切换),N ∈ {4, 64, 1024, 2048} | MCU,DWT µs,Phase 12,N=100/档 | 20 / 114 / **1611** / 3208µs(斜率 1.56µs/B + 固定 14µs) | SPI2/DMA/总线异常 | | **L3** | 发送分块握手 | `write_send_buf(1KB)` → `SENBUF_FREE` 的等待时长(= `net_send_locked` 每 chunk 的真实等待) | MCU(netTask 上下文),Phase 13 | **219µs**/chunk | 芯片发送路径 / 重传(D1) / 链路(D7) | | **L4** | 芯片→线上+PC | 数据交入芯片协议栈 → PC 首见字节 / 收齐全帧(peer 逐 `recv()` 批次打时间戳) | PC(peer),Phase 13/14 | 首批 8.6ms;**段间间隙 ≥200ms = 重传**(P0-a 后粒度;旧固件 500ms) | D1/D4/D7("网络延迟"直接证据) | -| **L5** | 队列往返 | 调用方视角 `net_recv(DONTWAIT)` / `net_send` 全程 = 入队 + netTask 调度 + 处理 + 通知 | MCU(调用方计时),Phase 13,**两档**:静默基线 + 压力档(并发 FTP 流量) | 静默:收 1223µs / 发 988µs(2026-09-22 重锁,P0-b 后) | D3(E-02 头阻塞,已修) / D5 调度 | +| **L5** | 队列往返 | 调用方视角 `net_recv(DONTWAIT)` / `net_send` 全程 = 入队 + netTask 调度 + 处理 + 通知 | MCU(调用方计时),Phase 13,**两档**:静默基线 + 压力档(并发 FTP 流量) | 静默:收 1223µs / 发 988µs(2026-09-22 重锁,P0-b 后;L3 对 DONTWAIT 路径逐位不变,重验留待 Phase 13 下次窗口) | D3(E-02 头阻塞,已两阶段修复) / D5 调度 | | **L6** | 请求→首字节 | peer 发 10B 请求 → MCU 收齐并回显(服务端视角);与 PC 侧对照,差值 = 线路 + PC 栈 | MCU + PC 双侧,Phase 13 | MCU 986µs / PC 3.9ms | MCU 收路径/调度 | | **L7** | 整帧 3209B 往返 | LCDMEM 全帧:PC 发 → 收齐(含 L3+L4) | PC 为主,Phase 13 | 61.0ms(M2);**spike(≥500ms)=0** | D1+D2+D4 综合 | | **L8** | 生产路径帧周期 | **真实 uiTask + 真实 `ui_net_sink`**(:7003)完整帧周期:请求拾取(10ms 拍)+ 队列 + 发送 + L4 + peer 侧编码 | MCU 探针 + PC,Phase 14 | 真机 61.6ms / 模拟器 6.8ms(含 peer 100ms 节拍) | 全段(用户真实体感) | @@ -395,24 +395,30 @@ D10 修复后实测 89ms(= 30ms 重试间隔 + 约 60ms 芯片沉降),故 | 指标 | 真机(50 帧静默档) | 模拟器(50 帧) | Δ(真机−模拟器) | 阈值 | |---|---|---|---|---| -| 帧周期 total | **61.6ms**(50.4/69.8) | **6.8ms**(0.6/13.1) | **+54.8ms** | ≤80ms | -| 首字节 | 9.6ms(3.2/14.2) | 6.7ms(0.5/13.0) | +2.9ms | — | -| **尾批延迟 tail lag** | **52.6ms**(44.1/59.1) | **0.0ms**(0/0.1) | **+52.6ms** | — | +| 帧周期 total | **58.9ms**(47.7/72.1,p95 69.9) | **6.8ms**(0.6/13.1) | **+52.1ms** | ≤80ms | +| 首字节 | 9.2ms(3.7/16.7) | 6.7ms(0.5/13.0) | +2.5ms | — | +| **尾批延迟 tail lag** | **50.4ms**(43.4/58.6) | **0.0ms**(0/0.1) | **+50.4ms** | — | | 帧 CRC / 位图非平凡 | 50/0、50/50 | 50/0、50/50 | — | 全通过 | -| 连接 / 断开重连(+INIT) | 17.1ms / 22.4ms | 10.5ms / 32.0ms | — | ≤150ms | +| 连接 / 断开重连(+INIT) | 20.9ms / 22.6ms(3/32.6) | 10.5ms / 32.0ms | — | ≤150ms | -(模拟器列为 2026-09-21 基线,模拟器工程本日未改动;真机列 = 2026-09-22 P0-a/P0-b 代码重测。 -旧真机值:帧周期 66.0ms / 首字节 13.9ms / 重连 23.5~34.7ms。) +(模拟器列为 2026-09-21 基线,模拟器工程不受 L3 影响(公开 API 不变);真机列 = +**2026-09-22 16:42 L3 pending 构建重锁**(`m3_data/m3_pending_quiet.json`,50/50 帧全 OK、零尖峰)。 +上一档真机值(P0-a/P0-b 分片代码,同日 11:35):帧周期 61.6ms / 首字节 9.6ms / 尾批 52.6ms / +重连 17.1/22.4ms → pending 构建:帧周期 med **58.9ms**(−2.7ms)、尾批 **50.4ms**(−2.2ms)—— +执行器零占用使生产路径净缩短(更早的空闲窗口)。) -**压力档(`--ftp-stress`,E-02 复现;第 15 帧起 FTP 停留半登录态)** +**压力档(`--ftp-stress`,E-02 复现;第 25 帧起 FTP 空闲登录保持)** | 分桶 | n | med | p95 | max | 尖峰(≥500ms) | |---|---|---|---|---|---| -| quiet(0~14 帧) | 15 | 59.9ms | 65.3ms | 65.3ms | 0 | -| stress(15~44 帧,**E-02 修复后 + P0-a/P0-b**) | 30 | **65.0ms** | 73.9ms | **133.5ms** | **0** | +| quiet(0~24 帧) | 25 | 58.4ms | 69.0ms | 69.8ms | 0 | +| stress(25~49 帧,**L3 pending 构建**) | 25 | **60.1ms** | 66.4ms | **69.3ms** | **0** | -(E-02 修复前 stress 档 med 17718ms、尖峰 1 次 = 17.7s 全网冻结;修复后零尖峰,见 §8.1。 -133.5ms 为压力启动瞬态单帧(FTP 连接建立与帧周期交叠),远低于 500ms 尖峰阈值。) +(E-02 修复前 stress 档 med 17718ms、尖峰 1 次 = 17.7s 全网冻结(旧固件);阶段一 5ms 分片修复后 +med 65.0ms/max 133.5ms(133.5 = 压力启动瞬态单帧);**L3 pending 化后 med 60.1ms/max 69.3ms** +——p99 尾部较分片档压缩近半(133.5→69.3),MCU 侧 `prod_cycle_mcu` 6706µs 在压力下纹丝不动 +(min 6698/max 6720):头阻塞工况不再向 UI 帧周期传导 = 结构性收益。本档重锁 = +`m3_data/m3_pending_stress.json`,2026-09-22 16:43。) ### 6.4 全段基线总表 @@ -421,20 +427,27 @@ D10 修复后实测 89ms(= 30ms 重试间隔 + 约 60ms 芯片沉降),故 | **L1** `spi_cmd_*` | SPI 字节命令(3 条) | 10 / 15 / 15µs | 10~16µs | 100 | 40/100µs | OK | | **L2** `spi_dma_*` | SPI DMA 读(4/64/1024/2048B) | 20 / 114 / **1611** / 3208µs | ±2µs | 100 | 见 §6.1 | OK | | **L3** `chunk_wait` | 写发送缓冲 → `SENBUF_FREE`(每 chunk) | **219µs** | 213/378µs | 64 | 10ms/500ms | OK | -| **L5** `queue_rt_recv` | 调用方 `net_recv(DONTWAIT)` 队列全程 | **1223µs** | 1194/1223µs | 20 | 10ms/100ms | OK | -| **L5** `queue_rt_send` | 调用方 `net_send` 队列全程 | **988µs** | 840/1216µs | 20 | 10ms/100ms | OK | +| **L5** `queue_rt_recv` | 调用方 `net_recv(DONTWAIT)` 队列全程 | **1223µs**¹ | 1194/1223µs | 20 | 10ms/100ms | OK | +| **L5** `queue_rt_send` | 调用方 `net_send` 队列全程 | **988µs**¹ | 840/1216µs | 20 | 10ms/100ms | OK | | **L6** `req2first_mcu` | 10B 请求到齐 → 回显发出(MCU 侧) | **986µs** | 979/1015µs | 10 | 20ms/200ms | OK | | **L7** `fullframe_mcu` | 9B 请求 → 3209B 全帧交给芯片 | **6614µs** | 6546/6649µs | 10 | 50ms/500ms | OK | -| **L8** `prod_cycle_mcu` | **生产路径**:LCDMEM 取帧+组帧+net_send(MCU 净成本) | **6707µs** | 6701/6757µs | 50 | 20ms/200ms | OK | +| **L8** `prod_cycle_mcu` | **生产路径**:LCDMEM 取帧+组帧+net_send(MCU 净成本) | **6706µs**(L3 重锁) | 6698/6720µs | 50 | 20ms/200ms | OK | | **L10** `logtax_line` | 一行 60 字符 `printf` @115200 | **4402µs** | 4396/8779µs | 10 | 10ms/25ms | OK(D6 量化) | -| **L11** `ui_loop` | uiTask 生产循环实测周期 | **10986µs** | 10951/11022µs | 120 | 25ms/50ms | OK | -| **L9** `relisten` | 断线后自动重监听耗时(MCU 侧,修复后) | **89000µs** | 89000µs ×3 | 3 | 100ms/500ms | OK | -| **L4/L8** peer cycle | 生产客户端完整帧周期(发→收齐 3209B) | **61.6ms** | 50.4/69.8ms | 50 | — | 见 §7 | -| **Δ** | `peer cycle(设备) − peer cycle(模拟器)` | **54.8ms** | — | 50/50 | ≤80ms | 见 §7.1 | +| **L11** `ui_loop` | uiTask 生产循环实测周期 | **10986µs**(L3 重锁,值不变) | 10951/11022µs | 120 | 25ms/50ms | OK | +| **L9** `relisten` | 断线后自动重监听耗时(MCU 侧,修复后) | **90000µs**(L3 重锁) | 90000µs ×3 | 3 | 100ms/500ms | OK | +| **L4/L8** peer cycle | 生产客户端完整帧周期(发→收齐 3209B) | **58.9ms**(L3 重锁) | 47.7/72.1ms | 50 | — | 见 §7 | +| **Δ** | `peer cycle(设备) − peer cycle(模拟器)` | **52.1ms**(L3 重锁) | — | 50/50 | ≤80ms | 见 §7.1 | -数据来源:L1/L2 = §6.1;其余 MCU 侧 = M2 B2 档(200ms、per-recv 日志已删)/ M3 静默档的串口 `[LAT]` 行 -(`m2_data/m2_quiet_r200.json`、`m3_data/m3_dev_quiet_r200.json`);A/B 对照档 = `m2_quiet_r500.json`(旧条件); -peer 侧 = `m3_data/m3_dev_*_r200.json`。旧 run15 摘录(`m2_serial_excerpt_run15.txt`)保留作 A/B 历史对照。 +¹ L5 两行为 2026-09-22 上午分片时代(M2 B2 档)数值:L3 对 DONTWAIT 快速路径**逐位不变**(dispatch +→ `net_poll` → `get_recv_len` 读,无 readable 门控),pending tick 无 pending 时为纯指针读零 SPI +(µs 级)——机制上不影响 L5;M2 重验未在本轮执行(低风险,留待 Phase 13 下次窗口,见 `docs/待处理内容.md` N-3)。 + +数据来源:L1/L2 = §6.1;L3/L5/L6/L7 = M2 B2 档(200ms、per-recv 日志已删)串口 `[LAT]` 行 +(`m2_data/m2_quiet_r200.json`);L8/L9/L11 = **L3 pending 构建 2026-09-22 16:42/16:43 重锁** +(`m3_data/m3_pending_quiet.json` / `m3_pending_stress.json` 之 MCU 侧 `[LAT]` 行);L10 = M3 静默档 +(`m3_data/m3_dev_quiet_r200.json`,与 L3 无关的串口税段);A/B 对照档 = `m2_quiet_r500.json`(旧条件); +peer 侧 = `m3_data/m3_pending_*.json`(L3 重锁)与 `m3_data/m3_dev_*_r200.json`(上一档,历史对照)。 +旧 run15 摘录(`m2_serial_excerpt_run15.txt`)保留作 A/B 历史对照。 ### 6.5 重锁规则 @@ -592,10 +605,21 @@ sock4 auto-relisten ok / relisten retry ok ← 监听器随后自行恢复 1. **D10 重试必须防饥饿**:调用方(accept/recv 路径每 10ms 一次)只登记一次重试,实际重试由 netTask 轮询到点执行;若让调用方每次立即重试并重置时刻,会永不重试。重试间隔 100ms→30ms 后恢复时间 147ms→89ms(芯片沉降约 60ms); -2. **E-02 分片长度 = 其他任务的最坏等待**:100ms 片下受压帧仍 ~750ms(多片排队),收到 **5ms** 片后才降到 - ~75ms; -3. **分片循环必须显式让出 CPU**:某片可能因 `net_poll` 自身耗时首轮即返回超时 → 本任务(Normal)立即 - 重排队会形成忙循环并**饿死 BelowNormal 的 uiTask**(实测 2.4~3.4s 周期尖刺);`vTaskDelay(1)` 后尖刺归零。 +2. **(历史,阶段一)E-02 分片长度 = 其他任务的最坏等待**:100ms 片下受压帧仍 ~750ms(多片排队),收到 + **5ms** 片后才降到 ~75ms——该"分片即上限"模型已于 2026-09-22 由 **L3 pending 化**取代 + (f16dc9a):执行器零占用后,其他任务的最坏等待 = 一个主循环节拍(~1ms),与任何片长无关 + (M3 压力档实测:med 60.1ms/max 69.3ms,p99 尾部较分片档 133.5ms 压缩近半); +3. **(历史,阶段一)分片循环必须显式让出 CPU**:某片可能因 `net_poll` 自身耗时首轮即返回超时 → 本任务 + (Normal)立即重排队会形成忙循环并**饿死 BelowNormal 的 uiTask**(实测 2.4~3.4s 周期尖刺); + `vTaskDelay(1)` 后尖刺归零——L3 pending 化后该让出协议随分片循环一并退役(调用方改睡任务通知, + 天然让出;netTask 侧无循环可忙); +4. **(现行,L3 pending 化)阻塞等待不在执行器内发生**:`net_recv_locked` 阻塞分支在数据不可得时登记 + pending(每 fd 至多一个、**不可覆盖**;`caller==NULL`/netTask 自身拒绝)即返回哨兵 + `NET_PENDING_REGISTERED`;完成判定在 `net_pending_tick`(主循环节拍,与 `net_process_messages` + 同位)按 数据→截止→CLOSED 排空/EOF+relisten→1s 看门狗 顺序执行,**cancel/settle 必通知** + (调用方永不悬空);pending 表独立于 `net_sock_t`(close 的 memset 不得抹掉跨时间状态)。 + 维护注意:队列中长 SEND/CLOSE 消息处理期间,pending 完成顺延至下轮 tick(~1ms 级;长 SEND + stall 期间最多顺延相应时长)——已知代价,勿"优化"回执行器内等待。 ### 8.4 相关既有缺陷(会掩盖/放大延迟,见 `docs/问题记录/错误码传播审计.md`) @@ -625,7 +649,7 @@ sock4 auto-relisten ok / relisten retry ok ← 监听器随后自行恢复 | L1/L2 超 crit | SPI 走线/PCB/SPI2 分频或 DMA 配置 | 对照 `docs/问题记录/CH395F_Trap_Records.md`;逻辑分析仪抓 SCK/CS | | L3 spike ≥200ms(连续台阶;旧固件 500ms) | **D1 重传 / D7 链路** | Wireshark `tcp.analysis.retransmission`;查 PHY 协商/网线/Wi-Fi | | L3 基线(非 spike)抬高 | 芯片发送路径 / 中断响应 | 对照 CH395F 手册 §5.17/5.18(注意:状态寄存器**不被 SET 类命令更新**,`GET_CMD_STATUS` 恒读到 RESET 的 0x10 陈旧残留,2026-09-22 台架实证——不可用作 SET 值验收) | -| L5 压力档爆表 | **E-02 头阻塞(已修)** → 回归 | 定位触发源(阻塞 recv 的 FTP/对时);核对 `net_recv_to` 分片在位 | +| L5 压力档爆表 | **E-02 头阻塞(已修)→ 回归** | 定位触发源(阻塞 recv 的 FTP/对时);核对 L3 pending 在位(`net_recv_locked` 阻塞分支 = 登记 pending 而非等待;`net_pending_tick` 在主循环) | | L5/L6 静默档抬高 | D5 调度(任务抢占/节拍) | 查任务优先级与 osDelay;`stack_report.py` 核对栈水位 | | L6/L7 整体抬高且 L1~L5 正常 | 线路+PC 段(L4) | Wireshark 段间间隙;`Δ` 对照定位 MCU 侧净贡献 | | **L7/L8 尾批固定迟到 ~50ms** | 已定性(§7.3):次 MSS 尾段被 Nagle 扣住 + Windows 延迟 ACK | 客户端侧解法已实测(§7.4):`--ack-probe` / `--ack-fast` → tail 52→3.9ms;生产客户端已实装;**设备侧无解**,不必再投入 | @@ -636,7 +660,7 @@ sock4 auto-relisten ok / relisten retry ok ← 监听器随后自行恢复 | **`[LAT]` 段行缺失/截断、wait-idle 判不出空闲** | **D12-b**:热路径日志洪水 | 删除 net 热路径逐调用日志(§8.1 D12-b) | | **开机日志连续丢行**(含必检标记 `net init: OK` 等)但系统健康 | **日志并发竞态**:多任务并发 `printf` → 非重入 `fputc`/`HAL_UART_Transmit` 丢整行、UART 状态短暂卡住(2026-09-22 台架实证:boot 时 testTask 启动行与 netTask 日志并发 → 连续 4 行丢失、~2s 后自恢复) | 必现证据行采用"静默采集 + 延迟到安静窗口打印"模式(范例:P0-a 验收行曾按此模式实装,验收完成后探针已移除);根治 = S8 日志非阻塞/串行化(§10.2) | | **`relisten` 段 FAIL、断线固定 ~588ms** | **D10** 回归(退回 `osDelay(500)`) | 核对 `net_relisten_try`/`net_relisten_retry_tick` 非阻塞重试在位(§8.1 D10) | -| **远端显示整帧卡住十几秒后自恢复** | **E-02** 回归 | 核对 `net_recv_to` 5ms 分片 + 让出在位(§8.1 E-02) | +| **远端显示整帧卡住十几秒后自恢复** | **E-02** 回归 | 核对 L3 pending 在位:`net_recv_locked` 阻塞分支登记 pending(哨兵 `NET_PENDING_REGISTERED`)+ `net_pending_tick` 在主循环 + 调用方剩余预算循环(lftpd/timeSync)(§8.3 要点 4) | | **INIT 应答帧字节数字段恒为 0** | **D17** 回归 | 核对 `remo_send_init` 发满 8B(§8.1 D17) | | **开机首个 FTP 会话第 2 个数据连接 425** | **D20**(已定位未修,§8.2) | 复现:`test/ftp_regression.py`(复位开边界);现场规避:客户端重试 425(瞬态 4xx);根治方向:数据 Socket 轮换 | | **`[LAT]` 多段数值雷同 / 全 0 却 verdict=OK** | **D18/D19**(测试工装) | 核对 `lat_probe_add_seg` 段名过滤 + `lat_time_init` 调用 + `med==0` 判无效 | @@ -655,7 +679,7 @@ sock4 auto-relisten ok / relisten retry ok ← 监听器随后自行恢复 |---|---|---|---| | D1 | CH395F TCP 重传固定周期(非 RTT 自适应) | 台架链路(有线 100M 全双工)多轮零重传尖峰 → 台架无丢包;**弱网(Wi-Fi/双工不匹配)仍是秒级卡顿首要嫌疑**,200ms 粒度台阶 = 重传指纹(旧固件 500ms) | **已修(P0-a,2026-09-22)**:`NET_RETRANS_PERIOD_MS` 500→**200**(窗口 8×200=1.6s,原 4s)。台架验收说明:`GET_CMD_STATUS` 对 SET 类命令无判别力(500/2000ms 超限对照均读 0x10 陈旧残留,§9.2)→ 接受性以手册范围(≤1000ms)+ 全套件零回归(§6.2/§6.3)+ 与 500ms 行为同构为准。验收探针(3×20ms 状态轮询 + 证据行)验收完成后已从代码移除,结论保留于本文档 | | D2 | 3209B × 1KB 发送 FIFO 停止等待(4 次串行分块握手,期间 netTask 全程占用) | `chunk_wait` 219µs/块 ≈ SPI 搬运成本的 1/7 → 握手本身**不是瓶颈**;每帧固定成本小(MCU 净 7.1ms) | 基线成本,可接受;根治 = 差量/RLE + 帧版本号(待办 S2) | -| D3 | netMsgQueue 头阻塞(= §8.1 E-02) | 已量化:一条空闲 FTP 控制连接冻结全网 17.7s | **已修复**(5ms 分片有界读 + 让出,§8.1) | +| D3 | netMsgQueue 头阻塞(= §8.1 E-02) | 已量化:一条空闲 FTP 控制连接冻结全网 17.7s | **两阶段闭环**:① 5ms 分片有界读 + 让出(f8d6e90/4a1605b,缓解)② **L3 pending 化**(f16dc9a,结构性——执行器零占用,缺陷类消灭,§8.3 要点 4) | | D4 | PC 端延迟 ACK 与"每段等 ACK"停止等待交互 | `--ack-fast` 带内实验证实:关掉延迟 ACK 尾批自行消失(52→3.9ms) | **已客户端侧解决**(生产客户端关延迟 ACK/轻推兜底,§7.4) | | D5 | uiTask 节拍:10ms 循环 + 每拍一次 64B recv + step 在 poll 前 | `ui_loop` 10986µs ≈ 设计值(渲染 ~1ms);拾取调度 ~2.3ms(P0-b 删 per-recv 日志后,原 ~6.8ms) | 基线行为;可选优化 S7(poll 前置 + while 排空),低优先 | | D6 | 阻塞式日志在关键路径(fputc 逐字节 @115200) | `logtax_line` 4402µs/行;per-recv 日志已删(2026-09-22):`queue_rt_recv` 5997→1223µs、帧周期 66.0→61.6ms、首字节 13.9→9.6ms | **部分已修(P0-b,2026-09-22)**;S8 非阻塞日志仍待办(同时是开机日志并发丢行 §9.2 的根治项) | @@ -722,7 +746,9 @@ sock4 auto-relisten ok / relisten retry ok ← 监听器随后自行恢复 | `m3_data/m3_dev_stress.json` | E-02 压力档(修复前:17.7s 尖峰) | | `m3_data/m3_dev_stress_fixed.json` | E-02 压力档(修复后:med 74.7ms / max 106.8ms,零尖峰) | | `m3_data/m3_dev_quiet_r200.json` | **2026-09-22 M3 静默档重锁基线**(50 帧,P0-a/P0-b 代码:帧周期 61.6ms) | -| `m3_data/m3_dev_stress_r200.json` | **2026-09-22 M3 压力档重锁基线**(45 帧,第 15 帧起 FTP stress:med 65.0ms / max 133.5ms,零尖峰) | +| `m3_data/m3_dev_stress_r200.json` | **2026-09-22 M3 压力档重锁基线**(45 帧,第 15 帧起 FTP stress:med 65.0ms / max 133.5ms,零尖峰)——分片时代数值,**已被 L3 档取代**(历史对照) | +| `m3_data/m3_pending_quiet.json` | **2026-09-22 M3 静默档 L3 重锁基线(当前)**(50 帧,pending 构建 16:42:帧周期 58.9ms / 首字节 9.2ms / 尾批 50.4ms,零尖峰,CRC 50/0) | +| `m3_data/m3_pending_stress.json` | **2026-09-22 M3 压力档 L3 重锁基线(当前)**(50 帧,第 25 帧起 FTP 空闲登录保持:stress 段 med 60.1ms / p95 66.4ms / max 69.3ms,零尖峰,CRC 50/0;MCU 侧 prod_cycle_mcu 6706µs 压力下平坦) | | `m3_data/m3_sim_quiet.json` | 模拟器基线 50 帧(Δ 对照,tail=0) | | `m3_data/m3_tail_ackprobe.json` | 尾批实验 ①:帧未收齐即回 1 字节(捎带 ACK)→ tail 3.9ms | | `m3_data/m3_tail_ackfast.json` | 尾批实验 ②:Windows 立即 ACK(不发探测字节)→ tail 3.9ms | diff --git a/docs/问题记录/Net层阻塞模型业界对照与演进方案.md b/docs/问题记录/Net层阻塞模型业界对照与演进方案.md index bf293d5d..77bca4ac 100644 --- a/docs/问题记录/Net层阻塞模型业界对照与演进方案.md +++ b/docs/问题记录/Net层阻塞模型业界对照与演进方案.md @@ -5,6 +5,9 @@ > 成熟项目模式的对照;(2) 演进方向"RECV 消息 → pending 请求"(正统事件驱动形态)的利弊与改动量估算。 > **留作备用**:第二档 #1(E-02+E-06+E-20+E-21 阻塞模型改造)排期实施时,以 §6 为设计基线、 > §6.5 为验证门禁。 +> **实施状态(2026-09-22 当日更新)**:**一期(RECV pending 化)已实施并全量台架复验**—— +> commit `f16dc9a`(分支 `wip/v2-pending-recv`,基线 v2-on-ui `2438de8`);实现与 §6.1 基线的 +> 偏差、§6.5 门禁逐条结果与实测数据见 **§6.7 实施记录**;二期(ACCEPT/SEND)未动,仍按 §7 排期。 > **日期**:2026-09-22 > **配套文档**:`错误码传播审计.md`(E-02 明细 / 修复计划 / 已闭环记录)、`docs/测试说明/链路延迟测试说明.md` > (M3 基线 / §8.3 实现要点 / §9 故障对照)、`AGENTS.md`(SPI 铁律 / 就绪屏障 / 内存预算) @@ -225,12 +228,50 @@ B 类(LwIP netconn)的三个构件在本项目的对应物: - pending 最大龄自检(selftest 留痕,防"永不完成"); - 排障文档同步(`错误码传播审计.md` / `链路延迟测试说明.md` §9 故障对照表)。 +### 6.7 实施记录(一期,2026-09-22,commit f16dc9a) + +**实现与 §6.1 基线的一致性/偏差**(diff 已逐行评审): + +| 基线条目 | 实施 | 说明 | +|---|---|---| +| pending 控制块 ≈20B/fd | `net_pending_t` = {active 1B, buf 4B, len 4B, deadline 4B, registered 4B, caller 4B} ≈24B/fd × 8 = **192B**(+4B `s_net_task_handle`) | 实测 SRAM +200B,与估算同量级 | +| 控制块位置:`net_sock_t` 内 | **偏差:独立静态数组** `s_net_pending[NET_MAX_SOCKETS]` | `net_close_locked` 对 `net_sock_t` 做整块 memset——置入表内则 close 静默抹掉 pending(调用方悬空);独立表 = §6.3#1 预警的"跨时间状态"与 socket 表解耦,仿 D10 relisten 表的生产验证模式 | +| 无数据 → 登记 pending、跳过本次通知 | 哨兵 `NET_PENDING_REGISTERED`(0x70000000)→ dispatch `do_notify=0` | 逐字一致 | +| 五路完成/取消 | tick 实际顺序:① 数据(`readable` 门控 SPI 读,ESTABLISHED/UDP_OPEN;spurious readable 清除)② deadline(状态无关、有符号回绕安全差值)→ TIMEDOUT ③ CLOSED:排空→数据否则 EOF(0)+auto-relisten ④ 他态等待(**不做**状态推断取消)⑤ 1s 看门狗强结算 + DBG_ERROR | 基线 #3 的"EOF 发现"实现为 CLOSED 态排空判定;基线 #4(CLOSE 先行完成 pending)= `net_close` 的 settle 钩子(排空→数据否则 CONNRESET);基线 #5(重建取消必通知)= `net_init` 顶部 `net_pending_cancel_all(CONNRESET)`(先于芯片复位);RESYNC_LISTEN 陈旧分支/`net_socket` 另加 cancel/clear 钩子 | +| 看门狗/自检(§6.6) | 1s 最大龄看门狗强结算 + DBG_ERROR | 简化版:强结算防"永不完成",未接 selftest 留痕(留二期) | +| 调用方简化:单次 `net_recv_to(…, 30000)` | **偏差:剩余预算循环**(`rem = 预算 − 已耗时` 作片长,`n==-2` 续轮,`rem==0` 退出) | 公开契约(30s 总超时语义、跨 TCP 分段累积)要求调用方保留循环骨架;删掉的是分片常数 + `vTaskDelay(1)` 让出协议(改为睡任务通知)——净效果与基线 #3 目标一致 | +| 登记守卫(基线未列,实施新增) | 每 fd 至多一个 pending(**不覆盖**);`caller==NULL` 或 `caller==netTask` 拒绝(BUSY) | 覆盖 = 丢首个调用方通知 = 永久挂起;netTask 上下文自通知 = 无完成者死锁——§6.3#1 边界风险的两条实证化防线 | + +**§6.5 验证门禁逐条结果**(2026-09-22 下午,设备 192.168.1.100,pending 构建): + +| # | 门禁 | 结果 | +|---|---|---| +| 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) | +| 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 半登录态,已实证) | +| 5 | UI 远端推流压力 | **PASS** = M3 静默/压力两档(ui_net_sink :7003 100Hz 全帧 CRC 50/50,零尖峰) | +| 6 | timeSync 三场景 | **PASS**:挂起客户端(e02_probe 主场景)/ 正常包(wall clock updated + RTC 回写);部分包场景由 Phase 8-RECV 100KB 跨段累积(同 `handle_conn` 跨片累积逻辑的 pending 化形态)等效覆盖 | +| 7 | 产品 `@test` + 全片回读 | **PASS**:Required 全中/Forbidden 零命中;烧录回读 `No difference found` | +| 8 | RAM/栈前后对比 | **PASS**:SRAM +200B(192B pending 表 + 4B 句柄 + 4B 他项)/Flash +608B;netTask 运行栈峰值 488B/4096(余量 88%)、静态最坏链 432B——零占用设计落点;六任务水位全 PASS(defaultTask 29% 边际 = 既有静态链,与 L3 无关) | + +**未执行/延后项(如实留档)**: +- §6.6"保留分片路径作影子对照/回退开关"→ **未保留**,分片协议直接退役;对照目的由"旧镜像 A/B"承担(A/B 轮即影子验证),回退路径 = git revert(单提交、API 不变); +- 探针族扩充(close/reconfig/EOF/disconnect-during-pending 专项)→ 二期随 SEND/ACCEPT 一并建; +- pending 看门狗接 selftest 留痕 → 二期; +- 模拟器差距 +1(`net_socket_sim.c` 单线程 Winsock 无法建模 pending)→ 附录清单更新随二期; +- **tick 放置后果(一期文档化、不修)**:pending 完成判定随主循环节拍运行——队列里排着长 SEND/CLOSE 消息处理时,同 tick 的 pending 完成顺延至下轮(~1ms 级,长 SEND stall 1s 期间最多顺延相应时长)= §6.3#3 的已知代价,按"文档化"处置; +- 台架期间另发现一次 49s 全系统日志静默(defaultTask/NAND syslog 排空停滞,net 栈照常工作)——既有存储侧现象,与 L3 无关,转 `docs/待处理内容.md` N-2。 + --- ## 7. 结论与实施建议 -1. **现状(分片)安全有效,不必急着演进**——残余风险可控且已基线锁定;pending 是结构演进, - 不是缺陷修复,无时间压力。 +1. **一期(RECV pending 化)已于 2026-09-22 实施并全量台架复验**(f16dc9a,`wip/v2-pending-recv`; + 门禁逐条结果见 §6.7):头阻塞缺陷类结构性消灭、调用方分片协议退役、M3 压力档 p99 尾部 + 133.5ms→69.3ms、队列响应性 92.5ms、RAM +200B。**二期(ACCEPT/SEND)待排期**—— + E-06/E-20/E-21 剩余分量(SEND 1s/分片 stall、accept 轮询计时失真、errno 分级)共用同一 + pending 机制扩展;届时 L3/L5 基线再重锁。 2. **实施时机 = 第二档 #1 排期窗口**:E-06/E-20/E-21 迟早要做,pending 是四条的公共地基, 一次做齐比四个独立补丁便宜。 3. **路线**:一期 RECV(影子验证)→ 二期 ACCEPT → SEND(最复杂:多分片/短发送/L3 探针钩子)。 diff --git a/docs/问题记录/错误码传播审计.md b/docs/问题记录/错误码传播审计.md index 2585588d..6a0b752e 100644 --- a/docs/问题记录/错误码传播审计.md +++ b/docs/问题记录/错误码传播审计.md @@ -40,7 +40,7 @@ E-60"write_enable WRTC2 与手册矛盾"经三方复核(手册表头 D7~D0 顺 | 编号 | 子系统 | 一句话 | |---|---|---| -| E-02 | net 执行器 | **队列头阻塞**:任一消费者的阻塞 recv(30s)在 netTask 上下文空转 → 全体消费者的队列消息停摆最长 30s(事件仍处理);FTP 客户端空闲 >30s 即可触发。**已修复(2026-09-22)**:lftpd(f8d6e90)/timeSync(4a1605b)两个触发源均改 `net_recv_to` 5ms 分片有界读,台架 A/B 实证(明细见 §3.2) | +| E-02 | net 执行器 | **队列头阻塞**:任一消费者的阻塞 recv(30s)在 netTask 上下文空转 → 全体消费者的队列消息停摆最长 30s(事件仍处理);FTP 客户端空闲 >30s 即可触发。**两阶段闭环(2026-09-22)**:阶段一 `net_recv_to` 5ms 分片有界读缓解(lftpd f8d6e90 / timeSync 4a1605b);阶段二 **L3 pending 化**(f16dc9a)——阻塞 RECV 改挂起请求、执行器零占用零阻塞、调用方分片协议退役;台架全量实证(明细见 §3.2) | | E-03 | net 层 | 全局 `s_net_errno` 跨任务覆写竞态(09-21 修复的**残留**):恢复与读取之间隔任务切换,健康连接可被误拆(ui_sink :460 每 10ms 读) | | E-04 | UI 远端推流 | `remo_send` 丢弃 `net_send` 返回值 → 3205B 响应弱网短发送**静默截断**(09-21 事故机制的调用方一侧未闭环) | | E-05 | net 层 | 3 任务直调 `net_socket/net_bind/net_getsockname` 跨任务写 netTask 属主的 socket 表 → alloc/close 交错可双分同一 fd(SPI 铁律未破,表属主破了) | @@ -155,10 +155,19 @@ E-60"write_enable WRTC2 与手册矛盾"经三方复核(手册表头 D7~D0 顺 - **模式**:P4 变体(串行化头阻塞,非丢消息) - **影响**:最长 30s 全网队列停摆——uiTask 100Hz 轮询、FTP 收发/accept、timeSync 全部排在队列里得不到处理;事件处理不受影响(等待循环内仍调 `net_poll`,`:1020`),受影响的**恰是队列**;与 E-06 叠加 → PASV 假 425;STOR 上传方向芯片 2KB 缓冲满 + 重传 8×500ms=4s 耗尽 → 必断 - **修复方向**:消费端阻塞 recv 改 `DONTWAIT` 分片 + 调用方重投 + 总超时(ui_sink 模式推广到 lftpd/timeSync);或 `net_process_messages` 在长阻塞间隙按 tick 继续排空队列;`NET_RECV_TIMEOUT_MS` 按服务可容忍量级分离(既有 P2-8 是本条的子集) -- **已修复(2026-09-22,两提交)**:落地方案为方向①的变体——"分片"用**有界阻塞片**而非 DONTWAIT 重投:新增 `net_recv_to` 接口(`msg.timeout_ms` 携带片长;片超时以独立返回码 -2 区分,无跨任务 errno 竞态);调用方累计总预算、片间 `vTaskDelay(1)` 让出 CPU(防 Normal 优先级忙循环饿死 BelowNormal 的 uiTask,M3 实证);5ms 片长 = 其他任务最坏等待(100ms 片下受压帧 ~750ms、5ms 片 ~10ms,`docs/测试说明/链路延迟测试说明.md` §8.3);30s 总预算保持旧超时语义 +- **已修复(2026-09-22,两阶段)**: + **阶段一(缓解,两提交)**:落地方案为方向①的变体——"分片"用**有界阻塞片**而非 DONTWAIT 重投:新增 `net_recv_to` 接口(`msg.timeout_ms` 携带片长;片超时以独立返回码 -2 区分,无跨任务 errno 竞态);调用方累计总预算、片间 `vTaskDelay(1)` 让出 CPU(防 Normal 优先级忙循环饿死 BelowNormal 的 uiTask,M3 实证);5ms 片长 = 其他任务最坏等待(100ms 片下受压帧 ~750ms、5ms 片 ~10ms,`docs/测试说明/链路延迟测试说明.md` §8.3);30s 总预算保持旧超时语义 ① **lftpd 侧(commit f8d6e90,M3 台架复验)**:`lftpd_inet_read_line`/`lftpd_inet_read` 的 30s 阻塞 recv 改 5ms 分片 + 30s 总预算;M3 压力档(空闲 FTP 半登录态)帧周期 med 17718ms/尖峰 17.7s → **med 65.0ms/max 133.5ms/零尖峰** ② **timeSync 侧(commit 4a1605b)**:`time_sync_handle_conn` 单次 30s 阻塞 `net_recv` 改同模式(5ms 片/30s 总预算/跨片累积容忍 TCP 分段/超时留痕 `time_sync: no TIME packet in 30s, drop conn`);产品构建 `@test` 闭环 PASS(Required 全中/Forbidden 零命中) **A/B 台架对照(`test/e02_probe.py`,2026-09-22 13:07~13:16,设备 192.168.1.100)**:挂起客户端连 :8888 后不发数据,2s 后 PC 测 FTP(:21) banner 时延 = 队列响应性——旧固件 **28554ms**(队头冻结;设备日志实证芯片侧握手与 MCU 侧 "connection received" 相隔 27s;旧代码 30s 后静默拆连**零日志**)vs 修复后 **109ms(产品构建)/75ms(测试构建)**;30s 预算耗尽拆连后监听均经 2 次 Trap 09 重试 ~8s 恢复(两侧行为同构,非本修复引入);修复版超时留痕在位、正常路径(8B TIME 包)`wall clock updated` + RTC 回写 + 监听重建全通。(注:旧固件轮的芯片侧监听状态为上次烧录遗留——ST-LINK 仅复位 MCU、CH395F 状态延续,不影响队列冻结证据,冻结主体为旧固件 netTask 的阻塞 recv) + **阶段二(结构闭环,commit f16dc9a,分支 wip/v2-pending-recv,2026-09-22)**:**L3 pending 化**——阻塞 RECV 消息改为**挂起请求**,执行器(netTask)不再为任何调用方阻塞:`net_recv_locked` 阻塞分支在数据不可得时登记 `net_pending_t`(每 fd 至多一个,不覆盖;`caller==NULL`/`caller==netTask` 拒绝自通知死锁)即返回哨兵 `NET_PENDING_REGISTERED`(0x70000000,dispatch 跳过即时通知);完成判定收敛到主循环节拍 `net_pending_tick`(每次 `net_process_messages` 各跑一遍):① 数据(readable 门控 SPI 读,ESTABLISHED/UDP_OPEN)② 截止(`NET_RECV_TIMEOUT_MS` 30s,状态无关、有符号回绕安全差值)→ TIMEDOUT ③ CLOSED:排空→数据否则 EOF(0)+auto-relisten ④ 他态等待(不做状态推断取消)⑤ 1s 看门狗强结算 + DBG_ERROR;`net_init`/`net_close`/RESYNC_LISTEN 陈旧分支/`net_socket` 的 cancel/settle 钩子**一律通知**——调用方永不悬空。调用方(lftpd/timeSync)同步退役分片协议:改为"剩余总预算"循环(`rem = 预算 - 已耗时` 作每次片长,`net_recv_to` 无数据即睡在任务通知上,醒即续——片间 `vTaskDelay(1)` 不再需要)。公开 API/返回语义(>0/0/-1/-2)与"通知值唯一回传通道"不变;pending 表独立静态数组(close 时 memset 的 `net_sock_t` 之外),仿 D10 relisten 表模式。 + **台架全量复验(2026-09-22 下午,pending 构建,分支 wip/v2-pending-recv)**: + - **e02_probe**:队列响应性 **92.5ms**(阶段一 109ms/75ms → 更快,执行器占用归零);30s 截止按节拍精确触发(30.1s,`no TIME packet in 30s, drop conn` 留痕在位);拆连后监听经 2 次 Trap 09 重试 6.6s 恢复(既有芯片行为,与阶段一同构);TIME 正常路径 `wall clock updated` PASS + - **M3 基线重锁(Phase 14,静默 + FTP 压力两档全 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)——**结构性收益:执行器零占用,头阻塞工况不再向 UI 帧周期传导** + - **功能套件(Phase 6/9/11 组合 + Phase 8-RECV 独占组合,分两次构建)**:64B/1460B 回显 11/11、select 回显 11/11、断开重连、KeepAlive 断连 + 自动重监听全 PASS;**Phase 8-RECV 100KB 阻塞接收(pending 主路径)50/50 块(2048B/块)逐块校验 + CRC32 整包一致**(0x9A0E0C8C),收齐后主动 close + auto-relisten 正常 + - **产品构建 `@test`**:PASS(Required 全中/Forbidden 零命中);netTask 运行栈峰值 **488B/4096(余量 88%)**、静态最坏链 432B——零占用设计实测落点 + - **RAM/Flash 代价(map A/B,同一测试配置)**:SRAM +200B(192B `s_net_pending[8]` + 4B `s_net_task_handle` + 4B 他项)、Flash +608B(code +528/RO +80)——远低于内存预算阈值 + - **台架新发现(与 L3 无关,A/B 归因后转 `docs/待处理内容.md` N-1/N-2)**:① TC-NET-604 4096B 经 2KB 芯片缓冲的回显残留停滞(前置 1460B 全 MSS 交换后触发,独立 4096B 正常;**切片构建复现行为逐字节相同** → 既有芯片侧问题,L3 无责)② 台架运行中一次 49s 全系统日志静默(net 栈期间照常处理连接 = defaultTask/NAND syslog 排空停滞,既有存储侧现象,L3 无责) #### E-03 全局 `s_net_errno` 跨任务覆写竞态(09-21 修复的残留) - **位置**:写方 = `net_socket.c:39` 单全局;netTask 侧 `:362/365/375/385/410` + **notify 值构造 `:419-423`**(`s_notified` 分支读同一全局);6 个队列包装器在**调用方上下文** `:660/758/818/1233/1286/1333`(仅失败路径写);6 个直调 API 在**调用方上下文**失败时写(`net_socket :442/449`、`net_bind :482-538`、`net_sendto/net_recvfrom`、`net_getsockname :1953-1964`),**成功不写** → stale 滞留(`:1609` 文档化)。读端:`ui_net_sink.c:460`(uiTask 100Hz,BelowNormal 被抢占窗口最大)、`test/net_test_task.c:230/381` @@ -312,8 +321,8 @@ E-60"write_enable WRTC2 与手册矛盾"经三方复核(手册表头 D7~D0 顺 | E-17 | `net_task.c:201-203` | RECONFIG `Get`+`Clear` 非原子 TOCTOU(=既有 P2-11)——**本次重评**:命令无载荷(执行读最新 RAM 副本、代次在执行时递增),丢失 = 本次重建跳过、下次保存/重启自愈,无数据丢失 → 维持清单、风险低于原评级 | `osEventFlagsWait` 原子消费 | | E-18 | `freertos.c:422-424` | ftpTask `WaitAll(osWaitForever)` 无超时 → 生产端故障时 FTP 永久静默阻塞 | 超时 + 降级日志 | | E-19 | `freertos.c:430`;`sys_events.h:28-29` | 死事件位:`FTP_READY` 置位在 `lftpd_start`(无限循环)返回后 = **不可达**;`TIMESYNC_READY` 从未置位 → 未来消费者 Will 永久阻塞 | 删除或改在首次监听成功后置位 | -| E-20 | `lftpd_inet.c:100-127`、`lftpd.c:555-561` | 控制通道 30s 阻塞 recv 兼存活判定 + 行>511B/EOF/真错误同返 -1 → 慢客户端被断、长命令杀会话、叠加 E-02 | DONTWAIT + 调用方状态机;超长回 501 保会话 | -| E-21 | `time_sync.c:128-144/:80-97` | accept 一切失败=无连接(200ms 静默重试、无 errno 分类/日志)+ 30s 阻塞 recv + close-then-rebuild 空窗 | errno 分级(BADF/INVAL→重建+日志);DONTWAIT + 会话超时(=既有 P2-8 扩展) | +| E-20 | `lftpd_inet.c:100-127`、`lftpd.c:555-561` | 控制通道 30s 阻塞 recv 兼存活判定 + 行>511B/EOF/真错误同返 -1 → 慢客户端被断、长命令杀会话、叠加 E-02 | DONTWAIT + 调用方状态机;超长回 501 保会话。(30s 阻塞 recv 分量已由 L3 pending 化解,f16dc9a:执行器不再阻塞;errno 分类/501 分量仍待办) | +| E-21 | `time_sync.c:128-144/:80-97` | accept 一切失败=无连接(200ms 静默重试、无 errno 分类/日志)+ 30s 阻塞 recv + close-then-rebuild 空窗 | errno 分级(BADF/INVAL→重建+日志);DONTWAIT + 会话超时(=既有 P2-8 扩展)。(30s 阻塞 recv 分量已由 L3 pending 化解,f16dc9a;errno 分级/空窗分量仍待办) | | E-22 | `lftpd.c:608-626`、`time_sync.c:96/:146-149` | close-then-relisten 每会话端口空窗 ~0.2-1.7s(合规对照 = `ui_net_sink.c:446-457`:EOF 不 close、靠 auto_relisten 常驻) | 向 ui_sink 模式看齐 | | E-23 | `test/net_test_task.c:869-917/:296-403` | 监听主循环与 phase7 无代次检查(网络重建后恒 BADF 空转)+ TC704 8 路 socket 与 3 个并发服务抢 8 槽 fd 池 → 假 FAIL | 代次检查 + 降并发/测试构建抑制服务任务 | | E-24 | `net_socket.c:1971-1975 × :162`;`lftpd.c:398-413` | `s_local_ip` 逐字节拼读 × reconfig 重写不原子 → PASV 227 响应 IP 混拼(低频人工触发) | getsockname 入队列或临界区快照 | @@ -399,7 +408,7 @@ E-60"write_enable WRTC2 与手册矛盾"经三方复核(手册表头 D7~D0 顺 | # | 项 | 内容 | |---|---|---| -| 1 | **E-02+E-06+E-20+E-21** | 阻塞模型改造:lftpd 控制通道/timeSync 改 `DONTWAIT` + 调用方状态机(ui_sink 模式推广);`net_process_messages` 长阻塞间隙按 tick 继续排空队列;`accept_timeout` 墙钟计时 + 去跨任务 state 直读。**E-02 部分已闭环(2026-09-22,f8d6e90+4a1605b)**:两触发源改 `net_recv_to` 分片有界读(落地方案 = 有界阻塞片,非 DONTWAIT 重投),台架 A/B 实证;E-06/E-20/E-21 部分仍待办(候选公共地基 = pending 请求机制,利弊/改动量/验证门禁见 `docs/问题记录/Net层阻塞模型业界对照与演进方案.md` §6) | +| 1 | **E-02+E-06+E-20+E-21** | 阻塞模型改造:lftpd 控制通道/timeSync 改 `DONTWAIT` + 调用方状态机(ui_sink 模式推广);`net_process_messages` 长阻塞间隙按 tick 继续排空队列;`accept_timeout` 墙钟计时 + 去跨任务 state 直读。**E-02 已全量闭环(2026-09-22)**:阶段一 = `net_recv_to` 分片有界读(f8d6e90+4a1605b,缓解);阶段二 = **L3 pending 化**(f16dc9a,wip/v2-pending-recv)——阻塞 RECV 改挂起请求、执行器零占用零阻塞、调用方分片协议退役,台架全量复验(M3 重锁/功能套件/e02_probe/产品 @test 全 PASS,明细见 §3.2 E-02 段);E-06/E-20/E-21 剩余分量(SEND/ACCEPT 阻塞路径、errno 分级、501 保会话)待办——公共地基 pending 机制一期(RECV)已落地,二期(SEND/ACCEPT)沿用同一机制扩展(利弊/改动量/验证门禁见 `docs/问题记录/Net层阻塞模型业界对照与演进方案.md` §6) | | 2 | **E-05** | `net_socket/net_bind/net_getsockname` 并入队列(新消息类型);过渡方案:alloc+init 临界区 + `s_dynamic_port` 收归 netTask | | 3 | **E-10/E-42/E-53/E-54** | GD5F 驱动错误通道统一:init 重试 1~2 次;`wait_busy`/轮询路径 HAL 检查;ECC 使能回读校验;错误向上传递 | | 4 | **E-22** | lftpd/timeSync 向 ui_sink close 规则看齐(EOF 不 close、auto_relisten 常驻、仅代次变化/判死时重建) | @@ -503,7 +512,7 @@ E-60"write_enable WRTC2 与手册矛盾"经三方复核(手册表头 D7~D0 顺 | 队列 | 定义处 | 深度 | 条目形态 | 回传机制 | 免疫/风险 | |---|---|---|---|---|---| -| `netMsgQueue` | `Src/freertos.c:166` | 8 | `net_msg_t` **按值**(fd/长度/输入指针) | 任务通知值(精确错误码/字节数);指针字段回写(net_accept 地址) | 09-21 后契约健全;残留 = 全局 errno 竞态(E-03)、头阻塞(E-02) | +| `netMsgQueue` | `Src/freertos.c:166` | 8 | `net_msg_t` **按值**(fd/长度/输入指针) | 任务通知值(精确错误码/字节数);指针字段回写(net_accept 地址) | 09-21 后契约健全;头阻塞(E-02)经 L3 pending 化解(f16dc9a:执行器零阻塞,阻塞 RECV 等待 = 挂起请求);残留 = 全局 errno 竞态(E-03) | | syslog 队列 | `sys_log_mcu.c:218-223`(惰性) | 64 | 输入型(id + 静态串指针) | 无回传(fire-and-forget) | 结构免疫 P1;preboot 窗口(E-08) | | `cfgSaveQueue` | `freertos.c`(defaultTask/uiTask 间) | 8 | 输入型(路径指针) | `s_save_pending` 锁存 + `s_save_result` 状态机 | 协议无损(§7-3) | @@ -530,4 +539,4 @@ E-60"write_enable WRTC2 与手册矛盾"经三方复核(手册表头 D7~D0 顺 --- -*报告完。59 项发现全部带 file:line 落点;P0/P1 核心机制经父审计组逐行复核(含 `docs/芯片手册/SD2506API-G.md` L392-398/L537/§4.8 原文核对与 `SD2506_Trap_Records.md` 硬件观测交叉验证)。2026-09-21 复核修订:E-32 由 P0 降 P2(充电器 P0 链被"出厂 82H"证伪)、E-39 机制改写(ARST 在 CTR3、驱动从未写过 CTR3)、E-60"write_enable WRTC2 与手册矛盾"经手册表头位序 + DFRobot GravityRtc 官方库/社区代码 + 实测三方复核证伪(0x84 本已含 D2=WRTC2,代码与手册 L392 一致)移除,见 §7-19;18H 寄存器事实经手册 §4.8 专用表复核(Bit7=EN_Charge、Bit1=Charge1、Bit0=Charge0,复位 0x03,出厂 0x82=EN+5k,总表 L119 该行转录有误以 §4.8 为准);§6 交叉引用补 P2-2/P2-6。审计期间未修改任何代码、未执行构建;2026-09-21 依第一档 #1 完成 E-32 修复(commit 41e111b:18H 回读校验 + 漂移时写允许窗口重置与回读验证、0FH 死写与误注移除、充电宏位订正;构建 0 错误 0 警告,台架 RTC 套件 Phase 1 6/6 + Phase 2 累计 17/17 PASS 含 set==readback,产品固件重烧后启动校验 PASS,ST-LINK 全片回读 No difference);同日依第一档 #2 完成 E-31 修复(commit da1a6e8:journal.c 三处错误源治理——扫描读失败不再覆盖为 TOO_BAD、读成功但 checkpoint 不符判 CORRUPT_MAP + nand_ftl.c 错误分类——仅真空白判 fresh、其余失败返回 STA_NOINIT 给 mount 层 + freertos.c 启动块重构为 storage_bring_up() 并加 3×2s 有界重试自愈策略;构建 0 错误 0 警告;产品固件台架回归 PASS:`@test` 闭环 Required(含 `Map resumed`/`FATFS mounted`)全中、Forbidden 零命中,既有卷 2441/96064 扇区 resume 成功、用户配置 523B 原样加载、FTP 屏障链通,ST-LINK 全片回读 No difference);2026-09-22 依第一档 #3 完成 E-01 修复(commit d030cb0:poll 超长判定基于 `cfg_store_stat` 真实 st.size 前置到 `s_load_file` 之前根治死码、超长走工厂默认+重建模板+自检留痕且不触发段回调保留在线修复通道、save 输出上限 CFG_OUT_MAX→CFG_FILE_MAX_LEN、`s_write_doc` 写盘唯一闸口硬拒超长、load/poll 超长处置补 SYSLOG_SELFTEST 留痕;构建 0 错误 0 警告;台架验证 PASS:FTP STOR 5047B → poll 守卫 4s 内触发并重建 523B 工厂模板(RETR 实测)、设备保持在线、重启 load 守卫同链自愈、再重启零 `[ERR]` 无销毁循环、selftest.log 双留痕、模拟器 cfgtest 两个新回归锁场景 PASS、@test 默认闭环 PASS、ST-LINK 全片回读 No difference;验证中暴露并修复关联缺陷 `cfg_store_write_atomic` f_rename 对已存在目标不覆盖致设备端一切覆盖写静默失败(commit 70f1cc8:rename 前先 unlink 目标),详见 E-01 明细"关联新发现");2026-09-22 依第二档 #1 完成 E-02 修复(commit f8d6e90:lftpd 侧 `net_recv_to` 5ms 分片有界读 + 30s 总预算,M3 压力档 17.7s 尖峰归零;commit 4a1605b:timeSync 侧同模式改造 + 超时留痕;产品构建 `@test` 闭环 PASS;台架 A/B(`test/e02_probe.py`):挂起对时客户端下 FTP banner 旧 28554ms → 新 109ms/75ms、30s 预算拆连留痕、监听恢复行为同构、正常对时路径全通;详见 E-02 明细"已修复")。* +*报告完。59 项发现全部带 file:line 落点;P0/P1 核心机制经父审计组逐行复核(含 `docs/芯片手册/SD2506API-G.md` L392-398/L537/§4.8 原文核对与 `SD2506_Trap_Records.md` 硬件观测交叉验证)。2026-09-21 复核修订:E-32 由 P0 降 P2(充电器 P0 链被"出厂 82H"证伪)、E-39 机制改写(ARST 在 CTR3、驱动从未写过 CTR3)、E-60"write_enable WRTC2 与手册矛盾"经手册表头位序 + DFRobot GravityRtc 官方库/社区代码 + 实测三方复核证伪(0x84 本已含 D2=WRTC2,代码与手册 L392 一致)移除,见 §7-19;18H 寄存器事实经手册 §4.8 专用表复核(Bit7=EN_Charge、Bit1=Charge1、Bit0=Charge0,复位 0x03,出厂 0x82=EN+5k,总表 L119 该行转录有误以 §4.8 为准);§6 交叉引用补 P2-2/P2-6。审计期间未修改任何代码、未执行构建;2026-09-21 依第一档 #1 完成 E-32 修复(commit 41e111b:18H 回读校验 + 漂移时写允许窗口重置与回读验证、0FH 死写与误注移除、充电宏位订正;构建 0 错误 0 警告,台架 RTC 套件 Phase 1 6/6 + Phase 2 累计 17/17 PASS 含 set==readback,产品固件重烧后启动校验 PASS,ST-LINK 全片回读 No difference);同日依第一档 #2 完成 E-31 修复(commit da1a6e8:journal.c 三处错误源治理——扫描读失败不再覆盖为 TOO_BAD、读成功但 checkpoint 不符判 CORRUPT_MAP + nand_ftl.c 错误分类——仅真空白判 fresh、其余失败返回 STA_NOINIT 给 mount 层 + freertos.c 启动块重构为 storage_bring_up() 并加 3×2s 有界重试自愈策略;构建 0 错误 0 警告;产品固件台架回归 PASS:`@test` 闭环 Required(含 `Map resumed`/`FATFS mounted`)全中、Forbidden 零命中,既有卷 2441/96064 扇区 resume 成功、用户配置 523B 原样加载、FTP 屏障链通,ST-LINK 全片回读 No difference);2026-09-22 依第一档 #3 完成 E-01 修复(commit d030cb0:poll 超长判定基于 `cfg_store_stat` 真实 st.size 前置到 `s_load_file` 之前根治死码、超长走工厂默认+重建模板+自检留痕且不触发段回调保留在线修复通道、save 输出上限 CFG_OUT_MAX→CFG_FILE_MAX_LEN、`s_write_doc` 写盘唯一闸口硬拒超长、load/poll 超长处置补 SYSLOG_SELFTEST 留痕;构建 0 错误 0 警告;台架验证 PASS:FTP STOR 5047B → poll 守卫 4s 内触发并重建 523B 工厂模板(RETR 实测)、设备保持在线、重启 load 守卫同链自愈、再重启零 `[ERR]` 无销毁循环、selftest.log 双留痕、模拟器 cfgtest 两个新回归锁场景 PASS、@test 默认闭环 PASS、ST-LINK 全片回读 No difference;验证中暴露并修复关联缺陷 `cfg_store_write_atomic` f_rename 对已存在目标不覆盖致设备端一切覆盖写静默失败(commit 70f1cc8:rename 前先 unlink 目标),详见 E-01 明细"关联新发现");2026-09-22 依第二档 #1 完成 E-02 修复(commit f8d6e90:lftpd 侧 `net_recv_to` 5ms 分片有界读 + 30s 总预算,M3 压力档 17.7s 尖峰归零;commit 4a1605b:timeSync 侧同模式改造 + 超时留痕;产品构建 `@test` 闭环 PASS;台架 A/B(`test/e02_probe.py`):挂起对时客户端下 FTP banner 旧 28554ms → 新 109ms/75ms、30s 预算拆连留痕、监听恢复行为同构、正常对时路径全通;详见 E-02 明细"已修复");2026-09-22 依第二档 #1 完成 E-02 阶段二(commit f16dc9a,分支 wip/v2-pending-recv):L3 pending 化——阻塞 RECV 改挂起请求(每 fd 一个、cancel/settle 必通知),完成判定收敛 netTask 主循环节拍 `net_pending_tick`(数据→截止→CLOSED 排空/EOF+relisten→1s 看门狗),执行器零占用零阻塞;lftpd/timeSync 分片协议退役为剩余预算循环;公开 API/返回语义不变。台架全量复验:M3 重锁静默 med 58.9/max 72.1ms、压力档 med 60.1/max 69.3/零尖峰(阶段一基线 65.0/133.5)、MCU 侧 prod_cycle_mcu 6706µs 压力下平坦;功能套件 6/9/11 全 PASS + Phase 8-RECV 100KB 阻塞接收 50/50 块 + CRC32 一致;e02_probe 队列响应性 92.5ms、30s 截止 30.1s 精确触发、TIME 路径全通;产品 `@test` PASS(netTask 栈峰值 488B/4096=88% 余量);RAM +200B/Flash +608B。台架新发现(A/B 归因与 L3 无关,转 `docs/待处理内容.md`):4096B 经 2KB 芯片缓冲的回显残留停滞(切片构建同现)+ 一次 49s defaultTask/NAND syslog 排空停滞。*