Files
STM32F4-Base/docs/测试说明/m2_data/README.md
T
wandering1 2fd8a86490 refactor(注释): 把内部阶段代号 S4 与 S7 换成平实语言——查不到的代号不算可检索锚点
用户 2026-10-14 就定过这条(以后没人知道这种编码,要简单明确),这次把最后两处内部分层代号清干净:
· 串口自检判据里的 S7 → 直接写自检台账联合判定;用例追溯里的 S4 → 写用例追溯校验。
· 涉及烧录编排器与日志校验器的帮助文本、两份数据目录 README 的字段说明,以及看门狗、存储维护、
  实机测试、链路延迟四篇文档的同一处措辞。

判据没变,改的只是**读起来能不能查得到**:S7/S4 这类号在任何登记表里都查不到定义,注释里留着,
后来人只能靠问人——而这类内部分层代号正是当年编号失控的起点。门禁:doc-links 与 id-check 均 rc=0。
2026-10-27 14:16:26 +08:00

7.7 KiB
Raw Blame History

M2 链路延迟实测数据(Phase 13,安静档)

本目录保存 M2(Phase 13:芯片 + 队列时延基线)的原始实测产物。判定阈值与解读见 ../链路延迟测试说明.md §6.2;缺陷总表见 docs/测试说明/链路延迟测试说明.md §8。

1. 运行元数据

项 值
日期 2026-09-22(设备 RTC 显示 2026-09-21,落后 1 天,仅显示差异;主机时间戳 = 设备 + 4s)
台架 COM6 @115200;目标 192.168.1.100:8080(Phase 13 独占 socket 2)
固件 test/board/test_config.h = TEST_SUITE_CH395F;test/board/ch395f_test.h = ENABLE_PHASE13_TESTS(仅此一项)
构建 keil-build skill(keil_build.py)→ 0 错误 0 警告(测试构建与产品构建均 0/0)
对端 .venv\Scripts\python.exe test\latency_peer.py --mode net(纯标准库,--wait 170)
会话顺序 HELLO → L5_RECV → L5_SEND → L3 → L10 → L6 → L7 → DONE
干扰 无(安静档,ftp_stress=0;未跑 --ftp-stress)
PASS 轮次 run12 / run13 / run15 三次独立完整 PASS(summary verdict=OK、=== Phase 13: 1/1 PASSED (failed=0) ===、peer exit 0)

复现命令(顺序不可反:先 clear 再起 peer,最后烧录):

& '.venv\Scripts\python.exe' .dsh\skills\keil-build\scripts\keil_build.py
& '.venv\Scripts\python.exe' .dsh\skills\serial-assistant\scripts\serial_tool.py clear
& '.venv\Scripts\python.exe' test\latency_peer.py --host 192.168.1.100 --port 8080 `
    --json "docs\测试说明\m2_data\m2_quiet_runNN.json" --wait 170      # 后台作业
& '.venv\Scripts\python.exe' .dsh\skills\stlink-flash\scripts\stlink_flash.py flash
& '.venv\Scripts\python.exe' .dsh\skills\serial-assistant\scripts\serial_tool.py wait-idle `
    --timeout 120 --settle-ms 10000 --max-ms 110000
# 判定:Grep .dsh\skills\serial-assistant\scripts\state\serial.log

判定标记:Required App init OK / Network Init / net init: OK / [LAT] report complete / === Phase 13: 1/1 PASSED;Forbidden HardFault / assert / [ERR] / [FAIL] / verdict=FAIL; peer 侧退出码 0 = PASS(收到 0xFF 并打印汇总,l7_crc.fail == 0)。

2. 产物清单

文件 内容
m2_quiet.json run15(最终代码,规范基线)peer 端原始 JSON,含 10 帧逐帧批次明细
m2_quiet_run13.json run13(PASS 复现)peer 端原始 JSON
m2_quiet_run14.json run14(PASS;但该轮 MCU 侧探针日志过载,仅 peer 侧数据有效,见 §6)
m2_serial_excerpt_run15.txt run15 串口证据片段 62 行(只含烧录重启后的会话:从 Phase 13 横幅/run_id 校准行到 1/1 PASSED + relisten)
m2_serial_excerpt_run13.txt run13 串口日志中 [LAT]/[NET]/Phase 13 相关 87 行(含烧录前旧固件段,需自行忽略)

3. 实测结果

3.1 MCU 侧([LAT] 报告,三次 PASS)

段 run12 med(min/max, n) run13 med(min/max, n) run15 med(min/max, n) warn / crit
queue_rt_recv 6014µs(5365/6020, 19) 6007µs(5392/6025, 20) 5997µs(5513/6033, 20) 10ms / 100ms
queue_rt_send 986µs(836/1204, 20) 987µs(833/1209, 20) 987µs(838/1209, 20) 10ms / 100ms
chunk_wait 235µs(215/238, 64) 219µs(213/377, 64) 219µs(214/381, 64) 10ms / 500ms(spike)
logtax_line 4396µs 4396µs(4390/4414) 4396µs(4394/4422) 10ms / 25ms
req2first_mcu 310µs(296/338, 10) 318µs(263/361, 10) 319µs(308/338, 10) 20ms / 200ms
fullframe_mcu 6021µs(5986/6103, 10) 6052µs(5966/6078, 10) 6028µs(5991/6066, 10) 50ms / 500ms

