Files
STM32F4-Base/Drivers/BSP/CH395F/ch395f_test.c
2026-07-21 00:30:59 +08:00

646 lines
22 KiB
C
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
/*
* 模块名称CH395F Driver Test Suite
* 模块功能CH395F 驱动各功能模块的测试入口,分阶段组织测试用例
* 适用平台STM32F4 系列CH395F 以太网芯片)
* 作者王建<E78E8B>? * 创建日期<E697A5>?026-07-19
* 修改记录<E8AEB0>? * 2026-07-19 Phase 1/2/3 implemented
*/
/* 头文件包含区 */
#include <string.h>
#include <stdio.h>
#include "ch395f_test.h"
#include "ch395f.h"
#include "net_socket.h"
#define DBG_TAG "[CH395T]"
#include "dbg_log.h"
test_stats_t g_test_stats;
/*
* Phase 2 配置默认<E9BB98>? */
#ifndef PHASE2_REMOTE_IP
#define PHASE2_REMOTE_IP "192.168.1.2"
#endif
#ifndef PHASE2_REMOTE_PORT
#define PHASE2_REMOTE_PORT 8081
#endif
#ifndef PHASE2_LOCAL_PORT
#define PHASE2_LOCAL_PORT 50000
#endif
#ifndef PHASE2_LOOP_COUNT
#define PHASE2_LOOP_COUNT 3
#endif
#ifndef PHASE2_TIMEOUT_MS
#define PHASE2_TIMEOUT_MS 10000
#endif
/*
* Phase 3 配置默认<E9BB98>? */
#ifndef PHASE3_REMOTE_IP
#define PHASE3_REMOTE_IP "192.168.1.2"
#endif
#ifndef PHASE3_REMOTE_PORT
#define PHASE3_REMOTE_PORT 8082
#endif
#ifndef PHASE3_LOCAL_PORT
#define PHASE3_LOCAL_PORT 60000
#endif
#ifndef PHASE3_ECHO_COUNT
#define PHASE3_ECHO_COUNT 30
#endif
#ifndef PHASE3_TIMEOUT_MS
#define PHASE3_TIMEOUT_MS 30000
#endif
/*
* 函数功能<EFBC9A>?TCP Server 多连接模式的数据 Socket 配置
* 入口参数port - TCP 源端口号
* <20>?<3F>?值<E580BC>? * 限定条件CH395F 协议栈已初始<E5889D>? * 函数说明重新设置数<E7BDAE>?Socket 的协议类型和源端<E6BA90>? */
static void restore_data_sockets(uint16_t port) {
int i = 0;
for (i = NET_TCP_SERVER_DATA_SOCK_START; i < NET_MAX_SOCKETS; i++) {
ch395f_set_proto_type((uint8_t)i, CH395F_PROTO_TYPE_TCP);
ch395f_set_sour_port((uint8_t)i, port);
}
DBG_INFO("data socks restored (port %d)", port);
}
/*
* ============================ Phase 1 ============================
* 函数功能:寄存器读写 + 中断一致性基础测试
* 入口参数:无
* <20>?<3F>?值<E580BC>? * 限定条件CH395F 芯片正常应答
* 函数说明<EFBC9A>?GET_VERSION / GET_CMD_STATUS / GET_IP_INF <20>?9 <20>? */
void ch395f_phase1_tests(void) {
uint8_t i = 0;
int ver = 0;
DBG_INFO("=== CH395F Phase 1 Tests ===");
/* Test 1: GET_VERSION */
ver = ch395f_get_version();
TEST_CHECK(ver > 0, "GET_VERSION: 0x%02X (ver=%d)", ver, ver & 0x3F);
/* Test 2: GET_CMD_STATUS */
uint8_t cmd_st = ch395f_get_cmd_status();
TEST_CHECK(cmd_st == CH395F_ERR_SUCCESS,
"GET_CMD_STATUS: 0x%02X (%s)", cmd_st,
cmd_st == CH395F_ERR_SUCCESS ? "SUCCESS" :
cmd_st == CH395F_ERR_BUSY ? "BUSY" : "OTHER");
/* Test 3: GET_IP_INF */
uint8_t ip_info[20];
ch395f_get_ip_inf(ip_info);
DBG_INFO("GET_IP_INF:");
DBG_INFO(" IP: %d.%d.%d.%d", ip_info[0], ip_info[1], ip_info[2], ip_info[3]);
DBG_INFO(" GW: %d.%d.%d.%d", ip_info[4], ip_info[5], ip_info[6], ip_info[7]);
DBG_INFO(" MASK: %d.%d.%d.%d", ip_info[8], ip_info[9], ip_info[10], ip_info[11]);
DBG_INFO(" DNS1: %d.%d.%d.%d", ip_info[12], ip_info[13], ip_info[14], ip_info[15]);
DBG_INFO(" DNS2: %d.%d.%d.%d", ip_info[16], ip_info[17], ip_info[18], ip_info[19]);
TEST_CHECK(ip_info[0]==192 && ip_info[1]==168 && ip_info[2]==1 && ip_info[3]==100,
"IP match");
TEST_CHECK(ip_info[4]==192 && ip_info[5]==168 && ip_info[6]==1 && ip_info[7]==1,
"GW match");
TEST_CHECK(ip_info[8]==255 && ip_info[9]==255 && ip_info[10]==255 && ip_info[11]==0,
"MASK match");
/* Test 4: GINT_STATUS_ALL (2-byte version) */
uint16_t gint_all = ch395f_get_glob_int_status_all();
TEST_CHECK((gint_all & 0xFF) == 0x04 || (gint_all & 0xFF) == 0x00,
"GINT_STATUS_ALL: 0x%04X (lo=0x%02X hi=0x%02X)",
gint_all, gint_all & 0xFF, (gint_all >> 8) & 0xFF);
/* Test 5: GINT_STATUS (1-byte version) <20>?read-clear check */
uint8_t gint_1b = ch395f_get_glob_int_status();
TEST_CHECK(gint_1b == 0x00,
"GINT_STATUS_1byte: 0x%02X (expect 0x00 after read-clear)", gint_1b);
/* Test 6: SOCK_STATUS(0) */
{
uint8_t st[2];
ch395f_get_socket_status(0, st);
TEST_CHECK(st[0] == 0x05 && st[1] == 0x01,
"SOCK_STATUS(0): sock=0x%02X(LISTEN), tcp=0x%02X(LISTEN)", st[0], st[1]);
}
/* Test 7: SET_ARP */
ch395f_set_arp(10, 5);
TEST_CHECK(1, "SET_ARP(period=10*100ms, cnt=5): OK");
/* Test 8: SET_TTL */
ch395f_set_ttl(0, 64);
TEST_CHECK(1, "SET_TTL(sock=0, ttl=64): OK");
/* Test 9: CLEAR_RECV_BUF + SOCK_INT poll */
ch395f_clear_recv_buf(0);
TEST_CHECK(1, "CLEAR_RECV_BUF(sock=0): OK");
for (i = 0; i < 8; i++) {
uint8_t si = ch395f_get_sock_int_status(i);
TEST_CHECK(si == 0x00, "SOCK_INT(%d): 0x%02X", i, si);
}
TEST_REPORT("Phase 1");
}
/*
* ============================ Phase 2 ============================
* 函数功能TCP Client 收发 + 关闭重连 ×3 <20>? * 入口参数:无
* <20>?<3F>?值<E580BC>? * 限定条件PC 端已启动 TCP Server<EFBC88>?192.168.1.2:8081<38>? * 函数说明:每轮连接→发送→接收→关闭,连续 3 <20>? */
void ch395f_phase2_tests(void) {
uint8_t sock = 0;
uint8_t sock_int = 0;
uint8_t rx_buf[300] = {0};
int i = 0;
uint32_t tick = 0;
uint16_t int_st = 0;
int iter_pass = 0;
DBG_INFO("=== CH395F Phase 2 Tests (TCP Client - Direct Driver) ===");
/* 解析目标 IP */
uint8_t ip_arr[4];
{
uint32_t a[4];
sscanf(PHASE2_REMOTE_IP, "%lu.%lu.%lu.%lu", &a[0], &a[1], &a[2], &a[3]);
ip_arr[0] = (uint8_t)a[0];
ip_arr[1] = (uint8_t)a[1];
ip_arr[2] = (uint8_t)a[2];
ip_arr[3] = (uint8_t)a[3];
}
DBG_INFO("Target: %s:%d", PHASE2_REMOTE_IP, PHASE2_REMOTE_PORT);
sock = (uint8_t)(NET_MAX_SOCKETS - 1);
/* 一次性配<E680A7>?*/
ch395f_set_proto_type(sock, CH395F_PROTO_TYPE_TCP);
ch395f_set_send_buf(sock, 28, 2);
ch395f_set_recv_buf(sock, 30, 2);
ch395f_set_des_ip(sock, ip_arr);
ch395f_set_des_port(sock, PHASE2_REMOTE_PORT);
for (i = 0; i < PHASE2_LOOP_COUNT; i++) {
DBG_INFO("--- Iteration %d/%d ---", i + 1, PHASE2_LOOP_COUNT);
iter_pass = 1;
ch395f_set_sour_port(sock, PHASE2_LOCAL_PORT + i);
if (ch395f_open_socket(sock) != CH395F_ERR_SUCCESS) { TEST_CHECK(0, "open socket"); iter_pass = 0; goto phase2_iter_done; }
if (ch395f_tcp_connect(sock) != CH395F_ERR_SUCCESS) { TEST_CHECK(0, "tcp connect"); iter_pass = 0; ch395f_close_socket(sock); goto phase2_iter_done; }
/* 等待 CONNECT */
tick = HAL_GetTick();
while (HAL_GetTick() - tick < PHASE2_TIMEOUT_MS) {
int_st = ch395f_get_glob_int_status_all();
if (int_st & (1U << (sock + 4))) {
sock_int = ch395f_get_sock_int_status(sock);
if (sock_int & CH395F_SINT_STAT_CONNECT) break;
}
HAL_Delay(10);
}
if (HAL_GetTick() - tick >= PHASE2_TIMEOUT_MS) { TEST_CHECK(0, "connect timeout"); iter_pass = 0; ch395f_close_socket(sock); goto phase2_iter_done; }
HAL_Delay(100);
/* 发送测试数<E8AF95>?*/
{
uint8_t test_buf[64] = {0};
const char *msg = "HelloFromCH395F_TCP_Client! This is a 64-byte test message.";
int p, mlen = (int)strlen(msg);
memcpy(test_buf, msg, mlen);
for (p = mlen; p < 64; p++) test_buf[p] = (uint8_t)('0' + (p - mlen) % 10);
ch395f_write_send_buf(sock, test_buf, 64);
}
/* Echo 循环:收数据 <20>?回发 */
{
int got_echo = 0;
tick = HAL_GetTick();
while (HAL_GetTick() - tick < 10000) {
uint16_t rlen = ch395f_get_recv_len(sock);
if (rlen > 0) {
uint16_t read_len = (rlen > sizeof(rx_buf)) ? (uint16_t)sizeof(rx_buf) : rlen;
memset(rx_buf, 0, sizeof(rx_buf));
ch395f_read_recv_buf(sock, rx_buf, read_len);
DBG_INFO("recv: %d bytes [%.30s]", read_len, (char *)rx_buf);
ch395f_write_send_buf(sock, rx_buf, read_len);
got_echo = 1;
break;
}
int_st = ch395f_get_glob_int_status_all();
if (int_st & (1U << (sock + 4))) {
sock_int = ch395f_get_sock_int_status(sock);
if (sock_int & CH395F_SINT_STAT_DISCONNECT) { DBG_INFO("DISCONNECT"); break; }
if (sock_int & CH395F_SINT_STAT_SOCK_TIMEOUT) { DBG_INFO("SOCK_TIMEOUT"); break; }
}
HAL_Delay(50);
}
if (!got_echo) { TEST_CHECK(0, "echo recv (iter %d)", i + 1); iter_pass = 0; }
}
phase2_iter_done:
if (iter_pass) TEST_CHECK(1, "Iteration %d PASS", i + 1);
/* 关闭 socket */
ch395f_close_socket(sock);
{
uint8_t st[2];
uint32_t wait = HAL_GetTick();
while (HAL_GetTick() - wait < 5000) {
ch395f_get_socket_status(sock, st);
if (st[0] == CH395F_SOCKET_CLOSED) break;
HAL_Delay(50);
}
DBG_INFO("closed: sock=0x%02X tcp=0x%02X", st[0], st[1]);
}
HAL_Delay(200);
}
restore_data_sockets(8080);
TEST_REPORT("Phase 2");
}
/*
* ============================ Phase 3 ============================
* 函数功能UDP Server Echo + PING + 大包测试
* 入口参数:无
* <20>?<3F>?值<E580BC>? * 限定条件PC 端已启动 UDP Client<EFBC88>?192.168.1.2:8082<38>? * 函数说明<EFBC9A>?20 次回显<E59B9E>? <20>?PING<4E>?0 次大包收<E58C85>? */
void ch395f_phase3_tests(void) {
uint8_t sock = 0;
uint8_t rx_buf[300] = {0};
uint32_t tick = 0;
int i = 0;
int echo_ok = 0;
DBG_INFO("=== CH395F Phase 3 Tests (UDP) ===");
sock = (uint8_t)(NET_MAX_SOCKETS - 1);
/* UDP Server 模式DesIP=0xFFFFFFFF <20>?接受任意来源 */
ch395f_set_proto_type(sock, CH395F_PROTO_TYPE_UDP);
ch395f_set_send_buf(sock, 28, 2);
ch395f_set_recv_buf(sock, 30, 2);
ch395f_set_sour_port(sock, PHASE3_LOCAL_PORT);
{
uint8_t zero_ip[4] = {0xFF, 0xFF, 0xFF, 0xFF};
ch395f_set_des_ip(sock, zero_ip);
}
ch395f_set_des_port(sock, 0);
TEST_CHECK(ch395f_open_socket(sock) == CH395F_ERR_SUCCESS,
"UDP socket %d opened (port=%d)", sock, PHASE3_LOCAL_PORT);
HAL_Delay(200);
/* Echo 循环<EFBC9A>?<3F>?解析来源 <20>?回显 */
for (i = 0; i < PHASE3_ECHO_COUNT; i++) {
tick = HAL_GetTick();
echo_ok = 0;
while (HAL_GetTick() - tick < PHASE3_TIMEOUT_MS) {
uint16_t rlen = ch395f_get_recv_len(sock);
if (rlen > 8) {
memset(rx_buf, 0, sizeof(rx_buf));
ch395f_read_recv_buf(sock, rx_buf, rlen);
uint16_t payload_len = rlen - 8;
uint16_t src_port = (uint16_t)rx_buf[2] | ((uint16_t)rx_buf[3] << 8);
uint8_t *src_ip = &rx_buf[4];
uint8_t *payload = &rx_buf[8];
DBG_INFO("UDP #%d: %dB from %d.%d.%d.%d:%d [%.32s]",
i + 1, payload_len,
src_ip[0], src_ip[1], src_ip[2], src_ip[3], src_port,
payload_len > 0 ? (char *)payload : "");
ch395f_set_des_ip(sock, src_ip);
ch395f_set_des_port(sock, src_port);
ch395f_write_send_buf(sock, payload, payload_len);
{
uint32_t swait = HAL_GetTick();
while (HAL_GetTick() - swait < 2000) {
uint16_t gs = ch395f_get_glob_int_status_all();
if (gs & (1U << (sock + 4))) {
if (ch395f_get_sock_int_status(sock) & CH395F_SINT_STAT_SENBUF_FREE)
break;
}
HAL_Delay(10);
}
}
echo_ok = 1;
break;
}
HAL_Delay(50);
}
TEST_CHECK(echo_ok, "UDP echo #%d/%d", i + 1, PHASE3_ECHO_COUNT);
if (!echo_ok) break;
}
ch395f_close_socket(sock);
TEST_CHECK(1, "UDP socket closed");
restore_data_sockets(8080);
TEST_REPORT("Phase 3");
}
/*
* ============================ Phase 4 ============================
* NET <20>?TCP Echo在主循环中调用用 net_recv + net_send 回显
*/
#ifdef ENABLE_PHASE4_TESTS
static char s_phase4_buf[2048];
#endif
/*
* 函数功能NET <20>?TCP Echo 测试
* 入口参数:无
* <20>?<3F>?值<E580BC>? * 限定条件net_init 已完<E5B7B2>? * 函数说明:在 netTask 中运行,轮询 Socket 1~7 回显接收数据
*/
void ch395f_phase4_tests(void) {
#ifdef ENABLE_PHASE4_TESTS
for (int i = NET_TCP_SERVER_DATA_SOCK_START; i < NET_MAX_SOCKETS; i++) {
net_sock_t *sk = net_get_sock(i);
if (sk == NULL || !sk->in_use || sk->state != NET_SOCK_STATE_ESTABLISHED) {
continue;
}
int n = net_recv_sock(sk, s_phase4_buf, sizeof(s_phase4_buf), NET_MSG_DONTWAIT);
if (n > 0) {
net_send_sock(sk, s_phase4_buf, n);
}
}
#endif
}
/*
* ============================ Phase 5 ============================
* NET <20>?UDP EchonetTask 中运行<E8A18C>?net_recvfrom + net_sendto 回显
*/
#ifndef PHASE5_LOCAL_PORT
#define PHASE5_LOCAL_PORT 60000
#endif
#ifdef ENABLE_PHASE5_TESTS
static int s_phase5_sock = -1;
static char s_phase5_buf[2048];
static uint32_t s_phase5_count = 0;
#endif
/*
* 函数功能NET <20>?UDP Echo 初始<E5889D>? * 入口参数:无
* <20>?<3F>?值<E580BC>? * 限定条件net_init 已完<E5B7B2>? * 函数说明<EFBC9A>?UDP Socket 并绑定本地端<E59CB0>? */
void ch395f_phase5_init(void) {
#ifdef ENABLE_PHASE5_TESTS
struct net_sockaddr_in addr;
s_phase5_sock = net_socket(NET_AF_INET, NET_SOCK_DGRAM, 0);
if (s_phase5_sock < 0) {
DBG_ERROR("Phase5: net_socket failed");
return;
}
memset(&addr, 0, sizeof(addr));
addr.sin_family = NET_AF_INET;
addr.sin_port = net_htons(PHASE5_LOCAL_PORT);
if (net_bind(s_phase5_sock, (struct net_sockaddr *)&addr, sizeof(addr)) < 0) {
DBG_ERROR("Phase5: net_bind failed");
net_close_sock(net_get_sock(s_phase5_sock));
s_phase5_sock = -1;
return;
}
s_phase5_count = 0;
DBG_INFO("Phase5: UDP socket %d bound to port %d", s_phase5_sock, PHASE5_LOCAL_PORT);
#endif
}
/*
* 函数功能NET <20>?UDP Echo 测试
* 入口参数:无
* <20>?<3F>?值<E580BC>? * 限定条件ch395f_phase5_init 已成功调<E58A9F>? * 函数说明:在 netTask 中运行,回显 UDP 接收数据
*/
void ch395f_phase5_tests(void) {
#ifdef ENABLE_PHASE5_TESTS
if (s_phase5_sock < 0) return;
struct net_sockaddr_in src;
int addrlen = sizeof(src);
int n = net_recvfrom(s_phase5_sock, s_phase5_buf, sizeof(s_phase5_buf),
NET_MSG_DONTWAIT,
(struct net_sockaddr *)&src, &addrlen);
if (n > 0) {
net_sendto(s_phase5_sock, s_phase5_buf, n, 0,
(struct net_sockaddr *)&src, sizeof(src));
s_phase5_count++;
TEST_CHECK(1, "Phase5: UDP echo #%lu (%d bytes)", s_phase5_count, n);
}
#endif
}
/*
* Phase 6 配置默认<E9BB98>? */
#ifndef PHASE6_ANNOUNCE_PORT
#define PHASE6_ANNOUNCE_PORT 60001
#endif
#ifndef PHASE6_ANNOUNCE_SOCK
#define PHASE6_ANNOUNCE_SOCK 6
#endif
/*
* ============================ Phase 6 ============================
* 函数功能DHCP 自动获取 IP 测试
* 入口参数:无
* <20>?<3F>?值<E580BC>? * 限定条件局域网内存<E58685>?DHCP Server
* 函数说明<EFBC9A>?DHCP <20>?轮询等待 IP <20>?打印结果 <20>?广播宣告 <20>?HELLO 回显
*/
void ch395f_phase6_tests(void) {
#ifdef ENABLE_PHASE6_TESTS
uint8_t status = 0;
uint8_t ip_info[20] = {0};
uint32_t tick = 0;
DBG_INFO("=== CH395F Phase 6 Tests (DHCP) ===");
/* 1. 启用 DHCP */
ch395f_set_dhcp(1);
TEST_CHECK(1, "DHCP enabled, waiting for IP...");
/* 2. 轮询等待 DHCP 完成 */
HAL_Delay(500);
tick = HAL_GetTick();
while (HAL_GetTick() - tick < 30000) {
uint16_t gint = ch395f_get_glob_int_status_all();
if (gint & CH395F_GINT_STAT_DHCP) {
DBG_INFO("DHCP interrupt");
}
status = ch395f_get_dhcp_status();
if (status == 0x00) {
TEST_CHECK(1, "DHCP: SUCCESS");
break;
}
HAL_Delay(500);
}
TEST_CHECK(HAL_GetTick() - tick < 30000,
"DHCP completed within 30s (status=0x%02X)", status);
if (HAL_GetTick() - tick >= 30000) {
goto phase6_end;
}
/* 3. 读取获取<E88EB7>?IP */
ch395f_get_ip_inf(ip_info);
DBG_INFO(" IP: %d.%d.%d.%d", ip_info[0], ip_info[1], ip_info[2], ip_info[3]);
DBG_INFO(" GW: %d.%d.%d.%d", ip_info[4], ip_info[5], ip_info[6], ip_info[7]);
DBG_INFO(" MASK: %d.%d.%d.%d", ip_info[8], ip_info[9], ip_info[10], ip_info[11]);
DBG_INFO(" DNS1: %d.%d.%d.%d", ip_info[12], ip_info[13], ip_info[14], ip_info[15]);
TEST_CHECK(ip_info[0] != 0 || ip_info[1] != 0 || ip_info[2] != 0 || ip_info[3] != 0,
"IP = %d.%d.%d.%d (non-zero)", ip_info[0], ip_info[1], ip_info[2], ip_info[3]);
/* 4. 广播宣告 + 等待 PC HELLO 确认 */
{
#define PHASE6_HELLO_PORT 60000
uint8_t anno_sock = PHASE6_ANNOUNCE_SOCK;
uint8_t bcast_ip[4] = {0xFF, 0xFF, 0xFF, 0xFF};
uint8_t rx_buf[64] = {0};
/* UDP Server 模式本地端<E59CB0>?60000<EFBC88>?HELLODesIP=0xFFFFFFFF */
ch395f_set_proto_type(anno_sock, CH395F_PROTO_TYPE_UDP);
ch395f_set_send_buf(anno_sock, 24, 2);
ch395f_set_recv_buf(anno_sock, 26, 2);
ch395f_set_sour_port(anno_sock, PHASE6_HELLO_PORT);
ch395f_set_des_ip(anno_sock, bcast_ip);
ch395f_set_des_port(anno_sock, 0);
if (ch395f_open_socket(anno_sock) == CH395F_ERR_SUCCESS) {
/* 发送广播宣告(宣告端口 = 60001来源端<E6BA90>?= 60000<30>?*/
ch395f_set_des_ip(anno_sock, bcast_ip);
ch395f_set_des_port(anno_sock, PHASE6_ANNOUNCE_PORT);
ch395f_write_send_buf(anno_sock, ip_info, 4);
/* 等待 SENDBUF_FREE手册要求每次 write_send_buf 后必须等待) */
{
uint32_t swait = HAL_GetTick();
while (HAL_GetTick() - swait < 2000) {
uint16_t gs = ch395f_get_glob_int_status_all();
if (gs & (1U << (anno_sock + 4))) {
if (ch395f_get_sock_int_status(anno_sock) & CH395F_SINT_STAT_SENBUF_FREE)
break;
}
HAL_Delay(10);
}
}
DBG_INFO("DHCP announcement: IP=%d.%d.%d.%d (port %d->%d)",
ip_info[0], ip_info[1], ip_info[2], ip_info[3],
PHASE6_HELLO_PORT, PHASE6_ANNOUNCE_PORT);
TEST_CHECK(1, "DHCP announcement sent");
/* 重置 Server 模式<EFBC8C>?PC 发<>?HELLO */
ch395f_set_des_ip(anno_sock, bcast_ip);
ch395f_set_des_port(anno_sock, 0);
uint32_t wait = HAL_GetTick();
uint8_t hello_ok = 0;
while (HAL_GetTick() - wait < 5000) {
/* 读取全局中断<EFBC88>?socket 中断状态) */
ch395f_get_glob_int_status_all();
uint16_t rlen = ch395f_get_recv_len(anno_sock);
if (rlen > 8) {
memset(rx_buf, 0, sizeof(rx_buf));
ch395f_read_recv_buf(anno_sock, rx_buf, rlen);
uint16_t payload_len = rlen - 8;
uint8_t *payload = &rx_buf[8];
if (payload_len == 5 && memcmp(payload, "HELLO", 5) == 0) {
uint8_t *src_ip = &rx_buf[4];
uint16_t src_port = (uint16_t)rx_buf[2] | ((uint16_t)rx_buf[3] << 8);
ch395f_set_des_ip(anno_sock, src_ip);
ch395f_set_des_port(anno_sock, src_port);
ch395f_write_send_buf(anno_sock, payload, payload_len);
HAL_Delay(100);
DBG_INFO("HELLO response sent to %d.%d.%d.%d:%d",
src_ip[0], src_ip[1], src_ip[2], src_ip[3], src_port);
TEST_CHECK(1, "HELLO echo OK");
hello_ok = 1;
break;
}
}
HAL_Delay(50);
}
TEST_CHECK(hello_ok, "HELLO echo within 5s");
ch395f_close_socket(anno_sock);
} else {
TEST_CHECK(0, "DHCP announcement: open socket failed");
}
}
phase6_end:
TEST_REPORT("Phase 6");
#endif
}
/*
* ============================ Phase 7 ============================
* Select/Poll I/O 多路复用测试 <20>?net_select() + net_recv/send echo
*/
#include "net_select.h"
#ifdef ENABLE_PHASE7_TESTS
static char s_phase7_buf[2048];
#endif
/*
* 函数功能Select/Poll I/O 多路复用测试
* 入口参数:无
* <20>?<3F>?值<E580BC>? * 限定条件net_init 已完成多连<E5A49A>?TCP Server 已启<E5B7B2>? * 函数说明:在 netTask 中运行,验证 select/poll 正确返回读写事件
*/
void ch395f_phase7_tests(void) {
#ifdef ENABLE_PHASE7_TESTS
static uint32_t s_phase7_count = 0;
net_fd_set readfds;
net_timeval tv;
FD_ZERO
NET_FD_ZERO(&readfds);
for (int i = NET_TCP_SERVER_DATA_SOCK_START; i < NET_MAX_SOCKETS; i++) {
net_sock_t *sk = net_get_sock(i);
if (sk && sk->in_use && sk->state == NET_SOCK_STATE_ESTABLISHED) {
NET_FD_SET(i, &readfds);
}
}
tv.tv_sec = 0;
tv.tv_usec = 50000;
int n = net_select(NET_MAX_SOCKETS, &readfds, NULL, NULL, &tv);
if (n <= 0) return;
for (int i = 0; i < NET_MAX_SOCKETS; i++) {
net_sock_t *sk = net_get_sock(i);
if (!sk || !NET_FD_ISSET(i, &readfds)) continue;
int len = net_recv_sock(sk, s_phase7_buf, sizeof(s_phase7_buf), NET_MSG_DONTWAIT);
if (len > 0) {
net_send_sock(sk, s_phase7_buf, len);
s_phase7_count++;
TEST_CHECK(1, "Phase7: select echo #%lu (sock=%d, %d bytes)", s_phase7_count, i, len);
}
}
#endif
}