通过测试排除了一些问题

This commit is contained in:
2026-07-19 04:32:18 +08:00
parent 1669cd216d
commit 4eb728583b
12 changed files with 1379 additions and 183 deletions

View File

@@ -124,6 +124,14 @@ static void ch395f_spi_dma_transfer(uint16_t len)
return;
}
}
/* 检查传输是否成功SPI 错误码必须为 0 */
if (hspi2.ErrorCode != 0U)
{
DBG_INFO("SPI DMA done with errors: ErrorCode=0x%lX, SPI_State=%d",
hspi2.ErrorCode, (int)hspi2.State);
__HAL_SPI_CLEAR_OVRFLAG(&hspi2);
}
}
/*
@@ -1177,6 +1185,9 @@ void ch395f_write_send_buf(uint8_t sock, uint8_t *p_data, uint16_t len)
/* 拷贝用户数据到 DMA 发送缓冲区 */
memcpy(&s_spi2_dma_tx_buf[4], p_data, len);
/* 数据同步屏障:确保 memcpy 写入在 DMA 读取前对总线可见 */
__DSB();
/* CS 拉低 -> DMA 批量传输 -> CS 拉高 */
ch395f_spi_begin();
ch395f_spi_dma_transfer(total);

View File

@@ -0,0 +1,576 @@
/*
* 模块名称CH395F Driver Test Suite
* 模块功能CH395F 驱动各功能模块的测试入口,分阶段组织测试用例
* 适用平台STM32F4 系列CH395F 以太网芯片)
* 作者:王建锋
* 创建日期2026-07-19
* 修改记录:
* 2026-07-19 Phase 1/2/3 implemented
*/
/* 头文件包含区 */
#include "ch395f_test.h"
#include "ch395f.h"
#include "net_socket.h"
#define DBG_TAG "[CH395T]"
#include "dbg_log.h"
#include <string.h>
#include <stdio.h>
/*
* Phase 2 配置默认值
*/
#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 配置默认值
*/
#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 20
#endif
#ifndef PHASE3_TIMEOUT_MS
#define PHASE3_TIMEOUT_MS 30000
#endif
/*
* 恢复 TCP Server 多连接模式的数据 Socket 配置
*/
static void restore_data_sockets(uint16_t port)
{
int i;
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 ============================
*/
void ch395f_phase1_tests(void)
{
uint8_t i;
int ver;
DBG_INFO("=== CH395F Phase 1 Tests ===");
/* Test 1: GET_VERSION */
ver = ch395f_get_version();
DBG_INFO("GET_VERSION: 0x%02X (ver=%d)", ver, ver & 0x3F);
/* Test 2: GET_CMD_STATUS */
uint8_t cmd_st = ch395f_get_cmd_status();
DBG_INFO("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]);
DBG_INFO(" IP match: %s", (ip_info[0]==192 && ip_info[1]==168 && ip_info[2]==1 && ip_info[3]==100) ? "YES" : "NO");
DBG_INFO(" GW match: %s", (ip_info[4]==192 && ip_info[5]==168 && ip_info[6]==1 && ip_info[7]==1) ? "YES" : "NO");
DBG_INFO(" MASK match: %s", (ip_info[8]==255 && ip_info[9]==255 && ip_info[10]==255 && ip_info[11]==0) ? "YES" : "NO");
/* Test 4: GINT_STATUS_ALL (2-byte version) */
uint16_t gint_all = ch395f_get_glob_int_status_all();
DBG_INFO("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();
DBG_INFO("GINT_STATUS_1byte (after clear): 0x%02X (expect 0x00 after read-clear)", gint_1b);
/* Test 6: SOCK_STATUS(0) */
{
uint8_t st[2];
ch395f_get_socket_status(0, st);
DBG_INFO("SOCK_STATUS(0): sock=0x%02X(OPEN), tcp=0x%02X(LISTEN)", st[0], st[1]);
}
/* Test 7: SET_ARP */
ch395f_set_arp(10, 5);
DBG_INFO("SET_ARP(period=10*100ms, cnt=5): OK");
/* Test 8: SET_TTL */
ch395f_set_ttl(0, 64);
DBG_INFO("SET_TTL(sock=0, ttl=64): OK");
/* Test 9: CLEAR_RECV_BUF + SOCK_INT poll */
ch395f_clear_recv_buf(0);
DBG_INFO("CLEAR_RECV_BUF(sock=0): OK");
for (i = 0; i < 8; i++)
{
uint8_t si = ch395f_get_sock_int_status(i);
DBG_INFO("SOCK_INT(%d): 0x%02X", i, si);
}
DBG_INFO("=== Phase 1 Tests Complete ===");
}
/*
* ============================ Phase 2 ============================
*/
void ch395f_phase2_tests(void)
{
uint8_t sock;
uint8_t status;
uint8_t sock_int;
uint8_t rx_buf[300];
int i;
uint32_t tick;
uint16_t int_st;
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);
/* 一次性配置 */
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);
ch395f_set_sour_port(sock, PHASE2_LOCAL_PORT + i);
status = ch395f_open_socket(sock);
if (status != CH395F_ERR_SUCCESS) { DBG_ERROR("open failed"); goto phase2_end; }
status = ch395f_tcp_connect(sock);
if (status != CH395F_ERR_SUCCESS) { DBG_ERROR("connect failed"); ch395f_close_socket(sock); goto phase2_end; }
/* 等待 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) { DBG_INFO("CONNECT"); break; }
}
HAL_Delay(10);
}
if (HAL_GetTick() - tick >= PHASE2_TIMEOUT_MS) { DBG_ERROR("connect timeout"); ch395f_close_socket(sock); goto phase2_end; }
HAL_Delay(100);
/* 发送测试数据 */
{
uint8_t test_buf[64];
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);
DBG_INFO("Sending test data (64 bytes)");
ch395f_write_send_buf(sock, test_buf, 64);
}
/* Echo 循环 */
for (;;)
{
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);
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"); goto phase2_iter_done; }
if (sock_int & CH395F_SINT_STAT_SOCK_TIMEOUT) { DBG_INFO("SOCK_TIMEOUT"); goto phase2_iter_done; }
}
HAL_Delay(50);
}
}
phase2_iter_done:
/* 关闭 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);
}
phase2_end:
restore_data_sockets(8080);
DBG_INFO("=== Phase 2 Tests Complete ===");
}
/*
* ============================ Phase 3 ============================
*/
void ch395f_phase3_tests(void)
{
uint8_t sock;
uint8_t rx_buf[300];
uint32_t tick, echo_start;
int i;
DBG_INFO("=== CH395F Phase 3 Tests (UDP) ===");
sock = (uint8_t)(NET_MAX_SOCKETS - 1);
/* UDP Server 模式DesIP=0xFFFFFFFF → 接受任意来源 */
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);
if (ch395f_open_socket(sock) != CH395F_ERR_SUCCESS)
{
DBG_ERROR("UDP open failed");
goto phase3_end;
}
DBG_INFO("UDP socket %d opened (server, port=%d, accept any)", sock, PHASE3_LOCAL_PORT);
HAL_Delay(200);
/* Echo 循环:收到 → 解析来源 → 回显,最多 PHASE3_ECHO_COUNT 轮 */
echo_start = HAL_GetTick();
for (i = 0; i < PHASE3_ECHO_COUNT; i++)
{
tick = HAL_GetTick();
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);
/* 8 字节头: [0-1]reserved [2-3]src_port(LE) [4-7]src_ip [8+]payload */
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);
/* 等 SENDBUF_FREE 再收下一个CH395F 要求写前必须空闲) */
{
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);
}
}
break;
}
HAL_Delay(50);
}
if (HAL_GetTick() - tick >= PHASE3_TIMEOUT_MS)
{
DBG_INFO("UDP recv timeout (%ds)", PHASE3_TIMEOUT_MS / 1000);
break;
}
}
if (i >= PHASE3_ECHO_COUNT)
DBG_INFO("Max echoes reached (%d)", PHASE3_ECHO_COUNT);
else
DBG_INFO("Elapsed: %lums", HAL_GetTick() - echo_start);
ch395f_close_socket(sock);
DBG_INFO("UDP socket closed");
phase3_end:
restore_data_sockets(8080);
DBG_INFO("=== Phase 3 Tests Complete ===");
}
/*
* ============================ Phase 4 ============================
* NET 层 TCP Echo在主循环中调用用 net_recv + net_send 回显
*/
static char s_phase4_buf[2048];
void ch395f_phase4_tests(void)
{
int i;
#ifdef ENABLE_PHASE4_TESTS
for (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);
}
}
#else
(void)i;
(void)s_phase4_buf;
#endif
}
/*
* ============================ Phase 5 ============================
* NET 层 UDP Echo主循环中运行用 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];
#endif
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;
}
DBG_INFO("Phase5: UDP socket %d bound to port %d", s_phase5_sock, PHASE5_LOCAL_PORT);
#endif
}
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));
}
#endif
}
/*
* ============================ Phase 6 ============================
* DHCP 自动获取 IP 测试
*/
void ch395f_phase6_tests(void)
{
#ifdef ENABLE_PHASE6_TESTS
uint8_t status;
uint8_t ip_info[20];
uint32_t tick;
DBG_INFO("=== CH395F Phase 6 Tests (DHCP) ===");
/* 1. 启用 DHCP */
ch395f_set_dhcp(1);
DBG_INFO("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)
{
DBG_INFO("DHCP: SUCCESS");
break;
}
HAL_Delay(500);
}
if (HAL_GetTick() - tick >= 30000)
{
status = ch395f_get_dhcp_status();
DBG_ERROR("DHCP timeout (status=0x%02X)", status);
goto phase6_end;
}
/* 3. 读取获取的 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]);
if (ip_info[0] == 0 && ip_info[1] == 0 && ip_info[2] == 0 && ip_info[3] == 0)
{
DBG_ERROR("DHCP: got 0.0.0.0 (failed)");
}
phase6_end:
DBG_INFO("=== Phase 6 Tests Complete ===");
#endif
}
/*
* ============================ Phase 7 ============================
* Select/Poll I/O 多路复用测试 — net_select() + net_recv/send echo
*/
#include "net_select.h"
#ifdef ENABLE_PHASE7_TESTS
static char s_phase7_buf[2048];
#endif
void ch395f_phase7_tests(void)
{
#ifdef ENABLE_PHASE7_TESTS
int i;
net_fd_set readfds;
net_timeval tv;
NET_FD_ZERO(&readfds);
/* 把 ESTABLISHED 状态的 TCP 数据 socket 加入监听集合 */
for (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);
}
}
/* 50ms 超时,避免阻塞主循环 */
tv.tv_sec = 0;
tv.tv_usec = 50000;
int n = net_select(NET_MAX_SOCKETS, &readfds, NULL, NULL, &tv);
if (n <= 0) return;
/* 处理就绪的 socket */
for (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);
}
}
#else
(void)0;
#endif
}

