feat(N34 阶段2): ch395f 五原语只加不接线 + Phase 15 套件 20/20

实施方案 docs/网络/N34-自愈审计/实施方案.md §4 五原语,形态按
E2/E3/E4 定案(实验方案.md):
1. 类型化状态回读 + 每 Socket 缓存(open=0 时 tcp_state 哨兵
   0xFF;sn>7 边界返 {00,FF} 计 fault);
2. 事件护栏 ch395f_sock_events:只读本 Socket SINT,全局寄存器
   唯一读者=net_poll(F-NET-7 契约);
3. ch395f_sock_reset_begin/poll 非阻塞状态机:读空 RX -> CLOSE
   -> 排空事件(quiescent 2 轮) -> 轮询 byte0=00H;GRACEFUL/
   QUARANTINE 最短等待 100/400ms(Trap 23);WAIT_CLOSE 内置
   LISTEN 态二段 CLOSE 补发(TC1502b 实证 ~180ms 落定);
4. ch395f_cmd_done 状态回读判据(E3:GET_CMD_STATUS 对
   OPEN/LISTEN/CLOSE 无判别力);
5. 链路态缓存 ch395f_glob_event_feed + link_up/变化计数
   (B9 判据 PHY!=DISCONN)。

Phase 15 板测(硬件层模式,Socket 7,无需 PC):20/20 PASS,
含二段关闭语义断言(一段 05/00、二段 byte0=00)。

