8a81fa9e41
- 板端 net_layer_udp_bench_test_main:TC-NET-1601~1609,逐步覆盖主机测替代不了的 5 条台架必验——形态切换与 bind 后首包、48 B 应答在客户端形态的载荷完整(TRAP-NET-22 的真机对照)、截断包排空、挂起等待期间的 IWDG 余量、DesIP 先于 OPEN_SOCKET 的顺序。 每步都有 25 s 预算,PC 缺席时报 [FAIL] 而不是把 testTask 钉死。 - PC peer test/host/udp_queue_bench.py:板端先 bind 当服务端,对端地址从收到的包里学 (PC 是 DHCP,TEST_PC_PEER_IP 那个固定地址不在本机上);对 >1024 B 的回显额外监听 第二片,把 net_send_locked 分块在 UDP 上的后果量出来。 - ch395f_test.h:阶段 16 宏默认关(与其它阶段一致),RAM 台账补 2026-11-03 实测—— 台架镜像 RW_IRAM1 96,232 B / 73.4%,阶段 16 自身代价 1,600 B;产品镜像 RW+ZI 与改造前逐字节相同。 - 文档:CH395F_Test_Guide §12.6 跑法与判据 + Python 脚本表加一行;覆盖率口径第 4 轮 「台架必验」指向本阶段的可执行形态,并写明尚未在真机上跑过。
179 lines
12 KiB
C
179 lines
12 KiB
C
/*
|
||
* 模块名称:CH395F Driver Test Suite
|
||
* 模块功能:CH395F 驱动各功能模块的测试入口,分阶段组织测试用例,
|
||
* 覆盖 SPI 命令路径、协议栈配置、Socket 状态机、大文件传输、
|
||
* 边界条件、KeepAlive、PHY 链路恢复等,基于单连接 socket 模式
|
||
* 适用平台:STM32F4 系列(CH395F 以太网芯片)
|
||
* 作者:王建锋
|
||
* 创建日期:2026-07-19
|
||
* 修改记录:
|
||
* 2026-07-22 全面重构为单连接模式,增加大文件传输、边界条件等测试
|
||
*
|
||
* === 测试阶段一览(硬件层 1~5/12 → NET 层 6~11/13/14,严格顺序执行) ===
|
||
* Phase | 层 | 描述
|
||
* ---------|----------|-----------------------------------------------
|
||
* Phase 1 | 硬件层 | 独立运行:寄存器读写 + SPI 命令路径验证
|
||
* Phase 2 | 硬件层 | PC 配合:TCP Client 收发 + 关闭重连
|
||
* Phase 3 | 硬件层 | PC 配合:UDP Server Echo(60 轮动态源地址回显,HELLO 探针不计数)
|
||
* Phase 4 | 硬件层 | PC 配合:DHCP 自动获取 IP
|
||
* Phase 5 | 硬件层 | PC 配合:大文件分块回传(裸命令,tcp_server 配合)
|
||
* Phase 6 | NET 层 | testTask:TCP Echo(单连接模式,基础收发验证)
|
||
* Phase 7 | NET 层 | testTask:TCP Client 主动连接(回显收发 + 关闭重连 + 连接超时)
|
||
* Phase 8 | NET 层 | testTask:大文件传输(20KB+ 分块收发)
|
||
* Phase 9 | NET 层 | testTask:Select/Poll I/O 多路复用
|
||
* Phase 10 | NET 层 | testTask:边界条件测试(零长度、DMA 边界、缓冲溢出)
|
||
* Phase 11 | NET 层 | testTask:KeepAlive 超时断开测试
|
||
* Phase 12 | 硬件层 | 独立运行:SPI 字节命令 / DMA 时延基线(SPI_CMD/SPI_DMA,无需 PC)
|
||
* Phase 13 | NET 层 | testTask:芯片 + 队列时延(CHUNK_WAIT~FRAME_RT/LOGTAX,需 PC peer,独立运行)
|
||
* Phase 14 | NET 层 | testTask:生产路径时延(PROD_CYCLE~UI_LOOP + 模拟器 A/B,需 PC peer)〔M3 规划〕
|
||
* Phase 16 | NET 层 | testTask:BSD UDP 数据面真机回归(形态切换/剥头/截断排空/挂起唤醒/分块边界,需 PC peer,独立运行)
|
||
* 时延分段定义/判定基线/执行流程:docs/测试说明/专项验证/链路延迟测试说明.md
|
||
*/
|
||
|
||
#ifndef CH395F_TEST_H
|
||
#define CH395F_TEST_H
|
||
|
||
#ifdef __cplusplus
|
||
extern "C" {
|
||
#endif
|
||
|
||
#include <stdint.h>
|
||
#include "test_common.h"
|
||
|
||
/*
|
||
* 阶段使能开关(取消注释即启用对应阶段)
|
||
*
|
||
* 构建模式互斥(详见 docs/测试说明/板级测试/CH395F_Test_Guide.md「构建模式与执行顺序」):
|
||
* 硬件层模式(阶段 1~5):netTask 入口自挂起(创建但不运行),testTask 独占 CH395F
|
||
* NET 层模式 (阶段 6~11):完整网络栈,netTask 轮询 + testTask 监听循环
|
||
*
|
||
* 注意:同层内可多选(Phase 6~10 共享 testTask 循环);
|
||
* Phase 4 (DHCP) 会改变 IP,必须独立运行;
|
||
* 两层同时启用会在下方触发 #error。
|
||
*/
|
||
/* ---- 硬件层(阶段 1~5/12)---- */
|
||
//#define ENABLE_PHASE1_TESTS /* [硬] 寄存器读写 + SPI 命令路径 */
|
||
//#define ENABLE_PHASE2_TESTS /* [硬] TCP Client 收发 + 关闭重连 */
|
||
//#define ENABLE_PHASE3_TESTS /* [硬] UDP Server Echo */
|
||
//#define ENABLE_PHASE4_TESTS /* [硬] DHCP 自动获取 IP(会改 IP!独立运行) */
|
||
//#define ENABLE_PHASE5_TESTS /* [硬] 大文件传输(硬件层,PC 配合) */
|
||
/* ---- NET 层(阶段 6~11)---- */
|
||
//#define ENABLE_PHASE6_TESTS /* [网] TCP Echo(单连接基础收发) */
|
||
//#define ENABLE_PHASE7_TESTS /* [网] TCP Client 主动连接(回显收发 + 关闭重连 + 连接超时) */
|
||
//#define ENABLE_PHASE8_TESTS /* [网] 大文件传输(100KB 文件收发) */
|
||
//#define ENABLE_PHASE9_TESTS /* [网] Select/Poll I/O 多路复用 */
|
||
//#define ENABLE_PHASE10_TESTS /* [网] 边界条件测试 */
|
||
/* [网] KeepAlive 超时断开:PC 连 8080 后须制造死对端(禁用网卡;防火墙规则对已建立
|
||
* 连接无效,E11 实证);勿与 Phase 6/9/10/13 混选(recv 互抢数据)。
|
||
* ⚠ 说明写在**上一行**而不是挂在 #define 行尾:见本节末尾的"开关行注释规范" */
|
||
#define ENABLE_PHASE11_TESTS /* [网] KeepAlive 超时断开(判据见 CH395F_Test_Guide) */
|
||
/* ---- 链路时延基线(M1;分段/阈值见 docs/测试说明/专项验证/链路延迟测试说明.md)---- */
|
||
//#define ENABLE_PHASE12_TESTS /* [硬] SPI 字节命令 / DMA 时延基线(SPI_CMD/SPI_DMA,无需 PC)—— M1 已完成,基线见说明文档 §6.1 */
|
||
//#define ENABLE_PHASE15_TESTS /* [硬] 自愈驱动原语:状态回读一致性/cmd_done/sock_reset 状态机跑通/链路缓存(无需 PC)——TC 详见 docs/测试说明/板级测试/CH395F_Test_Guide.md 阶段 15;台架 21/21 PASS */
|
||
/* ---- 链路时延(M2/M3;分段/阈值见 docs/测试说明/专项验证/链路延迟测试说明.md)---- */
|
||
//#define ENABLE_PHASE13_TESTS /* [网] 芯片 + 队列时延(CHUNK_WAIT~FRAME_RT/LOGTAX,需 PC peer)—— M2 已完成,基线见说明文档 §6.2 */
|
||
/* [网] 生产路径时延(PROD_CYCLE~UI_LOOP + 模拟器 Δ)—— M3,需 peer --mode remo(:7003);
|
||
* 与 Phase 11 共存安全:peer 缺席时有 LAT_P14_TIMEOUT_MS 整体超时,自动 done,
|
||
* 不永久挡 accept */
|
||
#define ENABLE_PHASE14_TESTS /* [网] 生产路径时延(PROD_CYCLE~UI_LOOP) */
|
||
/* [网] BSD UDP 数据面真机回归(阶段 16,PR #74 UDP 队列化的台架对照):需 PC 端
|
||
* `python test/host/udp_queue_bench.py --board <板 IP>`,**只开本宏**——阶段 7/11/14
|
||
* 会把 TEST_LATENCY_PROBE 带进产品路径,污染要证的 UDP 面。判据见 CH395F_Test_Guide 阶段 16。 */
|
||
//#define ENABLE_PHASE16_TESTS /* [网] BSD UDP 数据面真机回归(需 PC peer,独立运行) */
|
||
|
||
/*
|
||
* 开关行注释规范(2026-10-25 构建矩阵实测踩出来的,别改回去):
|
||
* 每个 ENABLE_PHASE*_TESTS 行只许带"同一行内闭合"的行尾注释,或不写注释;
|
||
* 需要多行说明就挪到该行的**上一段**。原因:关一个阶段的动作是在行首加两个
|
||
* 斜杠,而它只注释到行尾——挂在行尾的跨行注释会从第二行起**变成裸代码**(实测
|
||
* 188 条 error #7: unrecognized token,报点落在注释的续行上,看着像头文件坏了,
|
||
* 其实只是注释被腰斩)。开阶段是同一个坑的反面:去掉行首斜杠并不会把注释拼回来。
|
||
* test/run_all_suites.py 的 _rewrite_config 只改 TEST_SUITE_* 行(那些行没有行尾
|
||
* 跨行注释)所以一直没炸;本文件是"人手工切阶段"的入口,必须自身安全。
|
||
*
|
||
* 链接余量构建实测(2026-10-25,本文件即数字与结论的唯一出处;2026-10-28 复核:
|
||
* RW_IRAM1 = 128 KB 的 .sct 区,92% 红线 = 120,586 B):
|
||
* 配置(TEST_SUITE_CH395F + 阶段) Code ZI RW_IRAM1 距红线余量
|
||
* 产品基线(阶段全关) 214,104 131,852 75,632 57.7% 44,954 B
|
||
* 默认阶段 11/14(只切套件宏) 217,468 134,076 77,920 59.5% 42,666 B
|
||
* NET 层全开 6~11/13/14 218,992 141,688 85,552 65.3% 35,034 B
|
||
* HW 层全开 1~5/12/15(最坏态) 229,256 147,176 90,952 69.4% 29,634 B
|
||
* HW 层无需 PC 1/12/15(台架冒烟用) 215,244 134,896 78,672 60.0% 41,914 B
|
||
*
|
||
* 同日 sync 追平后的复测(合入 59da40b 与 891ca81 两笔之后,产品基线前进到
|
||
* Code=215,744 / RO=21,396 / RW=1,224 / ZI=131,984,RW_IRAM1 75,784 B / 57.82%):
|
||
* 配置 Code ZI RW_IRAM1 距红线余量
|
||
* 默认阶段 11/14 219,112 134,208 78,072 59.6% 42,514 B
|
||
* NET 层全开 6~10/13/14 220,636 141,804 85,688 65.4% 34,898 B
|
||
* HW 层全开 1~5/12/15(最坏态) 230,900 147,300 91,088 69.5% 29,498 B
|
||
* HW 层无需 PC 1/12/15 216,888 135,020 78,808 60.1% 41,778 B
|
||
* 四档仍全部 0 错误 0 警告、链接通过;PHASE5 三块缓冲依旧在链(hw_full 的
|
||
* ch395f_test_task.o 数据段仍是 12,285 B)。上表 04 点那组的产品基线已前进,
|
||
* 作为当日历史记录保留、不追改(两组差值都在 +136~+152 B 量级,来自新增的
|
||
* adc_cal 数据段;结论"最坏态仍余约 29 KB、不必扩 scatter"不变)。
|
||
*
|
||
* 2026-11-03 阶段 16(BSD UDP 数据面真机回归)复核,本文件仍是数字唯一出处。
|
||
* 同一棵树的产品基线这几天已前进到 Code=249,124 / RO=29,836 / RW=2,052 / ZI=149,996,
|
||
* RW_IRAM1 94,624 B / 72.2%、RW_CCM 57,376 B / 87.9%——比 10-28 那组高约 19 KB,
|
||
* 是期间合入的东西,与阶段 16 无关,别把它算到本阶段头上。
|
||
* 配置(TEST_SUITE_CH395F + 只开阶段 16) Code ZI RW_IRAM1 距红线余量
|
||
* UDP 台架镜像 257,176 151,596 96,232 73.4% 24,354 B
|
||
* 阶段 16 自己的全部代价 = `net_test_task.o` 的 1,600 B .bss(一个 1600 B 收发缓冲,
|
||
* 装得下 1472 B 上限的数据报)。产品构建(四行宏全恢复默认)RW+ZI 与改造前逐字节相同;
|
||
* UDP 队列化本身在产品镜像里只多 `net_udp.o` 的 224 B .bss。跑法与判据见
|
||
* docs/测试说明/板级测试/CH395F_Test_Guide.md §12.6。
|
||
*
|
||
* 台架冒烟(2026-10-25,_wt 同树构建 → 主树烧录,boot log 20261025_050539):
|
||
* 镜像 ch395f_hw_nopc_v2.hex(戳 suite=CH395F dstr=off)单次开机跑完 1/12/15 三段,
|
||
* 汇总行 Phase 1: 9/9、Phase 12: 1/1、Phase 15: **21/21**(failed=0),全程无 Fault。
|
||
* 同轮暴露两类设计外/设计内 [ERR]:P2 越界守卫留痕(设计内,见 ch395f.c)与
|
||
* [WD] task stall 刷屏 468 条(**设计外**:HW 层构建的必需心跳掩码没生效,
|
||
* 因为 App/util/task_watchdog.c 未 include test_config.h,看不到本文件的
|
||
* ENABLE_HW_LAYER_TESTS → 那段剔除 netTask 的分支自加入起就是死代码)。
|
||
* 修复后复跑(同日 f3 镜像 05:51:31 戳,boot log 20261025_055725):VERDICT PASS——
|
||
* 三段汇总 9/9、1/1、21/21,身份戳核对 + 烧后回读一致,六标签判据零命中;
|
||
* [WD] task stall 468→14:net 类 431→0(task_watchdog.c 补 include 后掩码复活实锤),
|
||
* 余 14 条 = 13 x mask=0x1F7(netTask 自挂起前喂那一次 vs 精确匹配判据的语义打架,
|
||
* 非缺喂)+ 1 x mask=0x1E5(uiTask 首个喂狗窗未到的瞬态),另有 1 条设计内 P2 留痕。
|
||
* Lead 裁决不放宽超集判定:全部属测试固件态,产品判据 req=0x1F7 无死分支不误报。
|
||
* 该条目关心的 PHASE5 三块静态缓冲(3 x PHASE5_CHUNK_SIZE = 4093)确实进了链接:
|
||
* hw_full 的 ch395f_test_task.o 数据段 = 12,285 B(3 x 4093 = 12,279 + 其余 6 B)。
|
||
* "理论余量足够"由未实测转为已实测:最坏态还余 29,634 B,不必把 .sct 扩到 192 KB
|
||
* (**约束:不建议把 scatter 扩到 192 KB**——会破坏既有克隆芯片兼容决策)。RW_CCM 四档恒为 57,376 B / 87.9%——
|
||
* 但该区已贴着 92% 线,任何往 CCM 加东西的改动都得单独核算。
|
||
*/
|
||
#if defined(ENABLE_PHASE1_TESTS) || defined(ENABLE_PHASE2_TESTS) || \
|
||
defined(ENABLE_PHASE3_TESTS) || defined(ENABLE_PHASE4_TESTS) || \
|
||
defined(ENABLE_PHASE5_TESTS) || defined(ENABLE_PHASE12_TESTS) || \
|
||
defined(ENABLE_PHASE15_TESTS)
|
||
#define ENABLE_HW_LAYER_TESTS 1
|
||
#endif
|
||
|
||
#if defined(ENABLE_PHASE6_TESTS) || defined(ENABLE_PHASE7_TESTS) || \
|
||
defined(ENABLE_PHASE8_TESTS) || defined(ENABLE_PHASE9_TESTS) || \
|
||
defined(ENABLE_PHASE10_TESTS) || defined(ENABLE_PHASE11_TESTS) || \
|
||
defined(ENABLE_PHASE13_TESTS) || defined(ENABLE_PHASE14_TESTS) || \
|
||
defined(ENABLE_PHASE16_TESTS)
|
||
#define ENABLE_NET_LAYER_TESTS 1
|
||
#endif
|
||
|
||
#if defined(ENABLE_HW_LAYER_TESTS) && defined(ENABLE_NET_LAYER_TESTS)
|
||
#error "硬件层(1~5)与NET层(6~11)测试互斥:请分两次构建,见 CH395F_Test_Guide 构建模式与执行顺序"
|
||
#endif
|
||
|
||
/* 测试统计(本套件独立,防跨套件串数;内核见 test_common.h) */
|
||
typedef test_stats_t ch395f_stats_t;
|
||
|
||
extern ch395f_stats_t g_test_stats;
|
||
|
||
#define TEST_CHECK(cond, fmt, ...) \
|
||
TEST_CHECK_IMPL(g_test_stats, cond, fmt, ##__VA_ARGS__)
|
||
|
||
#define TEST_REPORT(name) TEST_REPORT_IMPL(g_test_stats, name)
|
||
|
||
#ifdef __cplusplus
|
||
}
|
||
#endif
|
||
|
||
#endif /* CH395F_TEST_H */
|