网络主要内容测试完成
This commit is contained in:
@@ -3,7 +3,7 @@
|
||||
* 模块功能:CH395F 全阶段测试入口,统一在独立 FreeRTOS 任务中运行。
|
||||
* 测试分两组:
|
||||
* Phase 1~5(硬件层)— 阻塞式独占执行(各自有内部循环/等待),netTask 未运行
|
||||
* Phase 4~10(NET 层)— 事件驱动,TCP 监听循环中运行(需 PC 客户端连接)
|
||||
* Phase 4~11(NET 层)— 事件驱动,TCP 监听循环中运行(需 PC 客户端连接)
|
||||
* 所有测试结果通过 TEST_CHECK/TEST_REPORT 宏输出到串口。
|
||||
* 作者:王建锋
|
||||
* 创建日期:2026-07-22
|
||||
@@ -11,6 +11,7 @@
|
||||
|
||||
#include <string.h>
|
||||
#include "ch395f_test_task.h"
|
||||
#include "net_test_task.h"
|
||||
#include "cmsis_os.h"
|
||||
#include "net_task.h"
|
||||
#include "net_socket.h"
|
||||
@@ -31,20 +32,6 @@ extern volatile uint8_t g_net_ready;
|
||||
*/
|
||||
test_stats_t g_test_stats;
|
||||
|
||||
/*
|
||||
* 收发缓冲区 —— 全局静态,不在任务栈上。
|
||||
* s_tx_buf 仅在 Phase 7(大文件传输)和 Phase 9(边界条件)中使用,
|
||||
* 其他 Phase 不需要发送固定模式数据,故条件编译节省 RAM。
|
||||
*/
|
||||
#define TEST_BUF_SIZE 65536
|
||||
#if defined(ENABLE_PHASE6_TESTS) || defined(ENABLE_PHASE7_TESTS) || \
|
||||
defined(ENABLE_PHASE8_TESTS) || defined(ENABLE_PHASE9_TESTS) || \
|
||||
defined(ENABLE_PHASE10_TESTS)
|
||||
static uint8_t s_rx_buf[TEST_BUF_SIZE];
|
||||
#endif
|
||||
#if defined(ENABLE_PHASE7_TESTS) || defined(ENABLE_PHASE9_TESTS)
|
||||
static uint8_t s_tx_buf[TEST_BUF_SIZE];
|
||||
#endif
|
||||
|
||||
/* ===================================================================
|
||||
* Phase 1 — 寄存器与 SPI 命令路径验证
|
||||
@@ -55,7 +42,9 @@ static uint8_t s_tx_buf[TEST_BUF_SIZE];
|
||||
* 共 9 项测试(P1-01 ~ P1-09),逐项执行,汇总报告。
|
||||
* =================================================================== */
|
||||
|
||||
/* 解析点分十进制 IP 字符串为数组(避免引入 sscanf 库) */
|
||||
/* 解析点分十进制 IP 字符串为数组(避免引入 sscanf 库)。
|
||||
* 仅硬件层阶段(1~5)使用,NET 层无需此辅助。 */
|
||||
#if defined(ENABLE_HW_LAYER_TESTS)
|
||||
static void test_parse_ip(const char *str, uint8_t *ip_arr)
|
||||
{
|
||||
uint32_t val;
|
||||
@@ -73,6 +62,7 @@ static void test_parse_ip(const char *str, uint8_t *ip_arr)
|
||||
}
|
||||
}
|
||||
}
|
||||
#endif /* ENABLE_HW_LAYER_TESTS */
|
||||
|
||||
#ifdef ENABLE_PHASE1_TESTS
|
||||
static void phase1_run(void) {
|
||||
@@ -1351,385 +1341,10 @@ static void phase5_run(void) {
|
||||
TEST_REPORT("Phase 5");
|
||||
}
|
||||
#endif
|
||||
/* ===================================================================
|
||||
* Phase 6 — NET 层 TCP Echo(基础收发)
|
||||
*
|
||||
* 测试目的:验证 BSD Socket API(net_socket)的单连接 TCP Echo 通路。
|
||||
* Socket 0 复用监听和数据通道。PC 发任意数据,MCU 原样返回。
|
||||
* 这是 Phase 7/8/9/10 的基础。
|
||||
*
|
||||
* 入口条件:Socket 0 处于 ESTABLISHED(TCP 连接已建立)。
|
||||
* 通过:数据收发一致。
|
||||
* 失败:send/recv 数量不匹配。
|
||||
* =================================================================== */
|
||||
|
||||
#ifdef ENABLE_PHASE6_TESTS
|
||||
static uint32_t s_phase6_count = 0;
|
||||
|
||||
static void phase6_run(int sockfd) {
|
||||
/*
|
||||
* 使用 NET_MSG_DONTWAIT 非阻塞接收 —— 没有数据时立即返回,
|
||||
* 不阻塞任务循环(Phase 7/8/9/10 也共享同一个循环)。
|
||||
* 收到数据后立即原样发送回显。
|
||||
*/
|
||||
int n = net_recv(sockfd, s_rx_buf, TEST_BUF_SIZE, NET_MSG_DONTWAIT);
|
||||
if (n > 0) {
|
||||
int sent = net_send(sockfd, s_rx_buf, n, 0);
|
||||
if (sent != n) {
|
||||
DBG_ERROR("echo: send %d != recv %d", sent, n);
|
||||
return;
|
||||
}
|
||||
s_phase6_count++;
|
||||
if (s_phase6_count <= 10 || (s_phase6_count % 100 == 0)) {
|
||||
DBG_INFO("Phase6: echo #%lu (%d bytes)", s_phase6_count, n);
|
||||
}
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
/* ===================================================================
|
||||
* Phase 7 — 大文件传输(超过 CH395F 硬件缓冲 4KB)
|
||||
*
|
||||
* 测试目的:验证超过 Socket 0 接收缓冲(4KB)的数据在 net_send/
|
||||
* net_recv 层的正确处理。net_send_locked 自动将大数据
|
||||
* 拆分为 ≤4096B 的块,每块通过一次 DMA 事务写入 CH395F。
|
||||
* 接收端同样分多次调用 ch395f_read_recv_buf 读空硬件缓冲。
|
||||
*
|
||||
* 数据模式:递增字节(s_tx_buf[i] = i & 0xFF),接收端按 offset 逐字节比对。
|
||||
* 通过:全部 20480 字节逐字节匹配。
|
||||
* 失败:任意字节不一致或收发过程中断。
|
||||
* =================================================================== */
|
||||
|
||||
#ifdef ENABLE_PHASE7_TESTS
|
||||
#define PHASE7_FILE_SIZE 20480
|
||||
|
||||
static void phase7_fill(uint8_t *buf, uint32_t size) {
|
||||
for (uint32_t i = 0; i < size; i++) {
|
||||
buf[i] = (uint8_t)(i & 0xFF);
|
||||
}
|
||||
}
|
||||
|
||||
static int phase7_verify(uint8_t *buf, uint32_t size, uint32_t offset) {
|
||||
for (uint32_t i = 0; i < size; i++) {
|
||||
if (buf[i] != (uint8_t)((offset + i) & 0xFF)) {
|
||||
DBG_ERROR("Phase7: mismatch at %lu (expect 0x%02X, got 0x%02X)",
|
||||
offset + i, (uint8_t)((offset + i) & 0xFF), buf[i]);
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
|
||||
static void phase7_run(int sockfd) {
|
||||
DBG_INFO("Phase7: starting %d-byte file transfer", PHASE7_FILE_SIZE);
|
||||
|
||||
phase7_fill(s_tx_buf, PHASE7_FILE_SIZE);
|
||||
|
||||
/*
|
||||
* 发送阶段:分块发送,每块最多 4096B。
|
||||
* net_send 内部通过消息队列转发到 netTask,由 net_send_locked
|
||||
* 按 CH395F_SPI_DMA_MAX_PAYLOAD(4096)自动拆分 DMA 事务。
|
||||
* 等待 PC 端回显(echod)全部数据。
|
||||
*/
|
||||
uint32_t sent = 0;
|
||||
while (sent < PHASE7_FILE_SIZE) {
|
||||
int chunk = (PHASE7_FILE_SIZE - sent) > 4096 ? 4096 : (PHASE7_FILE_SIZE - sent);
|
||||
int n = net_send(sockfd, s_tx_buf + sent, chunk, 0);
|
||||
if (n <= 0) {
|
||||
DBG_ERROR("Phase7: send fail at %lu (ret=%d)", sent, n);
|
||||
return;
|
||||
}
|
||||
sent += (uint32_t)n;
|
||||
DBG_INFO("Phase7: sent %lu/%d", sent, PHASE7_FILE_SIZE);
|
||||
}
|
||||
|
||||
/*
|
||||
* 接收阶段:分块接收,逐块验证。
|
||||
* PC 回显数据需与发送数据逐字节一致(递增模式)。
|
||||
* 验证失败立即返回,不继续接收剩余数据。
|
||||
*/
|
||||
uint32_t recvd = 0;
|
||||
while (recvd < PHASE7_FILE_SIZE) {
|
||||
int n = net_recv(sockfd, s_rx_buf, TEST_BUF_SIZE, 0);
|
||||
if (n <= 0) {
|
||||
DBG_ERROR("Phase7: recv fail at %lu (ret=%d)", recvd, n);
|
||||
return;
|
||||
}
|
||||
int ok = phase7_verify(s_rx_buf, (uint32_t)n, recvd);
|
||||
TEST_CHECK(ok, "Phase7: verify at %lu (%d bytes)", recvd, n);
|
||||
if (!ok) return;
|
||||
recvd += (uint32_t)n;
|
||||
}
|
||||
|
||||
TEST_CHECK(1, "Phase7: %d-byte file transfer complete", PHASE7_FILE_SIZE);
|
||||
}
|
||||
#endif
|
||||
|
||||
/* ===================================================================
|
||||
* Phase 8 — Select/Poll I/O 多路复用
|
||||
*
|
||||
* 测试目的:验证 net_select() API 在单 Socket 模式下正确工作:
|
||||
* 1. Socket 0 有数据到达时 select 返回正数
|
||||
* 2. NET_FD_ISSET 正确指示就绪的 Socket
|
||||
* 3. 超时(50ms 无数据)时返回 0
|
||||
*
|
||||
* 入口条件:Socket 0 处于 ESTABLISHED。
|
||||
* 通过:select 检测到数据并成功回显。
|
||||
* 失败:select 未检测到数据或回显失败。
|
||||
* =================================================================== */
|
||||
|
||||
#ifdef ENABLE_PHASE8_TESTS
|
||||
#include "net_select.h"
|
||||
static uint32_t s_phase8_count = 0;
|
||||
|
||||
static void phase8_run(int sockfd) {
|
||||
net_fd_set readfds;
|
||||
net_timeval tv;
|
||||
|
||||
/*
|
||||
* 配置 select:只监测 Socket 0 的可读状态,超时 50ms。
|
||||
* NET_FD_ZERO 清空集合,NET_FD_SET 添加 Socket 0。
|
||||
* 50ms 超时确保不阻塞任务循环太久。
|
||||
*/
|
||||
NET_FD_ZERO(&readfds);
|
||||
NET_FD_SET(sockfd, &readfds);
|
||||
tv.tv_sec = 0;
|
||||
tv.tv_usec = 50000;
|
||||
|
||||
int nfds = net_select(sockfd + 1, &readfds, NULL, NULL, &tv);
|
||||
if (nfds <= 0) return;
|
||||
|
||||
/* Socket 0 可读:非阻塞接收并回显 */
|
||||
if (NET_FD_ISSET(sockfd, &readfds)) {
|
||||
int n = net_recv(sockfd, s_rx_buf, TEST_BUF_SIZE, NET_MSG_DONTWAIT);
|
||||
if (n > 0) {
|
||||
int sent = net_send(sockfd, s_rx_buf, n, 0);
|
||||
if (sent == n) {
|
||||
s_phase8_count++;
|
||||
TEST_CHECK(1, "Phase8: select echo #%lu (%d bytes)", s_phase8_count, n);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
/* ===================================================================
|
||||
* Phase 9 — 边界条件测试
|
||||
*
|
||||
* 测试目的:验证以下 DMA 和协议栈边界情况:
|
||||
* 1. TC-NET-901: 4095B(SPI 最大载荷 -1,单次 DMA 容纳)
|
||||
* 2. TC-NET-902: 4096B(= SPI 最大载荷,填满单次 DMA)
|
||||
* 3. TC-NET-903: 4097B(超过 SPI 最大载荷,拆 2 次 DMA)
|
||||
* 4. TC-NET-904: 零长度发送(返回 -1)
|
||||
* 5. TC-NET-905: 20 × 100B 连续快速发送
|
||||
*
|
||||
* 各用例通过状态机(s_phase9_stage)串行执行,每次 phase9_run 推进一个
|
||||
* 步骤(发送→等待→接收→验证→下一阶段)。发送数据为递增模式字节
|
||||
* (buf[i] = seed + i),接收端按相同模式验证。
|
||||
*
|
||||
* 入口条件:Socket 0 处于 ESTABLISHED。
|
||||
* 通过:各用例自身判定。
|
||||
* =================================================================== */
|
||||
|
||||
#ifdef ENABLE_PHASE9_TESTS
|
||||
static int s_phase9_stage = 0;
|
||||
static uint32_t s_phase9_recv = 0;
|
||||
|
||||
static void phase9_fill(uint8_t *buf, uint32_t size, uint8_t seed) {
|
||||
for (uint32_t i = 0; i < size; i++) {
|
||||
buf[i] = (uint8_t)(seed + i);
|
||||
}
|
||||
}
|
||||
|
||||
static int phase9_verify(uint8_t *buf, uint32_t size, uint8_t seed) {
|
||||
for (uint32_t i = 0; i < size; i++) {
|
||||
if (buf[i] != (uint8_t)(seed + i)) return 0;
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
|
||||
static void phase9_run(int sockfd) {
|
||||
/* 阶段 0 → 1:发送 4095B */
|
||||
if (s_phase9_stage == 0) {
|
||||
DBG_INFO("Phase9: 4095B (DMA-1)");
|
||||
phase9_fill(s_tx_buf, 4095, 0x10);
|
||||
int sent = net_send(sockfd, s_tx_buf, 4095, 0);
|
||||
TEST_CHECK(sent == 4095, "Phase9: send 4095B (sent=%d)", sent);
|
||||
s_phase9_recv = 0;
|
||||
s_phase9_stage = 1;
|
||||
return;
|
||||
}
|
||||
/* 阶段 1:接收并验证 4095B 回显 */
|
||||
if (s_phase9_stage == 1) {
|
||||
int n = net_recv(sockfd, s_rx_buf + s_phase9_recv, (int)(4095 - s_phase9_recv), 0);
|
||||
if (n > 0) {
|
||||
s_phase9_recv += (uint32_t)n;
|
||||
if (s_phase9_recv >= 4095) {
|
||||
TEST_CHECK(phase9_verify(s_rx_buf, 4095, 0x10), "Phase9: verify 4095B");
|
||||
s_phase9_stage = 2;
|
||||
}
|
||||
}
|
||||
return;
|
||||
}
|
||||
/* 阶段 2 → 3:发送 4096B(DMA 边界精确值) */
|
||||
if (s_phase9_stage == 2) {
|
||||
DBG_INFO("Phase9: 4096B (DMA exact)");
|
||||
phase9_fill(s_tx_buf, 4096, 0x20);
|
||||
int sent = net_send(sockfd, s_tx_buf, 4096, 0);
|
||||
TEST_CHECK(sent == 4096, "Phase9: send 4096B (sent=%d)", sent);
|
||||
s_phase9_recv = 0;
|
||||
s_phase9_stage = 3;
|
||||
return;
|
||||
}
|
||||
/* 阶段 3:接收并验证 4096B 回显 */
|
||||
if (s_phase9_stage == 3) {
|
||||
int n = net_recv(sockfd, s_rx_buf + s_phase9_recv, (int)(4096 - s_phase9_recv), 0);
|
||||
if (n > 0) {
|
||||
s_phase9_recv += (uint32_t)n;
|
||||
if (s_phase9_recv >= 4096) {
|
||||
TEST_CHECK(phase9_verify(s_rx_buf, 4096, 0x20), "Phase9: verify 4096B");
|
||||
s_phase9_stage = 4;
|
||||
}
|
||||
}
|
||||
return;
|
||||
}
|
||||
/* 阶段 4 → 5:发送 4097B(超过 DMA 上限,自动拆 4096+1) */
|
||||
if (s_phase9_stage == 4) {
|
||||
DBG_INFO("Phase9: 4097B (DMA+1, 2 SPI xacts)");
|
||||
phase9_fill(s_tx_buf, 4097, 0x30);
|
||||
int sent = net_send(sockfd, s_tx_buf, 4097, 0);
|
||||
TEST_CHECK(sent == 4097, "Phase9: send 4097B (sent=%d)", sent);
|
||||
s_phase9_recv = 0;
|
||||
s_phase9_stage = 5;
|
||||
return;
|
||||
}
|
||||
/* 阶段 5:接收并验证 4097B 回显 */
|
||||
if (s_phase9_stage == 5) {
|
||||
int n = net_recv(sockfd, s_rx_buf + s_phase9_recv, (int)(4097 - s_phase9_recv), 0);
|
||||
if (n > 0) {
|
||||
s_phase9_recv += (uint32_t)n;
|
||||
if (s_phase9_recv >= 4097) {
|
||||
TEST_CHECK(phase9_verify(s_rx_buf, 4097, 0x30), "Phase9: verify 4097B");
|
||||
s_phase9_stage = 6;
|
||||
}
|
||||
}
|
||||
return;
|
||||
}
|
||||
/* 阶段 6:零长度发送 —— 期望 net_send 返回 -1(NET_ERR_INVAL) */
|
||||
if (s_phase9_stage == 6) {
|
||||
DBG_INFO("Phase9: zero-length send");
|
||||
int sent = net_send(sockfd, s_tx_buf, 0, 0);
|
||||
TEST_CHECK(sent < 0, "Phase9: send 0B returns %d (expect <0)", sent);
|
||||
s_phase9_stage = 7;
|
||||
return;
|
||||
}
|
||||
/* 阶段 7:20 × 100B 快速发送 */
|
||||
if (s_phase9_stage == 7) {
|
||||
DBG_INFO("Phase9: 20x rapid sends (100B each)");
|
||||
phase9_fill(s_tx_buf, 100, 0x40);
|
||||
int all_ok = 1;
|
||||
for (int i = 0; i < 20; i++) {
|
||||
if (net_send(sockfd, s_tx_buf, 100, 0) != 100) {
|
||||
TEST_CHECK(0, "Phase9: rapid #%d fail", i + 1);
|
||||
all_ok = 0; break;
|
||||
}
|
||||
osDelay(1);
|
||||
}
|
||||
if (all_ok) {
|
||||
TEST_CHECK(1, "Phase9: 20x rapid sends OK");
|
||||
s_phase9_recv = 0;
|
||||
s_phase9_stage = 8;
|
||||
} else {
|
||||
s_phase9_stage = 0;
|
||||
}
|
||||
return;
|
||||
}
|
||||
/* 阶段 8:接收 2000B 回显总和并验证 */
|
||||
if (s_phase9_stage == 8) {
|
||||
int n = net_recv(sockfd, s_rx_buf + s_phase9_recv, (int)(2000 - s_phase9_recv), 0);
|
||||
if (n > 0) {
|
||||
s_phase9_recv += (uint32_t)n;
|
||||
if (s_phase9_recv >= 2000) {
|
||||
TEST_CHECK(1, "Phase9: all echo received");
|
||||
TEST_REPORT("Phase 9");
|
||||
s_phase9_stage = 0;
|
||||
}
|
||||
}
|
||||
return;
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
/* ===================================================================
|
||||
* Phase 10 — TCP KeepAlive 超时断开
|
||||
*
|
||||
* 测试目的:验证 CH395F 的 TCP KeepAlive 机制:
|
||||
* 1. 连接空闲超过 idle 阈值(60s)后开始发送探测包
|
||||
* 2. 探测无响应(默认 3 次 × 5s = 15s)后触发 TIMEOUT
|
||||
* 3. Socket 自动关闭并回到 LISTEN
|
||||
*
|
||||
* 入口条件:Socket 0 处于 ESTABLISHED,PC 连接后静置(不发数据)。
|
||||
* 通过:KeepAlive 断开时间 ≥ 60s(从连接建立到 recv 返回 0 的间隔)。
|
||||
* 失败:不到 60s 就断开(可能是其他原因导致)或 75s 后仍未断开。
|
||||
* =================================================================== */
|
||||
|
||||
#ifdef ENABLE_PHASE10_TESTS
|
||||
static int s_phase10_armed = 0;
|
||||
static uint32_t s_phase10_start = 0;
|
||||
|
||||
static void phase10_run(int sockfd) {
|
||||
/*
|
||||
* 第一次调用:记录开始时间并 arm。
|
||||
* 后续调用:非阻塞 recv,若返回 0 表示连接已断开(KeepAlive 触发)。
|
||||
* 计算耗时与 60s idle 阈值比较。
|
||||
*/
|
||||
if (!s_phase10_armed) {
|
||||
s_phase10_armed = 1;
|
||||
s_phase10_start = HAL_GetTick();
|
||||
DBG_INFO("Phase10: idle wait for KeepAlive timeout (60s)");
|
||||
return;
|
||||
}
|
||||
|
||||
int n = net_recv(sockfd, s_rx_buf, 64, NET_MSG_DONTWAIT);
|
||||
if (n == 0) {
|
||||
uint32_t elapsed = HAL_GetTick() - s_phase10_start;
|
||||
TEST_CHECK(elapsed >= 60000,
|
||||
"Phase10: KeepAlive triggered after %lums (expect >=60000ms)", elapsed);
|
||||
TEST_REPORT("Phase 10");
|
||||
s_phase10_armed = 0;
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
/* ===================================================================
|
||||
* 任务入口:StartCh395fTestTask
|
||||
*
|
||||
* 执行顺序(按构建模式二选一,见 docs/CH395F_Test_Guide.md「构建模式与执行顺序」):
|
||||
* 硬件层模式(阶段 1~5):netTask 不创建,本任务调用
|
||||
* net_stack_bring_up() 完成协议栈初始化后独占 CH395F 阻塞执行。
|
||||
* NET 层模式(阶段 6~10):
|
||||
* 1. 等待 g_net_ready(netTask 初始化完成标志)
|
||||
* 2. 创建 TCP 监听 Socket(单连接模式,端口 8080)
|
||||
* 3. 进入事件驱动循环,等待 PC 连接并执行 NET 层测试
|
||||
*
|
||||
* 单连接模式说明:
|
||||
* Socket 0 复用监听和数据通道。accept 返回的 fd 与监听 fd 相同。
|
||||
* 连接断开后需重新 listen。连接恢复检测在循环末尾通过
|
||||
* net_get_sock() 检查状态并自动处理。
|
||||
* =================================================================== */
|
||||
|
||||
void StartCh395fTestTask(void *argument)
|
||||
{
|
||||
(void)argument;
|
||||
|
||||
#if defined(ENABLE_NET_LAYER_TESTS)
|
||||
int sockfd = -1;
|
||||
int phase_active = 0;
|
||||
uint32_t accept_retry = 0;
|
||||
struct net_sockaddr_in client_addr;
|
||||
int addrlen = sizeof(client_addr);
|
||||
#endif
|
||||
|
||||
DBG_INFO("Test task started");
|
||||
|
||||
#if defined(ENABLE_HW_LAYER_TESTS)
|
||||
@@ -1737,133 +1352,42 @@ void StartCh395fTestTask(void *argument)
|
||||
* 初始化并独占 CH395F —— 无 net_poll() 并发读取中断,无 SPI 并发事务 */
|
||||
if (net_stack_bring_up() != 0) {
|
||||
DBG_ERROR("net stack bring-up FAIL");
|
||||
goto task_end;
|
||||
} else {
|
||||
/* ==================== 阻塞阶段 ====================
|
||||
* Phase 1~5(硬件层)在 TCP 监听之前执行,不依赖外部连接。
|
||||
* 各 Phase 有各自的测试逻辑,完成后继续下一 Phase。
|
||||
*/
|
||||
#ifdef ENABLE_PHASE1_TESTS
|
||||
phase1_run();
|
||||
#endif
|
||||
#ifdef ENABLE_PHASE2_TESTS
|
||||
phase2_run();
|
||||
#endif
|
||||
#ifdef ENABLE_PHASE3_TESTS
|
||||
phase3_run();
|
||||
#endif
|
||||
#ifdef ENABLE_PHASE4_TESTS
|
||||
phase4_run();
|
||||
#endif
|
||||
#ifdef ENABLE_PHASE5_TESTS
|
||||
phase5_run();
|
||||
#endif
|
||||
}
|
||||
#else
|
||||
/* NET 层模式(阶段 6~10):等待 netTask 完成 net_init() 及 CH395F 初始化 */
|
||||
/* NET 层模式(阶段 6~11):等待 netTask 完成 net_init() 及 CH395F 初始化。
|
||||
* Phase 7(TCP Client)与阶段 6/8~11(TCP Server 监听循环)互斥,
|
||||
* 二者共用单连接 Socket 0,故按宏选择入口。 */
|
||||
while (!g_net_ready) {
|
||||
osDelay(100);
|
||||
}
|
||||
DBG_INFO("netTask ready");
|
||||
#if defined(ENABLE_PHASE7_TESTS)
|
||||
net_layer_client_test_main();
|
||||
#else
|
||||
net_layer_test_main();
|
||||
#endif
|
||||
#endif
|
||||
|
||||
/* ==================== 阻塞阶段 ====================
|
||||
* Phase 1~5(硬件层)在 TCP 监听之前执行,不依赖外部连接。
|
||||
* 各 Phase 有各自的测试逻辑,完成后继续下一 Phase。
|
||||
*/
|
||||
#ifdef ENABLE_PHASE1_TESTS
|
||||
phase1_run();
|
||||
#endif
|
||||
#ifdef ENABLE_PHASE2_TESTS
|
||||
phase2_run();
|
||||
#endif
|
||||
#ifdef ENABLE_PHASE3_TESTS
|
||||
phase3_run();
|
||||
#endif
|
||||
#ifdef ENABLE_PHASE4_TESTS
|
||||
phase4_run();
|
||||
#endif
|
||||
#ifdef ENABLE_PHASE5_TESTS
|
||||
phase5_run();
|
||||
#endif
|
||||
|
||||
#ifdef ENABLE_NET_LAYER_TESTS
|
||||
/* ==================== 创建 TCP 监听(NET 层模式) ==================== */
|
||||
|
||||
DBG_INFO("Creating test socket...");
|
||||
sockfd = net_socket(NET_AF_INET, NET_SOCK_STREAM, 0);
|
||||
if (sockfd < 0) {
|
||||
DBG_ERROR("Test task: net_socket failed");
|
||||
goto task_end;
|
||||
}
|
||||
DBG_INFO("Test task: socket %d created", sockfd);
|
||||
|
||||
{
|
||||
struct net_sockaddr_in addr;
|
||||
memset(&addr, 0, sizeof(addr));
|
||||
addr.sin_family = NET_AF_INET;
|
||||
addr.sin_port = net_htons(8080);
|
||||
if (net_bind(sockfd, (struct net_sockaddr *)&addr, sizeof(addr)) < 0) {
|
||||
DBG_ERROR("Test task: net_bind failed");
|
||||
goto task_end;
|
||||
}
|
||||
DBG_INFO("Test task: bound to port 8080");
|
||||
}
|
||||
|
||||
if (net_listen(sockfd) < 0) {
|
||||
DBG_ERROR("Test task: net_listen failed");
|
||||
goto task_end;
|
||||
}
|
||||
DBG_INFO("Test task: listening on 8080 (single-socket mode)");
|
||||
|
||||
/* ==================== 事件驱动阶段 ====================
|
||||
* Phase 6~10(NET 层)在 TCP 监听循环中运行,需要 PC 客户端连接。
|
||||
* 没有连接时循环等待;连接建立后执行对应 Phase。
|
||||
* 断开后自动重新 listen。
|
||||
*/
|
||||
for (;;) {
|
||||
if (!phase_active) {
|
||||
int acc = net_accept(sockfd, (struct net_sockaddr *)&client_addr, &addrlen);
|
||||
if (acc < 0) {
|
||||
if (accept_retry % 100 == 0) {
|
||||
DBG_INFO("Test task: waiting for connection...");
|
||||
}
|
||||
accept_retry++;
|
||||
osDelay(100);
|
||||
continue;
|
||||
}
|
||||
accept_retry = 0;
|
||||
phase_active = 1;
|
||||
DBG_INFO("Test task: client accepted (fd=%d)", acc);
|
||||
|
||||
/* 连接建立,重置各 Phase 内部状态 */
|
||||
#ifdef ENABLE_PHASE9_TESTS
|
||||
s_phase9_stage = 0;
|
||||
#endif
|
||||
#ifdef ENABLE_PHASE10_TESTS
|
||||
s_phase10_armed = 0;
|
||||
#endif
|
||||
}
|
||||
|
||||
/* 每 10ms 依次执行各已启用 Phase */
|
||||
#ifdef ENABLE_PHASE6_TESTS
|
||||
phase6_run(sockfd);
|
||||
#endif
|
||||
#ifdef ENABLE_PHASE7_TESTS
|
||||
phase7_run(sockfd);
|
||||
phase_active = 0; /* Phase 7 一次性完成,发完即止 */
|
||||
#endif
|
||||
#ifdef ENABLE_PHASE8_TESTS
|
||||
phase8_run(sockfd);
|
||||
#endif
|
||||
#ifdef ENABLE_PHASE9_TESTS
|
||||
phase9_run(sockfd);
|
||||
#endif
|
||||
#ifdef ENABLE_PHASE10_TESTS
|
||||
phase10_run(sockfd);
|
||||
#endif
|
||||
|
||||
/*
|
||||
* 连接状态检查:通过 net_get_sock 获取 Socket 控制块,
|
||||
* 如果连接已断开(state != ESTABLISHED),关闭并重新 listen。
|
||||
* 这是单连接模式的关键 —— Socket 0 必须始终处于 LISTEN 或 ESTABLISHED。
|
||||
*/
|
||||
{
|
||||
net_sock_t *sk = net_get_sock(sockfd);
|
||||
if (sk == NULL || !sk->in_use || sk->state != NET_SOCK_STATE_ESTABLISHED) {
|
||||
DBG_INFO("Test task: connection closed, re-listen...");
|
||||
net_close(sockfd);
|
||||
osDelay(500);
|
||||
net_listen(sockfd);
|
||||
phase_active = 0;
|
||||
}
|
||||
}
|
||||
|
||||
osDelay(10);
|
||||
}
|
||||
#endif /* ENABLE_NET_LAYER_TESTS */
|
||||
|
||||
task_end:
|
||||
for (;;) {
|
||||
osDelay(1000);
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user