三轮均:6 段 verdict=OK、spikes=0、summary verdict=OK、1/1 PASSED。

run12 的 queue_rt_recv n=19 而非 20:对端 20×100B 中相邻两包被 TCP 合并成一次收 (完成判定按字节 2000B),属正常合并,非丢包(三轮字节数均为 2000)。

3.2 PC 侧端到端(peer JSON)

段 run12 med(min/max) run13 med(min/max) run15 med(min/max) CRC
L6 端到端(op→回显) 12.5ms(5.5/16.0) 13.8ms(5.9/16.0) 8.9ms(6.3/16.0) —
L7 首字节 10.9ms(7.9/16.2) 11.8ms(7.5/17.7) 11.3ms(7.8/16.5) —
L7 全帧 3209B 61.1ms(54.2/61.5) 61.7ms(59.9/70.9) 57.9ms(52.6/72.3) 10/0

4. 关键发现:L7 尾批固定迟到 4460ms

run15 逐帧明细(10/10 帧结构完全一致):

frame#1: first=11.620ms batches=[1024,1024,1024,137] tail_lag=+53.8ms
frame#2: first=11.327ms batches=[1024,1024,1024,137] tail_lag=+46.5ms
frame#3: first= 8.160ms batches=[1024,1024,1024,137] tail_lag=+46.5ms
frame#4: first= 7.773ms batches=[1024,1024,1024,137] tail_lag=+44.8ms
frame#5: first= 9.858ms batches=[1024,1024,1024,137] tail_lag=+53.9ms
frame#6: first=11.900ms batches=[1024,1024,1024,137] tail_lag=+43.8ms
frame#7: first=10.465ms batches=[1024,1024,1024,137] tail_lag=+44.2ms
frame#8: first=10.615ms batches=[1024,1024,1024,137] tail_lag=+43.4ms
frame#9: first=11.328ms batches=[1024,1024,1024,137] tail_lag=+60.2ms
frame#10:first=16.522ms batches=[1024,1024,1024,137] tail_lag=+55.7ms
  • 前 3 批各 1024B 在 ~4ms 内到齐;第 4 批 137B(=3209−3072)稳定落在 +43~+60ms;
  • MCU 侧把整个 3209B 交给芯片只花 6.0ms(fullframe_mcu)→ 延迟不在 MCU 发送路径;
  • 缺口在芯片 TCP 尾段发送 / 对端 ACK 交互(候选:Nagle 式小段等待 + 对端延迟 ACK);
  • 该尾批主导整帧时长(total ≈ 首字节 + 尾批延迟),是远端显示"每帧多 ~50ms"的直接来源;
  • M3 待办:Wireshark(tcp.port==8080)确认尾段是被芯片扣住还是被对端 ACK 拖住,再定对策 (对端 TCP_NODELAY / 帧长与 chunk 对齐),未证实前不改协议。

5. 结论(回答 M2 立项问题)

  1. 安静档不存在 500ms 台阶:三轮 6 段全 OK、零尖峰、p95≈med;
  2. 会话级 MCU 净成本量级 ~6ms(queue_rt_recv,与 netTask 轮询节拍同量级);
  3. 芯片 chunk 级不是瓶颈:chunk_wait med 219µs ≈ 每 chunk SPI 成本(1.61ms)的 1/7;
  4. 生产链路的可见延迟主要在 PC/线路段(L6:MCU 侧 0.32ms vs 端到端 8.9~13.8ms) 与 L7 尾批 ~50ms。

6. 测量方法学(两条必须记住的坑)

  1. 探针不得在 net 热路径逐调用打日志(run14 实证):在 net_wait_result 内加 pick/block 两行后,日志量 40KB → 1.04MB(9,644/9,779 行 = 98.6%),115200 下 丢行/串行错位,冲掉 [LAT] 段证据,wait-idle 永远判不出空闲;并实测把 queue_rt_send med 从 987µs 抬到 7685µs(7.8×)、queue_rt_recv p95 抬到 21ms。 → 该轮 MCU 侧数据不作基线;诊断需求改在 [LAT] 段报告侧聚合。
  2. 首连必失败是有意为之的正常现象:peer 首连时常在 MCU 启动期完成握手,随后芯片 空闲超时(15~30s 无数据)RST → WinError 10054;peer 自动 +2s 重连后会话正常 (run12/13/15 均如此)。另注意:首连时若 MCU 正在烧录,attempt1 由上一版固件 服务(日志里那段偏高的数据不属于本轮固件),只有烧录重启后的会话才计入本轮基线。

7. 未纳入本目录的数据

  • run1run11 为缺陷定位过程(D11D16 见 docs/测试说明/链路延迟测试说明.md §6.1),其中 run10/run11 的 L7 失败、 run9 的 170s 连接拒绝均已定位并修复;
  • 压力档(--ftp-stress 复现)与 --mode remo(生产 RemoDispBus 客户端)属 M3。