View File

@@ -0,0 +1,85 @@
/*
* 模块名称CH395F Driver Test Suite
* 模块功能CH395F 驱动各功能模块的测试入口,分阶段组织测试用例,
* 覆盖 SPI 命令路径、协议栈配置、Socket 状态机等
* 适用平台STM32F4 系列CH395F 以太网芯片)
* 作者:王建锋
* 创建日期2026-07-19
* 修改记录:
*/
#ifndef __CH395F_TEST_H
#define __CH395F_TEST_H
#ifdef __cplusplus
extern "C" {
#endif
/*
* 阶段使能开关(取消注释即启用对应阶段)
* 注意Phase 6 (DHCP) 会改变 IP建议独立运行
*/
//#define ENABLE_PHASE1_TESTS /* 寄存器读写 + 中断一致性 */
//#define ENABLE_PHASE2_TESTS /* TCP Client 收发 + 关闭重连 */
//#define ENABLE_PHASE3_TESTS /* UDP Server Echo */
//#define ENABLE_PHASE4_TESTS /* NET 层 TCP Echo需主循环调用 */
//#define ENABLE_PHASE5_TESTS /* NET 层 UDP Echo需主循环调用 */
//#define ENABLE_PHASE6_TESTS /* DHCP 自动获取 IP会改 IP */
//#define ENABLE_PHASE7_TESTS /* Select/Poll I/O 多路复用 */
/*
* Phase 1: 底层寄存器测试版本、IP、中断、ARP/TTL 等)
* 非破坏性net_init() 后即可运行
*/
void ch395f_phase1_tests(void);
/*
* Phase 2: TCP Client 功能测试3 轮收发 + 关闭重连)
* 需 PC 端先运行:
* python test/ch395f_socket_test.py tcp_server --port 8081
*/
void ch395f_phase2_tests(void);
/*
* Phase 3: UDP Server Echo 测试HELLO 探针 + PING + 大包)
* 需 PC 端先运行:
* python test/ch395f_socket_test.py udp_client --ip 192.168.1.100 --port 60000 --timeout 30
*/
void ch395f_phase3_tests(void);
/*
* Phase 4: NET 层 TCP Echo主循环中运行
* 需 PC 端运行(主循环进入后):
* python test/ch395f_socket_test.py tcp_client --ip 192.168.1.100 --port 8080
*/
void ch395f_phase4_tests(void);
/*
* Phase 5: NET 层 UDP Echo主循环中运行
* 需 PC 端运行(主循环进入后):
* python test/ch395f_socket_test.py udp_client --ip 192.168.1.100 --port 60000 --timeout 30
* 限定条件:需在 USER CODE BEGIN 2 中调用 ch395f_phase5_init() 创建 Socket
* USER CODE BEGIN 3 中调用 ch395f_phase5_tests() 做 echo
*/
void ch395f_phase5_init(void);
void ch395f_phase5_tests(void);
/*
* Phase 6: DHCP 测试
* 自动获取 IP打印结果。需独立运行会改变 IP
*/
void ch395f_phase6_tests(void);
/*
* Phase 7: Select/Poll 测试(主循环中运行)
* 使用 net_select() 检测可读 socketnet_recv/net_send 回显
* 需 PC 端运行:
* python test/ch395f_socket_test.py tcp_client --ip 192.168.1.100 --port 8080
*/
void ch395f_phase7_tests(void);
#ifdef __cplusplus
}
#endif
#endif /* __CH395F_TEST_H */

