chore(编号): 存量编号全量转语义短语,门禁识别面与语料同批重打

登记簿、文档与代码注释里的存量字母加数字编号(N-x / S-x / T-x / E-x / A-x / 卡号)
一律改写为语义短语,净删 2,028 处引用;删除基线与待确认、并行分道方案、排期详述、
采集保护收尾 4 篇(内容已并入 docs/任务规划/README 与登记簿)。

门禁机器与三张账同批重打:check_ids.py 新增变更记录行豁免与第二根护栏
undecidable_total_ceiling;check_test_traceability.py 只加 stdout/stderr UTF-8
reconfigure(TC_RE 未动);check_cubemx_survival.py 的 --write 固定 newline=LF;
id_registry / id_aliases(+19 条 retired-to-phrase)/ id_known_backlog 重打。

test/ 56 个文件同步 TC 标签语义化,其中 18 个 TU 改了 CHECK / printf 里的标签文字,
是本批唯一改变构建产物的文件集合。

为什么合成一笔、不拆四笔(实测撞闸,非偏好):pre-commit 跑钩子前会 stash 未 staged
部分,拆开后中间提交必然是「新规则 + 旧语料」——实跑可判定 85.15% < 基线 86.00%、
不可判定 1,453 > 上限 1,166,编号门禁直接拦下。编号识别面与它描述的语料只能同码移动。

实跑基线(工作区全量):754 文件 / 8,230 处编号字面量 / 可判定 7,079 = 86.01%
(基线 86.0%,容差 0.1pp)/ 不可判定绝对数 1,151(上限 1,166)/ 校验 1-6 错误级 0 /
告警 = 悬空 2(App/algo/freq.c 的 S2,属 §4.4 同号不同义)+ 孤儿 50。

基线从 84.0 抬到 86.0 的理由见 docs/门禁说明/id-check.md §7.6:本批真删了 2,028 处
引用,可判定面随真实内容上升,不是把分母做小。同批新增排除 docs/硬件平台/ 语料,使
识别面少 264 处——芯片手册位号与网表料号不属编号空间(registry 有 excluded_paths_note)。

⚠ 余量只剩 0.11pp(约 10 处)与绝对数 15 处:把「可判定的引用」改成散文会立刻撞第二
根护栏。另遗留一项:id_aliases 里 retired 的 N / S / T / A 别名没有 scope(U1~U5 有),
今后有人新写一个 A-4,校验 3 不会响,只能靠人,建议下批补 scope。

固件不变证据:115 个 .c/.h 剥注释并归一字符串后与 HEAD 逐字节全等,残留代码差异 0;
App / Src / Drivers 的字符串字面量零改动。@build 0 错误 0 警告;40/40 主机套件、2,889
断言全通过;覆盖率 line 89.2% / func 92.6%;pre-commit 48 钩子 --all-files 全绿;
check_doc_links --all 通过(176 文档,章节引用无法判定 0);逐字节卫生核过:14 个带
BOM 文件与 HEAD 一致、0 个 CR、0 个 U+FFFD,字符串字面量纯 ASCII。

.cubemx_survival_baseline.json 的 watchdog-module 哈希 56bf27 变 2bb051 属合法:
Src/freertos.c 的 USER CODE 区内只有注释文字随编号改写,代码未变。

