docs(测试): 阶段 16 按两轮镜像分别登记尺寸,产品 Code 对齐 249,120(#73)
恒剥改造让产品构建 `Code` 从 249,124 变成 249,120,`docs/测试说明/板级测试/CH395F_Test_Guide.md` §12.6 里两处跟着真机重算: - 构建实测段不再只写一个镜像——第一轮的 `phase16c.hex`(836,489 B,Code 259,768 / RO 37,244)与 全绿那轮的 `phase16d.hex`(836,608 B,Code 259,764 / RO 37,288 / RW 2,060 / ZI 151,596)分开登记, 并写明第二轮与前一轮的差异来源:生产代码少一次形态比较(−4 B)+ 断言文案改写(RO +44); 产品态那行改成 `Code 249,120`,并说明与 249,124 的 −4 B 属生产代码变化、与阶段 16 无关。 - 「实测结果」那行补上板端串口原文里的构建戳 `Nov 4 2026 08:40:28`。 - 2026-11-03 夜那条进度里的「1603 之后仍未测」改成「当时未测(次日已补全)」,避免读起来像现状。 - `docs/测试说明/单元测试/主机单测覆盖率口径.md` 第 4 轮的真机回归条目,把「head `1b5e5d4` + 剥头修正」 改成剥头修正实际所在的提交 `b5671e8`。
This commit is contained in:
@@ -726,7 +726,7 @@ uint16_t ch395f_link_change_count(void);
|
||||
- **随机长跑把两条"测法自误"逼了出来(不是被测码 bug,但只有长跑才逼得出)**:⑤ **连续 `sendto` 必须先把 SENBUF_FREE 钉成电平**——不注入 SENBUF_FREE 时,第二次发送会**合法地**转挂起(`net_send_locked` 自旋 2 个 tick 就 `net_send_pending_register`),而本套的挂起 send 替身从不完成,于是 `FATAL: blocking wait still got no receipt after 50 rounds` 直接掐死整个套件、连汇总行都没有(正确姿势照 440i/440j:`ch395f_fake_set_sint_sticky(fd, CH395F_SINT_STAT_SENBUF_FREE)` + `push_glob(1<<(fd+4))` + `g_ns_int_pin_set=0`,注释里点名 TRAP-NET-04,并写明"背靠背发送的真机面留给 TC-NET-1609")。⑥ **假件的 `ch395f_get_recv_len` 是"按调用序号取、耗尽后重复最后一个"的脚本且容量有限**——240 轮只追加不清空,序号撞满容量后每轮都读到同一个陈旧长度(症状:`len` 在随机而 `n` 恒为 28,前 24 轮却全绿,最容易误判成产品 bug)。补了加法假件助手 `ch395f_fake_reset_recv_len(sock)`(只把该 sock 的脚本长度与序号归零,既有单轮用例不调用它、行为一字未变),soak 每轮开头调一次。教训:**长跑用例对假件的第一要求是"状态可重排",不是"能追加"**。
|
||||
- **本轮覆盖率**(收尾那次全仓跑数,`--update-baseline` 已把数字连同本轮提交一起落盘):`net_udp.c` 237/239 行(99.2%)、函数 **14/14**;`net_socket.c` 966/969(99.7%)、函数 **59/59**;`net_pending.c` 173/199(86.9%);全仓 line 8372/9290(90.1%)、47/47 套绿,无回退。剩两处未覆盖:`net_udp.c` 的槽越界兜底(调用方已挡,属防御性代码)与 `net_socket.c` 错误码槽重查竞态(真并发才走得到,改造前后同为那 2 行)。
|
||||
- **台架必验(登记于本轮,2026-11-04 已全部跑完,见下一条)**:① 两端真机互通,服务器形态收发 + 客户端形态往返,重点看 48 B 这类小应答**载荷完整**且源地址正确;② `sendto` 切形态后 `net_udp_set_peer(fd, NULL)` 能否真恢复收其它源的包——手册只写 DesIP 语义,没写切换时机;③ 截断包排空后下一个包是否完整(scratch 循环在真芯片读指针上的行为);④ 挂起 recv 等待期间的 IWDG 余量;⑤ bind 在 open **之前**写 DesIP 的顺序在真芯片上的实际效果(TRAP-NET-14 的 UDP 侧对照)。
|
||||
- **真机回归结果(2026-11-04 08:42,PR #74 分支 head `1b5e5d4` + 剥头修正)**:板端 `=== Phase 16: 77/77 PASSED (failed=0) ===`、PC peer `=== UDP Bench PC Peer: 27/27 PASSED (failed=0) ===`,①~⑤ **全部成立**,逐条串口原文见 `docs/测试说明/板级测试/CH395F_Test_Guide.md` §12.6 的「实测结果」表。**第一轮(08:16)其实是 33/47**:`TC-NET-1603` 报 `tag 0x02 got 0x38 (n=56)`,把本轮最大的一条设计错误照了出来——**芯片加不加 8 字节信息头是在 OPEN_SOCKET 那一刻由 DesIP 定死的,运行时把 DesIP 改成具体对端并不会让头消失**,而 UDP-4/UDP-24 当时按"客户端形态不剥头"写死了假件脚本,240 轮随机全绿也没发现。修法:`net_udp_datagram_read` 的剥头条件改为**只看 `avail >= 8`、与 `udp_mode` 无关**(`udp_mode` 退化为发送去向 + 对端记账),主机侧 UDP-4 与 UDP-24 客户端轮按真机重写(UDP-4 补一条 `addrlen`/family 断言,改完判据后覆盖率门禁又照出兜底那侧一行没人走,补 UDP-26 残包组 → 全套 **677/677**),板级 1603 的判据文字同步改写;定案登记在 TRAP-NET-22 的 2026-11-04 追加段。产品镜像尺寸 `Code=249120 RO=29836 RW=2052 ZI=149996`(比改造前基线少 4 B,`RW/ZI` 一字未增)。
|
||||
- **真机回归结果(2026-11-04 08:42,PR #74 分支 head 走到 `b5671e8`(剥头修正)之后)**:板端 `=== Phase 16: 77/77 PASSED (failed=0) ===`、PC peer `=== UDP Bench PC Peer: 27/27 PASSED (failed=0) ===`,①~⑤ **全部成立**,逐条串口原文见 `docs/测试说明/板级测试/CH395F_Test_Guide.md` §12.6 的「实测结果」表。**第一轮(08:16)其实是 33/47**:`TC-NET-1603` 报 `tag 0x02 got 0x38 (n=56)`,把本轮最大的一条设计错误照了出来——**芯片加不加 8 字节信息头是在 OPEN_SOCKET 那一刻由 DesIP 定死的,运行时把 DesIP 改成具体对端并不会让头消失**,而 UDP-4/UDP-24 当时按"客户端形态不剥头"写死了假件脚本,240 轮随机全绿也没发现。修法:`net_udp_datagram_read` 的剥头条件改为**只看 `avail >= 8`、与 `udp_mode` 无关**(`udp_mode` 退化为发送去向 + 对端记账),主机侧 UDP-4 与 UDP-24 客户端轮按真机重写(UDP-4 补一条 `addrlen`/family 断言,改完判据后覆盖率门禁又照出兜底那侧一行没人走,补 UDP-26 残包组 → 全套 **677/677**),板级 1603 的判据文字同步改写;定案登记在 TRAP-NET-22 的 2026-11-04 追加段。产品镜像尺寸 `Code=249120 RO=29836 RW=2052 ZI=149996`(比改造前基线少 4 B,`RW/ZI` 一字未增)。
|
||||
- **这 5 条已落成可执行的板级阶段**:阶段 16(`docs/测试说明/板级测试/CH395F_Test_Guide.md` §12.6,板端 `test/board/net_test_task.c` 的 `net_layer_udp_bench_test_main`,PC 侧 `test/host/udp_queue_bench.py`),TC-NET-1601~1609 与 ①~⑤ 的对应关系写在表里。**真机跑了四轮才跑完整**:2026-11-03 夜第一次上台架,① 的上半段已见证据——`TC-NET-1601` 建 socket/bind `:6001`/形态回 SERVER、`TC-NET-1602` 服务端形态收到 20 B 且 `addrlen`/`sin_family`/源端口全对、回显逐字节一致并把形态翻成 CLIENT;②③④⑤ 未测,板子当晚两次失电(SWD `No target connected`、ping 不通,19:19 与 21:0x 各一次),两趟还各暴露一个**台架**缺陷(peer 被 Windows 的 ICMP 10054 打死;单步预算 8 s < 板端 25 s park 导致整条梯子错位,另有一版 peer 在失败后瞬间狂重发,单个日志刷到 940,949 B),修法与守卫见上面那份指南。2026-11-04 08:16 第一次跑完整梯子是 **33/47**,唯一的真缺陷就是上面那条剥头判据,14 条 FAIL 全是它的级联;修完 08:42 第二轮 **77/77**,跑完立刻把板子恢复成产品镜像(`Code=249120`,串口 `[PROF2]` 心跳连续、`netn=0`、`[ERR][WD] task stall` 零条)并释放台架锁。
|
||||
- **同一轮补的免对端那半(2026-11-04)**:第一次上台架就是被"没有对端"卡住的——peer 脚本被 Windows 的 ICMP 10054 打死、梯子错位,1601 之后一步都测不到,整趟证据归零。故阶段 16 加了 **TC-NET-1610**:17 条断言不需要 PC 发一个包,把「形态记账(新建 socket 与 bind 都读 SERVER、`sendto` 显式对端才切 CLIENT)」「参数与出参守卫(未 bind 报 -5、流式 API 读 `DGRAM` 报 -3、`to_ms == 0` 报 -3、`src_addr` 缺 `addrlen` 或容量只有 4 字节报 -3、空缓冲 `DONTWAIT` 报 -7)」「`net_recvfrom_to(2000)` 返回 **-2** 且实测睡眠落在 2~4.5 s(等待睡在任务通知上,不在 SPI 总线上自旋)」「`net_close` 后同一槽重新 bind 不被上一条命毒化」四类在真芯片上一次确认。执行位置在 1601 之前、编号留在段尾(编号是台账用的,不等于执行顺序)。代价只有 flash:Code +2,380 B、RO +3,108 B(全是断言字符串),`RW/ZI` 一字未增——它复用那块 1,600 B 收发缓冲。**ARMCC 已编过(bench 与产品两态都 0 error 0 warning),并在 2026-11-04 08:42 那轮真机上 17 条全绿**(`TC-NET-1610a..q`,含 `1610i: park slept 2002ms against a 2000ms budget` 这条"睡在通知上"的硬证据)——它也正是那一轮板子断线时唯一还能自证的段落,先跑完再等对端的设计目的达到了。
|
||||
- 本轮改动面:`Drivers/BSP/NET/net_udp.c` 与 `Drivers/BSP/NET/net_udp.h`(新)、`net_socket.c` / `net_socket.h`、`net_pending.c` / `net_pending.h`、`net_types.h`、`MDK-ARM/STM32F407-Demo.uvprojx`、`scripts/check_registration.py`、`test/host/common/ch395f_fake.c` 与 `test/host/common/ch395f_fake.h`、`test/host/net_socket/`(含新分片);文档 → `docs/网络/BSD_Socket_API_使用指南.md` §6.0 / §6.1 / §6.2 / §6.3 / §9.0、`docs/网络/BSD_Socket_API_函数调用关系.md` §4.11、`docs/问题记录/CH395F_Trap_Records.md`(TRAP-NET-14 UDP 段 + 新条)。
|
||||
|
||||
@@ -1165,7 +1165,7 @@ WAIT_CLOSE 阶段已内置二段补发(只补一次),生产 net 层则靠
|
||||
(假件当时按"客户端不剥头"脚本化,240 轮全绿也照样没发现这件事——TRAP-NET-22 教训④)。
|
||||
改完的第二轮就是下面的全绿。
|
||||
|
||||
**实测结果(2026-11-04 08:42,板端 `fw build: Nov 4 2026`,phase16d.hex,PC = DHCP 192.168.31.161)**:
|
||||
**实测结果(2026-11-04 08:42,板端 `fw build: Nov 4 2026 08:40:28`,`phase16d.hex`,PC = DHCP 192.168.31.161)**:
|
||||
|
||||
```
|
||||
板端 === Phase 16: 77/77 PASSED (failed=0) ===
|
||||
@@ -1217,17 +1217,21 @@ open 起来,形态记账(SERVER/CLIENT)、参数与出参守卫、"阻塞
|
||||
它只证明**对端脚本**可用,不证明板端行为——真机那一趟仍然一条都不能省。
|
||||
- TC-NET-1607 用 30 s 预算版的挂起等待,不用无限版:同一套 park/唤醒机制,但无人值守的台架不该留一个
|
||||
能把任务钉死的等待。无限版(`timeout_ms = 0` → deadline = 0)的语义由主机单测 UDP-6 钉住。
|
||||
- 本阶段构建实测(2026-11-04 01:06,含 TC-NET-1610 免对端自检,`MDK-ARM/STM32F407-Demo/STM32F407-Demo.map`):Code 259,768 /
|
||||
RO 37,244 / RW 2,060 / ZI 151,596;RW_IRAM1 **96,232 B = 73.4%**(距 92% 红线余 24,354 B),
|
||||
RW_CCM 57,376 B / 87.9% 与产品一致。免对端自检那 17 条只加 Code(+2,380) 与 RO(+3,108,全是断言
|
||||
字符串),RW/ZI 一字未增——它复用 `s_udp_buf`,没带新缓冲。产品态(宏回默认后重新构建)Code 249,124 /
|
||||
RW 2,052 / ZI 149,996,与本阶段之前逐字节一致——阶段 16 的代码在产品里被预处理干净。台账数字以
|
||||
`test/board/ch395f_test.h` 那段为准。
|
||||
- 本阶段构建实测(含 TC-NET-1610 免对端自检,`MDK-ARM/STM32F407-Demo/STM32F407-Demo.map`):**第一轮的镜像**
|
||||
构建于 2026-11-04 01:06(`phase16c.hex`,836,489 B),Code 259,768 / RO 37,244 / RW 2,060 / ZI 151,596;
|
||||
**第二轮(全绿那次)的镜像**构建于 08:40:28(`phase16d.hex`,836,608 B),带的是恒剥修正后的生产代码
|
||||
(`net_udp.c` 少一次形态比较,Code −4)与改写后的断言文案(RO +44),
|
||||
Code 259,764 / RO 37,288 / RW 2,060 / ZI 151,596。台架态 `RW_IRAM1` **96,232 B = 73.4%**(距 92% 红线余
|
||||
24,354 B),`RW_CCM` 57,376 B / 87.9% 与产品一致。免对端自检那 17 条只加 Code(+2,380) 与 RO(+3,108,全是断言
|
||||
字符串),RW/ZI 一字未增——它复用 `s_udp_buf`,没带新缓冲。产品态(宏回默认后重新构建)Code **249,120** /
|
||||
RW 2,052 / ZI 149,996,比恒剥改造之前的 249,124 少 4 B——那 4 B 是剥头判据少一次形态比较(生产代码变化),
|
||||
与阶段 16 无关;**阶段 16 的代码在产品里被预处理干净,对产品态零成本**。台账数字以
|
||||
`test/board/ch395f_test.h` 那段为准,受管区数字由 `scripts/ram_baseline.py --write` 机器回填。
|
||||
- **真机进度(2026-11-03 夜)**:第一次上台架已跑通**前半段**——板端
|
||||
`TC-NET-1601a/b/c`(建 socket、bind :6001、`net_udp_get_mode` 回 SERVER)与
|
||||
`TC-NET-1602`(服务端形态收到 20 B、`addrlen`/`sin_family`/源端口都对、逐字节一致,回显后模式
|
||||
翻成 CLIENT)**全绿**,PC peer 侧同样收到那 20 B 回显;这就是队列化后的 UDP 收包路径在真芯片上
|
||||
的第一份证据(剥 8 字节信息头 + 源地址回填 + 回显发送全部正确)。**1603 之后仍未测**:板子在
|
||||
的第一份证据(剥 8 字节信息头 + 源地址回填 + 回显发送全部正确)。**当时 1603 之后未测**(次日已补全,见上面「实测结果」):板子在
|
||||
21:0x 再次失电(SWD `No target connected`、ping 不通、ST-LINK 探针仍在),与 19:19 那次同一现象。
|
||||
- 首跑抓到两处**台架**缺陷(都不是被测代码的问题,已改掉并各自有守卫):
|
||||
1. peer 死在 `WinError 10054`——板子还没 bind 时那一下 ICMP 端口不可达会被 Windows 记在套接句上,
|
||||
|
||||
Reference in New Issue
Block a user