View File

@@ -328,7 +328,41 @@ int net_bind(int sockfd, const struct net_sockaddr *addr, int addrlen)
/* 设置本地端口(转换为主机序) */
sock->local_port = net_ntohs(addr_in->sin_port);
sock->state = NET_SOCK_STATE_BOUND;
/* UDP (SOCK_DGRAM): 直接在此打开 CH395F Socket */
if (sock->type == NET_SOCK_DGRAM)
{
uint8_t status;
/* Socket 4-7 默认无收发缓冲,需显式分配 */
if (sockfd >= 4)
{
ch395f_set_send_buf((uint8_t)sockfd, 28, 2);
ch395f_set_recv_buf((uint8_t)sockfd, 30, 2);
}
ch395f_set_proto_type((uint8_t)sockfd, CH395F_PROTO_TYPE_UDP);
ch395f_set_sour_port((uint8_t)sockfd, sock->local_port);
/* DesIP=0xFFFFFFFF → UDP Server 模式(接受任意来源) */
{
uint8_t broadcast[4] = {0xFF, 0xFF, 0xFF, 0xFF};
ch395f_set_des_ip((uint8_t)sockfd, broadcast);
}
ch395f_set_des_port((uint8_t)sockfd, 0);
status = ch395f_open_socket((uint8_t)sockfd);
if (status != CH395F_ERR_SUCCESS)
{
s_net_errno = NET_ERR_BUSY;
return -1;
}
sock->state = NET_SOCK_STATE_UDP_OPEN;
}
else
{
sock->state = NET_SOCK_STATE_BOUND;
}
return 0;
}
@@ -377,9 +411,15 @@ int net_listen(int sockfd, int backlog)
ch395f_tcp_listen(sockfd);
/* 多连接模式:为数据 Socket 设置协议类型和源端口(不 OPEN
* Socket 4-7 默认无收发缓冲,需在此分配
* CH395F 根据这些信息在客户端连接时自动分配空闲 Socket */
for (int ds = NET_TCP_SERVER_DATA_SOCK_START; ds < NET_MAX_SOCKETS; ds++)
{
if (ds >= 4)
{
ch395f_set_send_buf((uint8_t)ds, 28, 2);
ch395f_set_recv_buf((uint8_t)ds, 30, 2);
}
ch395f_set_proto_type((uint8_t)ds, CH395F_PROTO_TYPE_TCP);
ch395f_set_sour_port((uint8_t)ds, sock->local_port);
}
@@ -798,11 +838,12 @@ int net_recvfrom(int sockfd, void *buf, int len, int flags,
{
struct net_sockaddr_in *addr_in = (struct net_sockaddr_in *)src_addr;
addr_in->sin_family = NET_AF_INET;
addr_in->sin_port = net_htons((uint16_t)(header[4] | (header[5] << 8)));
addr_in->sin_addr.s_addr = ((uint32_t)header[0]) |
((uint32_t)header[1] << 8) |
((uint32_t)header[2] << 16) |
((uint32_t)header[3] << 24);
/* CH395F UDP 头: [0-1] reserved [2-3] src_port(LE) [4-7] src_ip */
addr_in->sin_port = net_htons((uint16_t)(header[2] | (header[3] << 8)));
addr_in->sin_addr.s_addr = ((uint32_t)header[4]) |
((uint32_t)header[5] << 8) |
((uint32_t)header[6] << 16) |
((uint32_t)header[7] << 24);
*addrlen = sizeof(struct net_sockaddr_in);
}
}

View File

@@ -20,7 +20,7 @@ extern "C" {
/*
* 总开关:取消注释启用所有调试输出
*/
/* #define DBG_ENABLE */
#define DBG_ENABLE
/*
* 调试级别开关:取消注释额外输出 DBG_DEBUG 级别