同批带上体积同码凭证与 RAM 台账行(@build 之后盖戳):RW_IRAM1 79,008 B / 60.3%,
RW_CCM 57,376 B / 87.9%,阈值 92%。
This commit is contained in:
2026-10-26 12:28:14 +08:00
parent 7635480e06
commit 0f7b5a87fb
253 changed files with 2234 additions and 4541 deletions
+37 -37
View File
@@ -46,7 +46,7 @@ test_stats_t g_test_stats;
* 测试目的:确认 CH395F 与 MCU 之间的 SPI 通信链路正常,所有底层命令
* 能够正确发送并得到预期回复。这是其他所有 Phase 的前提条件。
*
* 共 9 项测试(P1-01 ~ P1-09),逐项执行,汇总报告。
* 共 9 项测试,逐项执行,汇总报告。
* =================================================================== */
/* 解析点分十进制 IP 字符串为数组(避免引入 sscanf 库)。
@@ -79,12 +79,12 @@ static void phase1_run(void) {
/* 全局中断寄存器读即清,唯一读者 = net_poll(F-NET-7;用户裁定 2026-10-13:
* 测试代码同样禁自行读取)。net_stack_bring_up() 的 set_phy 强制重协商会
* 锁存 GINT_STAT_PHY_CHANGE(0x0004)——由 P1-06 内部双读自清,不在此预清。 */
* 锁存 GINT_STAT_PHY_CHANGE(0x0004)——由全局中断状态项内部双读自清,不在此预清。 */
DBG_INFO("=== CH395F Phase 1 Tests ===");
DBG_INFO("--- 9 test items (P1-01 ~ P1-09) ---");
DBG_INFO("--- 9 test items ---");
/* ---- P1-01: ch395f_check_exist() ----
/* ---- ch395f_check_exist() ----
* 原理:SPI 写入命令 0x06 (CMD_CHECK_EXIST) 后跟测试字节 0x57。
* CH395F 硬件将测试字节按位取反后返回,期望收到 ~0x57 = 0xA8。
* 通过:函数返回 CH395F_ERR_SUCCESS(0x00)= SPI 回显取反匹配。
@@ -95,15 +95,15 @@ static void phase1_run(void) {
*/
{
ch395f_status_t ret = ch395f_check_exist();
DBG_INFO(" [P1-01] ch395f_check_exist()");
DBG_INFO(" ch395f_check_exist()");
DBG_INFO(" SPI write: CMD=0x06, DATA=0x57");
DBG_INFO(" expect: ~0x57 = 0xA8");
DBG_INFO(" actual: 0x%02X", (uint8_t)ret);
TEST_CHECK(ret == CH395F_ERR_SUCCESS,
"P1-01 check_exist = 0x%02X (expect 0x00=~0x57=0xA8 match)", (uint8_t)ret);
"check_exist = 0x%02X (expect 0x00=~0x57=0xA8 match)", (uint8_t)ret);
}
/* ---- P1-02: ch395f_get_version() ----
/* ---- ch395f_get_version() ----
* 原理:SPI 写入命令 0x27 (CMD_GET_IC_VER),读取芯片版本字节。
* 通过:版本值 == 0x4A(CH395F 硬件版本)。
* 失败:版本值 ≠ 0x4A(芯片型号不匹配、未正确初始化或损坏)。
@@ -111,14 +111,14 @@ static void phase1_run(void) {
*/
{
uint8_t ver = (uint8_t)ch395f_get_version();
DBG_INFO(" [P1-02] ch395f_get_version()");
DBG_INFO(" ch395f_get_version()");
DBG_INFO(" expect: 0x4A");
DBG_INFO(" actual: 0x%02X", ver);
TEST_CHECK(ver == 0x4A,
"P1-02 version = 0x%02X (expect 0x4A)", ver);
"version = 0x%02X (expect 0x4A)", ver);
}
/* ---- P1-03: 设置 IP → 回读验证 ----
/* ---- 设置 IP → 回读验证 ----
* 原理:ch395f_set_ip_addr() 将 IP 写入 CH395F 内部寄存器,
* 然后通过 ch395f_get_ip_inf() 回读完整网络信息(IP+GW+MASK)。
* 前 4 字节为 IP 地址。
@@ -132,15 +132,15 @@ static void phase1_run(void) {
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(" [P1-03] ch395f_set_ip_addr(192.168.1.100)");
DBG_INFO(" ch395f_set_ip_addr(192.168.1.100)");
DBG_INFO(" expect: IP[0..3] = 192.168.1.100");
DBG_INFO(" actual: %d.%d.%d.%d", ip_info[0], ip_info[1], ip_info[2], ip_info[3]);
TEST_CHECK(match, "P1-03 IP = %d.%d.%d.%d (expect 192.168.1.100)",
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]);
}
/* ---- P1-04: 设置网关 → 回读验证 ----
* 原理:同 P1-03,通过 ch395f_set_gwip_addr() 写入,ch395f_get_ip_inf()
/* ---- 设置网关 → 回读验证 ----
* 原理:同「设置 IP → 回读」项,通过 ch395f_set_gwip_addr() 写入,ch395f_get_ip_inf()
* 回读的第 5-8 字节为网关地址。
* 通过:回读 GW[0..3] == 192.168.1.1。
* 失败:任意字节不匹配。
@@ -152,15 +152,15 @@ static void phase1_run(void) {
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(" [P1-04] ch395f_set_gwip_addr(192.168.1.1)");
DBG_INFO(" ch395f_set_gwip_addr(192.168.1.1)");
DBG_INFO(" expect: GW[0..3] = 192.168.1.1");
DBG_INFO(" actual: %d.%d.%d.%d", ip_info[4], ip_info[5], ip_info[6], ip_info[7]);
TEST_CHECK(match, "P1-04 GW = %d.%d.%d.%d (expect 192.168.1.1)",
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]);
}
/* ---- P1-05: 设置掩码 → 回读验证 ----
* 原理:同 P1-03,ch395f_set_mask_addr() 写入,ch395f_get_ip_inf()
/* ---- 设置掩码 → 回读验证 ----
* 原理:同「设置 IP → 回读」项,ch395f_set_mask_addr() 写入,ch395f_get_ip_inf()
* 回读的第 9-12 字节为子网掩码。
* 通过:回读 MASK[0..3] == 255.255.255.0。
* 失败:任意字节不匹配。
@@ -172,14 +172,14 @@ static void phase1_run(void) {
ch395f_get_ip_inf(ip_info);
int32_t match = (ip_info[8] == 255 && ip_info[9] == 255 &&
ip_info[10] == 255 && ip_info[11] == 0);
DBG_INFO(" [P1-05] ch395f_set_mask_addr(255.255.255.0)");
DBG_INFO(" ch395f_set_mask_addr(255.255.255.0)");
DBG_INFO(" expect: MASK[0..3] = 255.255.255.0");
DBG_INFO(" actual: %d.%d.%d.%d", ip_info[8], ip_info[9], ip_info[10], ip_info[11]);
TEST_CHECK(match, "P1-05 MASK = %d.%d.%d.%d (expect 255.255.255.0)",
TEST_CHECK(match, "MASK = %d.%d.%d.%d (expect 255.255.255.0)",
ip_info[8], ip_info[9], ip_info[10], ip_info[11]);
}
/* ---- P1-06: ch395f_get_glob_int_status_all()(16 位版) ----
/* ---- ch395f_get_glob_int_status_all()(16 位版) ----
* 全库唯一允许 net_poll 之外读全局寄存器的位置——被测对象就是该 API 本身
* (硬件层模式独占上下文,无并发消费者)。读即清语义 → 先读一次自清
* (吸收 bring_up 锁存的 PHY_CHANGE),短暂延时后第二次读为断言值。
@@ -194,14 +194,14 @@ static void phase1_run(void) {
(void)ch395f_get_glob_int_status_all(); /* 自清读(被测 API 自身,见上) */
HAL_Delay(10);
uint16_t gint_all = ch395f_get_glob_int_status_all();
DBG_INFO(" [P1-06] ch395f_get_glob_int_status_all()");
DBG_INFO(" ch395f_get_glob_int_status_all()");
DBG_INFO(" expect: 0x0000");
DBG_INFO(" actual: 0x%04X", gint_all);
TEST_CHECK(gint_all == 0x0000,
"P1-06 glob_int_status_all = 0x%04X (expect 0x0000)", gint_all);
"glob_int_status_all = 0x%04X (expect 0x0000)", gint_all);
}
/* ---- P1-07: 打开→关闭 Socket 0 → 验证 CMD_STATUS ----
/* ---- 打开→关闭 Socket 0 → 验证 CMD_STATUS ----
* 原理:连续执行 open_socket(0) 和 close_socket(0),然后读取
* 命令状态寄存器,确认 Socket 状态机正常流转。
* 通过:CMD_STATUS == 0x00(CH395F_ERR_SUCCESS),表示两次命令均成功执行。
@@ -211,16 +211,16 @@ static void phase1_run(void) {
uint8_t open_ret = ch395f_open_socket(0);
uint8_t close_ret = ch395f_close_socket(0);
uint8_t cmd_st = ch395f_get_cmd_status();
DBG_INFO(" [P1-07] ch395f_open_socket(0) -> ch395f_close_socket(0)");
DBG_INFO(" ch395f_open_socket(0) -> ch395f_close_socket(0)");
DBG_INFO(" expect: CMD_STATUS == 0x00 (CH395F_ERR_SUCCESS)");
DBG_INFO(" actual: open=%d, close=%d, CMD_STATUS=0x%02X",
open_ret, close_ret, cmd_st);
TEST_CHECK(cmd_st == CH395F_ERR_SUCCESS,
"P1-07 open=%d close=%d cmd=0x%02X (expect 0x00)",
"open=%d close=%d cmd=0x%02X (expect 0x00)",
open_ret, close_ret, cmd_st);
}
/* ---- P1-08: 设置 ARP 参数 ----
/* ---- 设置 ARP 参数 ----
* 原理:ch395f_set_arp(period, retry) 配置 ARP 请求周期和重试次数。
* period = 10(×100ms = 1s)、retry = 5(最多 5 次重试)。
* 通过:CMD_STATUS == 0x00(参数写入成功)。
@@ -229,14 +229,14 @@ static void phase1_run(void) {
{
ch395f_set_arp(10, 5);
uint8_t cmd_st = ch395f_get_cmd_status();
DBG_INFO(" [P1-08] ch395f_set_arp(period=10, retry=5)");
DBG_INFO(" ch395f_set_arp(period=10, retry=5)");
DBG_INFO(" expect: CMD_STATUS == 0x00");
DBG_INFO(" actual: CMD_STATUS = 0x%02X", cmd_st);
TEST_CHECK(cmd_st == CH395F_ERR_SUCCESS,
"P1-08 set_arp CMD_STATUS = 0x%02X (expect 0x00)", cmd_st);
"set_arp CMD_STATUS = 0x%02X (expect 0x00)", cmd_st);
}
/* ---- P1-09: 设置 TTL ----
/* ---- 设置 TTL ----
* 原理:ch395f_set_ttl(sock, ttl) 设置指定 Socket 的 IP 报 TTL 值。
* sock = 0(Socket 0)、ttl = 64(默认值)。
* 通过:CMD_STATUS == 0x00。
@@ -245,11 +245,11 @@ static void phase1_run(void) {
{
ch395f_set_ttl(0, 64);
uint8_t cmd_st = ch395f_get_cmd_status();
DBG_INFO(" [P1-09] ch395f_set_ttl(sock=0, ttl=64)");
DBG_INFO(" ch395f_set_ttl(sock=0, ttl=64)");
DBG_INFO(" expect: CMD_STATUS == 0x00");
DBG_INFO(" actual: CMD_STATUS = 0x%02X", cmd_st);
TEST_CHECK(cmd_st == CH395F_ERR_SUCCESS,
"P1-09 set_ttl CMD_STATUS = 0x%02X (expect 0x00)", cmd_st);
"set_ttl CMD_STATUS = 0x%02X (expect 0x00)", cmd_st);
}
TEST_REPORT("Phase 1");
@@ -1029,7 +1029,7 @@ static void phase2_run(void)
*
* 前置条件:PC 运行 udp_client 发包到 192.168.1.100:60000
* 会话结构:累计 PHASE3_TOTAL_ROUNDS(60) 个有效数据包后关闭 Socket
* 第 1~30 轮 = TC-301(PC 发 64B);第 31~60 轮 = TC-302(1B/64B/200B)
* 第 1~30 轮 = TC-NET-301(PC 发 64B);第 31~60 轮 = TC-NET-302(1B/64B/200B)
* "HELLO"(5B) 为 PC 就绪探针:照常回显但不计入轮次
* 通过:60/60 有效轮回显成功。
* 失败:任意轮回显超时或解析错误。
@@ -1037,7 +1037,7 @@ static void phase2_run(void)
#ifdef ENABLE_PHASE3_TESTS
/* UDP 有效回显轮数:1~30 = TC-301(64B),31~60 = TC-302(变长)。
/* UDP 有效回显轮数:1~30 = TC-NET-301(64B),31~60 = TC-NET-302(变长)。
* "HELLO" 探针只回显不计数,与 test/ch395f_socket_test.py udp_client 约定 */
#ifndef PHASE3_TOTAL_ROUNDS
#define PHASE3_TOTAL_ROUNDS 60
@@ -1329,7 +1329,7 @@ phase4_end:
#define PHASE5_TOTAL_BYTES (256*1024) /* 回传总量 */
#endif
#ifndef PHASE5_CHUNK_SIZE
#define PHASE5_CHUNK_SIZE 4093 /* 单块 = socket 默认发送缓冲,DP-04 边界 */
#define PHASE5_CHUNK_SIZE 4093 /* 单块 = socket 默认发送缓冲,DMA 边界安全 */
#endif
#ifndef PHASE5_CONN_TIMEOUT_MS
#define PHASE5_CONN_TIMEOUT_MS 15000
@@ -1452,7 +1452,7 @@ static void phase5_run(void) {
/* ---- 发送缓冲空闲:生成并写入一块 ---- */
phase5_gen_block(tx, (uint32_t)blk_tx); /* 确定性生成第 blk_tx 块模式(TX/RX 可复现) */
sum_tx += phase5_sum32(tx, PHASE5_CHUNK_SIZE); /* 先累加发送侧总账(与 RX 侧对账用) */
ch395f_write_send_buf(sock, tx, PHASE5_CHUNK_SIZE); /* 4096B 单次写入(= 发送缓冲上限,DP-04 边界) */
ch395f_write_send_buf(sock, tx, PHASE5_CHUNK_SIZE); /* 4096B 单次写入(= 发送缓冲上限,DMA 边界安全) */
blk_tx++; /* 该块已交出 */
can_write = 0; /* 进入等待 SENBUF_FREE 状态 */
tx_sw = HAL_GetTick(); /* 记录等待起点(供超时判定) */
@@ -1520,7 +1520,7 @@ static void phase5_run(void) {
break; /* 缓冲空,跳出排空循环 */
}
if (rlen > PHASE5_CHUNK_SIZE) {
rlen = PHASE5_CHUNK_SIZE; /* 单次读取上限 = 块大小(DP-04 4KB DMA 边界) */
rlen = PHASE5_CHUNK_SIZE; /* 单次读取上限 = 块大小(DMA 边界安全,4KB) */
}
ch395f_read_recv_buf(sock, rx, rlen); /* 一次 SPI 事务读走 rlen 字节 */
{