645 lines
22 KiB
C
645 lines
22 KiB
C
/*
|
||
* 模å<C2A1>—å<E28094><C3A5>称:CH395F Driver Test Suite
|
||
* 模å<C2A1>—功能:CH395F 驱动å<C2A8>„功能模å<C2A1>—的测试入å<C2A5>£ï¼Œåˆ†é˜¶æ®µç»„织测试用例
|
||
* 适用平å<C2B3>°ï¼šSTM32F4 系列(CH395F 以太网芯片)
|
||
* 作者:王建� * 创建日期�026-07-19
|
||
* 修改记录� * 2026-07-19 Phase 1/2/3 implemented
|
||
*/
|
||
|
||
/* 头文件包å<E280A6>«åŒº */
|
||
#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 é…<C3A9>置默认ï¿? */
|
||
#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 é…<C3A9>置默认ï¿? */
|
||
#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
|
||
|
||
/*
|
||
* 函数功能:æ<C5A1>¢ï¿?TCP Server 多连接模å¼<C3A5>的数æ<C2B0>® Socket é…<C3A9>ç½®
|
||
* å…¥å<C2A5>£å<C2A3>‚数:port - TCP æº<C3A6>端å<C2AF>£å<C2A3>·
|
||
* ï¿?ï¿?值:ï¿? * é™<C3A9>定æ<C5A1>¡ä»¶ï¼šCH395F å<><C3A5>è®®æ ˆå·²åˆ<C3A5>å§‹ï¿? * 函数说明:é‡<C3A9>新设置数ï¿?Socket çš„å<E2809E><C3A5>议类型和æº<C3A6>端ï¿? */
|
||
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 ============================
|
||
* 函数功能:寄å˜å™¨è¯»å†™ + 䏿–一致性基础测试
|
||
* å…¥å<C2A5>£å<C2A3>‚数:æ—
|
||
* ï¿?ï¿?值:ï¿? * é™<C3A9>定æ<C5A1>¡ä»¶ï¼šCH395F 芯片æ£å¸¸åº”ç”
|
||
* 函数说明:包�GET_VERSION / GET_CMD_STATUS / GET_IP_INF �9 � */
|
||
|
||
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) ï¿?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 æ”¶å<C2B6>‘ + å…³é—é‡<C3A9>连 ×3 ï¿? * å…¥å<C2A5>£å<C2A3>‚数:æ—
|
||
* ï¿?ï¿?值:ï¿? * é™<C3A9>定æ<C5A1>¡ä»¶ï¼šPC 端已å<C2B2>¯åЍ TCP Server(默ï¿?192.168.1.2:8081ï¿? * 函数说明:æ¯<C3A6>轮连接→å<E28099>‘é€<C3A9>→接收→关é—ï¼Œè¿žç» 3 ï¿? */
|
||
|
||
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) ===");
|
||
|
||
/* è§£æž<C3A6>ç›®æ ‡ 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);
|
||
|
||
/* 一次性é…<C3A9>ï¿?*/
|
||
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);
|
||
|
||
/* å<>‘é€<C3A9>测试数ï¿?*/
|
||
{
|
||
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 循环:收数æ<C2B0>® ï¿?回å<C5BE>‘ */
|
||
{
|
||
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 + 大包测试
|
||
* å…¥å<C2A5>£å<C2A3>‚数:æ—
|
||
* ï¿?ï¿?值:ï¿? * é™<C3A9>定æ<C5A1>¡ä»¶ï¼šPC 端已å<C2B2>¯åЍ UDP Client(默ï¿?192.168.1.2:8082ï¿? * 函数说明:包ï¿?20 次回显�? ï¿?PINGï¿?0 次大包收ï¿? */
|
||
|
||
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 模å¼<C3A5>:DesIP=0xFFFFFFFF ï¿?接å<C2A5>—ä»»æ„<C3A6>æ<EFBFBD>¥æº<C3A6> */
|
||
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 循环:收ï¿?ï¿?è§£æž<C3A6>æ<EFBFBD>¥æº<C3A6> ï¿?回显 */
|
||
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 ï¿?TCP Echo:在主循环ä¸è°ƒç”¨ï¼Œç”¨ net_recv + net_send 回显
|
||
*/
|
||
|
||
#ifdef ENABLE_PHASE4_TESTS
|
||
static char s_phase4_buf[2048];
|
||
#endif
|
||
|
||
/*
|
||
* 函数功能:NET �TCP Echo 测试
|
||
* å…¥å<C2A5>£å<C2A3>‚数:æ—
|
||
* ï¿?ï¿?值:ï¿? * é™<C3A9>定æ<C5A1>¡ä»¶ï¼šnet_init 已完ï¿? * 函数说明:在 netTask ä¸è¿<C3A8>行,轮询 Socket 1~7 回显接收数æ<C2B0>®
|
||
*/
|
||
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(i, s_phase4_buf, sizeof(s_phase4_buf), NET_MSG_DONTWAIT);
|
||
if (n > 0) {
|
||
net_send(i, s_phase4_buf, n, 0);
|
||
}
|
||
}
|
||
#endif
|
||
}
|
||
|
||
/*
|
||
* ============================ Phase 5 ============================
|
||
* NET ï¿?UDP Echo:netTask ä¸è¿<C3A8>行,ï¿?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 ï¿?UDP Echo åˆ<C3A5>å§‹ï¿? * å…¥å<C2A5>£å<C2A3>‚数:æ—
|
||
* ï¿?ï¿?值:ï¿? * é™<C3A9>定æ<C5A1>¡ä»¶ï¼šnet_init 已完ï¿? * 函数说明:创ï¿?UDP Socket 并绑定本地端ï¿? */
|
||
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(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 �UDP Echo 测试
|
||
* å…¥å<C2A5>£å<C2A3>‚数:æ—
|
||
* ï¿?ï¿?值:ï¿? * é™<C3A9>定æ<C5A1>¡ä»¶ï¼šch395f_phase5_init å·²æˆ<C3A6>功调ï¿? * 函数说明:在 netTask ä¸è¿<C3A8>行,回显 UDP 接收数æ<C2B0>®
|
||
*/
|
||
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 é…<C3A9>置默认ï¿? */
|
||
#ifndef PHASE6_ANNOUNCE_PORT
|
||
#define PHASE6_ANNOUNCE_PORT 60001
|
||
#endif
|
||
#ifndef PHASE6_ANNOUNCE_SOCK
|
||
#define PHASE6_ANNOUNCE_SOCK 6
|
||
#endif
|
||
|
||
/*
|
||
* ============================ Phase 6 ============================
|
||
* 函数功能:DHCP 自动获å<C2B7>– IP 测试
|
||
* å…¥å<C2A5>£å<C2A3>‚数:æ—
|
||
* ï¿?ï¿?值:ï¿? * é™<C3A9>定æ<C5A1>¡ä»¶ï¼šå±€åŸŸç½‘内å˜ï¿?DHCP Server
|
||
* 函数说明:å<C5A1>¯ï¿?DHCP ï¿?轮询ç‰å¾… IP ï¿?打å<E2809C>°ç»“æžœ ï¿?广æ’宣告 ï¿?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 完æˆ<C3A6> */
|
||
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. 读å<C2BB>–获å<C2B7>–ï¿?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 模å¼<C3A5>:本地端ï¿?60000(接ï¿?HELLO),DesIP=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) {
|
||
/* å<>‘é€<C3A9>广æ’宣告(宣告端å<C2AF>£ = 60001,æ<C592>¥æº<C3A6>端ï¿?= 60000ï¿?*/
|
||
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(手册è¦<C3A8>求:æ¯<C3A6>次 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");
|
||
|
||
/* é‡<C3A9>ç½® Server 模å¼<C3A5>,ç‰ï¿?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) {
|
||
/* 读å<C2BB>–免局䏿–(刷ï¿?socket 䏿–状æ€<C3A6>) */
|
||
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 多路å¤<C3A5>用测试 ï¿?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 多路å¤<C3A5>用测试
|
||
* å…¥å<C2A5>£å<C2A3>‚数:æ—
|
||
* ï¿?ï¿?值:ï¿? * é™<C3A9>定æ<C5A1>¡ä»¶ï¼šnet_init 已完æˆ<C3A6>,多连ï¿?TCP Server å·²å<C2B2>¯ï¿? * 函数说明:在 netTask ä¸è¿<C3A8>行,验è¯<C3A8> 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++) {
|
||
if (!NET_FD_ISSET(i, &readfds)) continue;
|
||
|
||
int len = net_recv(i, s_phase7_buf, sizeof(s_phase7_buf), NET_MSG_DONTWAIT);
|
||
if (len > 0) {
|
||
net_send(i, s_phase7_buf, len, 0);
|
||
s_phase7_count++;
|
||
TEST_CHECK(1, "Phase7: select echo #%lu (sock=%d, %d bytes)", s_phase7_count, i, len);
|
||
}
|
||
}
|
||
#endif
|
||
}
|
||
|