diff --git a/AGENTS.md b/AGENTS.md index 97bcbe72..4fa5fe4e 100644 --- a/AGENTS.md +++ b/AGENTS.md @@ -147,7 +147,7 @@ - 所有 `net_*` socket 操作经 `netMsgQueue` 在 netTask 串行执行;非 netTask 任务直接调 `net_*` API,勿直接碰 CH395F 驱动 - **`net_*` 公开 API 的错误码经"任务通知值"回传**:`net_msg_t` 是**按值拷入队列**的,netTask 改的是自己那份副本,调用方永远看不到 → 错误码搭 `xTaskNotify()` 通知值回来。**勿给 `net_msg_t` 加"回传用"字段**(调用方只会读到栈垃圾) - **单连接 socket 的断开语义**:EOF 时 net 层已 `auto_relisten`,应用层**不得**在 EOF 时 `net_close` 该 fd(会连监听一起毁掉 → 端口"连接被拒");仅当数据 fd ≠ 监听 fd(模拟器多连接后端)时才关 -- 网口配置:`/config.ini` [network] 段(工厂默认 192.168.1.100/24、gw .1;MAC 全零 = 芯片内置;UI 保存立即生效;**旧档 `/cfg/netcfg.bin` 迁移已于 2026-10-10 删除**,旧档存在则被忽略);同文件 **[ftp] 段 = FTP 鉴权**(`user` / `pwd_hash` = SHA-256(user‖password) / `write`,出厂默认 admin/admin,默认口令在用有启动告警;连续 5 次失败锁 60 s)→ `docs/子系统设计/网络配置说明.md` +- 网口配置:`/config.ini` [network] 段(工厂默认 192.168.31.100/24、gw .1;MAC 全零 = 芯片内置;UI 保存立即生效;**旧档 `/cfg/netcfg.bin` 迁移已于 2026-10-10 删除**,旧档存在则被忽略);同文件 **[ftp] 段 = FTP 鉴权**(`user` / `pwd_hash` = SHA-256(user‖password) / `write`,出厂默认 admin/admin,默认口令在用有启动告警;连续 5 次失败锁 60 s)→ `docs/子系统设计/网络配置说明.md` - **新 .c 文件必须手动注册到两处**才能双端编译:`MDK-ARM/STM32F407-Demo.uvprojx` + `simulator/CMakeLists.txt`(用 `new-source-file` skill);⚠ **新文件落在还没有的新目录,还要把该目录加进 `uvprojx` 的 ``**——否则报错落在**消费者 TU** 上(`cannot open source input file`),极易误判 - 测试构建:`test/board/test_config.h` 的 `TEST_SUITE_CH395F/STORAGE/GD5F/RTC` **互斥**(一次只能一个,`#error`);全部注释 = 产品构建,**受 `test-suite-switch` 钩子门禁**;`ENABLE_DESTRUCTIVE_TESTS` **默认关闭**(关闭时套件只读模式,可随时在在用设备上跑)——⚠ 跑一轮破坏性 GD5F 即让 dhara 多记一个坏块且该计数持久化,普通恢复清不掉 → `docs/测试说明/专项验证/存储维护与容量恢复.md`;板级套件运行用 **`board-test-suite` skill** - **改驱动前先读对应 `docs/问题记录/*_Trap_Records.md`**(CH395F / GD5F2GQ5UE / SD2506);各模块测试指南见 `docs/测试说明/` diff --git a/Drivers/BSP/NET/net_socket.c b/Drivers/BSP/NET/net_socket.c index 9636f7dd..020fbc86 100644 --- a/Drivers/BSP/NET/net_socket.c +++ b/Drivers/BSP/NET/net_socket.c @@ -268,9 +268,9 @@ static bool s_mac_is_zero(const uint8_t *p_mac) { /* * 函数功能:网络子系统初始化(配置 CH395F + 启用多连接模式) - * 入口参数:ip - IP 地址字符串 "192.168.1.100",NULL 使用 DHCP 自动获取 const char * - * mask - 子网掩码字符串 "255.255.255.0",NULL 使用默认值 const char * - * gateway - 网关地址字符串 "192.168.1.1",NULL 使用默认值 const char * + * 入口参数:ip - IP 地址字符串(点分十进制),NULL 使用 DHCP 自动获取 const char * + * mask - 子网掩码字符串,NULL 使用默认值 const char * + * gateway - 网关地址字符串,NULL 使用默认值 const char * * mac - MAC 地址(6 字节,低字节在前),NULL/全零使用芯片内置 const uint8_t * * 返回值:0 - 初始化成功 int * -1 - 初始化失败(芯片检测/复位/协议栈初始化失败) int @@ -2930,7 +2930,7 @@ int net_sock_state(int sockfd) { /* * 函数功能:将点分十进制 IP 地址字符串转换为网络字节序的 32 位地址 - * 入口参数:cp - 点分十进制 IP 字符串(如 "192.168.1.100") const char * + * 入口参数:cp - 点分十进制 IP 字符串 const char * * 出口参数:无 * 返回值:网络字节序的 32 位 IP 地址(0 表示参数无效) uint32_t * 限定条件:无 @@ -2939,9 +2939,9 @@ int net_sock_state(int sockfd) { * 本文件内 s_addr 只有这一族(2026-10-24:两套 IP 字节序约定统一为 POSIX 网络序):net_inet_ntoa 的 * 「先 NTOHL、再高段在前」正是本函数的解析逆运算;net_getsockname、 * net_getpeername、net_recvfrom 填的 s_addr 也同族,故三者可直接相等比较。 - * 2. 小端主机(STM32F407 与 PC 模拟器均是)上 "192.168.1.100" 的数值为 - * 0x6401A8C0(内存字节 C0 A8 01 64)。旧实现在小端累加后又多做一次 - * HTONL,得到 0xC0A80164,与 ntoa 不互逆——那是同一文件里的第二套约定, + * 2. 小端主机(STM32F407 与 PC 模拟器均是)上 "192.168.31.100" 的数值为 + * 0x641FA8C0(内存字节 C0 A8 1F 64)。旧实现在小端累加后又多做一次 + * HTONL,得到 0xC0A81F64,与 ntoa 不互逆——那是同一文件里的第二套约定, * 已连同其消费者(connect/sendto 的 des_ip 拆装)一起改为本族。 * 3. 段值超过 255 时按低 8 位截断(旧实现会把溢出位溅进相邻段,更不可预期); * 非法字符仍按 0 处理,失败返回值维持 0,不改 NET_INADDR_NONE 的语义。 @@ -2988,9 +2988,9 @@ uint32_t net_inet_addr(const char *cp) { * 函数说明:1. 先经 NET_NTOHL 转为主机字节序再格式化输出 * 2. ⚠ 段序(E13 定案 修复):NTOHL 后主机序数值的高字节才是 * 点分第一段。**入参必须是网络序整数**(&addr 的第 0 字节 = 第一段, - * 小端上 192.168.1.100 = 0x6401A8C0,见 net_inet_addr 的约定说明), - * 于是 0x6401A8C0 → NTOHL → 0xC0A80164 → 高字节 0xC0 = 192 首段 ✓。 - * 原实现低段在前,同一入参会显示成字节反转的 "100.1.168.192"。 + * 小端上 192.168.31.100 = 0x641FA8C0,见 net_inet_addr 的约定说明), + * 于是 0x641FA8C0 → NTOHL → 0xC0A81F64 → 高字节 0xC0 = 192 首段 ✓。 + * 原实现低段在前,同一入参会显示成字节反转的 "100.31.168.192"。 * 3. ⚠ 本注释旧版举的例子写成「192.168.1.100 → 0xC0A80164 → 同串」, * 那个 0xC0A80164 取的是**已废弃的另一族**(当时 net_inet_addr 的返回 * 值),按本函数的真实算法它打印出来恰是 "100.1.168.192"。两套 s_addr @@ -3100,7 +3100,7 @@ static int alloc_socket(void) { /* * 函数功能:将点分十进制 IP 地址字符串解析为 4 字节数组 - * 入口参数:str - 点分十进制 IP 字符串(如 "192.168.1.100") const char * + * 入口参数:str - 点分十进制 IP 字符串 const char * * ip_arr - 输出:4 字节 IP 数组(网络序,低字节在前) uint8_t * * 出口参数:ip_arr - 填充解析后的 IP 地址 * 返回值:无 diff --git a/Drivers/BSP/NET/net_socket.h b/Drivers/BSP/NET/net_socket.h index 59fa04d2..ceea41f6 100644 --- a/Drivers/BSP/NET/net_socket.h +++ b/Drivers/BSP/NET/net_socket.h @@ -85,9 +85,9 @@ int net_msg_queue_adopt(osMessageQueueId_t queue_id); /* * 函数功能:网络子系统初始化(配置 CH395F + 启用多连接模式) - * 入口参数:ip - 本地 IP 地址字符串 "192.168.1.100",NULL 使用 DHCP - * mask - 子网掩码字符串 "255.255.255.0",NULL 使用默认 - * gateway - 网关地址字符串 "192.168.1.1",NULL 使用默认 + * 入口参数:ip - 本地 IP 地址字符串(点分十进制),NULL 使用 DHCP + * mask - 子网掩码字符串,NULL 使用默认 + * gateway - 网关地址字符串,NULL 使用默认 * mac - MAC 地址(6 字节,低字节在前),NULL 或全零使用芯片内置 * 返回值:0 成功,-1 失败 * 限定条件:SPI2 已正确初始化 @@ -465,14 +465,14 @@ int net_sock_state(int sockfd); /* * 函数功能:将 IP 地址字符串转为网络字节序 - * 入口参数:cp - 点分十进制字符串 "192.168.1.100" + * 入口参数:cp - 点分十进制字符串 * 返回值:网络字节序 IP,失败返回 0 * 限定条件:cp 指针非空 * 函数说明:不支持域名解析 * * s_addr 的**唯一约定**(2026-10-24 定案:两套 IP 字节序约定统一为 POSIX 网络序;全仓只此一族,勿再引入第二套): * 网络字节序整数 —— &s_addr 的第 0 个内存字节 == 点分第一段。 - * 小端主机(STM32F407 与 PC 模拟器都是)上 "192.168.1.100" 的数值 = 0x6401A8C0。 + * 小端主机(STM32F407 与 PC 模拟器都是)上 "192.168.31.100" 的数值 = 0x641FA8C0。 * 与 net_inet_ntoa 互为逆运算;net_getsockname / net_getpeername / net_recvfrom * 填出来的 s_addr、以及 net_bind / net_connect / net_sendto 收进去的 s_addr * 全在同一族,故可直接做相等比较(旧实现里 inet_addr 与其余四个不互逆, diff --git a/Drivers/BSP/NETCFG/net_cfg.c b/Drivers/BSP/NETCFG/net_cfg.c index c3c94619..e39d6028 100644 --- a/Drivers/BSP/NETCFG/net_cfg.c +++ b/Drivers/BSP/NETCFG/net_cfg.c @@ -41,9 +41,9 @@ /* 私有宏定义区 */ /* 工厂默认值(单一来源:s_cfg 初值与 s_defaults 共用,避免两处漂移) */ -#define NET_CFG_DEF_IP { 192u, 168u, 1u, 100u } +#define NET_CFG_DEF_IP { 192u, 168u, 31u, 100u } #define NET_CFG_DEF_MASK { 255u, 255u, 255u, 0u } -#define NET_CFG_DEF_GW { 192u, 168u, 1u, 1u } +#define NET_CFG_DEF_GW { 192u, 168u, 31u, 1u } #define NET_CFG_DEF_MAC { 0u, 0u, 0u, 0u, 0u, 0u } /* 静态变量定义区 */ diff --git a/Drivers/BSP/NETCFG/net_cfg.h b/Drivers/BSP/NETCFG/net_cfg.h index b3ebf4c9..423f7ed5 100644 --- a/Drivers/BSP/NETCFG/net_cfg.h +++ b/Drivers/BSP/NETCFG/net_cfg.h @@ -36,9 +36,9 @@ extern "C" { * mac 全零哨兵:不设置芯片 MAC(用芯片内置值,存于芯片 EEPROM) */ typedef struct { - uint8_t ip[4]; /* IP 地址(工厂默认 192.168.1.100) */ - uint8_t mask[4]; /* 子网掩码(工厂默认 255.255.255.0) */ - uint8_t gw[4]; /* 默认网关(工厂默认 192.168.1.1) */ + uint8_t ip[4]; /* IP 地址(工厂默认 = net_cfg.c 的 NET_CFG_DEF_IP) */ + uint8_t mask[4]; /* 子网掩码(工厂默认 = net_cfg.c 的 NET_CFG_DEF_MASK) */ + uint8_t gw[4]; /* 默认网关(工厂默认 = net_cfg.c 的 NET_CFG_DEF_GW) */ uint8_t mac[6]; /* MAC 地址(全零 = 芯片内置 MAC) */ } net_cfg_t; diff --git a/MDK-ARM/ftp_freeze_probe.py b/MDK-ARM/ftp_freeze_probe.py index cca29f89..c9ef2dd4 100644 --- a/MDK-ARM/ftp_freeze_probe.py +++ b/MDK-ARM/ftp_freeze_probe.py @@ -11,7 +11,7 @@ # * Only the device's own production logs are used for the device-side timeline # (window them by the per-round "TS " line printed here). # -# Usage: ftp_freeze_probe.py [--ip 192.168.1.100] [--port 21] [--size 65536] +# Usage: ftp_freeze_probe.py [--ip <设备IP>] [--port 21] [--size 65536] # [--rounds 10] [--gap 3] [--keep] # Output lines (machine-auditable): # TS @@ -22,6 +22,13 @@ import argparse, hashlib, io, os, random, socket, sys, time from ftplib import FTP, error_reply, error_temp, error_perm, all_errors +# 台架连接默认值单一真源在 test/host/bench_defaults.py(跨目录:补 sys.path 后 import) +_sys_path = os.path.join(os.path.dirname(os.path.abspath(__file__)), + "..", "test", "host") +if _sys_path not in sys.path: + sys.path.insert(0, _sys_path) +import bench_defaults # noqa: E402 + # Device-side FTP auth: lftpd validates against /config.ini [ftp] (user / pwd_hash). # This device has NO anonymous channel (USER anonymous -> 530), so the probe must log # in with the factory account. Override with --user/--password if it was changed. @@ -48,7 +55,7 @@ def liveness(ip, port, timeout=3.0): def main(): global FTP_USER, FTP_PASS # 两处登录点都读模块常量,命令行覆盖后即刻生效 ap = argparse.ArgumentParser() - ap.add_argument("--ip", default="192.168.1.100") + ap.add_argument("--ip", default=bench_defaults.DEVICE_IP) ap.add_argument("--port", type=int, default=21) ap.add_argument("--size", type=int, default=65536) ap.add_argument("--rounds", type=int, default=10) diff --git a/MDK-ARM/tcp_reconnect_probe.py b/MDK-ARM/tcp_reconnect_probe.py index 4a8fced5..4f45b2c3 100644 --- a/MDK-ARM/tcp_reconnect_probe.py +++ b/MDK-ARM/tcp_reconnect_probe.py @@ -11,7 +11,7 @@ # * on failure the probe keeps retrying for --recover-s to distinguish # "transient" from "permanently dead listener" # -# Usage: tcp_reconnect_probe.py [--host 192.168.1.100] [--port 21] [--rounds 50] +# Usage: tcp_reconnect_probe.py [--host <设备IP>] [--port 21] [--rounds 50] # [--gap-ms 600] [--timeout 3] [--recover-s 10] # [--banner] (read one line after connect, e.g. FTP 220) # Output: @@ -19,7 +19,14 @@ # ROUND gap= connect= recovered= # SUMMARY rounds= ok= fail= unrecovered= # Exit: 0 all rounds connected / 1 any failure / 2 usage -import argparse, socket, sys, time +import argparse, os, socket, sys, time + +# 台架连接默认值单一真源在 test/host/bench_defaults.py(跨目录:补 sys.path 后 import) +_sys_path = os.path.join(os.path.dirname(os.path.abspath(__file__)), + "..", "test", "host") +if _sys_path not in sys.path: + sys.path.insert(0, _sys_path) +import bench_defaults # noqa: E402 def log(m): sys.stdout.write(m + "\n"); sys.stdout.flush() @@ -36,7 +43,7 @@ def try_connect(host, port, timeout, banner): def main(): ap = argparse.ArgumentParser() - ap.add_argument("--host", default="192.168.1.100") + ap.add_argument("--host", default=bench_defaults.DEVICE_IP) ap.add_argument("--port", type=int, default=21) ap.add_argument("--rounds", type=int, default=50) ap.add_argument("--gap-ms", type=int, default=600) diff --git a/docs/产品需求/产品需求设计文档.md b/docs/产品需求/产品需求设计文档.md index 94f843bf..28e04408 100644 --- a/docs/产品需求/产品需求设计文档.md +++ b/docs/产品需求/产品需求设计文档.md @@ -1276,18 +1276,18 @@ for (i = 1; i < LED_COUNT; i++) /* LE ; DTU 通用配置文件 [network] ; IP 地址 -ip=192.168.1.100 +ip=192.168.31.100 ; 子网掩码 mask=255.255.255.0 ; 默认网关 -gateway=192.168.1.1 +gateway=192.168.31.1 ; MAC 地址 (全零 = 使用芯片内置 MAC) mac=00:00:00:00:00:00 ``` **值类型**:`IP4`(`a.b.c.d`)、`MAC`(`aa:bb:cc:dd:ee:ff`)、`UINT`(十进制,兼容 `0x`)、`STR`(≤31 字符)。 -**工厂默认**:IP `192.168.1.100` / 掩码 `255.255.255.0` / 网关 `192.168.1.1` / MAC 全零(= 芯片内置)。 +**工厂默认**:IP `192.168.31.100` / 掩码 `255.255.255.0` / 网关 `192.168.31.1` / MAC 全零(= 芯片内置)。 > MAC 全零是"使用芯片内置 MAC"的**哨兵**,不是"MAC 为 0"。恢复出厂:FTP `DELE /config.ini` → 下次上电重新生成模板。 diff --git a/docs/子系统设计/网络配置说明.md b/docs/子系统设计/网络配置说明.md index 69f68d9f..375d7173 100644 --- a/docs/子系统设计/网络配置说明.md +++ b/docs/子系统设计/网络配置说明.md @@ -15,7 +15,7 @@ | **入口** | 屏幕:`通讯参数 → 网口设置`(修改密码 `123` 可编辑;查看密码 `000` 只读) | | **存储** | NAND Flash 文件 `/config.ini`(INI `[network]` 段,通用配置文件,掉电不丢);旧版 `/cfg/netcfg.bin` **不再读取**(存在则忽略,见 §3.2) | | **生效** | 按「保存」后**立即生效**(网络重建约 1~3s,既有 TCP 连接会断开,无需重启) | -| **工厂默认** | `192.168.1.100` / `255.255.255.0` / `192.168.1.1` / 芯片内置 MAC | +| **工厂默认** | `192.168.31.100` / `255.255.255.0` / `192.168.31.1` / 芯片内置 MAC | **典型操作(改 IP)**: @@ -32,9 +32,9 @@ | 参数 | 字段 | 工厂默认 | 说明 | |---|---|---|---| -| IP 地址 | `ip[4]` | **192.168.1.100** | 静态 IP(不启用 DHCP) | +| IP 地址 | `ip[4]` | **192.168.31.100** | 静态 IP(不启用 DHCP) | | 子网掩码 | `mask[4]` | **255.255.255.0** | /24 | -| 默认网关 | `gw[4]` | **192.168.1.1** | | +| 默认网关 | `gw[4]` | **192.168.31.1** | | | MAC 地址 | `mac[6]` | **全零** | 全零 = 不覆盖芯片内置 MAC(见 §2) | 工厂默认值是**单一来源**:`net_cfg.c` 顶部 `NET_CFG_DEF_*` 宏,同时用于 `s_cfg` 静态初始化与 `s_defaults`(引擎注册的 `p_defaults` 目标),避免两处漂移。 @@ -71,9 +71,9 @@ ; ============================================================ [network] -ip=192.168.1.100 +ip=192.168.31.100 mask=255.255.255.0 -gw=192.168.1.1 +gw=192.168.31.1 mac=00:00:00:00:00:00 ``` @@ -96,7 +96,7 @@ mac=00:00:00:00:00:00 | 存在 | — | 正常加载现有文件 | - **删除理由**:该一次性路径把整条配置**写**链(`net_cfg_save → cfg_file_save → cfg_store_write_atomic → f_rename → FatFS → dhara FTL`)无条件挂进启动期调用图,使 defaultTask 的 armlink 静态最坏栈链 **+600 B**;而本仓库不存在携带旧档的设备。 -- **对使用方的影响**:卷上仍残留旧档的设备升级本版本后,网口配置**回落工厂默认**(`192.168.1.100/24`、gw `.1`),需经 UI「网口设置」或 FTP 上传 `/config.ini` 重新配置。 +- **对使用方的影响**:卷上仍残留旧档的设备升级本版本后,网口配置**回落工厂默认**(`192.168.31.100/24`、gw `.1`),需经 UI「网口设置」或 FTP 上传 `/config.ini` 重新配置。 ### 3.3 存储后端(双端) diff --git a/docs/子系统设计/配置文件设计说明.md b/docs/子系统设计/配置文件设计说明.md index 766f9b78..fc7d7561 100644 --- a/docs/子系统设计/配置文件设计说明.md +++ b/docs/子系统设计/配置文件设计说明.md @@ -104,11 +104,11 @@ [network] ; IP 地址 -ip=192.168.1.100 +ip=192.168.31.100 ; 子网掩码 mask=255.255.255.0 ; 默认网关 -gateway=192.168.1.1 +gateway=192.168.31.1 ; MAC 地址 (全零 = 使用芯片内置 MAC) mac=00:00:00:00:00:00 ``` @@ -117,7 +117,7 @@ mac=00:00:00:00:00:00 | 类型 | 语法 | 示例 | 解析失败处理 | |---|---|---|---| -| `CFG_VAL_IP4` | `a.b.c.d`(兼容前导零) | `192.168.1.100` | 该键取工厂默认 + `DBG_ERROR` | +| `CFG_VAL_IP4` | `a.b.c.d`(兼容前导零) | `192.168.31.100` | 该键取工厂默认 + `DBG_ERROR` | | `CFG_VAL_MAC` | `aa:bb:cc:dd:ee:ff`(十六进制) | `a4:94:b6:12:34:56` | 同上 | | `CFG_VAL_UINT` | 十进制(兼容 `0x` 前缀) | `7003` | 同上 | | `CFG_VAL_STR` | 原始字符串(≤31 字符) | `hello` | 同上 | diff --git a/docs/测试说明/专项验证/ADC前端注入验证流程.md b/docs/测试说明/专项验证/ADC前端注入验证流程.md index dee536c1..d5373f58 100644 --- a/docs/测试说明/专项验证/ADC前端注入验证流程.md +++ b/docs/测试说明/专项验证/ADC前端注入验证流程.md @@ -330,7 +330,7 @@ TPAFE 是双极性、二进制补码,可以注负压;STM32 是单极性, | 板子 | 产品构建(`test/board/test_config.h` 四个 `TEST_SUITE_*` 全注释)+ `/keil-build` 0 错误 0 警告 + 烧录 `-Rst -Run` 与回读校验 | → `stlink-flash` skill 与 AGENTS.md「构建与验证」 | | `[adc_cal]` 状态 | **保持未标定**(`eng=0`),别为"读数好看"先写标定值 | 现在 `meas:` / `phasor` 的量纲是 **ADC 引脚电压 V**(`App/algo/meas.h` 文件头的 A-lite 口径);标定一生效就换成二次值,本节全部期望值作废 | | 串口 | 全程抓 RX 落盘:用 `serial-assistant` skill(`open` → `clear` → 跑 → 读日志文件或 `log --tail`) | 日志文件就是证据本体,§8.10 归档归档的就是它;**长跑别用 `/serial-boot-test`**——它绑定一轮启动语义(静默 8 s、总超时 30 s、`max_boot_count` = 1,且 forbidden 含 `[ERR]`,而削顶轮故意造 `[ERR]`),约 135 min 的 session 必然超时或误判;daemon 全量写 `state/serial.log`(20 MB 上限自动截头保尾 10 MB)→ `docs/测试说明/流程与规范/自动化测试流程.md` 长时间采集一节 | -| 网口(可选) | 要读 104 那一路就插网线、PC 与板同网段(出厂 192.168.1.100),跑现成主站 `test/host/iec104_master.py`(`--ip` / `--port` / `--addr`) | 104 是浮点无量化 + 带品质,是 `meas:` 之外的第二条腿 | +| 网口(可选) | 要读 104 那一路就插网线、PC 与板同网段(出厂 192.168.31.100),跑现成主站 `test/host/iec104_master.py`(`--ip` / `--port` / `--addr`) | 104 是浮点无量化 + 带品质,是 `meas:` 之外的第二条腿 | | FTP 客户端 | 走现成 21 端口取段文件(出厂 `[ftp]` 账号,连续 5 次失败锁 60 s) | 段文件是相位 / 谐波轮定量档的样本出口;段文件名 `/wave/WAVE.BIN`(00~99 轮转),**取完立刻改名归档**,否则下一次触发把它盖掉 | | 录波触发路径 | 产品构建里唯一**免改代码**的路径 = UI 菜单第 26 叶「手动录波」确认页(`Drivers/BSP/UI/ui_page_wave_manual.c` → `App/task/ui_task.c:605`) | 保护启动上升沿也算一次触发,但保护判据现处**未标定闭锁**态(AGENTS.md「现状」),别指望它自动来段;bench 定时自抓在双层编译门 `DTU_BENCH` 且 `WAVE_BENCH_AUTOCAP` 非 0 之内(默认 0,`App/task/adc_task.c:153`),开它就走 §8.9 的还原判据 | | 共地 | 发生器 LO/GND 与板 AGND **单点**相连 | 不共地量到的是两地之差;现象见 §8.8 | diff --git a/docs/测试说明/专项验证/故障录波板级到场轮执行手册.md b/docs/测试说明/专项验证/故障录波板级到场轮执行手册.md index 68ca142c..0022abb8 100644 --- a/docs/测试说明/专项验证/故障录波板级到场轮执行手册.md +++ b/docs/测试说明/专项验证/故障录波板级到场轮执行手册.md @@ -29,7 +29,7 @@ flowchart LR ## 2. 到场检查清单(人到板边,打开这份清单逐条打勾) -- [ ] 板上电、网灯亮:会话里让 agent 跑 `ping 192.168.1.100`——通了就行(这台装置一直在线,串口 COM3、网线、ST-LINK 都常年插在这台电脑上,正常**都不用动**) +- [ ] 板上电、网灯亮:会话里让 agent 跑 `ping 192.168.31.100`——通了就行(这台装置一直在线,串口 COM3、网线、ST-LINK 都常年插在这台电脑上,正常**都不用动**) - [ ] 信号发生器:和 2026-10-27 那次已知电压注入用的**是同一台**(波形档正弦、幅值 rms 直读;接线与端子位置照 `docs/测试说明/专项验证/ADC前端注入验证流程.md` §8.3 那四条,本文不重抄) - [ ] 万用表一块(并接监视 UA 端子,接线照上一条引的那四条) - [ ] 打开这个仓库的 agent 会话,对它说一句:**"按故障录波到场轮手册,先做第 X 幕"**——后面每步它自己跑,该你出手时它会说"到你接线了" diff --git a/docs/测试说明/专项验证/链路延迟测试说明.md b/docs/测试说明/专项验证/链路延迟测试说明.md index b23bea93..98aa38e4 100644 --- a/docs/测试说明/专项验证/链路延迟测试说明.md +++ b/docs/测试说明/专项验证/链路延迟测试说明.md @@ -258,7 +258,7 @@ DTU-RemoteLCD 客户端;输出每帧 `req2first / total / recv 批次到达时 & '.venv\Scripts\python.exe' .dsh\skills\keil-build\scripts\keil_build.py # 必须 0 错 0 警 # 1) 先 clear 再起 peer(顺序不可反:wait-idle 需要看到会话活跃期) & '.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 ` +& '.venv\Scripts\python.exe' test\host\latency_peer.py --host 192.168.31.100 --port 8080 ` --json "docs\测试说明\测试数据\m2_data\m2_quiet.json" --wait 170 # 后台作业 # 2) 烧录(Reset&Run 不可省) & '.venv\Scripts\python.exe' .dsh\skills\stlink-flash\scripts\stlink_flash.py flash @@ -284,16 +284,16 @@ DTU-RemoteLCD 客户端;输出每帧 `req2first / total / recv 批次到达时 & '.venv\Scripts\python.exe' .dsh\skills\keil-build\scripts\keil_build.py # 0 错 0 警(Phase 14 构建) & '.venv\Scripts\python.exe' .dsh\skills\serial-assistant\scripts\serial_tool.py clear & '.venv\Scripts\python.exe' .dsh\skills\stlink-flash\scripts\stlink_flash.py flash # 先烧录,再起 peer(顺序不可反!) -& '.venv\Scripts\python.exe' test\latency_peer.py --mode remo --host 192.168.1.100 --port 7003 ` +& '.venv\Scripts\python.exe' test\host\latency_peer.py --mode remo --host 192.168.31.100 --port 7003 ` --samples 45 --stress-from 15 --ftp-stress --json "docs\测试说明\测试数据\m3_data\m3_dev_stress.json" # 模拟器基线(Δ 的对照端) & "simulator\build_sim.bat"; .\simulator\build\Debug\lvgl_sim.exe # 等 7003 就绪 -& '.venv\Scripts\python.exe' test\latency_peer.py --mode remo --host 127.0.0.1 --port 7003 ` +& '.venv\Scripts\python.exe' test\host\latency_peer.py --mode remo --host 127.0.0.1 --port 7003 ` --samples 50 --json "docs\测试说明\测试数据\m3_data\m3_sim_quiet.json" # 尾批定性/解法(都不需要抓包工具) -& '.venv\Scripts\python.exe' test\latency_peer.py --mode remo --host 192.168.1.100 --port 7003 ` +& '.venv\Scripts\python.exe' test\host\latency_peer.py --mode remo --host 192.168.31.100 --port 7003 ` --samples 30 --ack-probe --json "docs\测试说明\测试数据\m3_data\m3_tail_ackprobe.json" # 带内补 ACK -& '.venv\Scripts\python.exe' test\latency_peer.py --mode remo --host 192.168.1.100 --port 7003 ` +& '.venv\Scripts\python.exe' test\host\latency_peer.py --mode remo --host 192.168.31.100 --port 7003 ` --samples 30 --ack-fast --json "docs\测试说明\测试数据\m3_data\m3_tail_ackfast.json" # 关延迟 ACK ``` diff --git a/docs/测试说明/单元测试/主机单测覆盖率口径.md b/docs/测试说明/单元测试/主机单测覆盖率口径.md index 37b75350..19c6c709 100644 --- a/docs/测试说明/单元测试/主机单测覆盖率口径.md +++ b/docs/测试说明/单元测试/主机单测覆盖率口径.md @@ -249,7 +249,7 @@ |---|---|---|---|---|---| | **FTP 一套** | `lftpd.c`(694)、`lftpd_io.c`(207)、`lftpd_inet.c`(171)、`lftpd_string.c`(11) = 1,083 | 0.99/0.90/0.93 | 真实 `ff.h` + 假 diskio;复用 `net_socket.h` | `docs/测试说明/板级测试/FTP_Test_Guide.md`、`docs/子系统设计/网络配置说明.md` §3.4(`pwd_hash`=SHA-256(user‖password)、连续 5 次失败锁 60 s、默认口令启动告警) | **20 次提交里 6 次是 fix**,最近两条都是"静默型":LIST/NLST 满块被截断回 550、对端行为误打 `[ERR]`(2026-10-23)——覆盖率最擅长照的就是这类"日志看不出根因" | | **NET 拆出来的四块** | `net_pending.c`(287)、`net_events.c`(263)、`net_listener.c`(191)、`net_select.c`(162) = 903 | 0.90/0.78/–/0.93 | **新建 `stub/ch395f.h`**(芯片寄存器只到函数边界)+ 假任务通知;`net_socket.h` 已有 | `docs/网络/网络自愈架构设计.md` §4.10(socket 读清点审计 + 新增一处读清的三条准入判据)、`docs/网络/Net层阻塞模型架构设计.md` | 挂起 recv、监听按代次重建、退避这些**语义在真机上极难复现**;这一族的 网络自愈("顺手全量清一遍把别的 socket 门焊死")与 N34 E14 都是 fix 出来的真事 | -| **配置与工具(最便宜,建议第一个落地)** | `net_cfg.c`(167)、`task_prof.c`(160)、`ftp_cfg.c`(59)、`prot_set_store.c`(43) = 429 | 1.00/0.97/–/– | 真实头即可(`cfg_file.h` 已被现有单测证明能在 PC 上编),最多补 `dbg_log.h` | `docs/子系统设计/网络配置说明.md`(工厂默认 192.168.1.100/24、MAC 全零=芯片内置、保存立即生效)、`docs/算法/采集与算法层设计说明.md` | 硬件符号 0~2 处,纯解析/编解码/格式化。**一天内能出第一份绿**,用来把"新增 `files_tested`"这条路先跑通 | +| **配置与工具(最便宜,建议第一个落地)** | `net_cfg.c`(167)、`task_prof.c`(160)、`ftp_cfg.c`(59)、`prot_set_store.c`(43) = 429 | 1.00/0.97/–/– | 真实头即可(`cfg_file.h` 已被现有单测证明能在 PC 上编),最多补 `dbg_log.h` | `docs/子系统设计/网络配置说明.md`(工厂默认 192.168.31.100/24、MAC 全零=芯片内置、保存立即生效)、`docs/算法/采集与算法层设计说明.md` | 硬件符号 0~2 处,纯解析/编解码/格式化。**一天内能出第一份绿**,用来把"新增 `files_tested`"这条路先跑通 | | **104 服务层** | `iec104_serv.c`(202) | 0.96 | 复用 `time_sync`/stub 的 `cmsis_os2.h` + 已有 `net_socket.h` | 与 `test/host/iec104/`(97 用例)同一套脚手架 | 同族的 `iec104_pts.c` 现在只有 **67.2%**(全仓最低之一);服务层进来才能把 YK/YX 编排的分支照全 | **落地进度(2026-10-23,同日推进)**: diff --git a/docs/测试说明/板级测试/CH395F_Test_Guide.md b/docs/测试说明/板级测试/CH395F_Test_Guide.md index a817d260..dbac5280 100644 --- a/docs/测试说明/板级测试/CH395F_Test_Guide.md +++ b/docs/测试说明/板级测试/CH395F_Test_Guide.md @@ -74,7 +74,7 @@ UDP 路径 `net_socket()` 中对 Socket 4~7 的兜底重设使用同一布局。 ### 测试环境 ``` -PC (192.168.1.2) ──── 交换机 ──── CH395F (192.168.1.100) +PC (192.168.31.2) ──── 交换机 ──── CH395F (192.168.31.100) MCU: STM32F407ZGTx @ 168MHz, Keil MDK-ARM v5 (ARMCC) ``` @@ -120,8 +120,8 @@ MCU: STM32F407ZGTx @ 168MHz, Keil MDK-ARM v5 (ARMCC) |----|------|----------|----------| | 1 | `ch395f_check_exist()`
SPI写: CMD=0x06, DATA=0x57
回读: ~0x57 = 0xA8 | 返回 `0x00`(`CH395F_ERR_SUCCESS`)
= 回读字节 `0xA8` 匹配 `~0x57` | 返回 `0xFF`(`CH395F_STATUS_NOT_DETECTED`)
= 回读字节 ≠ `0xA8`,回显取反不匹配 | | 2 | `ch395f_get_version()` | 版本值 == `0x4A`(CH395F 芯片版本) | 版本值 ≠ `0x4A`(芯片不匹配或未响应) | -| 3 | `ch395f_set_ip_addr(192.168.1.100)` → `ch395f_get_ip_inf()` 回读 IP | `ip_info[0..3] == 192.168.1.100` | 任意字节不匹配(写入/回读不一致) | -| 4 | `ch395f_set_gwip_addr(192.168.1.1)` → `ch395f_get_ip_inf()` 回读 GW | `ip_info[4..7] == 192.168.1.1` | 任意字节不匹配 | +| 3 | `ch395f_set_ip_addr(192.168.31.100)` → `ch395f_get_ip_inf()` 回读 IP | `ip_info[0..3] == 192.168.31.100` | 任意字节不匹配(写入/回读不一致) | +| 4 | `ch395f_set_gwip_addr(192.168.31.1)` → `ch395f_get_ip_inf()` 回读 GW | `ip_info[4..7] == 192.168.31.1` | 任意字节不匹配 | | 5 | `ch395f_set_mask_addr(255.255.255.0)` → `ch395f_get_ip_inf()` 回读 MASK | `ip_info[8..11] == 255.255.255.0` | 任意字节不匹配 | | 6 | `ch395f_get_glob_int_status_all()`(16 位)
注:测试入口处已预读一次清除 `PHY_CHANGE` 残留(`net_stack_bring_up()` 强制 PHY 重协商 + 等待链路期间锁存,硬件层模式无 netTask 消费) | 返回值 == `0x0000`(无待处理中断) | 返回值 ≠ `0x0000`(有残留中断未清除) | | 7 | `ch395f_open_socket(0)` → `ch395f_close_socket(0)` → `ch395f_get_cmd_status()` | `CMD_STATUS == 0x00`(`CH395F_ERR_SUCCESS`) | `CMD_STATUS` 非 `0x00`(Socket 操作失败) | @@ -161,7 +161,7 @@ MCU: STM32F407ZGTx @ 168MHz, Keil MDK-ARM v5 (ARMCC) | 步 | 操作 | 成功标准 | 失败标准 | |----|------|----------|----------| -| 1 | `ch395f_set_proto_type(0, CH395F_PROTO_TYPE_TCP)` + 设置目标 IP `192.168.1.2`、端口 `8081`、本地端口 `50000` | 配置写入成功(CMD_STATUS == `0x00`) | 配置失败(SPI 异常或寄存器未更新) | +| 1 | `ch395f_set_proto_type(0, CH395F_PROTO_TYPE_TCP)` + 设置目标 IP `192.168.31.2`、端口 `8081`、本地端口 `50000` | 配置写入成功(CMD_STATUS == `0x00`) | 配置失败(SPI 异常或寄存器未更新) | | 2 | `ch395f_open_socket(0)` 打开 Socket 0 | 返回 `CH395F_ERR_SUCCESS`(`0x00`) | 返回值非 `0x00`(Socket 硬件异常或 SPI 通信失败) | | 3 | `ch395f_tcp_connect(0)` 发起 TCP 连接 | 返回 `CH395F_ERR_SUCCESS`(`0x00`) | 返回值非 `0x00`(连接命令下发失败) | | 4 | 轮询 `GET_GLOB_INT_STATUS` 的 `(sock+4)` 位 + `SINT_STAT` 等待 `CH395F_SINT_STAT_CONNECT`,超时 10s | 检测到 CONNECT 中断(连接已建立,进入 ESTABLISHED) | 超时未建立连接(目标不可达 / 链路异常) | @@ -210,13 +210,13 @@ MCU: STM32F407ZGTx @ 168MHz, Keil MDK-ARM v5 (ARMCC) | **优先级** | P1 | | **类型** | 负向测试(硬件层) | | **标题** | 目标端口无服务时连接超时 | -| **前置条件** | 1. PC **未**运行 TCP Server(`192.168.1.2:8081` 无监听)
2. TC-NET-201 通过 | +| **前置条件** | 1. PC **未**运行 TCP Server(`192.168.31.2:8081` 无监听)
2. TC-NET-201 通过 | **测试步骤与判定标准**: | 步 | 操作 | 成功标准 | 失败标准 | |----|------|----------|----------| -| 1 | `ch395f_set_proto_type(0, CH395F_PROTO_TYPE_TCP)` + 设置目标 IP `192.168.1.2`、端口 `8081` | 配置写入成功(CMD_STATUS == `0x00`) | 配置失败(SPI 异常或寄存器未更新) | +| 1 | `ch395f_set_proto_type(0, CH395F_PROTO_TYPE_TCP)` + 设置目标 IP `192.168.31.2`、端口 `8081` | 配置写入成功(CMD_STATUS == `0x00`) | 配置失败(SPI 异常或寄存器未更新) | | 2 | `ch395f_open_socket(0)` → `ch395f_tcp_connect(0)` | OPEN / CONNECT 均返回 `CH395F_ERR_SUCCESS`(`0x00`),命令异步下发不立即报错 | 命令返回值非 `0x00`(Socket 硬件异常) | | 3 | 轮询 `GET_GLOB_INT_STATUS` 的 `(sock+4)` 位,等待负向结果,超时窗 30s;同时扫全局 `UNREACH` 位作备注 | 收到 `SOCK_TIMEOUT` 或 `DISCONNECT`,且期间未收到 `CH395F_SINT_STAT_CONNECT`。按耗时细分:
**<3s** = RST 快速拒绝(端口关闭,实测主路径——芯片毫秒级上报 SOCK_TIMEOUT)
**≥3s** = 真无应答(离线/防火墙丢包)。全局 `UNREACH`(ARP 失败)仅备注不影响判定 | 误收到 `CONNECT`(PC 服务未关闭,环境错误——串口给出明确指引)或 30s 内无任何中断(状态机挂死) | | 4 | `ch395f_close_socket(0)` 并轮询 `GET_SOCKET_STATUS` 等待 `CH395F_SOCKET_CLOSED` | Socket 正常关闭、系统无崩溃 / 死锁 | 关闭异常或任务挂死 | @@ -277,7 +277,7 @@ MCU: STM32F407ZGTx @ 168MHz, Keil MDK-ARM v5 (ARMCC) | **优先级** | P0 | | **类型** | 功能测试(硬件层) | | **标题** | 30 轮 64B UDP 数据报回显 | -| **前置条件** | PC: `python test/host/ch395f_socket_test.py udp_client --ip 192.168.1.100 --port 60000` | +| **前置条件** | PC: `python test/host/ch395f_socket_test.py udp_client --ip 192.168.31.100 --port 60000` | > **会话结构**(固件单会话,与 udp_client 脚本约定):累计 **60 个有效数据包**后关闭 Socket——第 1~30 轮对应本用例(PC 发 64B),第 31~60 轮对应 TC-NET-302(变长);脚本 `"HELLO"` 就绪探针只回显、**不计数**,不占用用例预算。 @@ -341,7 +341,7 @@ CH395F PC (dhcp_server) - **xid/chaddr 回填**:OFFER/ACK 必须原样回传 DISCOVER 的 `xid([4:8])` 与 `chaddr([28:34])`(TRAP-NET-03:早期 xid 偏移错误导致芯片丢弃响应) - **option53 位置**:报文类型在 `data[242]`(236B 固定头 + magic `63825363` + option 偏移),`len<=250` 视为无效包 -- **双广播发送**:OFFER/ACK 同时发 `255.255.255.255` 与 `192.168.1.255`(规避 Windows 定向广播路由限制) +- **双广播发送**:OFFER/ACK 同时发 `255.255.255.255` 与 `192.168.31.255`(规避 Windows 定向广播路由限制) - **REQUEST 重试**:PC 最多等 8×5s;期间收到重复 DISCOVER 则重发 OFFER **固件会话结构**(phase4_run): @@ -364,7 +364,7 @@ CH395F PC (dhcp_server) | **优先级** | P0 | | **类型** | 功能测试(硬件层) | | **标题** | DISCOVER → OFFER → REQUEST → ACK 全流程获取 IP | -| **前置条件** | 管理员 PowerShell: `python test/host/ch395f_socket_test.py dhcp_server --ip 192.168.1.77 --dhcp-iface 192.168.1.2`(`--ip` 建议 ≠ 静态 IP,以证明确为动态获取) | +| **前置条件** | 管理员 PowerShell: `python test/host/ch395f_socket_test.py dhcp_server --ip 192.168.31.77 --dhcp-iface 192.168.31.2`(`--ip` 建议 ≠ 静态 IP,以证明确为动态获取) | **测试步骤与判定标准**: @@ -551,7 +551,7 @@ MCU (TCP Client, ch395f_* 裸命令) PC (tcp_bulk --port 8081) ```mermaid flowchart LR - PC["PC(Python)
tcp_client / tcp_server"] -->|"TCP 8080 · 以太网"| CH["CH395F(192.168.1.100)
Socket 0(单连接复用)"] + PC["PC(Python)
tcp_client / tcp_server"] -->|"TCP 8080 · 以太网"| CH["CH395F(192.168.31.100)
Socket 0(单连接复用)"] CH -->|"SPI2(分频=8)"| MCU["MCU(STM32F407)
netTask: net_poll() 10ms
testTask: net_layer_test_main()
└─ phase6_run() 原样回显"] ``` @@ -593,7 +593,7 @@ sequenceDiagram | **优先级** | P0 | | **类型** | 功能测试 | | **标题** | Socket 0:OPEN → TCP_LISTEN → ESTABLISHED(单连接) | -| **前置条件** | 1. `net_init("192.168.1.100")` 成功、SYS_EVT_NET_READY 已广播(netTask 周期 `net_poll()` 运行)
2. `net_layer_test_main()` 已 `net_socket`+`net_bind(8080)`+`net_listen`(进入 LISTEN)
3. PC: `python .\test\ch395f_socket_test.py tcp_client --ip 192.168.1.100 --port 8080` | +| **前置条件** | 1. `net_init("192.168.31.100")` 成功、SYS_EVT_NET_READY 已广播(netTask 周期 `net_poll()` 运行)
2. `net_layer_test_main()` 已 `net_socket`+`net_bind(8080)`+`net_listen`(进入 LISTEN)
3. PC: `python .\test\ch395f_socket_test.py tcp_client --ip 192.168.31.100 --port 8080` | **测试步骤与判定标准**: @@ -751,7 +751,7 @@ net_socket(NET_AF_INET, NET_SOCK_STREAM) // 取空闲 Socket(非监听 So ```mermaid flowchart LR - MCU["MCU(STM32F407)
netTask: net_poll() 10ms
testTask: net_layer_client_test_main()
└─ net_connect → 收发 → close"] -->|"SPI2(分频=8)"| CH["CH395F(192.168.1.100)
Socket N(非 0 空闲)"] + MCU["MCU(STM32F407)
netTask: net_poll() 10ms
testTask: net_layer_client_test_main()
└─ net_connect → 收发 → close"] -->|"SPI2(分频=8)"| CH["CH395F(192.168.31.100)
Socket N(非 0 空闲)"] CH -->|"TCP 8081 · 以太网"| PC["PC(Python)
tcp_server(回显服务器)"] ``` @@ -796,7 +796,7 @@ sequenceDiagram | 步 | 操作 | 成功标准 | 失败标准 | |----|------|----------|----------| | 1 | `net_socket(NET_AF_INET, NET_SOCK_STREAM)` 创建 TCP socket | 返回 sockfd(`0~7`),非 `-1` | 返回 `-1`(无空闲 Socket 或 net 层未初始化) | -| 2 | 构造 `struct net_sockaddr_in`(sin_family=`NET_AF_INET`,sin_port=`net_htons(8081)`,sin_addr=`net_inet_addr("192.168.1.2")`)后 `net_connect(sockfd, &addr, len)` | 返回 `0`(连接命令已异步下发) | 返回 `-1`(地址非法或协议栈异常) | +| 2 | 构造 `struct net_sockaddr_in`(sin_family=`NET_AF_INET`,sin_port=`net_htons(8081)`,sin_addr=`net_inet_addr("192.168.31.2")`)后 `net_connect(sockfd, &addr, len)` | 返回 `0`(连接命令已异步下发) | 返回 `-1`(地址非法或协议栈异常) | | 3 | 在 netTask 周期 `net_poll()` 推进下,调用 `net_select(sockfd+1, NULL, &wfds, NULL, &tv)` 等待可写事件,超时 10s | 返回正数且 `NET_FD_ISSET(sockfd)` 指示连接建立(ESTABLISHED) | 超时未连接,`net_errno == NET_ERR_WOULDBLOCK` 持续 | | 4 | `net_send(sockfd, buf, 64, 0)` 发送 64 字节递增模式数据(`0x00..0x3F`) | 返回值 == `64`(全部发出) | 返回值 `< 0`(发送失败)或 `≠ 64`(未完全发出) | | 5 | `net_recv(sockfd, buf, 64, 0)` 阻塞接收回显,超时 10s | 返回值 == `64`、与原数据逐字节一致、且固件字节级比对 + 累加和 `TEST_CHECK` 通过 | 返回值 `< 0`(超时/断开)或 `≠ 64`(数据不完整)或任意字节不符 或 固件 `TEST_CHECK` 失败 | @@ -837,7 +837,7 @@ sequenceDiagram | **优先级** | P1 | | **类型** | 负向测试(NET 层) | | **标题** | 目标端口无服务时 net_connect 超时 | -| **前置条件** | 1. PC **未**运行 TCP Server(`192.168.1.2:8081` 无监听)
2. TC-NET-701 通过 | +| **前置条件** | 1. PC **未**运行 TCP Server(`192.168.31.2:8081` 无监听)
2. TC-NET-701 通过 | **测试步骤与判定标准**: @@ -867,7 +867,7 @@ sequenceDiagram | 步 | 操作 | 成功标准 | 失败标准 | |----|------|----------|----------| -| 1 | 循环 i=0..4:`net_socket()` 创建 5 个 TCP socket(本地端口 51000+i),`net_connect(192.168.1.2:8081)` | 5 个 `net_connect` 均返回 `0` | 任一返回 `-1` | +| 1 | 循环 i=0..4:`net_socket()` 创建 5 个 TCP socket(本地端口 51000+i),`net_connect(192.168.31.2:8081)` | 5 个 `net_connect` 均返回 `0` | 任一返回 `-1` | | 2 | netTask `net_poll()` 推进下,`net_select` 等待全部 5 路可写 | 5 路均在 10s 内 ESTABLISHED | 任一超时未建立 | | 3 | 每路 `net_send(sockfd, 64B)` → `net_recv(sockfd, 64B)` 校验 | 5 路收发各 64B、字节级比对 + 累加和 `TEST_CHECK` 通过 | 任一收发失败 / 数据不符 / `TEST_CHECK` 失败 | @@ -889,7 +889,7 @@ sequenceDiagram | **耗时** | 取决于文件大小与速率(100KB 约数秒) | | **入口** | `ENABLE_PHASE8_TESTS` | | **配置** | `PHASE8_FILE_SIZE`(默认 102400 = 100KB);`PHASE8_DIRECTION`(SEND / RECV / ECHO,默认 ECHO) | -| **PC 配合** | `python ./test/host/ch395f_socket_test.py tcp_file --ip 192.168.1.100 --port 8080 --op recv --file rx_100k.bin --size 102400`(文件发送)
`... --op send --file tx_100k.bin --size 102400`(文件接收) | +| **PC 配合** | `python ./test/host/ch395f_socket_test.py tcp_file --ip 192.168.31.100 --port 8080 --op recv --file rx_100k.bin --size 102400`(文件发送)
`... --op send --file tx_100k.bin --size 102400`(文件接收) | > 架构:MCU 为 TCP Server(`net_test_task` 监听 8080,`net_accept` 后 `phase8_run(acc)`);PC 用 `tcp_file` 子命令作 Client 连接 MCU:8080。一次 `phase8_run` 对应一次 PC 连接。 @@ -912,7 +912,7 @@ sequenceDiagram | **优先级** | P0 | | **类型** | 功能测试(文件发送) | | **标题** | MCU 流式发送 100KB 至 PC 并落盘校验 | -| **前置条件** | 1. PC: `python ./test/host/ch395f_socket_test.py tcp_file --ip 192.168.1.100 --port 8080 --op recv --file rx_100k.bin --size 102400`(先连接等待数据)
2. `ENABLE_PHASE8_TESTS`,`PHASE8_FILE_SIZE=102400`,`PHASE8_DIRECTION=SEND`
3. `net_init` 完成,MSS=1024 | +| **前置条件** | 1. PC: `python ./test/host/ch395f_socket_test.py tcp_file --ip 192.168.31.100 --port 8080 --op recv --file rx_100k.bin --size 102400`(先连接等待数据)
2. `ENABLE_PHASE8_TESTS`,`PHASE8_FILE_SIZE=102400`,`PHASE8_DIRECTION=SEND`
3. `net_init` 完成,MSS=1024 | | **测试步骤** | 1. MCU `net_accept` 建链(PC 已连接)
2. 循环填充一个滑动窗口(≤ s_tx_buf)并调用 `net_send`;`net_send` 内部按硬件发送 FIFO(`NET_SEND_CHUNK_MAX`=1KB,见 TRAP-NET-16)自动拆分写入,直至 100KB 发完
3. PC 接收全部字节写入 `rx_100k.bin`,按递增模式或预置 CRC32 校验 | | **通过标准** | PC 收满 102400B 且逐字节/CRC32 校验一致,MCU 无发送错误 | | **覆盖原则** | DMA 边界安全(分块发送、DMA 边界)、缓冲架构(1KB 发送缓冲) | @@ -926,7 +926,7 @@ sequenceDiagram | **优先级** | P0 | | **类型** | 功能测试(文件接收) | | **标题** | PC 流式发送 100KB 文件,MCU 接收并校验 | -| **前置条件** | 1. PC: `python ./test/host/ch395f_socket_test.py tcp_file --ip 192.168.1.100 --port 8080 --op send --file tx_100k.bin --size 102400`(先连接并发送;无文件则生成 100KB 递增模式)
2. 同 TC-NET-801(`PHASE8_DIRECTION=RECV`) | +| **前置条件** | 1. PC: `python ./test/host/ch395f_socket_test.py tcp_file --ip 192.168.31.100 --port 8080 --op send --file tx_100k.bin --size 102400`(先连接并发送;无文件则生成 100KB 递增模式)
2. 同 TC-NET-801(`PHASE8_DIRECTION=RECV`) | | **测试步骤** | 1. MCU `net_accept` 建链(PC 已连接)
2. 循环 `net_recv`(≤2KB/次,保守一次读空)→ 按 offset 字节校验 + 累计 CRC32,直至收满 100KB
3. PC 在文件末尾附 4 字节 CRC32(小端);MCU 收齐后比对 CRC32 | | **通过标准** | MCU 收满 102400B,字节校验全过且 CRC32 匹配,无溢出/截断 | | **覆盖原则** | DMA 边界安全(接收缓冲 2KB 一次读空) | @@ -940,7 +940,7 @@ sequenceDiagram | **优先级** | P1 | | **类型** | 恢复/压力测试 | | **标题** | MCU 发 100KB 经 PC 回显原样返回,MCU 收齐校验 | -| **前置条件** | MCU: `PHASE8_DIRECTION=ECHO`(net_accept 监听 8080);PC: `python ./test/host/ch395f_socket_test.py tcp_file --ip 192.168.1.100 --port 8080 --op echo`(PC 作 Client 连 MCU 并原样回显) | +| **前置条件** | MCU: `PHASE8_DIRECTION=ECHO`(net_accept 监听 8080);PC: `python ./test/host/ch395f_socket_test.py tcp_file --ip 192.168.31.100 --port 8080 --op echo`(PC 作 Client 连 MCU 并原样回显) | | **测试步骤** | MCU 发 100KB → PC 回显 → MCU 收 100KB 字节校验 | | **通过标准** | 100KB 全过,验证 100KB 经回显链路完整 | | **覆盖原则** | 单连接 socket、DMA 边界安全 | @@ -1140,7 +1140,7 @@ WAIT_CLOSE 阶段已内置二段补发(只补一次),生产 net 层则靠 | 参数 | 默认值 | 说明 | |------|--------|------| -| `--ip` | 192.168.1.100 | 目标 IP | +| `--ip` | 192.168.31.100 | 目标 IP | | `--port` | 因模式而异 | 端口 | | `--count` | 10 | 测试次数 | | `--timeout` | 30 | 超时秒数 | diff --git a/docs/测试说明/板级测试/FTP_Test_Guide.md b/docs/测试说明/板级测试/FTP_Test_Guide.md index 9cf49a63..359f26d8 100644 --- a/docs/测试说明/板级测试/FTP_Test_Guide.md +++ b/docs/测试说明/板级测试/FTP_Test_Guide.md @@ -25,7 +25,7 @@ ### 2.1 硬件与网络 - CH395F 网口经以太网连接到 PC 或同一台交换机。 -- PC 网卡与固件 IP **同网段**。固件默认静态 IP **192.168.1.100**(掩码 255.255.255.0);PC 可设 192.168.1.x(如 192.168.1.77)。 +- PC 网卡与固件 IP **同网段**。固件默认静态 IP **192.168.31.100**(掩码 255.255.255.0);PC 可设 192.168.31.x(如 192.168.31.77)。 - **启动时序(2026-09-21 现行实现,取代旧文档的 `osDelay(7000)`)**:`netTask` 完成 `net_init()` + PHY 稳定后置 `SYS_EVT_NET_READY`;`defaultTask` 挂载卷 + 加载配置后置 `SYS_EVT_STORAGE_READY`;`ftpTask` 以 `osEventFlagsWait(两位, osFlagsWaitAll | osFlagsNoClear)` 等**两位同时就绪**再 `lftpd_start`。串口出现 `[FTP] waiting for connection...` 即可连接(实测:上电后约 0.5~1s,取决于存储挂载耗时)。 - ⚠ **就绪位等待必须带 `osFlagsNoClear`**(2026-09-21 实证,详见 §8.6):`osEventFlagsWait` 默认**消费**所等待的位,若被其它等待者清掉,`ftpTask` 的 `WaitAll(两位)` 永不成立 → FTP 静默不监听。 - **单客户端**:监听 socket 与数据通道复用,同一时刻只服务 1 个会话;上一个会话未 `QUIT` 就断开时,服务端约 30s 后才丢弃旧会话并重新 listen,期间新连接被拒(`WinError 10061`)。脚本已内置连接重试;**不要用裸 TCP 工具探测 21 端口**(探测本身会占掉唯一会话,见 §8.7)。 @@ -51,14 +51,14 @@ ## 4. PC 端脚本手测(主要手段) -所有脚本支持 `--host`(默认 `192.168.1.100`)、`--port`(默认 21)、`--user` / `--password` +所有脚本支持 `--host`(默认 `192.168.31.100`)、`--port`(默认 21)、`--user` / `--password` (默认出厂账号 `admin` / `admin`;设备口令改过就要显式传,**没有匿名通道**),在 `test/` 目录运行;`ftp_up_dl_test.py` / `ftp_speed_test.py` 内置**连接重试**(单客户端:旧会话未释放时自动等待重试,默认 6 次 × 3s)。 推荐入口:`& '.venv\Scripts\python.exe' test/host/ftp_up_dl_test.py`(功能闭环:登录/TYPE I/PASV/STOR/LIST/RETR/比对/DELE/QUIT)与 `& '.venv\Scripts\python.exe' test/host/ftp_speed_test.py --size 128`(大文件 + 吞吐);后者同时是 **ftpTask 栈水位测量**的负载(见 `docs/内存管理/RAM使用分析与优化方案.md` §4.0.6)。 ### 4.1 冒烟测试:`ftp_test.py` - 用途:验证连接、登录、`PWD`、`PASV`、`LIST` 基本链路。 -- 命令:`python ./test/host/ftp_test.py --host 192.168.1.100` +- 命令:`python ./test/host/ftp_test.py --host 192.168.31.100` - 预期: - 连接成功并读到 `220` 欢迎; - `USER admin` 返回 `331`(需要口令)、`PASS admin` 返回 `230`; @@ -70,7 +70,7 @@ ### 4.2 上传 / 下载 / 比对:`ftp_up_dl_test.py` - 用途:验证 `STOR`/`RETR`/`DELE` 与数据一致性(`TYPE I` 二进制 + `PASV`)。 -- 命令:`python ./test/host/ftp_up_dl_test.py --host 192.168.1.100` +- 命令:`python ./test/host/ftp_up_dl_test.py --host 192.168.31.100` - 流程:登录 → `TYPE I` → `STOR up_test.dat` → `LIST` 校验存在 → `RETR up_test.dat` → 逐字节比对 → `DELE` 清理 → `QUIT`。 - 预期:`*** MATCH! Upload/Download success. ***`,且 LIST 中出现 `up_test.dat`。 - 判据:上传/下载字节数相等且内容逐字节一致。 @@ -78,7 +78,7 @@ ### 4.3 速度与大数据量:`ftp_speed_test.py` - 用途:测量上传/下载吞吐,作回归基线,同时验证大文件不丢字节。 -- 命令:`python ./test/host/ftp_speed_test.py --host 192.168.1.100 --size 512`(默认 512KB,`--size` 可调)。 +- 命令:`python ./test/host/ftp_speed_test.py --host 192.168.31.100 --size 512`(默认 512KB,`--size` 可调)。 - 预期:上传/下载均返回 `226`,回读 `MATCH!`,打印 KB/s。 - 注意:脚本使用 8.3 文件名 `SPEEDTST.DAT`(**FTP 仅支持 8.3 短文件名**,见 §8.3);以回读比对(MATCH)为最终判据,中间打印的 Sent 字段仅供参考。 - 判据:size 一致 + MATCH + 速度稳定(受 SPI2 分频 8 限制,通常约 300~450 KB/s,参见 `CH395F_Test_Guide.md` 阶段 5 吞吐基线)。 @@ -106,7 +106,7 @@ ## 5. GUI 客户端手测(可选) -- **FileZilla**:主机 `192.168.1.100`,端口 21,用户 `admin`、密码 `admin`(**匿名会被 530 拒**);可拖拽上传/下载、浏览目录。 +- **FileZilla**:主机 `192.168.31.100`,端口 21,用户 `admin`、密码 `admin`(**匿名会被 530 拒**);可拖拽上传/下载、浏览目录。 - 要点:使用二进制模式传输;文件名遵守 8.3;**一次只连一个客户端**。 --- diff --git a/docs/测试说明/板级测试/实机测试实施指南.md b/docs/测试说明/板级测试/实机测试实施指南.md index bc4e8802..45576f2e 100644 --- a/docs/测试说明/板级测试/实机测试实施指南.md +++ b/docs/测试说明/板级测试/实机测试实施指南.md @@ -71,7 +71,7 @@ ```bash # 一键闭环(selftest.log 自动 FTP 抓取;无故障记录 = PASS) -& '.venv\Scripts\python.exe' .dsh/skills/serial-boot-test/scripts/run_boot_test.py --require-selftest-pass --device-ip 192.168.1.100 +& '.venv\Scripts\python.exe' .dsh/skills/serial-boot-test/scripts/run_boot_test.py --require-selftest-pass --device-ip 192.168.31.100 # 或手动联合判定(本轮串口日志 + selftest.log 本地副本) & '.venv\Scripts\python.exe' .dsh/skills/serial-boot-test/scripts/verify_log.py \ diff --git a/docs/环境与部署/并行任务工作树方案.md b/docs/环境与部署/并行任务工作树方案.md index 032d5378..36510e87 100644 --- a/docs/环境与部署/并行任务工作树方案.md +++ b/docs/环境与部署/并行任务工作树方案.md @@ -208,7 +208,7 @@ D:/Code/DTU Code/ - 串口 `COM6` @115200 - ST-LINK SN `0B250D12A218303030303032` -- 设备 IP `192.168.1.100` +- 设备 IP `192.168.31.100` 机制:`_wt/.state/locks/{build,bench}.lock` 记录持有者(任务 ID + pid + 时间戳 + 备注 + 自报 TTL)。 diff --git a/docs/环境与部署/项目部署环境要求.md b/docs/环境与部署/项目部署环境要求.md index 5173ff0c..8fa88fec 100644 --- a/docs/环境与部署/项目部署环境要求.md +++ b/docs/环境与部署/项目部署环境要求.md @@ -553,9 +553,9 @@ $env:DTU_KEIL_UV4 = 'D:\NotExist\UV4.exe' # 仅当前会话,不动用户级 | 参数 | 工厂默认 | 修改方式 | |---|---|---| -| IP | **192.168.1.100**(静态,无 DHCP) | 屏幕 `通讯参数 → 网口设置`(修改密码 `123`)保存后**立即生效**(网络重建约 1~3 s);或预置 `/config.ini`(INI;旧版 `/cfg/netcfg.bin` **不再读取**——存在则忽略、不迁移,配置回落工厂默认,2026-10-10 起) | +| IP | **192.168.31.100**(静态,无 DHCP) | 屏幕 `通讯参数 → 网口设置`(修改密码 `123`)保存后**立即生效**(网络重建约 1~3 s);或预置 `/config.ini`(INI;旧版 `/cfg/netcfg.bin` **不再读取**——存在则忽略、不迁移,配置回落工厂默认,2026-10-10 起) | | 子网掩码 | 255.255.255.0(/24) | 同上 | -| 默认网关 | 192.168.1.1 | 同上 | +| 默认网关 | 192.168.31.1 | 同上 | | MAC | 全零 = 芯片内置 MAC | 同上(全零是"使用芯片内置 MAC"的哨兵,不是"MAC 为 0") | | PHY | 强制 100M 全双工 | 固件固定,不可配 | @@ -583,7 +583,7 @@ $env:DTU_KEIL_UV4 = 'D:\NotExist\UV4.exe' # 仅当前会话,不动用户级 | # | 项目 | 方法 | 通过标准 | |---|---|---|---| | 1 | 上电自启动 | 断电上电 + 串口采集 | `/serial-boot-test` PASS:Required `App init OK;Network Init;net init: OK;PHY: 100M FULL`,无 `FAIL/ERROR/HardFault` | -| 2 | 网络连通 | PC ping 192.168.1.100 | 通(PHY 100M FULL) | +| 2 | 网络连通 | PC ping 192.168.31.100 | 通(PHY 100M FULL) | | 3 | 远程显示 | DTU-RemoteLCD 连 7003 | 出图(160×160 1bpp)+ 远端菜单导航可用 | | 4 | FTP | FTP 客户端连 :21 | 列目录 / 读写 `/` 下文件 | | 5 | UI 功能 | 屏幕 / 远端操作 | 菜单 7 项导航、内容页、密码(查看 `000` / 修改 `123`)、网口设置保存后立即生效 | diff --git a/docs/网络/BSD_Socket_API_使用指南.md b/docs/网络/BSD_Socket_API_使用指南.md index b4985e46..6f8bc330 100644 --- a/docs/网络/BSD_Socket_API_使用指南.md +++ b/docs/网络/BSD_Socket_API_使用指南.md @@ -222,7 +222,7 @@ int main(void) * 本项目中由 netTask 调用(网口配置已由 defaultTask 在就绪屏障前 * 加载进 RAM 副本,netTask 只读副本组网) */ - int ret = net_init("192.168.1.100", "255.255.255.0", "192.168.1.1", NULL); + int ret = net_init("192.168.31.100", "255.255.255.0", "192.168.31.1", NULL); if (ret != 0) { printf("网络初始化失败!\r\n"); return -1; @@ -258,7 +258,7 @@ int main(void) /* 外设初始化... */ /* BSD Socket API 初始化 */ - net_init("192.168.1.100", "255.255.255.0", "192.168.1.1", NULL); + net_init("192.168.31.100", "255.255.255.0", "192.168.31.1", NULL); /* 创建 Socket、绑定、监听... */ @@ -395,7 +395,7 @@ void tcp_client(void) /* 2. 设置服务器地址 */ addr.sin_family = AF_INET; addr.sin_port = net_htons(8080); - addr.sin_addr.s_addr = net_inet_addr("192.168.1.200"); + addr.sin_addr.s_addr = net_inet_addr("192.168.31.200"); /* 3. 连接服务器 */ printf("正在连接服务器...\r\n"); @@ -473,7 +473,7 @@ void udp_client(void) /* 3. 设置目标地址 */ dest_addr.sin_family = AF_INET; dest_addr.sin_port = net_htons(8888); - dest_addr.sin_addr.s_addr = net_inet_addr("192.168.1.200"); + dest_addr.sin_addr.s_addr = net_inet_addr("192.168.31.200"); /* 4. 发送数据 */ const char *msg = "UDP Hello!"; @@ -726,7 +726,7 @@ void event_callback_example(void) ### 9.0 `s_addr` 的唯一约定(2026-10-24 统一;全仓只此一族,勿再引入第二套) **定义**:`sin_addr.s_addr` 一律存**网络字节序整数**,判据是 `&s_addr` 的**第 0 个内存字节 == 点分第一段**。 -小端主机(STM32F407 与 PC 模拟器都是)上 `"192.168.1.100"` 的数值 = **`0x6401A8C0`**(内存里是 `C0 A8 01 64`)。 +小端主机(STM32F407 与 PC 模拟器都是)上 `"192.168.31.100"` 的数值 = **`0x641FA8C0`**(内存里是 `C0 A8 1F 64`)。 | 方向 | 用哪个 API | 要点 | |---|---|---| @@ -759,11 +759,11 @@ uint16_t host_port = net_ntohs(net_port); ```c /* 字符串转网络序 IP */ -uint32_t ip = net_inet_addr("192.168.1.100"); +uint32_t ip = net_inet_addr("192.168.31.100"); /* 网络序 IP 转字符串 */ char ip_str[16]; -net_inet_ntoa(ip, ip_str); /* ip_str = "192.168.1.100" */ +net_inet_ntoa(ip, ip_str); /* ip_str = "192.168.31.100" */ ``` ### 9.3 填充地址结构体 @@ -773,7 +773,7 @@ struct net_sockaddr_in addr; addr.sin_family = AF_INET; addr.sin_port = net_htons(8080); /* 端口转换 */ -addr.sin_addr.s_addr = net_inet_addr("192.168.1.100"); /* IP 转换 */ +addr.sin_addr.s_addr = net_inet_addr("192.168.31.100"); /* IP 转换 */ /* 如果要绑定任意地址 */ addr.sin_addr.s_addr = net_inet_addr("0.0.0.0"); @@ -1180,7 +1180,7 @@ NET_FD_ISSET(fd, fdset) /* 检查 fd 是否在集合中 */ #include #include -#define SERVER_IP "192.168.1.200" +#define SERVER_IP "192.168.31.200" #define SERVER_PORT 8080 void tcp_client_reconnect(void) @@ -1191,7 +1191,7 @@ void tcp_client_reconnect(void) uint32_t reconnect_interval = 5000; /* 5 秒重连间隔 */ /* 初始化网络 */ - net_init("192.168.1.100", "255.255.255.0", "192.168.1.1", NULL); + net_init("192.168.31.100", "255.255.255.0", "192.168.31.1", NULL); while (1) { diff --git a/scripts/board_ui_nav.py b/scripts/board_ui_nav.py index cd8a3d14..c2244d70 100644 --- a/scripts/board_ui_nav.py +++ b/scripts/board_ui_nav.py @@ -49,6 +49,13 @@ import subprocess import sys import time +# 台架连接默认值单一真源在 test/host/bench_defaults.py(跨目录:补 sys.path 后 import) +_sys_path = os.path.join(os.path.dirname(os.path.abspath(__file__)), + "..", "test", "host") +if _sys_path not in sys.path: + sys.path.insert(0, _sys_path) +import bench_defaults # noqa: E402 + try: sys.stdout.reconfigure(encoding="utf-8", errors="replace") sys.stderr.reconfigure(encoding="utf-8", errors="replace") @@ -500,7 +507,7 @@ class BoardDevice(object): CMD_KEY = 2 CMD_LCDMEM = 3 - def __init__(self, ip="192.168.1.100", port=7003): + def __init__(self, ip=bench_defaults.DEVICE_IP, port=7003): self.s = socket.create_connection((ip, port), timeout=5) self.s.settimeout(3) diff --git a/scripts/gen_task_table.py b/scripts/gen_task_table.py index da1ce5e5..5677e852 100644 --- a/scripts/gen_task_table.py +++ b/scripts/gen_task_table.py @@ -77,7 +77,7 @@ ROLE = { "timeSyncTask": "墙钟时间同步", "adcTask": "TPAFE5160 采样(TIM3 1kHz 事件驱动 + 原子快照 + STM32 ADC DMA,纯消费者)", "iec104Task": "IEC 60870-5-104 上行(工厂默认 :2404 监听,遥信/遥测/定值区)", - "protectTask": "保护判据 20ms 节拍(保护判据元件 + 采样故障闭锁,B5)", + "protectTask": "保护判据 20ms 节拍(保护判据元件 + 采样故障闭锁)", } diff --git a/scripts/size_attestation.json b/scripts/size_attestation.json index 2c006708..68797493 100644 --- a/scripts/size_attestation.json +++ b/scripts/size_attestation.json @@ -1,15 +1,15 @@ { - "built_at": "2026-10-30T18:28:23+08:00", - "fingerprint": "80504df8fdee0a2565df3636eebbb366c615866c93f41e27e8940521fe566f0c", + "built_at": "2026-11-02T14:32:47+08:00", + "fingerprint": "c5294354ba3e05e51882676c7edddf995852d114c6f6413016e49adc7f6ac2a6", "fingerprint_files": 1466, "fingerprint_source": "git-index", "gated_regions": [ "RW_IRAM1", "RW_CCM" ], - "git_head": "51ce59006be80de59d312df97dce9ed78b0eeaea", + "git_head": "e63abb919a5934511ffc7e8fea2c5b86dbfc70fc", "map": "MDK-ARM/STM32F407-Demo/STM32F407-Demo.map", - "map_mtime": 1793356087, + "map_mtime": 1793600487, "pct": { "ER_IROM1": 26.37, "RW_CCM": 87.89, diff --git a/simulator/sim/net_socket_sim.c b/simulator/sim/net_socket_sim.c index 81403958..c1d8e917 100644 --- a/simulator/sim/net_socket_sim.c +++ b/simulator/sim/net_socket_sim.c @@ -809,7 +809,7 @@ int net_get_errno(void) { /* * 函数功能:将点分十进制 IP 字符串转为网络字节序 32 位地址 - * 入口参数:cp - 点分十进制字符串(如 "192.168.1.100") + * 入口参数:cp - 点分十进制字符串 * 出口参数:无 * 返回值:网络字节序 IP(参数无效返回 0) * 限定条件:无 diff --git a/simulator/sim_config.ini b/simulator/sim_config.ini index 96e5ca2b..f61bd310 100644 --- a/simulator/sim_config.ini +++ b/simulator/sim_config.ini @@ -7,7 +7,7 @@ ; ============================================================ [network] -ip=192.168.1.100 +ip=192.168.31.100 mask=255.255.255.0 -gw=192.168.1.1 +gw=192.168.31.1 mac=00:00:00:00:00:00 diff --git a/simulator/tests/check_content_pages.py b/simulator/tests/check_content_pages.py index de68d980..6ca5b2e3 100644 --- a/simulator/tests/check_content_pages.py +++ b/simulator/tests/check_content_pages.py @@ -35,6 +35,35 @@ from pathlib import Path EXE = Path(__file__).resolve().parents[1] / "build" / "Debug" / "lvgl_sim.exe" REF_DIR = Path(__file__).resolve().parent / "ref" +# 工厂默认 = 黄金参考的真源:Drivers/BSP/NETCFG/net_cfg.c 的 NET_CFG_DEF_* 宏。 +# run_sim 一律在空临时目录跑(无 ini → 模拟器按编译期宏显示),故断言值必须与该宏 +# 一致;这里现读现算,改默认 IP 只动 C 宏,本脚本零同步(2026-11-02 教训:本文件 +# 曾钉死 7 处补零字面量,IP 迁移时逐处爆红)。 +_NETCFG_C = Path(__file__).resolve().parents[2] / "Drivers" / "BSP" / "NETCFG" / "net_cfg.c" + + +def _read_net_cfg_default(name): + """抽取 `#define name { a, b, c, d }` 四字节(容忍 u 后缀/任意空白)。 + + 解析失败立即报错——绝不回退到写死旧值(宁可红在明处)。 + """ + pat = r"#define\s+%s\s*\{\s*(\d+)u?\s*,\s*(\d+)u?\s*,\s*(\d+)u?\s*,\s*(\d+)u?\s*\}" % name + m = re.search(pat, _NETCFG_C.read_text(encoding="utf-8-sig")) + if not m: + raise RuntimeError("net_cfg.c 的 %s 解析失败:宏形态变了就同步本函数的正则(勿改回写死值)" % name) + return tuple(int(g) for g in m.groups()) + + +def _fmt_ip03(octets): + """net_cfg_fmt_ipv4 的既有口径:后三段补零成 3 位、首段原样(同一格式化真源)。""" + return "%d.%03d.%03d.%03d" % octets + + +EXP_IP = _fmt_ip03(_read_net_cfg_default("NET_CFG_DEF_IP")) +EXP_MASK = _fmt_ip03(_read_net_cfg_default("NET_CFG_DEF_MASK")) +EXP_GW = _fmt_ip03(_read_net_cfg_default("NET_CFG_DEF_GW")) +EXP_IP_TAIL = EXP_IP.split(".", 1)[1] # 编辑态首字节被光标反显覆盖,只断言尾部 + # (页名, 注入键序):与 ui_menu.c 节点映射/路由一致(u=上 d=下 l=左 r=右 e=回车 s=ESC); # 密码页 = 受保护叶子(参数定值/整定/参数 node 8,默认密码 123) PAGES = [ @@ -316,7 +345,7 @@ TEXTS = { ("r5名", "MAC地址", (103, 116), False), ("r5值", "00:00:00:00:00:00", (103, 116), False), # net_cfg_fmt_ipv4 的既有口径是三段补零(与网口设置页同一格式化真源),照实断言 - ("r6名", "IP地址", (116, 129), False), ("r6值", "192.168.001.100", (116, 129), False), + ("r6名", "IP地址", (116, 129), False), ("r6值", EXP_IP, (116, 129), False), ("r7名", "运行时长", (129, 142), False), ("r7值", "00:00:00", (129, 142), False), ("页脚", "第 1 页,共 1 页", (140, 160), False), ], @@ -480,18 +509,18 @@ TEXTS = { ], "netcfg": [ ("标题", "网口设置", (0, 24), False), - ("r0名", "IP地址", (24, 38), True), ("r0值", "192.168.001.100", (24, 38), True), - ("r1名", "子网掩码", (38, 52), False), ("r1值", "255.255.255.000", (38, 52), False), - ("r2名", "默认网关", (52, 66), False), ("r2值", "192.168.001.001", (52, 66), False), + ("r0名", "IP地址", (24, 38), True), ("r0值", EXP_IP, (24, 38), True), + ("r1名", "子网掩码", (38, 52), False), ("r1值", EXP_MASK, (38, 52), False), + ("r2名", "默认网关", (52, 66), False), ("r2值", EXP_GW, (52, 66), False), ("r3名", "MAC地址", (66, 80), False), ("r3值", "00:00:00:00:00:00", (66, 80), False), ("r4名", "保存", (80, 95), False), ("r4值", "ENTER", (80, 95), False), ("页脚", "第 1 页,共 1 页", (140, 160), False), ], "netcfg_ro": [ ("标题", "网口设置", (0, 24), False), - ("r0名", "IP地址", (24, 38), True), ("r0值", "192.168.001.100", (24, 38), True), - ("r1名", "子网掩码", (38, 52), False), ("r1值", "255.255.255.000", (38, 52), False), - ("r2名", "默认网关", (52, 66), False), ("r2值", "192.168.001.001", (52, 66), False), + ("r0名", "IP地址", (24, 38), True), ("r0值", EXP_IP, (24, 38), True), + ("r1名", "子网掩码", (38, 52), False), ("r1值", EXP_MASK, (38, 52), False), + ("r2名", "默认网关", (52, 66), False), ("r2值", EXP_GW, (52, 66), False), ("r3名", "MAC地址", (66, 80), False), ("r3值", "00:00:00:00:00:00", (66, 80), False), ("r4名", "保存", (80, 95), False), ("r4值", "ENTER", (80, 95), False), ("页脚", "第 1 页,共 1 页", (140, 160), False), @@ -499,7 +528,7 @@ TEXTS = { "netcfg_edit": [ ("标题", "网口设置", (0, 24), False), ("r0名", "IP地址", (24, 38), True), - ("r0值尾", "168.001.100", (24, 38), True), # 首字节 192 被光标反显覆盖 + ("r0值尾", EXP_IP_TAIL, (24, 38), True), # 首字节(192 那段)被光标反显覆盖 ("r1名", "子网掩码", (38, 52), False), ("r4名", "保存", (80, 95), False), ], @@ -578,7 +607,7 @@ TEXTS = { ], "netcfg_save": [ ("标题", "网口设置", (0, 24), False), - ("r0名", "IP地址", (24, 38), False), ("r0值", "192.168.001.100", (24, 38), False), + ("r0名", "IP地址", (24, 38), False), ("r0值", EXP_IP, (24, 38), False), ("r3名", "MAC地址", (66, 80), False), ("r4名", "保存", (80, 95), True), ("r4值", "OK", (80, 95), True), ], diff --git a/simulator/tests/ref/shot_info.bin b/simulator/tests/ref/shot_info.bin index b22e5c1a..8b850815 100644 Binary files a/simulator/tests/ref/shot_info.bin and b/simulator/tests/ref/shot_info.bin differ diff --git a/simulator/tests/ref/shot_netcfg.bin b/simulator/tests/ref/shot_netcfg.bin index 3a01afea..fa8a6dba 100644 Binary files a/simulator/tests/ref/shot_netcfg.bin and b/simulator/tests/ref/shot_netcfg.bin differ diff --git a/simulator/tests/ref/shot_netcfg_edit.bin b/simulator/tests/ref/shot_netcfg_edit.bin index 6a11dd31..ec218dfb 100644 Binary files a/simulator/tests/ref/shot_netcfg_edit.bin and b/simulator/tests/ref/shot_netcfg_edit.bin differ diff --git a/simulator/tests/ref/shot_netcfg_ro.bin b/simulator/tests/ref/shot_netcfg_ro.bin index 3a01afea..fa8a6dba 100644 Binary files a/simulator/tests/ref/shot_netcfg_ro.bin and b/simulator/tests/ref/shot_netcfg_ro.bin differ diff --git a/simulator/tests/ref/shot_netcfg_save.bin b/simulator/tests/ref/shot_netcfg_save.bin index 1ab99021..b56a5cc6 100644 Binary files a/simulator/tests/ref/shot_netcfg_save.bin and b/simulator/tests/ref/shot_netcfg_save.bin differ diff --git a/test/board/ch395f_test_task.c b/test/board/ch395f_test_task.c index 7448de12..62d593d7 100644 --- a/test/board/ch395f_test_task.c +++ b/test/board/ch395f_test_task.c @@ -122,41 +122,44 @@ static void phase1_run(void) { * 原理:ch395f_set_ip_addr() 将 IP 写入 CH395F 内部寄存器, * 然后通过 ch395f_get_ip_inf() 回读完整网络信息(IP+GW+MASK)。 * 前 4 字节为 IP 地址。 - * 通过:回读 IP[0..3] == 192.168.1.100(与写入值一致)。 + * 通过:回读 IP[0..3] == 写入的 set_ip(回读与写入一致;值本身任意合法, + * 不校验工厂默认——工厂默认断言在 net_cfg 主机单测里钉)。 * 失败:任意字节不匹配(SPI 写入/回读路径异常或寄存器未更新)。 */ { - uint8_t set_ip[4] = {192, 168, 1, 100}; + uint8_t set_ip[4] = {192, 168, 31, 100}; ch395f_set_ip_addr(set_ip); memset(ip_info, 0, sizeof(ip_info)); ch395f_get_ip_inf(ip_info); - int32_t match = (ip_info[0] == 192 && ip_info[1] == 168 && - ip_info[2] == 1 && ip_info[3] == 100); - DBG_INFO(" ch395f_set_ip_addr(192.168.1.100)"); - DBG_INFO(" expect: IP[0..3] = 192.168.1.100"); + int32_t match = (memcmp(ip_info, set_ip, sizeof(set_ip)) == 0); + DBG_INFO(" ch395f_set_ip_addr(%d.%d.%d.%d)", + set_ip[0], set_ip[1], set_ip[2], set_ip[3]); + DBG_INFO(" expect: IP[0..3] = 写入值(上一行)"); DBG_INFO(" actual: %d.%d.%d.%d", ip_info[0], ip_info[1], ip_info[2], ip_info[3]); - TEST_CHECK(match, "IP = %d.%d.%d.%d (expect 192.168.1.100)", - ip_info[0], ip_info[1], ip_info[2], ip_info[3]); + TEST_CHECK(match, "IP = %d.%d.%d.%d (expect %d.%d.%d.%d)", + ip_info[0], ip_info[1], ip_info[2], ip_info[3], + set_ip[0], set_ip[1], set_ip[2], set_ip[3]); } /* ---- 设置网关 → 回读验证 ---- * 原理:同「设置 IP → 回读」项,通过 ch395f_set_gwip_addr() 写入,ch395f_get_ip_inf() * 回读的第 5-8 字节为网关地址。 - * 通过:回读 GW[0..3] == 192.168.1.1。 + * 通过:回读 GW[0..3] == 写入的 set_gw(同「设置 IP → 回读」项,值任意合法)。 * 失败:任意字节不匹配。 */ { - uint8_t set_gw[4] = {192, 168, 1, 1}; + uint8_t set_gw[4] = {192, 168, 31, 1}; ch395f_set_gwip_addr(set_gw); memset(ip_info, 0, sizeof(ip_info)); ch395f_get_ip_inf(ip_info); - int32_t match = (ip_info[4] == 192 && ip_info[5] == 168 && - ip_info[6] == 1 && ip_info[7] == 1); - DBG_INFO(" ch395f_set_gwip_addr(192.168.1.1)"); - DBG_INFO(" expect: GW[0..3] = 192.168.1.1"); + int32_t match = (memcmp(ip_info + 4, set_gw, sizeof(set_gw)) == 0); + DBG_INFO(" ch395f_set_gwip_addr(%d.%d.%d.%d)", + set_gw[0], set_gw[1], set_gw[2], set_gw[3]); + DBG_INFO(" expect: GW[0..3] = 写入值(上一行)"); DBG_INFO(" actual: %d.%d.%d.%d", ip_info[4], ip_info[5], ip_info[6], ip_info[7]); - TEST_CHECK(match, "GW = %d.%d.%d.%d (expect 192.168.1.1)", - ip_info[4], ip_info[5], ip_info[6], ip_info[7]); + TEST_CHECK(match, "GW = %d.%d.%d.%d (expect %d.%d.%d.%d)", + ip_info[4], ip_info[5], ip_info[6], ip_info[7], + set_gw[0], set_gw[1], set_gw[2], set_gw[3]); } /* ---- 设置掩码 → 回读验证 ---- @@ -269,7 +272,7 @@ static void phase1_run(void) { #ifdef ENABLE_PHASE2_TESTS #ifndef PHASE2_REMOTE_IP -#define PHASE2_REMOTE_IP "192.168.1.2" +#define PHASE2_REMOTE_IP TEST_PC_PEER_IP #endif #ifndef PHASE2_REMOTE_PORT #define PHASE2_REMOTE_PORT 8081 @@ -854,7 +857,7 @@ static void phase2_tc204(void) /* TC-NET-203(硬件层):TCP Client 连接超时(负向测试,P1) * - * 前置环境:PC 未在 192.168.1.2:8081 提供服务(与 TC-NET-201/202 互斥, + * 前置环境:PC 未在 PHASE2_REMOTE_IP:8081 提供服务(与 TC-NET-201/202 互斥, * 需先关闭 PC 端 tcp_server)。固件自行辨别环境错误: * 若等待期间误收到 CONNECT,说明 PC 服务未关,判 FAIL 并给出指引。 * @@ -1027,7 +1030,7 @@ static void phase2_run(void) * 4. 向对应源地址回显数据 * 5. SENDBUF_FREE 中断等待(确保发送缓冲可用) * - * 前置条件:PC 运行 udp_client 发包到 192.168.1.100:60000 + * 前置条件:PC 运行 udp_client 发包到板 IP:60000(板 IP = config.ini [network] 设置值) * 会话结构:累计 PHASE3_TOTAL_ROUNDS(60) 个有效数据包后关闭 Socket * 第 1~30 轮 = TC-NET-301(PC 发 64B);第 31~60 轮 = TC-NET-302(1B/64B/200B) * "HELLO"(5B) 为 PC 就绪探针:照常回显但不计入轮次 @@ -1317,7 +1320,7 @@ phase4_end: /* 回传参数(TC-NET-502 合规测试时按档位修改重编译) */ #ifndef PHASE5_REMOTE_IP -#define PHASE5_REMOTE_IP "192.168.1.2" +#define PHASE5_REMOTE_IP TEST_PC_PEER_IP #endif #ifndef PHASE5_REMOTE_PORT #define PHASE5_REMOTE_PORT 8081 /* PC tcp_server 监听端口 */ diff --git a/test/board/net_test_task.c b/test/board/net_test_task.c index f173beae..031d2d35 100644 --- a/test/board/net_test_task.c +++ b/test/board/net_test_task.c @@ -112,7 +112,7 @@ static void phase6_run(int32_t sockfd) { * * 测试目的:验证 BSD Socket API 的 TCP Client 路径(net_socket + net_bind * + net_connect + net_send + net_recv): - * 1. MCU 主动连接 PC 回显服务器(192.168.1.2:8080) + * 1. MCU 主动连接 PC 回显服务器(默认 PHASE7_REMOTE_IP:8080) * 2. 64B 递增数据回显后,固件侧逐字节比对 + 32 位累加和校验 * 3. 关闭并重新连接(规避 TIME_WAIT:每轮换本地端口) * 4. 连接超时负向用例(PC 服务关闭时 connect 不应成功) @@ -128,7 +128,7 @@ static void phase6_run(int32_t sockfd) { #include "net_select.h" #ifndef PHASE7_REMOTE_IP -#define PHASE7_REMOTE_IP "192.168.1.2" +#define PHASE7_REMOTE_IP TEST_PC_PEER_IP #endif #ifndef PHASE7_REMOTE_PORT #define PHASE7_REMOTE_PORT 8081 diff --git a/test/board/net_test_task.h b/test/board/net_test_task.h index d9003efe..dc529f2a 100644 --- a/test/board/net_test_task.h +++ b/test/board/net_test_task.h @@ -5,6 +5,10 @@ extern "C" { #endif +/* 台架 PC 对端 IP 单一真源(PHASE2/5/7_REMOTE_IP 的缺省值;改台架只动这里, + * 个别构建也可在编译行 -DPHASE*_REMOTE_IP="..." 临时覆盖)。 */ +#define TEST_PC_PEER_IP "192.168.31.2" + /* NET 层测试事件循环入口(定义于 net_test_task.c)。 * 由 testTask 在 NET 层构建模式下调用,内部创建单连接 TCP 监听 * 并驱动 Phase 6/8~11 依次执行,连接断开后自动重新 listen。 */ diff --git a/test/host/bench_defaults.py b/test/host/bench_defaults.py new file mode 100644 index 00000000..d9b5da8a --- /dev/null +++ b/test/host/bench_defaults.py @@ -0,0 +1,19 @@ +# -*- coding: utf-8 -*- +"""台架连接默认值单一真源(test/host/*.py 直接 `import bench_defaults`)。 + +2026-11-02 设备 IP 由 192.168.1.100 迁到 192.168.31.100 时,25+ 个脚本的 +argparse 缺省值/模块常量逐处爆红——收口到本文件后,换台架只改这里。 + +对应关系(同一事实一处详述,勿在别处复制值): +- 设备 IP/网关:编译期工厂默认在 Drivers/BSP/NETCFG/net_cfg.c 的 NET_CFG_DEF_*, + 本文件是**台架脚本侧**的连接缺省,两者当前一致但语义不同(工厂默认 vs 台架约定)。 +- PC 对端 IP:板测固件侧单一真源是 test/board/net_test_task.h 的 TEST_PC_PEER_IP, + 本文件 PC_IP 与其保持同值(改台架两处都要动——C 与 Python 无共享编译单元)。 +""" + +DEVICE_IP = "192.168.31.100" # DTU 板子(台架标准地址,用户裁定 2026-11-02) +DEVICE_GW = "192.168.31.1" # 台架网关(PC 热点/路由侧) +PC_IP = "192.168.31.2" # 台架 PC 自身网卡地址(= TEST_PC_PEER_IP 同值) + +# /24 子网定向广播(从 DEVICE_IP 现算,不再单独钉一个 .255 字面量) +NET_BCAST = DEVICE_IP.rsplit(".", 1)[0] + ".255" diff --git a/test/host/cfg_file/cfg_file_test.c b/test/host/cfg_file/cfg_file_test.c index a47e7c7c..cedebd61 100644 --- a/test/host/cfg_file/cfg_file_test.c +++ b/test/host/cfg_file/cfg_file_test.c @@ -474,8 +474,8 @@ static void tc_ip4(void) { CHECK(s_decode_ip4(d, "0.0.0.0") == 0 && d[0] == 0u && d[3] == 0u, "all-zero"); CHECK(s_decode_ip4(d, "255.255.255.255") == 0 && d[0] == 255u && d[3] == 255u, "all-255"); - CHECK(s_decode_ip4(d, "192.168.1.100") == 0 && - d[0] == 192u && d[1] == 168u && d[2] == 1u && d[3] == 100u, "typical"); + CHECK(s_decode_ip4(d, "192.168.31.100") == 0 && + d[0] == 192u && d[1] == 168u && d[2] == 31u && d[3] == 100u, "typical"); CHECK(s_decode_ip4(d, "1.2.3") == -1, "too few octets rejected"); CHECK(s_decode_ip4(d, "1.2.3.4.5") == -1, "too many octets rejected"); CHECK(s_decode_ip4(d, "256.1.1.1") == -1, "octet >255 rejected"); diff --git a/test/host/cfg_file_store_mcu/cfg_file_store_mcu_test.c b/test/host/cfg_file_store_mcu/cfg_file_store_mcu_test.c index 66b6c9d8..a913523b 100644 --- a/test/host/cfg_file_store_mcu/cfg_file_store_mcu_test.c +++ b/test/host/cfg_file_store_mcu/cfg_file_store_mcu_test.c @@ -268,9 +268,9 @@ static void tc_read(void) /* 001 成功 + 只读模式 */ reset_all(); - (void)ff_fake_mkfile(P_CFG, (const uint8_t *)"net ip=192.168.1.100\n", 20u); - ok = (cfg_store_read(P_CFG, buf, sizeof(buf), &n) == 0) && (n == 20u) - && (memcmp(buf, "net ip=192.168.1.100\n", 20u) == 0) + (void)ff_fake_mkfile(P_CFG, (const uint8_t *)"net ip=192.168.31.100\n", 21u); + ok = (cfg_store_read(P_CFG, buf, sizeof(buf), &n) == 0) && (n == 21u) + && (memcmp(buf, "net ip=192.168.31.100\n", 21u) == 0) && (g_ff_obs.last_open_mode == (BYTE)FA_READ) && (s_lock_waits == 1) && (s_lock_releases == 1) && (s_lock_seq_err == 0); CHECK(ok, "TC-CFGFST-001 read ok: content and length correct, opened with FA_READ only (no write bit)"); diff --git a/test/host/ch395f_reuse_host.py b/test/host/ch395f_reuse_host.py index 825f2da2..7e8d212e 100644 --- a/test/host/ch395f_reuse_host.py +++ b/test/host/ch395f_reuse_host.py @@ -11,6 +11,8 @@ import struct import sys import time +import bench_defaults # 台架连接默认值单一真源 + # {idx: (tx_len, close_mode)} 与固件表一致 VARS = { 0: (100, 0), # 0ms control @@ -125,7 +127,7 @@ def e4_round(host, rg, rounds_per_variant, first_budget): def main(): ap = argparse.ArgumentParser() - ap.add_argument("--host", default="192.168.1.100") + ap.add_argument("--host", default=bench_defaults.DEVICE_IP) ap.add_argument("--cycles", type=int, default=3) ap.add_argument("--mode", choices=["legacy", "e4"], default="legacy") ap.add_argument("--rounds", type=int, default=10, help="e4: rounds per variant") diff --git a/test/host/ch395f_socket_test.py b/test/host/ch395f_socket_test.py index 095140bd..bda6c800 100644 --- a/test/host/ch395f_socket_test.py +++ b/test/host/ch395f_socket_test.py @@ -19,7 +19,7 @@ CH395F BSD Socket API 测试程序 tcp_file - 文件收发:PC 作 Client 连 MCU:8080(阶段 8),--op send/recv 收发 100KB 文件(含 CRC32) 选项: - --ip 目标 IP 地址(默认: 192.168.1.100) + --ip 目标 IP 地址(默认见 bench_defaults.DEVICE_IP) --port 端口号(默认: 8080) --count 测试次数(默认: 10) --size 数据包大小(默认: 1024) @@ -28,7 +28,7 @@ CH395F BSD Socket API 测试程序 示例: # 测试 CH395F TCP Server - python ch395f_socket_test.py tcp_client --ip 192.168.1.100 --port 8080 + python ch395f_socket_test.py tcp_client --port 8080 # 测试 CH395F TCP Client python ch395f_socket_test.py tcp_server --port 8080 @@ -37,18 +37,18 @@ CH395F BSD Socket API 测试程序 python ch395f_socket_test.py udp_server --port 8888 # 测试 CH395F UDP Server - python ch395f_socket_test.py udp_client --ip 192.168.1.100 --port 8888 + python ch395f_socket_test.py udp_client --port 8888 # 压力测试(多连接) - python ch395f_socket_test.py stress --ip 192.168.1.100 --port 8080 --count 7 + python ch395f_socket_test.py stress --port 8080 --count 7 # 阶段 5 双向大块(先收 256KB 再回放 256KB) python ch395f_socket_test.py tcp_bulk --port 8081 --bulk 262144 --chunk 4096 # 阶段 8 文件收发(PC 连 MCU:8080) - python ch395f_socket_test.py tcp_file --ip 192.168.1.100 --port 8080 --op recv --file rx_100k.bin --size 102400 - python ch395f_socket_test.py tcp_file --ip 192.168.1.100 --port 8080 --op send --file tx_100k.bin - python ch395f_socket_test.py tcp_file --ip 192.168.1.100 --port 8080 --op echo # TC-NET-803 回显(MCU 为 server) + python ch395f_socket_test.py tcp_file --port 8080 --op recv --file rx_100k.bin --size 102400 + python ch395f_socket_test.py tcp_file --port 8080 --op send --file tx_100k.bin + python ch395f_socket_test.py tcp_file --port 8080 --op echo # TC-NET-803 回显(MCU 为 server) """ import socket @@ -63,6 +63,8 @@ import string import zlib from datetime import datetime +import bench_defaults # 台架连接默认值单一真源 + # TCP 回显服务器(tcp_server 模式)参数 INTER_ACCEPT_TIMEOUT = 60 # 首个连接后,等待下一个连接的超时秒数 ECHO_IDLE_TIMEOUT = 30 # 连接内无数据的空闲超时秒数 @@ -963,7 +965,7 @@ def dhcp_server_test(args): options) # Try both global broadcast and subnet broadcast - for bcast in ['255.255.255.255', '192.168.1.255']: + for bcast in ['255.255.255.255', bench_defaults.NET_BCAST]: sock.sendto(offer, (bcast, DHCP_CLIENT_PORT)) log_success("发送 DHCP OFFER") @@ -994,7 +996,7 @@ def dhcp_server_test(args): _ip_to_bytes(offer_ip), _ip_to_bytes(server_ip), ack_options) - for bcast in ['255.255.255.255', '192.168.1.255']: + for bcast in ['255.255.255.255', bench_defaults.NET_BCAST]: sock.sendto(ack, (bcast, DHCP_CLIENT_PORT)) log_success(f"发送 DHCP ACK → {offer_ip}") log_success("DHCP 分配完成!") @@ -1016,7 +1018,7 @@ def dhcp_server_test(args): _ip_to_bytes(offer_ip), _ip_to_bytes(server_ip), options) - for bcast in ['255.255.255.255', '192.168.1.255']: + for bcast in ['255.255.255.255', bench_defaults.NET_BCAST]: sock.sendto(offer, (bcast, DHCP_CLIENT_PORT)) log_info(f"重发 DHCP OFFER (retry={retry+1})") except socket.timeout: @@ -1245,10 +1247,10 @@ def main(): formatter_class=argparse.RawDescriptionHelpFormatter, epilog=""" 示例: - %(prog)s tcp_client --ip 192.168.1.100 --port 8080 + %(prog)s tcp_client --port 8080 %(prog)s tcp_server --port 8080 - %(prog)s stress --ip 192.168.1.100 --port 8080 --count 5 - %(prog)s dhcp_server --dhcp-iface 192.168.1.2 --ip 192.168.1.100 + %(prog)s stress --port 8080 --count 5 + %(prog)s dhcp_server --dhcp-iface --ip <设备 IP> %(prog)s tcp_bulk --port 8081 --bulk 262144 --chunk 4096 """ ) @@ -1257,7 +1259,7 @@ def main(): 'tcp_echo', 'udp_echo', 'stress', 'packet_size', 'dhcp_server', 'tcp_bulk', 'tcp_file'], help='测试模式') - parser.add_argument('--ip', default='192.168.1.100', help='目标 IP 地址 / DHCP 待分配 IP') + parser.add_argument('--ip', default=bench_defaults.DEVICE_IP, help='目标 IP 地址 / DHCP 待分配 IP') parser.add_argument('--port', type=int, default=8080, help='端口号') parser.add_argument('--count', type=int, default=10, help='测试次数') parser.add_argument('--size', type=int, default=1024, help='数据包大小') @@ -1268,9 +1270,9 @@ def main(): help='tcp_file 方向: send=读文件发往 MCU, recv=从 MCU 收文件落盘, echo=连 MCU 回显') parser.add_argument('--file', default=None, help='tcp_file 文件路经(send: 读取; recv: 写入)') parser.add_argument('--max-conn', type=int, default=0, help='最大并发连接数(默认0=不限;按并发计数,非累计,TC-NET-704 并发测试用 8)') - parser.add_argument('--dhcp-iface', default='192.168.1.2', help='DHCP 服务器网卡 IP') + parser.add_argument('--dhcp-iface', default=bench_defaults.PC_IP, help='DHCP 服务器网卡 IP') parser.add_argument('--dhcp-mask', default='255.255.255.0', help='DHCP 分配的子网掩码') - parser.add_argument('--dhcp-gw', default='192.168.1.1', help='DHCP 分配的网关') + parser.add_argument('--dhcp-gw', default=bench_defaults.DEVICE_GW, help='DHCP 分配的网关') args = parser.parse_args() diff --git a/test/host/e02_probe.py b/test/host/e02_probe.py index 34780b7e..f5c611b8 100644 --- a/test/host/e02_probe.py +++ b/test/host/e02_probe.py @@ -27,7 +27,9 @@ import socket import sys import time -DEV = "192.168.1.100" +import bench_defaults # 台架连接默认值单一真源 + +DEV = bench_defaults.DEVICE_IP tag = sys.argv[1] if len(sys.argv) > 1 else "run" t0 = time.time() diff --git a/test/host/e11_keepalive_probe.py b/test/host/e11_keepalive_probe.py index 3dc4c178..d2b6aec4 100644 --- a/test/host/e11_keepalive_probe.py +++ b/test/host/e11_keepalive_probe.py @@ -30,6 +30,8 @@ import subprocess import sys import time +import bench_defaults # 台架连接默认值单一真源 + TAG_C, TAG_D = 0xAA, 0xBB CMD_KEEPLIVE = 0 RULE_NAME = "SELFHEAL-E11-DROP" @@ -88,7 +90,7 @@ def connect(host: str, port: int, timeout: float = 5.0): def main() -> int: ap = argparse.ArgumentParser() - ap.add_argument("--host", default="192.168.1.100") + ap.add_argument("--host", default=bench_defaults.DEVICE_IP) ap.add_argument("--port", type=int, default=7003) ap.add_argument("--mode", choices=["idle", "block"], required=True) ap.add_argument("--hold-s", type=float, default=90.0) diff --git a/test/host/ftp_abort_probe.py b/test/host/ftp_abort_probe.py index d7ce1fa5..aa5f89cf 100644 --- a/test/host/ftp_abort_probe.py +++ b/test/host/ftp_abort_probe.py @@ -19,6 +19,8 @@ import argparse, hashlib, io, random, re, socket, struct, sys, time from ftplib import FTP, all_errors +import bench_defaults # 台架连接默认值单一真源 + def log(m): sys.stdout.write(m + "\n"); sys.stdout.flush() @@ -66,7 +68,7 @@ def followup_ok(ip, port, size=4096): def main(): ap = argparse.ArgumentParser() - ap.add_argument("--ip", default="192.168.1.100") + ap.add_argument("--ip", default=bench_defaults.DEVICE_IP) ap.add_argument("--port", type=int, default=21) ap.add_argument("--rounds", type=int, default=10) ap.add_argument("--send", type=int, default=8192, help="bytes sent before the RST") diff --git a/test/host/ftp_auth_bench.py b/test/host/ftp_auth_bench.py index 9723d033..715e81d6 100644 --- a/test/host/ftp_auth_bench.py +++ b/test/host/ftp_auth_bench.py @@ -16,7 +16,7 @@ 注意:CH395F 单连接——每步用完必须 quit() 释放 socket,否则下一步连不上; 跑之前确保 UI 远程显示(7003)/对时(8888)客户端未占用 socket。 -用法(设备默认 192.168.1.100,出厂口令 admin/admin): +用法(设备默认见 bench_defaults.DEVICE_IP,出厂口令 admin/admin): & '.venv\\Scripts\\python.exe' test/host/ftp_auth_bench.py 改过口令: ... --pwd <新口令> 跳过 60s 锁定等待(只验锁定触发不验解锁): ... --skip-unlock @@ -32,6 +32,8 @@ import sys import time from ftplib import FTP, error_perm +import bench_defaults # 台架连接默认值单一真源 + LOCK_WAIT_S = 62 # 固件锁定 60 s + 余量 @@ -66,7 +68,7 @@ def _try_login(host, port, timeout, user, pwd): def main(argv=None): ap = argparse.ArgumentParser(description="FTP auth bench matrix") - ap.add_argument("--host", default="192.168.1.100") + ap.add_argument("--host", default=bench_defaults.DEVICE_IP) ap.add_argument("--port", type=int, default=21) ap.add_argument("--timeout", type=int, default=15) ap.add_argument("--user", default="admin") diff --git a/test/host/ftp_integrity_test.py b/test/host/ftp_integrity_test.py index 246a3571..f86bef31 100644 --- a/test/host/ftp_integrity_test.py +++ b/test/host/ftp_integrity_test.py @@ -26,6 +26,8 @@ import sys import time from ftplib import FTP, error_perm +import bench_defaults # 台架连接默认值单一真源 + NAME = "e12a.bin" # 8.3 短名(FatFs FF_USE_LFN=0) @@ -45,7 +47,7 @@ def first_diff(a: bytes, b: bytes): def main() -> int: ap = argparse.ArgumentParser() - ap.add_argument("--host", default="192.168.1.100") + ap.add_argument("--host", default=bench_defaults.DEVICE_IP) ap.add_argument("--port", type=int, default=21) ap.add_argument("--user", default="admin") ap.add_argument("--pwd", default="admin") diff --git a/test/host/ftp_list_fill_test.py b/test/host/ftp_list_fill_test.py index 175ef533..bc4163be 100644 --- a/test/host/ftp_list_fill_test.py +++ b/test/host/ftp_list_fill_test.py @@ -16,7 +16,7 @@ break 并回 -1,cmd_list 据此回 **550**——目录一大,客户端拿到 3. LIST 的完成回包是 226 而不是 550(ftplib 在非 2xx 完成时会抛异常,正是这条) 清理:无论成败都逐个 DELE;删除失败会打 WARN(不影响判定,但会留残留文件要手清)。 -用法:python ftp_list_fill_test.py [--host 192.168.1.100] [--files 26] +用法:python ftp_list_fill_test.py [--host <设备IP>] [--files 26] [--user admin] [--password admin] 注:--files 26 是按每行约 63 B 反推的下限(26×63 ≈ 1638 > 1536);目录本来就有 条目时更小也能触发,取 26 保证空目录也能越过一块。 @@ -27,7 +27,9 @@ import io import sys from ftplib import FTP, all_errors -HOST = "192.168.1.100" +import bench_defaults # 台架连接默认值单一真源 + +HOST = bench_defaults.DEVICE_IP PORT = 21 # 设备无匿名通道:账号取 /config.ini 的 [ftp],出厂默认 admin/admin USER = "admin" diff --git a/test/host/ftp_regression.py b/test/host/ftp_regression.py index 3a710f11..676aa224 100644 --- a/test/host/ftp_regression.py +++ b/test/host/ftp_regression.py @@ -12,7 +12,7 @@ net 层当作"刚建立就断开"释放。修复见 net_socket.c handle_disconne 内容校验;任一环节失败即退出码 1。 用法: - & '.venv\\Scripts\\python.exe' test/host/ftp_regression.py --host 192.168.1.100 + & '.venv\\Scripts\\python.exe' test/host/ftp_regression.py --host <设备IP> """ import argparse @@ -21,13 +21,15 @@ import sys import time from ftplib import FTP +import bench_defaults # 台架连接默认值单一真源 + SMALL = b"D20-small-" + b"A" * 1017 # 1024B BIG = bytes(((i * 7 + 3) & 0xFF) for i in range(32768)) # 32KB 模式数据 def main(argv=None): ap = argparse.ArgumentParser(description="FTP data-connection regression (D20)") - ap.add_argument("--host", default="192.168.1.100", help="device IP") + ap.add_argument("--host", default=bench_defaults.DEVICE_IP, help="device IP") ap.add_argument("--port", type=int, default=21, help="FTP control port") ap.add_argument("--timeout", type=int, default=20, help="socket timeout (s)") # 2026-10-11 起 FTP 强制鉴权:匿名登录被 530 拒;默认口令 admin/admin diff --git a/test/host/ftp_speed_test.py b/test/host/ftp_speed_test.py index 2a5971e2..b1bf3793 100644 --- a/test/host/ftp_speed_test.py +++ b/test/host/ftp_speed_test.py @@ -1,7 +1,7 @@ #!/usr/bin/env python3 """ FTP 速度测试 — 上传/下载大文件,测量传输速度 -用法:python ftp_speed_test.py --host 192.168.1.100 [--size 512] [--port 21] +用法:python ftp_speed_test.py --host <设备IP> [--size 512] [--port 21] [--user admin] [--password admin] """ @@ -12,7 +12,9 @@ import re import argparse import os -HOST = "192.168.1.100" +import bench_defaults # 台架连接默认值单一真源 + +HOST = bench_defaults.DEVICE_IP PORT = 21 # 设备侧 FTP 鉴权走 /config.ini 的 [ftp](user / pwd_hash),出厂默认 admin/admin; # **没有匿名通道**(USER anonymous 一律回 530)。 diff --git a/test/host/ftp_test.py b/test/host/ftp_test.py index b55df586..649155c9 100644 --- a/test/host/ftp_test.py +++ b/test/host/ftp_test.py @@ -2,7 +2,7 @@ # -*- coding: utf-8 -*- """ FTP Server 测试脚本 — 连接 STM32F4 上的 lftpd 服务器 -用法:python ftp_test.py [--host 192.168.1.100] [--port 21] [--user admin] [--password admin] +用法:python ftp_test.py [--host <设备IP>] [--port 21] [--user admin] [--password admin] """ import socket @@ -10,7 +10,9 @@ import sys import time import argparse -HOST = "192.168.1.100" +import bench_defaults # 台架连接默认值单一真源 + +HOST = bench_defaults.DEVICE_IP PORT = 21 # 设备侧 FTP 鉴权走 /config.ini 的 [ftp](user / pwd_hash),出厂默认 admin/admin; # **没有匿名通道**(USER anonymous 一律回 530)。 diff --git a/test/host/ftp_up_dl_test.py b/test/host/ftp_up_dl_test.py index 8fbc2f2f..9a199c66 100644 --- a/test/host/ftp_up_dl_test.py +++ b/test/host/ftp_up_dl_test.py @@ -2,7 +2,7 @@ # -*- coding: utf-8 -*- """ FTP 上传+下载测试脚本 -用法:python ftp_up_dl_test.py --host 192.168.1.100 [--user admin] [--password admin] +用法:python ftp_up_dl_test.py --host <设备IP> [--user admin] [--password admin] """ import socket @@ -12,7 +12,9 @@ import re import argparse import os -HOST = "192.168.1.100" +import bench_defaults # 台架连接默认值单一真源 + +HOST = bench_defaults.DEVICE_IP PORT = 21 # 设备侧 FTP 鉴权走 /config.ini 的 [ftp](user / pwd_hash = SHA-256(user‖password)), # 出厂默认 admin/admin;**没有匿名通道**(USER anonymous 一律回 530)。 diff --git a/test/host/iec104_master.py b/test/host/iec104_master.py index 63f4ef9a..15576d07 100644 --- a/test/host/iec104_master.py +++ b/test/host/iec104_master.py @@ -30,7 +30,7 @@ round-trip log as bench evidence). RX decode fix (2026-10-25, task-21/m104fix): cause-byte semantics above; offline sample-frame selftest: python test/host/test_iec104_master_rx.py -Usage: python iec104_master.py [--ip 192.168.1.100] [--port 2404] +Usage: python iec104_master.py [--ip <设备IP>] [--port 2404] [--addr 0x8858] [--low 0.05] [--restore 10.0] @@ -49,6 +49,8 @@ bench leg, firmware side App/cfg/prot_set_store.c): """ import argparse import collections + +import bench_defaults # 台架连接默认值单一真源 import socket import struct import sys @@ -469,7 +471,7 @@ def b7_check(m, ck, args): def main(): ap = argparse.ArgumentParser(description=__doc__.splitlines()[0]) - ap.add_argument("--ip", default="192.168.1.100") + ap.add_argument("--ip", default=bench_defaults.DEVICE_IP) ap.add_argument("--port", type=int, default=2404) ap.add_argument("--addr", default="0x8858", help="setpoint comm addr to drive COV (OC1 current)") diff --git a/test/host/latency_peer.py b/test/host/latency_peer.py index 876d54b6..0656a871 100644 --- a/test/host/latency_peer.py +++ b/test/host/latency_peer.py @@ -18,7 +18,7 @@ per-batch arrival curve / >=500ms spikes (TCP retransmission fingerprint). Both the serial log and this JSON carry HOST timestamps -> direct correlation. Usage: - python latency_peer.py --host 192.168.1.100 --port 8080 --json m2_net.json + python latency_peer.py --port 8080 --json m2_net.json python latency_peer.py --mode net --ftp-stress ... (head-of-line repro) Pure stdlib (socket/json/time/argparse/threading). ASCII output only. @@ -31,6 +31,8 @@ import sys import threading import time +import bench_defaults # 台架连接默认值单一真源 + # --- Protocol constants (mirror test/board/net_latency_test.c Phase 13 defines) --- HELLO = b"\x5a\xa5\x58\x01" OP_QUEUE_RT_RECV = 0x01 @@ -783,7 +785,7 @@ def main(argv=None): ap.add_argument("--mode", default="net", choices=["net", "remo"], help="net = Phase 13 test protocol :8080; " "remo = production RemoDispBus client :7003 (Phase 14 / simulator)") - ap.add_argument("--host", default="192.168.1.100", help="device IP") + ap.add_argument("--host", default=bench_defaults.DEVICE_IP, help="device IP") ap.add_argument("--port", type=int, default=None, help="listen port (default: 8080 for net, 7003 for remo)") ap.add_argument("--wait", type=int, default=180, diff --git a/test/host/lftpd/lftpd_test.c b/test/host/lftpd/lftpd_test.c index 9f94eecf..95883655 100644 --- a/test/host/lftpd/lftpd_test.c +++ b/test/host/lftpd/lftpd_test.c @@ -346,7 +346,7 @@ int net_getsockname(int sockfd, struct net_sockaddr *addr, int *addrlen) (void)sockfd; (void)addrlen; - a->sin_addr.s_addr = 0x0101A8C0u; /* 192.168.1.1 的宿主序表示(假件自定) */ + a->sin_addr.s_addr = 0x011FA8C0u; /* 192.168.31.1 的宿主序表示(假件自定) */ a->sin_port = net_htons(21u); return g_sockname_rc; } @@ -512,7 +512,7 @@ static void tc_passive(void) /* 直调处理器:走 handle_control_channel 的话,会话退出时 cleanup 一定把被动监听 关掉(那正是 TC-LFTPD-006 要验的行为),这里要看的是 PASV 自己留下的状态。 */ (void)cmd_pasv(&g_cli, NULL); - CHECK((strcmp(rep(0), "227 Entering Passive Mode (192,168,1,1,19,136).\r\n") == 0) && + CHECK((strcmp(rep(0), "227 Entering Passive Mode (192,168,31,1,19,136).\r\n") == 0) && (g_cli.data_socket == 20) && (g_n.listen_calls == 1), "TC-LFTPD-011 the 227 tuple: ip through htonl then high byte to low byte (dotted order), port high/low, and the passive listen handle is recorded"); diff --git a/test/host/n30_repro.py b/test/host/n30_repro.py index 6fcac6f2..7dd2501e 100644 --- a/test/host/n30_repro.py +++ b/test/host/n30_repro.py @@ -6,10 +6,12 @@ import io import sys from ftplib import FTP, error_temp, error_perm +import bench_defaults # 台架连接默认值单一真源 + def main(): ap = argparse.ArgumentParser() - ap.add_argument("--host", default="192.168.1.100") + ap.add_argument("--host", default=bench_defaults.DEVICE_IP) ap.add_argument("--port", type=int, default=21) ap.add_argument("--user", default=None, help="None=anonymous") ap.add_argument("--pwd", default=None) diff --git a/test/host/net_cfg/net_cfg_test.c b/test/host/net_cfg/net_cfg_test.c index 42741e9f..635199cb 100644 --- a/test/host/net_cfg/net_cfg_test.c +++ b/test/host/net_cfg/net_cfg_test.c @@ -32,9 +32,9 @@ * * 覆盖点: * —— 出厂默认(load 之前也必须可用,TC-NETCFG-001..004)—— - * TC-NETCFG-001 未 load 时 ip = 工厂默认 192.168.1.100 + * TC-NETCFG-001 未 load 时 ip = 工厂默认 192.168.31.100 * TC-NETCFG-002 未 load 时 mask = 255.255.255.0 - * TC-NETCFG-003 未 load 时 gw = 192.168.1.1 + * TC-NETCFG-003 未 load 时 gw = 192.168.31.1 * TC-NETCFG-004 未 load 时 mac = 全零(哨兵 = 不覆盖芯片内置 MAC) * —— 注册与 load(TC-NETCFG-005..011)—— * TC-NETCFG-005 首次 load 注册 [network] 段恰好一次(且 load 返回 0) @@ -257,15 +257,15 @@ static void save_hook_probe(void) static void tc_defaults(void) { const net_cfg_t *p = net_cfg_get(); - static const uint8_t def_ip[4] = { 192u, 168u, 1u, 100u }; + static const uint8_t def_ip[4] = { 192u, 168u, 31u, 100u }; static const uint8_t def_mask[4] = { 255u, 255u, 255u, 0u }; - static const uint8_t def_gw[4] = { 192u, 168u, 1u, 1u }; + static const uint8_t def_gw[4] = { 192u, 168u, 31u, 1u }; static const uint8_t zero[6] = { 0u, 0u, 0u, 0u, 0u, 0u }; printf("-- TC-NETCFG-001..004 defaults before load --\n"); - CHECK(bytes_eq(p->ip, def_ip, 4u), "TC-NETCFG-001 ip = 192.168.1.100"); + CHECK(bytes_eq(p->ip, def_ip, 4u), "TC-NETCFG-001 ip = 192.168.31.100"); CHECK(bytes_eq(p->mask, def_mask, 4u), "TC-NETCFG-002 mask = 255.255.255.0"); - CHECK(bytes_eq(p->gw, def_gw, 4u), "TC-NETCFG-003 gw = 192.168.1.1"); + CHECK(bytes_eq(p->gw, def_gw, 4u), "TC-NETCFG-003 gw = 192.168.31.1"); CHECK(mac_eq(p->mac, zero), "TC-NETCFG-004 mac = all zero (chip built-in sentinel)"); } diff --git a/test/host/net_events/net_events_test.c b/test/host/net_events/net_events_test.c index 5eef16b2..ba4af754 100644 --- a/test/host/net_events/net_events_test.c +++ b/test/host/net_events/net_events_test.c @@ -209,13 +209,13 @@ static void tc_connect(void) printf("-- TC-NETEV-001..006 CONNECT --\n"); reset_all(); p = mk(0, NET_SOCK_STATE_LISTENING, 2404u); - ch395f_fake_set_peer(0, 192u, 168u, 1u, 50u, 51234u); + ch395f_fake_set_peer(0, 192u, 168u, 31u, 50u, 51234u); handle_connect_event(p); /* remote_ip 是**低字节在前**拼的(remote[0] 落在最低 8 位),与网络序相反: - * 192.168.1.50 -> 0x3201A8C0。这是既有实现的字节序,钉住它是防止有人"顺手 + * 192.168.31.50 -> 0x321FA8C0。这是既有实现的字节序,钉住它是防止有人"顺手 * 改成大端"导致所有按 IP 比对/白名单的判断静默错位。 */ CHECK((p->remote_ip_arr[0] == 192u) && (p->remote_ip_arr[3] == 50u) && - (p->remote_ip == ((192u) | (168u << 8) | (1u << 16) | (50u << 24))) && + (p->remote_ip == ((192u) | (168u << 8) | (31u << 16) | (50u << 24))) && (p->remote_port == 51234u), "TC-NETEV-001 peer tuple parsing: ip assembled little-endian into 32 bits, port from bytes 5/6"); CHECK((p->state == NET_SOCK_STATE_ESTABLISHED) && (p->session_dead == 0u) && diff --git a/test/host/net_socket/net_socket_test.c b/test/host/net_socket/net_socket_test.c index 0c924647..74d99bd5 100644 --- a/test/host/net_socket/net_socket_test.c +++ b/test/host/net_socket/net_socket_test.c @@ -121,7 +121,7 @@ static void bring_up(void) * 调用的(App/task/net_task.c:92),而本层执行任务句柄(UDP 上下文守卫的判据) * 正是在这里捕获——这里若不换身份,整个 UDP 守卫就只能测到"自己判自己" */ g_ns_cur_task = (TaskHandle_t)&g_ns_task_net; - (void)net_init("192.168.1.100", "255.255.255.0", "192.168.1.1", NULL); + (void)net_init("192.168.31.100", "255.255.255.0", "192.168.31.1", NULL); g_ns_cur_task = (TaskHandle_t)&g_ns_task_caller; g_peers.pending_capture_calls = 0; /* bring_up 内部的登记动作不该算进场景 */ g_ns_error_count = 0; @@ -160,13 +160,13 @@ static int mk_sock(int type, net_sock_state_t state) /* TC-NETSOCK-100 点分十进制 ↔ 32 位:**正向断言**(字节序统一修复后) * 全仓唯一约定:s_addr 是网络字节序整数,&s_addr 的第 0 个内存字节 == 点分第一段; - * 小端主机上 "192.168.1.100" 的数值 = 0x6401A8C0。本组断言的落点是「互逆」与 + * 小端主机上 "192.168.31.100" 的数值 = 0x641FA8C0。本组断言的落点是「互逆」与 * 「同族可比」,不是某个中间数值——数值只是这条约定的一个投影。 */ static void tc_100_inet_helpers(void) { /* 往返不变量的样本集:两个全零/全一边界 + 三个非回文地址(非回文才能考出顺位) */ static const char *const k_ips[5] = { - "0.0.0.0", "255.255.255.255", "1.1.1.1", "192.168.1.100", "10.0.0.0" + "0.0.0.0", "255.255.255.255", "1.1.1.1", "192.168.31.100", "10.0.0.0" }; char buf[16]; int i; @@ -174,12 +174,12 @@ static void tc_100_inet_helpers(void) reset_all(); CHECK(net_inet_addr(NULL) == 0U, "TC-NETSOCK-100a inet_addr(NULL) returns 0 (invalid)"); - CHECK(net_inet_addr("192.168.1.100") == 0x6401A8C0U, - "TC-NETSOCK-100b inet_addr returns network-order int (LE value 0x6401A8C0 = bytes C0 A8 01 64)"); - CHECK(net_inet_ntoa(net_inet_addr("192.168.1.100"), buf) == buf && - strcmp(buf, "192.168.1.100") == 0, + CHECK(net_inet_addr("192.168.31.100") == 0x641FA8C0U, + "TC-NETSOCK-100b inet_addr returns network-order int (LE value 0x641FA8C0 = bytes C0 A8 1F 64)"); + CHECK(net_inet_ntoa(net_inet_addr("192.168.31.100"), buf) == buf && + strcmp(buf, "192.168.31.100") == 0, "TC-NETSOCK-100c ntoa(inet_addr(s)) == s: the two are exact inverses"); - CHECK(net_inet_ntoa(0x6401A8C0U, buf) == buf && strcmp(buf, "192.168.1.100") == 0, + CHECK(net_inet_ntoa(0x641FA8C0U, buf) == buf && strcmp(buf, "192.168.31.100") == 0, "TC-NETSOCK-100d ntoa segment order is MSB-first (fixed by E13/TRAP-NET-21, unchanged here)"); CHECK(net_inet_ntoa(0U, NULL) == NULL, "TC-NETSOCK-100e ntoa(NULL buf) returns NULL without crashing"); CHECK(net_inet_addr("10.0.0.1") == 0x0100000AU, @@ -237,8 +237,8 @@ static void tc_102_parse_ip(void) (void)memset(a, 0xEE, sizeof(a)); parse_ip_string(NULL, a); CHECK(a[0] == 0xEEU, "TC-NETSOCK-102a parse_ip_string(NULL) returns at once, target buffer untouched"); - parse_ip_string("192.168.1.100", a); - CHECK(a[0] == 192U && a[1] == 168U && a[2] == 1U && a[3] == 100U, + parse_ip_string("192.168.31.100", a); + CHECK(a[0] == 192U && a[1] == 168U && a[2] == 31U && a[3] == 100U, "TC-NETSOCK-102b parse_ip_string puts segment 0 at [0] (the order chip set_ip_addr wants)"); parse_ip_string("10.20.30.40", NULL); /* 只验不崩 */ CHECK(1, "TC-NETSOCK-102c parse_ip_string with NULL target does not crash"); @@ -333,7 +333,7 @@ static void tc_105_bind(void) (void)memset(&in, 0, sizeof(in)); in.sin_family = NET_AF_INET; in.sin_port = net_htons(2404); - in.sin_addr.s_addr = net_inet_addr("192.168.1.100"); + in.sin_addr.s_addr = net_inet_addr("192.168.31.100"); CHECK(net_bind(-1, (struct net_sockaddr *)&in, sizeof(in)) == -1 && net_get_errno() == NET_ERR_BADF, "TC-NETSOCK-105a out of range fd -> BADF"); @@ -442,7 +442,7 @@ static void tc_107_peer_and_localname(void) int fd; reset_all(); - (void)net_init("192.168.1.100", "255.255.255.0", "192.168.1.1", NULL); + (void)net_init("192.168.31.100", "255.255.255.0", "192.168.31.1", NULL); CHECK(net_getsockname(-1, sa, &addrlen) == -1 && net_get_errno() == NET_ERR_BADF, "TC-NETSOCK-107a getsockname out of range -> BADF"); @@ -460,10 +460,10 @@ static void tc_107_peer_and_localname(void) addrlen == (int)sizeof(in), "TC-NETSOCK-107e fills family, port (network order) and length"); /* 钉**具体顺位**而不是二选一:getsockname 走的是「首段在最低字节」这一族 - * (与 net_inet_ntoa、net_events 的 remote_ip 同族),所以 192.168.1.100 = - * 0x6401A8C0。net_inet_addr 返回的是另一族(首段在最高字节,0xC0A80164), + * (与 net_inet_ntoa、net_events 的 remote_ip 同族),所以 192.168.31.100 = + * 0x641FA8C0。net_inet_addr 返回的是另一族(首段在最高字节,0xC0A81F64), * 两族不互逆——已作为疑似缺陷报出,这里刻意不写成「两个都行」。 */ - CHECK(in.sin_addr.s_addr == 0x6401A8C0U, + CHECK(in.sin_addr.s_addr == 0x641FA8C0U, "TC-NETSOCK-107f local IP byte order = first octet in low byte (ntoa family)"); addrlen = 1; diff --git a/test/host/net_socket/ns_s5_io.c b/test/host/net_socket/ns_s5_io.c index b98c81ed..eb95f062 100644 --- a/test/host/net_socket/ns_s5_io.c +++ b/test/host/net_socket/ns_s5_io.c @@ -33,7 +33,7 @@ static void tc_400_net_init_downlink(void) /* 1) 芯片不在位:直接失败,且不得继续下发任何参数 */ reset_all(); g_fx.exist_rc = (int)CH395F_STATUS_NOT_DETECTED; - CHECK(net_init("192.168.1.100", "255.255.255.0", "192.168.1.1", NULL) == -1, + CHECK(net_init("192.168.31.100", "255.255.255.0", "192.168.31.1", NULL) == -1, "TC-NETSOCK-400a chip not present -> -1"); CHECK(g_fxchip.reset_calls == 0 && g_fxchip.init_calls == 0, "TC-NETSOCK-400b when absent it must not reset or initialise (do not drag the error into the stack)"); @@ -42,21 +42,21 @@ static void tc_400_net_init_downlink(void) /* 2) 协议栈初始化失败 */ reset_all(); g_fx.init_rc = (int)CH395F_STATUS_ERROR; - CHECK(net_init("192.168.1.100", "255.255.255.0", "192.168.1.1", NULL) == -1, + CHECK(net_init("192.168.31.100", "255.255.255.0", "192.168.31.1", NULL) == -1, "TC-NETSOCK-400d ch395f_init failure -> -1"); CHECK(g_fxchip.ping_calls == 0, "TC-NETSOCK-400e after an init failure PING must not be enabled (half-configured state)"); /* 3) 版本门控:低于 0x46 必须**拒置** bit3(SOCKET_CLOSE),退回芯片自动关断 */ reset_all(); g_fx.version = 0x45U; - CHECK(net_init("192.168.1.100", "255.255.255.0", "192.168.1.1", NULL) == 0, + CHECK(net_init("192.168.31.100", "255.255.255.0", "192.168.31.1", NULL) == 0, "TC-NETSOCK-400f a too-old version is not fatal: bring-up continues"); CHECK(g_fx.fun_para == 0U && g_ns_error_count == 1, "TC-NETSOCK-400g ver<0x46 -> FUN_PARA actually sends 0 (bit3 refused) plus [ERR], never silently degraded"); /* 4) 版本够新:FUN_PARA=0x08;bit1(TCP_SERVER 多连接) 与 bit0(保留) 都必须为 0 */ reset_all(); - CHECK(net_init("192.168.1.100", "255.255.255.0", "192.168.1.1", NULL) == 0, + CHECK(net_init("192.168.31.100", "255.255.255.0", "192.168.31.1", NULL) == 0, "TC-NETSOCK-400h normal initialisation succeeds"); /* bit3=SOCKET_CLOSE 要置;bit1=TCP_SERVER 多连接(本项目单连接模型)与 * bit0=保留位都必须为 0——旧实现把 0x09 当「多 Socket 模式」下发,2026-10-11 @@ -76,7 +76,7 @@ static void tc_400_net_init_downlink(void) "TC-NETSOCK-400l SET-class commands (MSS/KeepAlive) come before INIT_CH395 (manual hard requirement)"); /* 5) IP/掩码/网关三样都按点分顺位下发,并缓存本机 IP 供 getsockname 用 */ - CHECK(g_fx.ip[0] == 192U && g_fx.ip[1] == 168U && g_fx.ip[2] == 1U && + CHECK(g_fx.ip[0] == 192U && g_fx.ip[1] == 168U && g_fx.ip[2] == 31U && g_fx.ip[3] == 100U && g_fx.gw[3] == 1U && g_fx.mask[0] == 255U, "TC-NETSOCK-400m IP, gateway and mask follow the parse_ip_string order (segment 0 lands at [0])"); CHECK(g_fxchip.set_dhcp_calls == 0 && g_fx.dhcp_enable == 0U, @@ -92,10 +92,10 @@ static void tc_400_net_init_downlink(void) /* 7) MAC:全零=用芯片内置,不下发;非零必须下发(写 EEPROM,须在 INIT 之前) */ reset_all(); - (void)net_init("192.168.1.100", "255.255.255.0", "192.168.1.1", mac_zero); + (void)net_init("192.168.31.100", "255.255.255.0", "192.168.31.1", mac_zero); CHECK(g_fxchip.set_mac_calls == 0, "TC-NETSOCK-400q all-zero MAC -> keep the chip built-in one, do not issue it"); reset_all(); - (void)net_init("192.168.1.100", "255.255.255.0", "192.168.1.1", mac_real); + (void)net_init("192.168.31.100", "255.255.255.0", "192.168.31.1", mac_real); CHECK(g_fxchip.set_mac_calls == 1 && g_fx.mac[0] == 0x02U && g_fx.mac[5] == 0x55U, "TC-NETSOCK-400r a non-zero MAC is issued (device online identity stays consistent with the UI)"); CHECK(ch395f_fake_log_find('M') < ch395f_fake_log_find('n') || @@ -104,7 +104,7 @@ static void tc_400_net_init_downlink(void) /* 8) 收发缓冲块布局:6 块/Socket,先配数据 Socket 再配监听 Socket 0(TRAP-NET-01) */ reset_all(); - (void)net_init("192.168.1.100", "255.255.255.0", "192.168.1.1", NULL); + (void)net_init("192.168.31.100", "255.255.255.0", "192.168.31.1", NULL); CHECK(g_fxchip.set_recv_buf_calls == NET_MAX_SOCKETS && g_fxchip.set_send_buf_calls == NET_MAX_SOCKETS, "TC-NETSOCK-400t all 8 sockets are explicitly reallocated (power-on defaults only cover 0-3)"); @@ -122,7 +122,7 @@ static void tc_400_net_init_downlink(void) /* 9) net_init 的第一件事是取消挂起并通知调用方(顺序错了 = 调用方永久挂死) */ reset_all(); - (void)net_init("192.168.1.100", "255.255.255.0", "192.168.1.1", NULL); + (void)net_init("192.168.31.100", "255.255.255.0", "192.168.31.1", NULL); CHECK(g_peers.pending_cancel_all_calls == 1 && g_peers.send_cancel_all_calls == 1, "TC-NETSOCK-400w both pending tables are cancelled before a rebuild (recv and send each one, missing one strands a task)"); @@ -358,7 +358,7 @@ static void tc_430_connect(void) (void)memset(&in, 0, sizeof(in)); in.sin_family = NET_AF_INET; in.sin_port = net_htons(8888); - in.sin_addr.s_addr = net_inet_addr("192.168.1.200"); + in.sin_addr.s_addr = net_inet_addr("192.168.31.200"); g_ns_cur_task = (TaskHandle_t)&g_ns_task_caller; CHECK(net_connect(fd, (struct net_sockaddr *)&in, (int)sizeof(in)) == 0, "TC-NETSOCK-430e connect command issued (asynchronous, the interrupt decides success)"); @@ -367,7 +367,7 @@ static void tc_430_connect(void) CHECK(s_net_socks[fd].remote_port == 8888U, "TC-NETSOCK-430g peer port stored in bookkeeping as host order"); CHECK(g_fx.des_ip[fd][0] == 192U && g_fx.des_ip[fd][1] == 168U && - g_fx.des_ip[fd][2] == 1U && g_fx.des_ip[fd][3] == 200U, + g_fx.des_ip[fd][2] == 31U && g_fx.des_ip[fd][3] == 200U, "TC-NETSOCK-430h destination IP issued as a big-endian array (the order set_des_ip needs, reversed means no link)"); CHECK(g_chip.set_port_calls == 1 && g_fx.des_port[fd] == 8888U, "TC-NETSOCK-430i source port issued once (SET_SOUR_PORT), the peer port goes via SET_DES_PORT=8888"); @@ -455,7 +455,7 @@ static void tc_440_udp_datagram(void) fd = net_socket(NET_AF_INET, NET_SOCK_DGRAM); (void)memset(&in, 0, sizeof(in)); in.sin_port = net_htons(8888); - in.sin_addr.s_addr = net_inet_addr("192.168.1.9"); + in.sin_addr.s_addr = net_inet_addr("192.168.31.9"); CHECK(net_sendto(fd, "hello", 5, 0, sa, (int)sizeof(in)) == 5, "TC-NETSOCK-440f sendto returns the number of bytes sent"); CHECK(g_fx.des_ip[fd][3] == 9U && g_fx.des_port[fd] == 8888U, diff --git a/test/host/net_socket/ns_s6_edges.c b/test/host/net_socket/ns_s6_edges.c index 81d92c72..105c9b50 100644 --- a/test/host/net_socket/ns_s6_edges.c +++ b/test/host/net_socket/ns_s6_edges.c @@ -402,17 +402,17 @@ static void tc_550_family_roundtrip(void) (void)memset(&in, 0, sizeof(in)); CHECK(net_getsockname(0, sa, &addrlen) == 0, "TC-NETSOCK-550a getsockname precondition ok"); - CHECK(in.sin_addr.s_addr == net_inet_addr("192.168.1.100"), + CHECK(in.sin_addr.s_addr == net_inet_addr("192.168.31.100"), "TC-NETSOCK-550b getsockname s_addr is the same family as inet_addr (direct equality)"); - CHECK(strcmp(net_inet_ntoa(in.sin_addr.s_addr, txt), "192.168.1.100") == 0, - "TC-NETSOCK-550c local address closes parse-store-print (old code printed 100.1.168.192)"); + CHECK(strcmp(net_inet_ntoa(in.sin_addr.s_addr, txt), "192.168.31.100") == 0, + "TC-NETSOCK-550c local address closes parse-store-print (old code printed 100.31.168.192)"); /* 2) connect 的对端簿记同样闭合(lftpd:864 与 104 显示走的就是这条链) */ fd = net_socket(NET_AF_INET, NET_SOCK_STREAM); (void)memset(&in, 0, sizeof(in)); in.sin_family = NET_AF_INET; in.sin_port = net_htons(2404U); - in.sin_addr.s_addr = net_inet_addr("192.168.1.200"); + in.sin_addr.s_addr = net_inet_addr("192.168.31.200"); g_ns_cur_task = (TaskHandle_t)&g_ns_task_net; CHECK(net_connect_locked(fd, sa, (int)sizeof(in)) == 0, "TC-NETSOCK-550d connect precondition ok"); @@ -420,13 +420,13 @@ static void tc_550_family_roundtrip(void) (void)memset(&in, 0, sizeof(in)); CHECK(net_getpeername(fd, sa, &addrlen) == 0, "TC-NETSOCK-550e getpeername ok (reads event cache, zero SPI)"); - CHECK(in.sin_addr.s_addr == net_inet_addr("192.168.1.200"), + CHECK(in.sin_addr.s_addr == net_inet_addr("192.168.31.200"), "TC-NETSOCK-550f getpeername peer equals the s_addr fed into net_connect"); - CHECK(strcmp(net_inet_ntoa(in.sin_addr.s_addr, txt), "192.168.1.200") == 0, + CHECK(strcmp(net_inet_ntoa(in.sin_addr.s_addr, txt), "192.168.31.200") == 0, "TC-NETSOCK-550g peer address prints right (lftpd connection-received log depends on it)"); CHECK(s_net_socks[fd].remote_ip_arr[0] == 192U && s_net_socks[fd].remote_ip_arr[3] == 200U, - "TC-NETSOCK-550h chip des_ip array stays wire order [192,168,1,200]: on-wire behaviour unchanged"); + "TC-NETSOCK-550h chip des_ip array stays wire order [192,168,31,200]: on-wire behaviour unchanged"); reset_all(); } diff --git a/test/host/pasv_probe.py b/test/host/pasv_probe.py index 32d48d03..fc10fe63 100644 --- a/test/host/pasv_probe.py +++ b/test/host/pasv_probe.py @@ -20,7 +20,9 @@ import socket import sys import time -IP_DEFAULT = "192.168.1.100" +import bench_defaults # 台架连接默认值单一真源 + +IP_DEFAULT = bench_defaults.DEVICE_IP def ftp_stor_round(ip, user, pwd, fname, payload): diff --git a/test/host/relisten_stress.py b/test/host/relisten_stress.py index f6d4a26a..518d39d7 100644 --- a/test/host/relisten_stress.py +++ b/test/host/relisten_stress.py @@ -16,10 +16,12 @@ import socket import sys import time +import bench_defaults # 台架连接默认值单一真源 + def main(): ap = argparse.ArgumentParser(description="listener reconnect stress") - ap.add_argument("--host", default="192.168.1.100") + ap.add_argument("--host", default=bench_defaults.DEVICE_IP) ap.add_argument("--port", type=int, required=True) ap.add_argument("--n", type=int, default=50) ap.add_argument("--gap-ms", type=int, default=100) diff --git a/test/host/remolcd_pull_test.py b/test/host/remolcd_pull_test.py index ef487aa0..dfc46893 100644 --- a/test/host/remolcd_pull_test.py +++ b/test/host/remolcd_pull_test.py @@ -3,7 +3,7 @@ """RemoDispBus(7003) 拉帧压力客户端:「双通道并发回归」的网络侧激励。 做什么: - 连 192.168.1.100:7003,先发 INIT 查询屏幕参数(应得 8 B:宽u16/高u16/帧字节数u32, + 连设备 IP(默认见 bench_defaults.DEVICE_IP):7003,先发 INIT 查询屏幕参数(应得 8 B:宽u16/高u16/帧字节数u32, 大端),随后按固定节拍持续发 LCDMEM(偏移 0) 拉整帧 3200 B 显存,逐帧校验 XOR 校验和与长度,统计请求数 / 应答数 / CRC 错 / 超时 / 往返延迟 min-avg-max。 可 --dump last_frame.pbm 存最后一帧(1bpp 布局与屏板帧 B 点阵段逐字节同构)。 @@ -39,7 +39,9 @@ import struct import sys import time -DEFAULT_IP = "192.168.1.100" +import bench_defaults # 台架连接默认值单一真源 + +DEFAULT_IP = bench_defaults.DEVICE_IP DEFAULT_PORT = 7003 TAG_CLIENT = 0xAA TAG_DEVICE = 0xBB diff --git a/test/host/time_sync_server.py b/test/host/time_sync_server.py index e3af15a9..ff54a22c 100644 --- a/test/host/time_sync_server.py +++ b/test/host/time_sync_server.py @@ -13,9 +13,9 @@ 字节 4..7 : 本地 Unix 时间戳,uint32,大端(主机字节序转换后由板子分解) 用法: - python time_sync_server.py # 默认推送到 192.168.1.100:8888 - python time_sync_server.py 192.168.1.100 # 指定板子 IP - python time_sync_server.py 192.168.1.100 9000 3 # 指定端口与间隔(秒) + python time_sync_server.py # 默认推送到设备 IP(bench_defaults.DEVICE_IP):8888 + python time_sync_server.py <设备IP> # 指定板子 IP + python time_sync_server.py <设备IP> 9000 3 # 指定端口与间隔(秒) 按 Ctrl+C 停止。 """ @@ -26,7 +26,9 @@ import sys import time import calendar -DEFAULT_MCU_IP = "192.168.1.100" +import bench_defaults # 台架连接默认值单一真源 + +DEFAULT_MCU_IP = bench_defaults.DEVICE_IP DEFAULT_PORT = 8888 DEFAULT_INTERVAL = 5.0