test(net/udp): 阶段 16 补 TC-NET-1610 免对端自检,断线时也有板端证据(#73)
第一次上台架就是被「没有对端」卡住的:peer 脚本被 Windows 的 ICMP 10054 打死、 梯子错位,TC-NET-1601 之后一步都测不到,整趟真机证据直接归零。板子的 10 pin 杜邦线 又断了(#73 讨论区已记),台架短期内还会反复断,所以把「不需要 PC 发一个包也能确认」 的那一半补进阶段 16。 板端 test/board/net_test_task.c 新增 udp_bench_peer_free_check(),17 条断言 (TC-NET-1610a~q),执行位置在 1601 之前、编号留在段尾:编号是给台账用的,不该因为 断线重跑而漂。四类判据: - 形态记账:新建 DGRAM socket 与 bind :6003 之后都读 NET_UDP_MODE_SERVER; - 参数与出参守卫:未 bind 的 net_sendto 报 -5 NOTCONN、流式 net_recv 读 DGRAM 报 -3 INVAL(绕开剥头就会静默吃 8 字节)、to_ms==0 报 -3 INVAL、src_addr 缺 addrlen 或容量只有 4 字节报 -3、空缓冲 DONTWAIT 当场报 -7 WOULDBLOCK(不登记挂起); - 「阻塞收包已改成挂起登记」:net_recvfrom_to(2000) 返回 -2,实测睡眠落在 2000~4500 ms——等待睡在任务通知上,不在 SPI 总线上自旋。预算取 2 s,压在产品 IWDG(2.5 s)与 netTask 喂狗窗口之下,万一退回旧版自旋,会先被看门狗抓到; - 关闭与复用:net_close 后同一槽重新 bind :6003 不被上一条命毒化(DONTWAIT 仍 -7), set_peer(fd, NULL) 在本就是 SERVER 时是无副作用的 0 返回(不许重开芯片 socket)。 代价只有 flash:bench 态 Code 257,388 → 259,768、RO 34,136 → 37,244(全是断言字符串), RW/ZI 一字未增(复用那块 1,600 B 收发缓冲),RW_IRAM1 仍 96,232 B / 73.4%。 产品态(四行宏回默认重新构建)Code=249,124 / RW=2,052 / ZI=149,996,与本阶段之前 逐字节一致,阶段 16 在产品里被预处理干净。两态均 0 error 0 warning(2026-11-04 01:06)。 文档同步:CH395F_Test_Guide §12.6 用例表补 TC-NET-1610 行与「没有对端也要有证据」一段; ch395f_test.h 的 RAM 台账补这轮增减数字与其来源;主机单测覆盖率口径 第 4 轮记明这半 「已编过、仍未在真机上跑过」——断线期间它一条也测不到,不能算证据。
This commit is contained in:
@@ -727,6 +727,7 @@ uint16_t ch395f_link_change_count(void);
|
||||
- **本轮覆盖率**(收尾那次全仓跑数,`--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 行)。
|
||||
- **台架必验(本轮无板子,主机测替代不了)**:① 两端真机互通,服务器形态收发 + 客户端形态往返,重点看 48 B 这类小应答**载荷完整**且源地址正确;② `sendto` 切形态后 `net_udp_set_peer(fd, NULL)` 能否真恢复收广播——手册只写 DesIP 语义,没写切换时机;③ 截断包排空后下一个包是否完整(scratch 循环在真芯片读指针上的行为);④ 挂起 recv 等待期间的 IWDG 余量;⑤ bind 在 open **之前**写 DesIP 的顺序在真芯片上的实际效果(TRAP-NET-14 的 UDP 侧对照)。
|
||||
- **这 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(剥 8 字节信息头与源地址回填在真芯片上成立);②③④⑤ 未测,板子当晚两次失电(SWD `No target connected`、ping 不通,19:19 与 21:0x 各一次),两趟还各暴露一个**台架**缺陷(peer 被 Windows 的 ICMP 10054 打死;单步预算 8 s < 板端 25 s park 导致整条梯子错位),修法与守卫见上面那份指南。PR #74 的合并前提仍是这条回归跑完整;跑完请把结果回填本条并把上面「台架必验」改写成实测结论。
|
||||
- **同一轮补的免对端那半(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 01:06),但仍未在真机上跑过**:台架断线期间它一条也测不到,所以这里只算"编过",不算证据。
|
||||
- 本轮改动面:`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 段 + 新条)。
|
||||
|
||||
### P3|**明确不做**(把理由写死,免得下次又被列回待办:29 个 `.c` = 4,814 行)
|
||||
|
||||
@@ -1152,6 +1152,12 @@ WAIT_CLOSE 阶段已内置二段补发(只补一次),生产 net 层则靠
|
||||
| TC-NET-1607 | 挂起等待期间的 IWDG 余量 | PC 迟到约 12 s 才发;板端 `net_recvfrom_to(..., 30000)` 醒来看见 24 B 正确载荷,实测等待落在 7~25 s,`net_get_generation()` 不变(没重建没复位)。硬证据在串口日志:这段 `[ERR][WD] task stall` 零条、`[PROF]` 心跳连续 | ④ |
|
||||
| TC-NET-1608 | 关旧 socket → 新开 → 重 bind :6002 | 新 socket 的首包必到(DesIP 要在 `OPEN_SOCKET` **之前**写才生效) | ⑤ |
|
||||
| TC-NET-1609 | 分块边界 1 / 20 / 1024 / 1025 / 1472 | 每条往返字节完全一致 | — |
|
||||
| TC-NET-1610 | **免对端自检**(17 条,编号留在段尾、执行放在 1601 之前,是为了断线重跑时编号不漂) | PC 一个包都不发也能确认:新建 DGRAM socket 读到 SERVER;未 bind 时 `net_sendto` 报 -5、流式 `net_recv` 读 DGRAM 报 -3;经队列 `bind :6003` 成功且 mode = SERVER;空缓冲 `DONTWAIT` 报 -7;`net_recvfrom_to(2000)` 返回 **-2** 且实测睡眠 2~4.5 s(等待睡在任务通知上,没在 SPI 总线上自旋);`to_ms == 0` 报 -3;`src_addr` 缺 `addrlen`、容量只有 4 字节都报 -3;`set_peer(fd, NULL)` 在本就是 SERVER 时返回 0 且无副作用;`net_close` 后同一槽重新 bind :6003 不被上一条命毒化 | — |
|
||||
|
||||
**没有对端也要有证据**:1601 之后每一步都在等 PC 的包——网线没插好、防火墙静默丢包、peer 脚本没起,
|
||||
任何一条都会让整条阶梯停在 1602(2026-11-03 首跑就是这么停的)。TC-NET-1610 只依赖芯片能把 socket
|
||||
open 起来,形态记账(SERVER/CLIENT)、参数与出参守卫、"阻塞收包已改成挂起登记"这三件事在完全不互通
|
||||
时也能一次确认;断线的时候,串口日志里的 `TC-NET-1610*` 就是判断"板子这半边是不是好的"的唯一依据。
|
||||
|
||||
**运行方法**:
|
||||
|
||||
@@ -1181,10 +1187,11 @@ WAIT_CLOSE 阶段已内置二段补发(只补一次),生产 net 层则靠
|
||||
它只证明**对端脚本**可用,不证明板端行为——真机那一趟仍然一条都不能省。
|
||||
- TC-NET-1607 用 30 s 预算版的挂起等待,不用无限版:同一套 park/唤醒机制,但无人值守的台架不该留一个
|
||||
能把任务钉死的等待。无限版(`timeout_ms = 0` → deadline = 0)的语义由主机单测 UDP-6 钉住。
|
||||
- 本阶段构建实测(2026-11-03 加固后,`MDK-ARM/STM32F407-Demo/STM32F407-Demo.map`):Code 257,388 /
|
||||
RO 34,136 / RW 2,060 / ZI 151,596;RW_IRAM1 **96,232 B = 73.4%**(距 92% 红线余 24,354 B),
|
||||
RW_CCM 57,376 B / 87.9% 与产品一致。产品态(宏回默认后重新构建)Code 249,124 / RW 2,052 /
|
||||
ZI 149,996,与本阶段之前逐字节一致——阶段 16 的代码在产品里被预处理干净。台账数字以
|
||||
- 本阶段构建实测(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` 那段为准。
|
||||
- **真机进度(2026-11-03 夜)**:第一次上台架已跑通**前半段**——板端
|
||||
`TC-NET-1601a/b/c`(建 socket、bind :6001、`net_udp_get_mode` 回 SERVER)与
|
||||
|
||||
Reference in New Issue
Block a user