/** * @file ch395f_reuse_bench.c * @brief N-30 芯片级 Socket 复用时序台架(裸机,内核前运行,OS/net/FTP 全剥离) * @details 直接调用 ch395f_* 命令,循环执行受控时序矩阵(延迟/关闭次序/载荷/Socket 号), * 每步打印芯片状态与中断寄存器,定位"关→开→监听→连接"复用时序中 * 芯片行为的确切规律。配套主机脚本 test/host/ch395f_reuse_host.py。 * 定案结论与实验矩阵演进 → CH395F_Trap_Records.md Trap 25。 * * 存档状态:本文件在主分支**不注册编译**(未加入 uvprojx),仅作实验工具存档; * 运行方法:在实验分支(如 n30-chip-bench)把本 .c 注册进 uvprojx Test 组、 * Src/main.c 的 USER CODE 2 区在 app_main_init() 之前调 ch395f_reuse_bench() * (内核前裸机循环,永不返回,断电退出),烧录后跑主机脚本对照芯片日志。 * 当前矩阵为定案轮(对照 vs "丢 CONNECT 捕获自 accept"修复组),见 s_vars[]。 * * close_mode:0=主机先关(芯片等 DISCONNECT);1=芯片先关;2=无数据连上即关 * verify:0=无修复;1=listen 后确认 LISTEN 重试;2=缓冲重分配; * 3=幽灵耐心等;4=等 CONNECT 期轮询状态+自 accept(定案修复) */ #include "ch395f_reuse_bench.h" #if N30_CHIP_BENCH #include "ch395f.h" #include "dbg_log.h" #include "stm32f4xx_hal.h" /* 变体表:{sock, close 后复开延迟 ms, TX 字节数, close_mode, verify_listen} */ typedef struct { uint8_t sock; uint16_t delay_ms; uint16_t tx_len; uint8_t close_mode; uint8_t verify; /* 1 = listen 后确认 TCP==0x01,否则 close 重试(修复假设) */ } bench_var_t; static const bench_var_t s_vars[] = { { 3, 0, 100, 0, 0 }, /* 0ms 对照 */ { 3, 300, 100, 0, 0 }, /* 300ms 对照 */ { 3, 800, 2000, 0, 0 }, /* 2KB 对照 */ { 3, 0, 100, 0, 4 }, /* 0ms + 丢CONNECT捕获自accept */ { 3, 300, 100, 0, 4 }, /* 300ms + 丢CONNECT捕获 */ { 3, 800, 2000, 0, 4 }, /* 2KB + 丢CONNECT捕获 */ }; #define BENCH_N_VARS (sizeof(s_vars) / sizeof(s_vars[0])) #define BENCH_PORT(i) (5000U + (uint16_t)(i)) /* TX 图案缓冲(静态,SRAM;2KB = 最大变体载荷) */ static uint8_t s_tx_pat[2048]; /* RX 排空缓冲 */ static uint8_t s_rx_buf[2048]; /* * 函数功能:轮询本 Socket 中断(读全局→读本 Socket,读即清) * 入口参数:sock - Socket 号 uint8_t * timeout - 超时 ms uint32_t * out_bits - 输出最后一次读到的 SINT 位 uint8_t * * 返回值:1=拿到中断 0=超时 int */ static int bench_wait_sock_int(uint8_t sock, uint32_t timeout, uint8_t *out_bits) { uint32_t t0 = HAL_GetTick(); while ((uint32_t)(HAL_GetTick() - t0) < timeout) { uint16_t glob = ch395f_get_glob_int_status_all(); if ((glob & (1U << (sock + 4U))) != 0U) { uint8_t si = ch395f_get_sock_int_status(sock); if (out_bits != 0) { *out_bits = si; } return 1; } HAL_Delay(10); } return 0; } /* 打印芯片两字节状态(Socket 态 / TCP 态) */ static void bench_log_state(const char *tag, uint8_t sock) { uint8_t st[2] = { 0, 0 }; ch395f_get_socket_status(sock, st); DBG_INFO("BENCH %s sock%u st=0x%02X/0x%02X t=%u", tag, (unsigned)sock, st[0], st[1], (unsigned)HAL_GetTick()); } /* 芯片级初始化(复刻 net_init 序列,剥离全部内核 API) */ static int bench_chip_init(void) { if (ch395f_check_exist() != CH395F_STATUS_OK) { DBG_ERROR("BENCH chip not found"); return -1; } ch395f_reset(); /* 等 PHY link(Trap 09:link up 前 open 必失败) */ for (int i = 0; i < 100; i++) { if (ch395f_get_phy_status() != 0U) { break; } HAL_Delay(100); } /* bit3=1 SOCKET_CLOSE;bit0 保留必须为 0(§5.52)→ 与生产 net_init 同构 */ ch395f_set_fun_para(0x08); ch395f_set_tcp_mss(CH395F_TCP_MSS); ch395f_set_retrans_count(3); ch395f_set_retrans_period(200); ch395f_set_keepalive_idle(60000); ch395f_set_keepalive_intvl(5000); ch395f_set_keepalive_cnt(3); /* 静态 IP(与生产一致) */ { uint8_t ip[4] = { 192, 168, 1, 100 }; uint8_t gw[4] = { 192, 168, 1, 1 }; uint8_t msk[4] = { 255, 255, 255, 0 }; ch395f_set_ip_addr(ip); ch395f_set_gwip_addr(gw); ch395f_set_mask_addr(msk); } if (ch395f_init() != CH395F_STATUS_OK) { DBG_ERROR("BENCH ch395f_init failed"); return -1; } /* 8 Socket 缓冲布局(与生产一致) */ for (int i = 7; i >= 0; i--) { uint8_t recv_start = (uint8_t)(i * 6); ch395f_set_send_buf((uint8_t)i, (uint8_t)(recv_start + 4), 2); ch395f_set_recv_buf((uint8_t)i, recv_start, 4); } ch395f_ping_enable(1); return 0; } /* 单轮实验 */ static void bench_round(unsigned idx) { const bench_var_t *v = &s_vars[idx]; uint8_t sock = v->sock; uint16_t port = BENCH_PORT(idx); uint8_t si = 0; /* 幽灵等待期已见 CONNECT 的标志(跳过后续 CONNECT 等待) */ int pre_connected = 0; DBG_INFO("BENCH === r%u sock%u port%u delay%u tx%u mode%u t=%u", idx, (unsigned)sock, (unsigned)port, (unsigned)v->delay_ms, (unsigned)v->tx_len, (unsigned)v->close_mode, (unsigned)HAL_GetTick()); /* 1. open + listen(Trap 09:close 后需延时重开,失败重试 ×3) */ ch395f_set_proto_type(sock, CH395F_PROTO_TYPE_TCP); ch395f_set_sour_port(sock, port); uint8_t ost = CH395F_ERR_SUCCESS; for (int open_try = 0; open_try < 3; open_try++) { ost = ch395f_open_socket(sock); if (ost == CH395F_ERR_SUCCESS) { break; } DBG_INFO("BENCH open retry%d err=0x%02X t=%u", open_try, ost, (unsigned)HAL_GetTick()); ch395f_close_socket(sock); HAL_Delay(500); } if (ost != CH395F_ERR_SUCCESS) { DBG_ERROR("BENCH open fail 0x%02X", ost); return; } uint8_t lst = ch395f_tcp_listen(sock); if (lst != CH395F_ERR_SUCCESS) { DBG_ERROR("BENCH listen fail 0x%02X", lst); ch395f_close_socket(sock); return; } /* 缓冲重分配变体:listen 后重设收发缓冲(隔离"缓冲管理残留"假设) */ if (v->verify == 2U) { uint8_t recv_start = (uint8_t)(sock * 6); ch395f_clear_recv_buf(sock); ch395f_set_send_buf(sock, (uint8_t)(recv_start + 4), 2); ch395f_set_recv_buf(sock, recv_start, 4); DBG_INFO("BENCH realloc done sock%u t=%u", (unsigned)sock, (unsigned)HAL_GetTick()); } /* 清残留中断(与生产 listen 后一致) */ for (int j = 0; j < 8; j++) { (void)ch395f_get_sock_int_status((uint8_t)j); } (void)ch395f_get_glob_int_status_all(); bench_log_state("post-listen", sock); /* 修复假设验证:listen 后 TCP 态必须真正 == 0x01(LISTEN); * mode1:close 快速重试;mode3:耐心等幽灵消退(5s,每 100ms 复查), * 期间幽灵→LISTEN 转变会补发 CONNECT 中断则直接放行 */ if (v->verify == 1U || v->verify == 3U) { uint32_t budget = (v->verify == 3U) ? 5000U : 1000U; int att_max = (v->verify == 3U) ? 2 : 4; for (int att = 0; att < att_max; att++) { uint8_t st[2] = { 0, 0 }; uint32_t tw = HAL_GetTick(); int connect_fired = 0; /* 等 TCP 进 LISTEN(幽灵消退)或 CONNECT 中断补发 */ while ((uint32_t)(HAL_GetTick() - tw) < budget) { uint16_t glob = ch395f_get_glob_int_status_all(); if ((glob & (1U << (sock + 4U))) != 0U) { uint8_t si = ch395f_get_sock_int_status(sock); if ((si & CH395F_SINT_STAT_CONNECT) != 0U) { connect_fired = 1; DBG_INFO("BENCH verify CONNECT during ghost-wait att%d t=%u", att, (unsigned)HAL_GetTick()); break; } } ch395f_get_socket_status(sock, st); if (st[1] == 0x01U) { break; } HAL_Delay(100); } DBG_INFO("BENCH verify att%d st=0x%02X/0x%02X cf=%d t=%u", att, st[0], st[1], connect_fired, (unsigned)HAL_GetTick()); if (connect_fired) { /* 幽灵期主机已连上:跳过 CONNECT 等待直接进流程 */ pre_connected = 1; break; } if (st[1] == 0x01U) { break; } /* 幽灵未消:close → 50ms → 重新 open+listen(mode3 只试一次) */ ch395f_close_socket(sock); HAL_Delay(50); ch395f_open_socket(sock); ch395f_tcp_listen(sock); for (int j = 0; j < 8; j++) { (void)ch395f_get_sock_int_status((uint8_t)j); } (void)ch395f_get_glob_int_status_all(); } } /* 2. 等 CONNECT(10s;幽灵等待期已见 CONNECT 则跳过) * v6 关键探针:等待期每 500ms 读芯片状态;若已 ESTABLISHED(0x04) * 说明握手完成但 CONNECT 中断丢失 → 补做 accept(对账②模拟) */ int got = pre_connected; uint32_t t0 = HAL_GetTick(); while (!got && (uint32_t)(HAL_GetTick() - t0) < 10000U) { if (bench_wait_sock_int(sock, 100, &si)) { if ((si & CH395F_SINT_STAT_CONNECT) != 0U) { got = 1; break; } DBG_INFO("BENCH unexpected int=0x%02X while wait", si); } if (v->verify == 4U) { uint8_t st[2] = { 0, 0 }; ch395f_get_socket_status(sock, st); if ((uint32_t)(HAL_GetTick() - t0) % 1000U < 110U) { DBG_INFO("BENCH wait-state st=0x%02X/0x%02X t=%u", st[0], st[1], (unsigned)HAL_GetTick()); } if (st[1] == 0x04U) { DBG_INFO("BENCH LOST-CONNECT caught: state ESTABLISHED, self-accept t=%u", (unsigned)HAL_GetTick()); got = 1; break; } } } if (!got) { DBG_ERROR("BENCH no CONNECT within 10s (host not synced?)"); ch395f_close_socket(sock); HAL_Delay(v->delay_ms); return; } bench_log_state("post-accept", sock); /* 对端信息 + RX 残渣检查(旧连接残留的直接证据) */ { uint8_t rem[6] = { 0 }; ch395f_get_remot_ipp(sock, rem); uint16_t rl = ch395f_get_recv_len(sock); DBG_INFO("BENCH remote port=%u recv_len=%u", (unsigned)(rem[4] | (rem[5] << 8)), (unsigned)rl); if (rl > 0U) { uint16_t n = (rl > 2048U) ? 2048U : rl; ch395f_read_recv_buf(sock, s_rx_buf, n); DBG_INFO("BENCH drained %u residue bytes", (unsigned)n); } } /* 3. TX 探针(1KB 分块,Trap 20) */ if (v->tx_len > 0U) { uint16_t sent = 0; while (sent < v->tx_len) { uint16_t chunk = (uint16_t)(v->tx_len - sent); if (chunk > 1024U) { chunk = 1024U; } ch395f_write_send_buf(sock, &s_tx_pat[sent], chunk); sent += chunk; /* 等 SENBUF_FREE(500ms) */ if (sent < v->tx_len) { uint32_t tw = HAL_GetTick(); while ((uint32_t)(HAL_GetTick() - tw) < 500U) { if (bench_wait_sock_int(sock, 50, &si)) { if ((si & CH395F_SINT_STAT_SENBUF_FREE) != 0U) { break; } } } } } DBG_INFO("BENCH tx %u written t=%u", (unsigned)v->tx_len, (unsigned)HAL_GetTick()); /* 连接存活观察窗:500ms 内每 50ms 记状态+中断(抓"秒杀") */ for (int k = 0; k < 10; k++) { uint16_t glob = ch395f_get_glob_int_status_all(); if ((glob & (1U << (sock + 4U))) != 0U) { si = ch395f_get_sock_int_status(sock); DBG_INFO("BENCH int during window=0x%02X t=%u", si, (unsigned)HAL_GetTick()); } HAL_Delay(50); bench_log_state("window", sock); } } /* 4. 关闭次序 */ if (v->close_mode == 1U) { /* 芯片先关 */ HAL_Delay(300); ch395f_close_socket(sock); DBG_INFO("BENCH chip closed first t=%u", (unsigned)HAL_GetTick()); } else { /* 等主机关(DISCONNECT 事件,5s) */ uint32_t tw = HAL_GetTick(); int disc = 0; while ((uint32_t)(HAL_GetTick() - tw) < 5000U) { if (bench_wait_sock_int(sock, 100, &si)) { if ((si & (CH395F_SINT_STAT_DISCONNECT | CH395F_SINT_STAT_SOCK_TIMEOUT)) != 0U) { disc = 1; break; } } } DBG_INFO("BENCH host-close seen=%d t=%u", disc, (unsigned)HAL_GetTick()); ch395f_close_socket(sock); } /* 5. 关闭后拆链观察:1s 内每 50ms 记状态 + 中断(Trap 14 滞后中断取证) */ for (int k = 0; k < 20; k++) { uint16_t glob = ch395f_get_glob_int_status_all(); uint8_t late = 0; if ((glob & (1U << (sock + 4U))) != 0U) { late = ch395f_get_sock_int_status(sock); } if (late != 0U) { DBG_INFO("BENCH late-int=0x%02X t=%u", late, (unsigned)HAL_GetTick()); } if ((k % 4) == 0) { bench_log_state("post-close", sock); } HAL_Delay(50); } /* 6. 受控延迟后进入下一轮 */ HAL_Delay(v->delay_ms); } void ch395f_reuse_bench(void) { DBG_INFO("BENCH ===== N30 chip-level reuse bench START ====="); if (bench_chip_init() != 0) { DBG_ERROR("BENCH init failed, giving up (normal boot continues)"); return; } DBG_INFO("BENCH chip ready, cycling %u variants forever", (unsigned)BENCH_N_VARS); for (unsigned i = 0; i < 2048U; i++) { s_tx_pat[i] = (uint8_t)(0xA5U + (i % 251U)); } unsigned idx = 0; for (;;) { bench_round(idx); idx = (idx + 1U) % (unsigned)BENCH_N_VARS; } } #endif /* N30_CHIP_BENCH */