RAM +56B < 64B(g_sock_state 16B + g_rst 32B + 链路/fault 8B);
产品 Code 与阶段 2 前逐字节同 209780(无调用者被链接器裁剪)。
@test PASS;relisten_stress 20/20、n30 3/3 零回归。
RAM 台账同步:RW_IRAM1 97952B 74.7% / RW_CCM 57376B 87.9%。
This commit is contained in:
2026-10-13 12:43:17 +08:00
parent 33405a57b5
commit f7f17931c9
8 changed files with 634 additions and 6 deletions
+123
View File
@@ -1653,6 +1653,125 @@ static void phase5_run(void) {
TEST_REPORT("Phase 5");
}
#endif
/* ===================================================================
* Phase 15 — N34 阶段 2 驱动原语(无需 PC)
*
* 测试目的:验证 ch395f 新增原语(实施方案 docs/网络/N34-自愈审计/实施方案.md §4)
* 语义正确:类型化状态回读一致性 / cmd_done(E3 定案=状态回读)/
* sock_reset 非阻塞状态机跑通(E4 定案序列)/ 链路态缓存 / 事件护栏。
* 污染会话下的复位载荷完整性已由 E4 bench 60 轮实证(实验方案 E4),
* 本 Phase 只验"状态机跑通 + 判据语义",不依赖 PC。
* 上下文:硬件层模式(testTask 独占 CH395F),用 Socket 7(产品监听 0~4 不涉)。
* =================================================================== */
#ifdef ENABLE_PHASE15_TESTS
static void phase15_run(void) {
const uint8_t sn = 7U;
ch395f_sock_state_t st;
uint32_t t0;
int done;
int rc;
DBG_INFO("=== CH395F Phase 15 Tests (N34 phase-2 primitives) ===");
/* ---- TC-1501: 状态回读一致性 + cmd_done 语义(E2/E3 定案形态) ---- */
ch395f_set_proto_type(sn, CH395F_PROTO_TYPE_TCP);
ch395f_set_sour_port(sn, 5107U);
(void)ch395f_open_socket(sn);
t0 = HAL_GetTick();
done = 0;
while ((uint32_t)(HAL_GetTick() - t0) < 50U) {
if (ch395f_cmd_done(sn, CH395F_DONE_OPEN) == 1) { done = 1; break; }
HAL_Delay(1);
}
TEST_CHECK(done == 1, "TC1501 open done within 50ms");
(void)ch395f_tcp_listen(sn);
t0 = HAL_GetTick();
done = 0;
while ((uint32_t)(HAL_GetTick() - t0) < 20U) {
if (ch395f_cmd_done(sn, CH395F_DONE_LISTEN) == 1) { done = 1; break; }
HAL_Delay(1);
}
/* E2 矩阵:LISTEN 可见延迟 100% <=10ms(24 轮无长尾) */
TEST_CHECK(done == 1, "TC1501 listen done within 20ms (E2: 100 pct <=10ms)");
TEST_CHECK(ch395f_sock_is_listening(sn) == 1, "TC1501 cached is_listening");
st = ch395f_sock_state_cached(sn);
TEST_CHECK(st.open == CH395F_SOCKET_OPEN && st.tcp_state == CH395F_TCP_LISTEN,
"TC1501 cached state 05/01 (got %02X/%02X)", st.open, st.tcp_state);
/* 二段关闭实证(2026-10-13 本 TC 二跑定案):LISTEN 态 Socket 的
* CLOSE_SOCKET 返 SUCCESS 但只拆监听(TCP 01->00),byte0 恒 05;
* 再发一次 CLOSE 才落 00。生产 net 层靠 Trap 09 open 重试吸收此行为,
* sock_reset 状态机在 WAIT_CLOSE 阶段自行补发(见 ch395f.c)。 */
uint8_t close_st = ch395f_close_socket(sn);
TEST_CHECK(close_st == CH395F_ERR_SUCCESS,
"TC1501 close cmd st=0x%02X (expect 00)", close_st);
st = ch395f_get_sock_state(sn);
TEST_CHECK(st.open == CH395F_SOCKET_OPEN && st.tcp_state == CH395F_TCP_CLOSED,
"TC1501 listen-close stage1: 05/00 listen torn down (got %02X/%02X)",
st.open, st.tcp_state);
(void)ch395f_close_socket(sn);
t0 = HAL_GetTick();
done = -1;
while ((uint32_t)(HAL_GetTick() - t0) < 500U) {
if (ch395f_cmd_done(sn, CH395F_DONE_CLOSE) == 1) { done = (int)(HAL_GetTick() - t0); break; }
HAL_Delay(1);
}
TEST_CHECK(done >= 0, "TC1501 listen-close stage2: byte0=00 in %dms (win 500)", done);
st = ch395f_get_sock_state(sn);
TEST_CHECK(st.tcp_state == CH395F_SOCK_STATE_NONE,
"TC1501 tcp_state sentinel 0xFF when closed (got %02X)", st.tcp_state);
st = ch395f_get_sock_state(8U);
TEST_CHECK(st.open == CH395F_SOCKET_CLOSED && st.tcp_state == CH395F_SOCK_STATE_NONE,
"TC1501 sn=8 boundary -> CLOSED+sentinel");
/* ---- TC-1502: sock_reset 非阻塞状态机跑通(E4 定案序列) ---- */
(void)ch395f_open_socket(sn);
rc = ch395f_sock_reset_begin(sn, CH395F_RESET_QUARANTINE);
TEST_CHECK(rc == 0, "TC1502 begin accepted (rc=%d)", rc);
TEST_CHECK(ch395f_sock_reset_begin(sn, CH395F_RESET_QUARANTINE) == -1,
"TC1502 busy reject on second begin");
t0 = HAL_GetTick();
rc = 1;
while (rc == 1 && (uint32_t)(HAL_GetTick() - t0) < 3000U) {
rc = ch395f_sock_reset_poll(sn);
HAL_Delay(1);
}
/* QUARANTINE 最短等待 400ms + 各阶段,3s 窗内必落定 */
TEST_CHECK(rc == 0, "TC1502 reset done within 3000ms (rc=%d)", rc);
TEST_CHECK(ch395f_cmd_done(sn, CH395F_DONE_CLOSE) == 1, "TC1502 chip CLOSED after reset");
TEST_CHECK(ch395f_sock_reset_poll(sn) == 0, "TC1502 poll idempotent after done");
/* 复位后可重开(复位语义 = 回到可用态) */
(void)ch395f_open_socket(sn);
TEST_CHECK(ch395f_cmd_done(sn, CH395F_DONE_OPEN) == 1, "TC1502 reopen after reset OK");
(void)ch395f_close_socket(sn);
/* TC-1502b: LISTEN 态 Socket 复位(走 WAIT_CLOSE 二段补发路径,GRACEFUL) */
(void)ch395f_open_socket(sn);
(void)ch395f_tcp_listen(sn);
rc = ch395f_sock_reset_begin(sn, CH395F_RESET_GRACEFUL);
t0 = HAL_GetTick();
rc = 1;
while (rc == 1 && (uint32_t)(HAL_GetTick() - t0) < 3000U) {
rc = ch395f_sock_reset_poll(sn);
HAL_Delay(1);
}
TEST_CHECK(rc == 0, "TC1502b reset on LISTEN socket done (rc=%d, two-stage absorbed)", rc);
TEST_CHECK(ch395f_cmd_done(sn, CH395F_DONE_CLOSE) == 1, "TC1502b chip CLOSED after listen-reset");
/* ---- TC-1503: 链路态缓存 + 事件护栏边界 ---- */
uint16_t c0 = ch395f_link_change_count();
ch395f_glob_event_feed(CH395F_GINT_STAT_PHY_CHANGE); /* 首次 feed 建档 */
ch395f_glob_event_feed(CH395F_GINT_STAT_PHY_CHANGE); /* 链路稳定:不应虚增计数 */
TEST_CHECK(ch395f_link_change_count() == c0, "TC1503 no spurious link change on stable link");
TEST_CHECK(ch395f_link_up_cached() == 1U, "TC1503 link_up cached (bench link present)");
TEST_CHECK(ch395f_sock_events(8U) == 0U, "TC1503 sock_events sn=8 boundary -> 0");
(void)ch395f_sock_events(sn); /* 读即清护栏:合法调用不崩 */
TEST_REPORT("Phase 15");
}
#endif
/*
* CH395F 测试套件入口(由 test_config.c 的 start_test_task 统一调度)。
* 此处只负责 CH395F 自身的硬件层 / NET 层逻辑,套件选择已上移到 test_config.c。
@@ -1688,6 +1807,10 @@ void ch395f_test_run(void)
/* Phase 12(链路时延基线 L1/L2,M1):独立于 Phase 1~5 的 SPI 时延
* 采样,放硬件层阶段末尾执行(说明文档:链路延迟测试说明.md) */
net_latency_phase12_run();
#endif
#ifdef ENABLE_PHASE15_TESTS
/* Phase 15(N34 阶段 2 驱动原语):独占态下直调驱动,放 HW 层末尾 */
phase15_run();
#endif
}
#else