d770e36c7c
- 源码注释:删去自愈收敛阶段 1/1.5/3等 scaffolding 称谓,改为语义引用 (E-02 收口 / F-NET-2/3/4 / docs/网络/网络自愈架构设计.md §5.2 E13); 涉及 net_socket/.h、net_events、net_listener、net_pending、net_types、 net_config、ch395f、time_sync、iec104_serv、ui_net_sink、lftpd、 simulator/sim/net_socket_sim、board/host 测试与探针 - 文档重构:网络自愈架构设计.md 与 Net层阻塞模型架构设计.md 改为现状口径 (删历史节与阶段叙事),NET/README.md、docs/README.md 同步 - 工具与配图:gen_net_instability_svg.py 与 docs/images/网络不稳根因总览.svg 随源码口径一并更新 - 门禁:@build 0 错误 0 警告
866 lines
32 KiB
C
866 lines
32 KiB
C
/*
|
||
* 模块名称:CH395F SPI Ethernet Protocol Stack Driver
|
||
* 模块功能:CH395F 以太网协议栈芯片 SPI 驱动,提供网络初始化、Socket 管理、
|
||
* 数据收发等功能。命令码参考 CH395 手册 v2.2 Table 5-1
|
||
* 适用平台:STM32F4 系列(SPI2 接口)
|
||
* 作者:王建锋
|
||
* 创建日期:2026-06-06
|
||
* 修改记录:
|
||
* 2026-06-06 王建锋 创建初始版本,按代码规范重构
|
||
*/
|
||
|
||
#ifndef CH395F_H
|
||
#define CH395F_H
|
||
|
||
/*
|
||
* 头文件包含区 - 仅包含本模块必需的头文件
|
||
*/
|
||
|
||
#ifdef __cplusplus
|
||
extern "C" {
|
||
#endif
|
||
|
||
#include "main.h"
|
||
|
||
/*
|
||
* 宏定义区 - SPI 命令码(来自 CH395 手册 v2.2 Table 5-1)
|
||
*/
|
||
|
||
/* 无输入数据,无输出数据 */
|
||
#define CH395F_CMD_RESET_ALL 0x05U
|
||
|
||
/* 无输入数据,1 字节输出 */
|
||
#define CH395F_CMD_GET_IC_VER 0x01U
|
||
#define CH395F_CMD_GET_CMD_STATUS 0x2CU
|
||
#define CH395F_CMD_GET_PHY_STATUS 0x26U
|
||
#define CH395F_CMD_GET_DHCP_STATUS 0x42U
|
||
|
||
/* 无输入数据,多字节输出(§5.16 / §5.14,勿按 1 字节读) */
|
||
#define CH395F_CMD_GET_GLOB_INT_STATUS_ALL 0x19U /* 2 字节 */
|
||
#define CH395F_CMD_GET_UNREACH_IPPT 0x28U /* 8 字节 */
|
||
|
||
/* 无输入数据,6 字节输出 */
|
||
#define CH395F_CMD_GET_MAC_ADDR 0x40U
|
||
|
||
/* 无输入数据,20 字节输出 */
|
||
#define CH395F_CMD_GET_IP_INF 0x43U
|
||
|
||
/* 1 字节输入,无输出数据 */
|
||
#define CH395F_CMD_SET_PHY 0x20U
|
||
#define CH395F_CMD_PING_ENABLE 0x3FU
|
||
#define CH395F_CMD_DHCP_ENABLE 0x41U
|
||
#define CH395F_CMD_SET_RETRAN_COUNT 0x2AU
|
||
|
||
/* 1 字节输入,1 字节输出 */
|
||
#define CH395F_CMD_CHECK_EXIST 0x06U
|
||
|
||
/* 4 字节输入,无输出数据(§5.52,勿按 1 字节写) */
|
||
#define CH395F_CMD_SET_FUN_PARA 0x55U
|
||
|
||
/* 2 字节输入(低字节在前),无输出数据 */
|
||
#define CH395F_CMD_SET_TTL 0x51U
|
||
#define CH395F_CMD_SET_ARP 0x44U
|
||
#define CH395F_CMD_SET_RETRAN_PERIOD 0x2BU
|
||
|
||
/* 3 字节输入,无输出数据 */
|
||
#define CH395F_CMD_SET_BAUDRATE 0x02U
|
||
|
||
/* 4 字节输入,无输出数据 */
|
||
#define CH395F_CMD_SET_IP_ADDR 0x22U
|
||
#define CH395F_CMD_SET_GWIP_ADDR 0x23U
|
||
#define CH395F_CMD_SET_MASK_ADDR 0x24U
|
||
|
||
/* 6 字节输入,无输出数据 */
|
||
#define CH395F_CMD_SET_MAC_ADDR 0x21U
|
||
|
||
/* 初始化命令(仅写入,执行时间较长) */
|
||
#define CH395F_CMD_INIT_CH395 0x27U
|
||
|
||
/* Socket 命令 */
|
||
/* 1 字节输入(socket 索引),无输出数据 */
|
||
#define CH395F_CMD_CLOSE_SOCKET_SN 0x3DU
|
||
#define CH395F_CMD_OPEN_SOCKET_SN 0x35U
|
||
#define CH395F_CMD_TCP_LISTEN_SN 0x36U
|
||
#define CH395F_CMD_TCP_CONNECT_SN 0x37U
|
||
#define CH395F_CMD_TCP_DISCONNECT_SN 0x38U
|
||
#define CH395F_CMD_CLEAR_RECV_BUF_SN 0x2EU
|
||
|
||
/* 1 字节输入,1 字节输出(socket 索引) */
|
||
#define CH395F_CMD_GET_INT_STATUS_SN 0x30U
|
||
#define CH395F_CMD_GET_SOCKET_STATUS_SN 0x2FU
|
||
|
||
/* 1 字节输入,2 字节输出 */
|
||
#define CH395F_CMD_GET_RECV_LEN_SN 0x3BU
|
||
|
||
/* 2 字节输入,无输出数据 */
|
||
#define CH395F_CMD_SET_PROTO_TYPE_SN 0x34U
|
||
#define CH395F_CMD_SET_IPRAW_PRO_SN 0x3EU
|
||
|
||
/* 3 字节输入,无输出数据 */
|
||
#define CH395F_CMD_SET_DES_PORT_SN 0x32U
|
||
#define CH395F_CMD_SET_SOUR_PORT_SN 0x33U
|
||
|
||
/* 5 字节输入,无输出数据(socket + 4 字节 IP) */
|
||
#define CH395F_CMD_SET_IP_ADDR_SN 0x31U
|
||
|
||
/* 1 字节输入,6 字节输出(socket 索引 -> 远程 IP + 端口) */
|
||
#define CH395F_CMD_GET_REMOT_IPP_SN 0x2DU
|
||
|
||
/* 3 字节输入 + 数据输出(socket + 长度) */
|
||
#define CH395F_CMD_READ_RECV_BUF_SN 0x3CU
|
||
|
||
/* 3 字节输入 + 数据输入(socket + 长度 + 数据) */
|
||
#define CH395F_CMD_WRITE_SEND_BUF_SN 0x39U
|
||
|
||
/*
|
||
* TCP MSS(CH395F_CMD_SET_TCP_MSS 参数)
|
||
* 由 net_init 经 ch395f_set_tcp_mss() 下发(须在 ch395f_init 之前);此处为单一真值源。
|
||
* 维持 1024:8 Socket 共享 24KB 缓冲时,单 Socket 接收缓冲 = 2×MSS = 2KB(手册 §9.2.8
|
||
* 满足上限的最大值)。MSS=512 裕量方案未采纳;当年支撑该决策的台架判据不可信,
|
||
* 已随 TC-NET-604 结案为非缺陷一并撤回(2026-09-23)——维持 1024 的
|
||
* 现有理由 = 手册允许的最大值、满缓冲周期段数少。MSS 只影响芯片分包与窗口动态,
|
||
* 与下方缓冲块布局解耦。
|
||
*/
|
||
#define CH395F_TCP_MSS 1024U
|
||
|
||
/* 内部缓冲 RAM 每块字节数(手册 §5.45:48 块 × 512B = 24KB) */
|
||
#define CH395F_RAM_BLOCK_SIZE 512U
|
||
/* 单 Socket 缓冲块数:固定布局(2026-09-22 与 MSS 解耦;此前由 MSS 推导,改 MSS 会
|
||
* 连带静默缩小布局):接收 4 块=2KB、发送 2 块=1KB,8 Socket × 6 块 = 48 块恰好用满。
|
||
* 布局满足手册 §9.2.8:接收 2KB = 2×MSS(1024)(建议下沿,零裕量——用满 48 块的代价)/
|
||
* ≥ MSS(必须)/ ≤ 6×MSS(建议);
|
||
* 发送 1KB = MSS(WCH FAQ 要求"发送缓冲 > MSS",此处取等值——生产实测(FTP 大文件
|
||
* 上传/下载 + UI 推流)在缓冲边界可正常成包)。 */
|
||
#define CH395F_RECV_BLOCKS 4U
|
||
#define CH395F_SEND_BLOCKS 2U
|
||
/* 单 Socket 硬件收发缓冲字节数(= 块数 × 块大小)。写入发送 FIFO 的单次长度严禁超过此值,
|
||
* 否则会写穿有限的发送缓冲(见 TRAP-NET-16)。 */
|
||
#define CH395F_SEND_BUF_SIZE_BYTES (CH395F_SEND_BLOCKS * CH395F_RAM_BLOCK_SIZE)
|
||
#define CH395F_RECV_BUF_SIZE_BYTES (CH395F_RECV_BLOCKS * CH395F_RAM_BLOCK_SIZE)
|
||
|
||
/*
|
||
* SPI DMA 事务限制
|
||
* CH395F_SPI_DMA_MAX_PAYLOAD: 单次 DMA 事务最大有效载荷(总缓冲 - 4 字节命令头)
|
||
* 缓冲按"一条命令读空整个 Socket 接收缓冲(2KB)"定容——排空契约(TRAP-NET-20,
|
||
* bit3=1 残数据由 MCU 读出)的形态本身就是整缓冲单读。
|
||
* (旧解释"部分读致 recv_len 归零、剩余数据不可见"未证实且与手册 §5.34 相左,
|
||
* 定容不依赖该解释;结案见 `CH395F_Trap_Records.md` 台架纪律。)
|
||
* 2026-09-22:与 MSS 解耦(此前 = 2×MSS+4,MSS 下调会把 DMA 缓冲缩到装不下整缓冲
|
||
* → 整缓冲读会被截断丢弃)。
|
||
*/
|
||
#define CH395F_SPI_DMA_BUF_SIZE (CH395F_RECV_BUF_SIZE_BYTES + 4U)
|
||
#define CH395F_SPI_DMA_MAX_PAYLOAD (CH395F_SPI_DMA_BUF_SIZE - 4U)
|
||
|
||
/* 其他命令 */
|
||
#define CH395F_CMD_SET_TCP_MSS 0x50U
|
||
#define CH395F_CMD_SET_RECV_BUF 0x52U
|
||
#define CH395F_CMD_SET_SEND_BUF 0x53U
|
||
#define CH395F_CMD_SET_KEEPALIVE_IDLE 0x56U
|
||
#define CH395F_CMD_SET_KEEPALIVE_INTVL 0x57U
|
||
#define CH395F_CMD_SET_KEEPALIVE_CNT 0x58U
|
||
#define CH395F_CMD_SET_KEEPALIVE_SN 0x59U
|
||
/* EEPROM(0xE9..0xEB)/GPIO(0xEC/0xED)/SLEEP(0x03) 命令宏与
|
||
* GET_GLOB_INT_STATUS(0x29,只有 2 字节版 0x19 有实现) 死声明已删除——
|
||
* 全仓零引用已核实;需要时按手册 §5.x 重新登记 */
|
||
|
||
/*
|
||
* CH395 命令执行状态码(CMD_GET_CMD_STATUS 返回值,与芯片手册一致)
|
||
*/
|
||
#define CH395F_ERR_SUCCESS 0x00U /* 成功 */
|
||
#define CH395F_ERR_BUSY 0x10U /* 忙,命令正在执行 */
|
||
#define CH395F_ERR_MEM 0x11U /* 内存管理错误 */
|
||
#define CH395F_ERR_BUF 0x12U /* 缓冲区错误 */
|
||
#define CH395F_ERR_TIMEOUT 0x13U /* 超时 */
|
||
#define CH395F_ERR_RTE 0x14U /* 路由错误 */
|
||
#define CH395F_ERR_ABRT 0x15U /* 连接中止 */
|
||
#define CH395F_ERR_RST 0x16U /* 连接复位 */
|
||
#define CH395F_ERR_CLSD 0x17U /* 连接关闭 */
|
||
#define CH395F_ERR_CONN 0x18U /* 无连接 */
|
||
#define CH395F_ERR_VAL 0x19U /* 值错误 */
|
||
#define CH395F_ERR_ARG 0x1AH /* 参数错误 */
|
||
#define CH395F_ERR_USE 0x1BH /* 已被使用 */
|
||
#define CH395F_ERR_IF 0x1CH /* MAC 错误 */
|
||
#define CH395F_ERR_ISCONN 0x1DH /* 已连接 */
|
||
#define CH395F_ERR_OPEN 0x20U /* 已打开 */
|
||
#define CH395F_CMD_RET_ABORT 0x5FU /* 命令中止(来自官方库) */
|
||
#define CH395F_ERR_UNKNOW 0xFAU /* 未知错误」 */
|
||
|
||
/*
|
||
* PHY 状态码
|
||
*/
|
||
#define CH395F_PHY_DISCONN 0x01U /* PHY 断开连接 */
|
||
#define CH395F_PHY_10M_FULL 0x02U /* 10M 全双工 */
|
||
#define CH395F_PHY_10M_HALF 0x04U /* 10M 半双工 */
|
||
#define CH395F_PHY_100M_FULL 0x08U /* 100M 全双工 */
|
||
#define CH395F_PHY_100M_HALF 0x10U /* 100M 半双工 */
|
||
#define CH395F_PHY_AUTO_NEGOTIATE 0x20U /* 自动协商 */
|
||
|
||
/*
|
||
* 功能参数标志位(CMD_SET_FUN_PARA,§5.52 表)
|
||
* bit3 SOCKET_CLOSE 需芯片版本 ≥0x46(版本门控见 net_init);
|
||
* bit1 TCP_SERVER 多连接模式——本项目单连接模型不用(红线,勿置 1);
|
||
* bit0 保留必须为 0(TRAP-NET-15 定案更正:0x09→0x08)
|
||
*/
|
||
#define CH395F_FUN_PARA_TCP_SERVER (1UL << 1) /* TCP Server 多连接模式 */
|
||
#define CH395F_FUN_PARA_SOCKET_CLOSE (1UL << 3) /* Socket 关闭控制(0=芯片自动,1=外部控制;TRAP-NET-20 排空契约) */
|
||
#define CH395F_FUN_PARA_DISABLE_SEND_OK (1UL << 4) /* 禁用 SEND_OK 中断 */
|
||
|
||
/*
|
||
* 协议类型
|
||
*/
|
||
#define CH395F_PROTO_TYPE_IP_RAW 0x00U
|
||
#define CH395F_PROTO_TYPE_MAC_RAW 0x01U
|
||
#define CH395F_PROTO_TYPE_UDP 0x02U
|
||
#define CH395F_PROTO_TYPE_TCP 0x03U
|
||
|
||
/*
|
||
* Socket 状态
|
||
*/
|
||
#define CH395F_SOCKET_CLOSED 0x00U
|
||
#define CH395F_SOCKET_OPEN 0x05U
|
||
|
||
/*
|
||
* TCP 状态
|
||
*/
|
||
#define CH395F_TCP_CLOSED 0x00U
|
||
#define CH395F_TCP_LISTEN 0x01U
|
||
#define CH395F_TCP_SYN_SENT 0x02U
|
||
#define CH395F_TCP_SYN_RCVD 0x03U
|
||
#define CH395F_TCP_ESTABLISHED 0x04U
|
||
#define CH395F_TCP_FIN_WAIT_1 0x05U
|
||
#define CH395F_TCP_FIN_WAIT_2 0x06U
|
||
#define CH395F_TCP_CLOSE_WAIT 0x07U
|
||
#define CH395F_TCP_CLOSING 0x08U
|
||
#define CH395F_TCP_LAST_ACK 0x09U
|
||
#define CH395F_TCP_TIME_WAIT 0x0AU
|
||
|
||
/*
|
||
* 全局中断状态位低字节(bit0~3 全局事件;§5.16——2 字节版
|
||
* GET_GLOB_INT_STATUS_ALL 低字节同语义。Socket 事件位(bit4 起)由
|
||
* net_poll 按 1U<<(i+4) 计算,旧 SOCK0..3 单列宏已删(
|
||
* 全仓零引用;1 字节版命令 0x29 亦已随死声明清理)
|
||
*/
|
||
#define CH395F_GINT_STAT_UNREACH 0x01U
|
||
#define CH395F_GINT_STAT_IP_CONFLI 0x02U
|
||
#define CH395F_GINT_STAT_PHY_CHANGE 0x04U
|
||
#define CH395F_GINT_STAT_DHCP 0x08U
|
||
|
||
/*
|
||
* 全局中断状态位(CMD_GET_GLOB_INT_STATUS_ALL 2字节版,支持Socket 0~7)
|
||
* 低字节高字节分别定义
|
||
*/
|
||
#define CH395F_GINT_STAT_SOCK4 0x0100U
|
||
#define CH395F_GINT_STAT_SOCK5 0x0200U
|
||
#define CH395F_GINT_STAT_SOCK6 0x0400U
|
||
#define CH395F_GINT_STAT_SOCK7 0x0800U
|
||
/* bit12 DHCPv6:官方 SDK 定义为 (1<<12),但 §5.16 明确 CH395F 的 [12:15] 为
|
||
* 保留位(仅 CH395X 系列产生)——本芯片上恒为 0,勿用作判据 */
|
||
#define CH395F_GINT_STAT_DHCPV6 0x1000U
|
||
|
||
/*
|
||
* Socket 中断状态位(CMD_GET_INT_STATUS_SN 返回值,来自手册表5-x)
|
||
*/
|
||
#define CH395F_SINT_STAT_SENBUF_FREE 0x01U /* bit0: 发送缓冲区空闲 */
|
||
#define CH395F_SINT_STAT_SEND_OK 0x02U /* bit1: 发送成功 */
|
||
#define CH395F_SINT_STAT_RECV_OK 0x04U /* bit2: 接收缓冲区非空 */
|
||
#define CH395F_SINT_STAT_CONNECT 0x08U /* bit3: TCP 连接成功 */
|
||
#define CH395F_SINT_STAT_DISCONNECT 0x10U /* bit4: TCP 连接断开 */
|
||
#define CH395F_SINT_STAT_DISCARD 0x20U /* bit5: 保留 */
|
||
#define CH395F_SINT_STAT_SOCK_TIMEOUT 0x40U /* bit6: 超时 */
|
||
|
||
/*
|
||
* 类型定义区 - 驱动返回码
|
||
*/
|
||
typedef enum {
|
||
CH395F_STATUS_OK = 0,
|
||
CH395F_STATUS_ERROR = -1,
|
||
CH395F_STATUS_TIMEOUT = -2,
|
||
CH395F_STATUS_NOT_DETECTED = -3
|
||
} ch395f_status_t;
|
||
|
||
/*
|
||
* 函数声明区 - SPI 基础事务层
|
||
*/
|
||
|
||
/*
|
||
* 函数功能:向 CH395 写入命令字节
|
||
* 入口参数:cmd - 命令码 uint8_t 0x00 - 0xFF
|
||
* 返回值:命令码回显值 uint8_t
|
||
* 限定条件:需在 ch395f_spi_begin() 和 ch395f_spi_end() 之间调用
|
||
* 函数说明:SPI 模式下命令与数据之间无需间隔
|
||
*/
|
||
uint8_t ch395f_write_cmd(uint8_t cmd);
|
||
|
||
/*
|
||
* 函数功能:向 CH395 写入数据字节
|
||
* 入口参数:data - 数据字节 uint8_t 0x00 - 0xFF
|
||
* 返回值:数据回显值 uint8_t
|
||
* 限定条件:需在 ch395f_spi_begin() 和 ch395f_spi_end() 之间调用
|
||
*/
|
||
uint8_t ch395f_write_data(uint8_t data);
|
||
|
||
/*
|
||
* 函数功能:从 CH395 读取数据字节
|
||
* 返回值:接收到的数据字节 uint8_t
|
||
* 限定条件:需在 ch395f_spi_begin() 和 ch395f_spi_end() 之间调用
|
||
*/
|
||
uint8_t ch395f_read_data(void);
|
||
|
||
/*
|
||
* 函数功能:查询 SPI 通道故障锁存(E-34 / P2-2)
|
||
* 返回值:0 - 正常 1 - 曾发生 SPI 超时/错误(字节级或 DMA 级)
|
||
* 限定条件:无
|
||
* 函数说明:锁存式(MCU 复位前一直有效);上层据此判定"SPI 通道异常"
|
||
* (区别于"无芯片"/"PHY 未链接");仅首条故障记日志
|
||
*/
|
||
uint8_t ch395f_spi_byte_fault(void);
|
||
|
||
/*
|
||
* 函数声明区 - 芯片检测与版本
|
||
*/
|
||
|
||
/*
|
||
* 函数功能:检测 CH395 芯片是否存在且通信正常
|
||
* 返回值:CH395F_STATUS_OK - 检测到芯片,CH395F_STATUS_NOT_DETECTED - 未检测到
|
||
* 限定条件:SPI2 已正确初始化
|
||
* 函数说明:发送 CMD_CHECK_EXIST (0x06) 及测试字节 0x57,
|
||
* 芯片应返回按位取反值 0xA8
|
||
*/
|
||
ch395f_status_t ch395f_check_exist(void);
|
||
|
||
/*
|
||
* 函数功能:读取 CH395 芯片版本号
|
||
* 返回值:版本字节(bit5:0 为版本号)uint8_t
|
||
* 限定条件:芯片已通过 ch395f_check_exist() 检测
|
||
*/
|
||
uint8_t ch395f_get_version(void);
|
||
|
||
/*
|
||
* 函数声明区 - 初始化
|
||
*/
|
||
|
||
/*
|
||
* 函数功能:软件复位 CH395
|
||
* 返回值:CH395F_STATUS_OK
|
||
* 限定条件:SPI2 已正确初始化
|
||
* 函数说明:复位耗时约 15ms(TE0),函数内部已包含延时
|
||
*/
|
||
ch395f_status_t ch395f_reset(void);
|
||
|
||
/*
|
||
* 函数功能:查询命令执行状态
|
||
* 返回值:状态字节(CH395F_ERR_SUCCESS / CH395F_ERR_BUSY / ...)uint8_t
|
||
* 限定条件:仅在长执行命令(如初始化)后调用
|
||
*/
|
||
uint8_t ch395f_get_cmd_status(void);
|
||
|
||
/*
|
||
* 函数功能:轮询等待命令执行完成
|
||
* 入口参数:timeout_ms - 超时时间(毫秒) uint32_t
|
||
* 返回值:命令执行状态码(CH395F_ERR_SUCCESS 或 CH395F_CMD_RET_ABORT)
|
||
* 限定条件:在发送长执行命令(OPEN/TCP_LISTEN/CONNECT/DISCONNECT/CLOSE/DHCP)后调用
|
||
* 函数说明:每 20ms 查询一次,直到命令完成或超时
|
||
*/
|
||
uint8_t ch395f_poll_cmd_status(uint32_t timeout_ms);
|
||
|
||
/*
|
||
* 函数功能:初始化 CH395(包含 MAC、PHY、TCP/IP 协议栈)
|
||
* 返回值:CH395F_STATUS_OK - 成功,CH395F_STATUS_TIMEOUT - 超时失败
|
||
* 限定条件:芯片已通过 ch395f_reset() 复位
|
||
* 函数说明:阻塞等待初始化完成或超时(典型 5ms,TE1)
|
||
*/
|
||
ch395f_status_t ch395f_init(void);
|
||
|
||
/*
|
||
* 函数声明区 - 网络参数配置
|
||
*/
|
||
|
||
/*
|
||
* 函数功能:设置 CH395 IP 地址(点分十进制序:p_ip[0]=第一段,如 192;
|
||
* 字节序曾误注为"低字节在前"——调用方 parse_ip_string 产出
|
||
* 点分数组直传、芯片按首段在前接受,台架多年 IP 生效实证)
|
||
* 入口参数:p_ip - 4 字节 IP 地址指针 uint8_t*
|
||
* 限定条件:指针非空,芯片已初始化
|
||
*/
|
||
void ch395f_set_ip_addr(uint8_t *p_ip);
|
||
|
||
/*
|
||
* 函数功能:设置网关 IP 地址(点分十进制序,同 ch395f_set_ip_addr)
|
||
* 入口参数:p_gwip - 4 字节网关 IP 指针 uint8_t*
|
||
* 限定条件:指针非空,芯片已初始化
|
||
*/
|
||
void ch395f_set_gwip_addr(uint8_t *p_gwip);
|
||
|
||
/*
|
||
* 函数功能:设置子网掩码(点分十进制序,同 ch395f_set_ip_addr)
|
||
* 入口参数:p_mask - 4 字节子网掩码指针 uint8_t*
|
||
* 限定条件:指针非空,芯片已初始化
|
||
*/
|
||
void ch395f_set_mask_addr(uint8_t *p_mask);
|
||
|
||
/*
|
||
* 函数功能:设置 MAC 地址(低字节在前,存储于 EEPROM)
|
||
* 入口参数:p_mac - 6 字节 MAC 地址指针 uint8_t*
|
||
* 限定条件:指针非空,芯片已初始化
|
||
* 函数说明:执行耗时约 30us(TE5)
|
||
*/
|
||
void ch395f_set_mac_addr(uint8_t *p_mac);
|
||
|
||
/*
|
||
* 函数功能:从 CH395 读取 MAC 地址
|
||
* 出口参数:p_mac - 6 字节 MAC 地址缓冲区指针 uint8_t*
|
||
* 限定条件:指针非空
|
||
*/
|
||
void ch395f_get_mac_addr(uint8_t *p_mac);
|
||
|
||
/*
|
||
* 函数功能:读取 IP 信息(IP + 掩码 + DNS,共 20 字节)
|
||
* 出口参数:p_buf - 20 字节缓冲区指针 uint8_t*
|
||
* 限定条件:指针非空
|
||
*/
|
||
void ch395f_get_ip_inf(uint8_t *p_buf);
|
||
|
||
/*
|
||
* 函数声明区 - PHY 管理
|
||
*/
|
||
|
||
/*
|
||
* 函数功能:获取 PHY 连接状态
|
||
* 返回值:PHY 状态码(CH395F_PHY_DISCONN、CH395F_PHY_10M_FULL 等)uint8_t
|
||
* 限定条件:芯片已初始化
|
||
*/
|
||
uint8_t ch395f_get_phy_status(void);
|
||
|
||
/*
|
||
* 函数功能:设置 PHY 连接模式
|
||
* 入口参数:phystat - 连接模式码 uint8_t 0x20 = 自动协商
|
||
* 限定条件:芯片已初始化
|
||
*/
|
||
void ch395f_set_phy(uint8_t phystat);
|
||
|
||
/*
|
||
* 函数功能:使能/关闭 CH395 响应 PING
|
||
* 入口参数:enable - 1 使能 PING 响应,0 关闭
|
||
* 限定条件:芯片已初始化
|
||
* 函数说明:手册 5.37 CMD_PING_ENABLE,默认关闭
|
||
*/
|
||
void ch395f_ping_enable(uint8_t enable);
|
||
|
||
/*
|
||
* 函数声明区 - DHCP
|
||
*/
|
||
|
||
/*
|
||
* 函数功能:启用/禁用 DHCP
|
||
* 入口参数:enable - 1 启用,0 禁用 uint8_t
|
||
* 限定条件:芯片已初始化
|
||
*/
|
||
void ch395f_set_dhcp(uint8_t enable);
|
||
|
||
/*
|
||
* 函数功能:获取 DHCP 状态
|
||
* 返回值:0 = 成功,非零 = 错误/超时 uint8_t
|
||
* 限定条件:芯片已初始化且 DHCP 已启用
|
||
*/
|
||
uint8_t ch395f_get_dhcp_status(void);
|
||
|
||
/*
|
||
* 函数声明区 - Socket 管理
|
||
*/
|
||
|
||
/*
|
||
* 函数功能:设置 Socket 协议类型
|
||
* 入口参数:sock - Socket 索引 uint8_t 0 - 7
|
||
* proto - 协议类型 uint8_t CH395F_PROTO_TYPE_xxx
|
||
* 限定条件:Socket 未打开
|
||
*/
|
||
void ch395f_set_proto_type(uint8_t sock, uint8_t proto);
|
||
|
||
/*
|
||
* 函数功能:设置 Socket 目标 IP 地址
|
||
* 入口参数:sock - Socket 索引 uint8_t 0 - 7
|
||
* p_ip - 4 字节目标 IP 指针 uint8_t*
|
||
* 限定条件:指针非空
|
||
* 函数说明:字节序与 ch395f_get_remot_ipp 输出一致(net_connect 直传其输出,
|
||
* 台架出站连接往返实证)
|
||
*/
|
||
void ch395f_set_des_ip(uint8_t sock, uint8_t *p_ip);
|
||
|
||
/*
|
||
* 函数功能:设置 Socket 目标端口(小端序)
|
||
* 入口参数:sock - Socket 索引 uint8_t 0 - 7
|
||
* port - 目标端口 uint16_t
|
||
* 限定条件:无
|
||
*/
|
||
void ch395f_set_des_port(uint8_t sock, uint16_t port);
|
||
|
||
/*
|
||
* 函数功能:设置 Socket 源端口(小端序)
|
||
* 入口参数:sock - Socket 索引 uint8_t 0 - 7
|
||
* port - 源端口 uint16_t
|
||
* 限定条件:无
|
||
*/
|
||
void ch395f_set_sour_port(uint8_t sock, uint16_t port);
|
||
|
||
/*
|
||
* 函数功能:打开 Socket
|
||
* 入口参数:sock - Socket 索引 uint8_t 0 - 7
|
||
* 返回值:命令执行状态码(CH395F_ERR_SUCCESS 表示成功) uint8_t
|
||
* 限定条件:协议类型、目标 IP、端口已设置
|
||
*/
|
||
uint8_t ch395f_open_socket(uint8_t sock);
|
||
|
||
/*
|
||
* 函数功能:关闭 Socket
|
||
* 入口参数:sock - Socket 索引 uint8_t 0 - 7
|
||
* 返回值:命令执行状态码(CH395F_ERR_SUCCESS 表示成功) uint8_t
|
||
* 限定条件:Socket 已打开
|
||
*/
|
||
uint8_t ch395f_close_socket(uint8_t sock);
|
||
|
||
/*
|
||
* 函数功能:启动 TCP 监听模式
|
||
* 入口参数:sock - Socket 索引 uint8_t 0 - 7
|
||
* 返回值:命令执行状态码(CH395F_ERR_SUCCESS 表示成功) uint8_t
|
||
* 限定条件:Socket 已打开且协议类型为 TCP
|
||
*/
|
||
uint8_t ch395f_tcp_listen(uint8_t sock);
|
||
|
||
/*
|
||
* 函数功能:启动 TCP 连接
|
||
* 入口参数:sock - Socket 索引 uint8_t 0 - 7
|
||
* 返回值:命令执行状态码(CH395F_ERR_SUCCESS 表示成功) uint8_t
|
||
* 限定条件:Socket 已打开且协议类型为 TCP
|
||
*/
|
||
uint8_t ch395f_tcp_connect(uint8_t sock);
|
||
|
||
/*
|
||
* 函数功能:断开 TCP 连接
|
||
* 入口参数:sock - Socket 索引 uint8_t 0 - 7
|
||
* 返回值:命令执行状态码(CH395F_ERR_SUCCESS 表示成功) uint8_t
|
||
* 限定条件:TCP 已建立连接
|
||
*/
|
||
uint8_t ch395f_tcp_disconnect(uint8_t sock);
|
||
|
||
/*
|
||
* 函数声明区 - Socket 数据传输
|
||
*/
|
||
|
||
/*
|
||
* 函数功能:向 Socket 发送缓冲区写入数据
|
||
* 入口参数:sock - Socket 索引 uint8_t 0 - 7
|
||
* p_data - 数据指针 uint8_t*
|
||
* len - 数据长度 uint16_t
|
||
* 限定条件:指针非空,长度大于 0,TCP 已连接或 UDP 已打开
|
||
*/
|
||
void ch395f_write_send_buf(uint8_t sock, uint8_t *p_data, uint16_t len);
|
||
|
||
/*
|
||
* 函数功能:从 Socket 接收缓冲区读取数据
|
||
* 入口参数:sock - Socket 索引 uint8_t 0 - 7
|
||
* p_data - 输出缓冲区指针 uint8_t*
|
||
* len - 待读取数据长度 uint16_t
|
||
* 限定条件:指针非空,长度大于 0,接收缓冲区有数据
|
||
*/
|
||
void ch395f_read_recv_buf(uint8_t sock, uint8_t *p_data, uint16_t len);
|
||
|
||
/*
|
||
* 函数功能:获取 Socket 接收缓冲区数据长度
|
||
* 入口参数:sock - Socket 索引 uint8_t 0 - 7
|
||
* 返回值:接收数据长度 uint16_t
|
||
* 限定条件:Socket 已打开
|
||
*/
|
||
uint16_t ch395f_get_recv_len(uint8_t sock);
|
||
|
||
/*
|
||
* 函数声明区 - 中断状态
|
||
*/
|
||
|
||
/*
|
||
* 函数功能:获取全局中断状态(2 字节版,支持 Socket 0~7)
|
||
* 返回值:中断状态 uint16_t(低字节=Socket 0~3 + PHY/DHCP,高字节=Socket 4~7 + DHCPv6)
|
||
* 限定条件:芯片已初始化
|
||
* ⚠ 护栏(F-NET-7,I7 不变量):本寄存器**读即清**且含全部 Socket 事件位——
|
||
* 任何未配对 SINT 消费的读取都会吞掉其它 Socket 的事件通知。
|
||
* **唯一读者 = net_poll(net_socket.c);测试/台架代码同样禁自行读取**
|
||
* (用户裁定 2026-10-13)——等事件一律直读本 Socket ch395f_get_sock_int_status()。
|
||
* 唯一例外:被测对象就是本 API 的板级用例(P1-06 寄存器断言 / Phase 12 L1
|
||
* 时延基准,硬件层独占上下文、无并发消费者)。
|
||
*/
|
||
uint16_t ch395f_get_glob_int_status_all(void);
|
||
|
||
/*
|
||
* 函数功能:获取 Socket 中断状态
|
||
* 入口参数:sock - Socket 索引 uint8_t 0 - 7
|
||
* 返回值:Socket 中断状态字节 uint8_t
|
||
* 限定条件:芯片已初始化
|
||
*/
|
||
uint8_t ch395f_get_sock_int_status(uint8_t sock);
|
||
|
||
/*
|
||
* 函数功能:获取 Socket 状态(2 字节输出)
|
||
* 入口参数:sock - Socket 索引 uint8_t 0 - 7
|
||
* status - 2 字节输出缓冲区 [0]=Socket状态, [1]=TCP状态
|
||
* 限定条件:芯片已初始化
|
||
* 函数说明:Socket 状态: 00H=CLOSED, 05H=OPEN
|
||
* TCP 状态: 00H=CLOSED, 01H=LISTEN, 02H=SYN_SENT, 03H=SYN_RCVD, 04H=ESTABLISHED
|
||
* ⚠ 必须给 **2 字节**缓冲:只给 1 字节会栈越界 1 字节(2026-09-22 实测
|
||
* net_socket.c 两处调用曾如此,已修)。
|
||
*/
|
||
void ch395f_get_socket_status(uint8_t sock, uint8_t *status);
|
||
|
||
/*
|
||
* 函数声明区 - Socket 远端信息
|
||
*/
|
||
|
||
/*
|
||
* 函数功能:获取远端 IP 和端口
|
||
* 入口参数:sock - Socket 索引 uint8_t 0 - 7
|
||
* p_buf - 6 字节输出缓冲区(4字节IP + 2字节端口)
|
||
* 限定条件:TCP Server 模式下连接建立后调用
|
||
* 函数说明:IP 低字节在前,端口低字节在前
|
||
*/
|
||
void ch395f_get_remot_ipp(uint8_t sock, uint8_t *p_buf);
|
||
|
||
/*
|
||
* 函数声明区 - 功能参数设置
|
||
*/
|
||
|
||
/*
|
||
* 函数功能:设置 CH395 功能参数
|
||
* 入口参数:para - 4 字节功能参数 uint32_t
|
||
* bit0: 未使用,必须为 0
|
||
* bit1: TCP Server 多连接模式使能
|
||
* bit2: 低功耗模式
|
||
* bit3: Socket 关闭控制(0=芯片自动关闭,1=外部关闭)
|
||
* bit4: 禁用 SEND_OK 中断
|
||
* 限定条件:必须在 ch395f_init() 之前调用
|
||
*/
|
||
void ch395f_set_fun_para(uint32_t para);
|
||
|
||
/*
|
||
* 函数声明区 - TCP MSS 设置
|
||
*/
|
||
|
||
/*
|
||
* 函数功能:设置 TCP MSS
|
||
* 入口参数:mss - MSS 值 uint16_t 60~1460
|
||
* 限定条件:必须在 ch395f_init() 之前调用
|
||
*/
|
||
void ch395f_set_tcp_mss(uint16_t mss);
|
||
|
||
/*
|
||
* 函数声明区 - Socket 缓冲区设置
|
||
*/
|
||
|
||
/*
|
||
* 函数功能:设置 Socket 接收缓冲区
|
||
* 入口参数:sock - Socket 索引 uint8_t 0 - 7
|
||
* start_block - 起始块地址 uint8_t
|
||
* block_count - 块个数 uint8_t
|
||
* 限定条件:必须在 OPEN_SOCKET_SN 之前调用
|
||
*/
|
||
void ch395f_set_recv_buf(uint8_t sock, uint8_t start_block, uint8_t block_count);
|
||
|
||
/*
|
||
* 函数功能:设置 Socket 发送缓冲区
|
||
* 入口参数:sock - Socket 索引 uint8_t 0 - 7
|
||
* start_block - 起始块地址 uint8_t
|
||
* block_count - 块个数 uint8_t
|
||
* 限定条件:必须在 OPEN_SOCKET_SN 之前调用
|
||
*/
|
||
void ch395f_set_send_buf(uint8_t sock, uint8_t start_block, uint8_t block_count);
|
||
|
||
/*
|
||
* 函数功能:清空 Socket 接收缓冲区
|
||
* 入口参数:sock - Socket 索引 uint8_t 0 - 7
|
||
* 限定条件:Socket 已打开
|
||
*/
|
||
void ch395f_clear_recv_buf(uint8_t sock);
|
||
|
||
/*
|
||
* 函数功能:设置 TCP KeepAlive 空闲时间
|
||
* 入口参数:time - 空闲时间(毫秒,必须为 500 的倍数) uint32_t
|
||
* 限定条件:必须在 ch395f_init() 之前调用
|
||
*/
|
||
void ch395f_set_keepalive_idle(uint32_t time);
|
||
|
||
/*
|
||
* 函数功能:设置 TCP KeepAlive 探测间隔
|
||
* 入口参数:time - 间隔时间(毫秒,必须为 500 的倍数) uint32_t
|
||
* 限定条件:必须在 ch395f_init() 之前调用
|
||
*/
|
||
void ch395f_set_keepalive_intvl(uint32_t time);
|
||
|
||
/*
|
||
* 函数功能:设置 TCP KeepAlive 探测次数
|
||
* 入口参数:cnt - 探测次数 uint8_t
|
||
* 限定条件:必须在 ch395f_init() 之前调用
|
||
*/
|
||
void ch395f_set_keepalive_cnt(uint8_t cnt);
|
||
|
||
/*
|
||
* 函数功能:启用/禁用指定 Socket 的 KeepAlive
|
||
* 入口参数:sock - Socket 索引 uint8_t 0 - 7
|
||
* enable - 1 启用,0 禁用 uint8_t
|
||
* 限定条件:Socket 已打开
|
||
*/
|
||
void ch395f_set_keepalive_enable(uint8_t sock, uint8_t enable);
|
||
|
||
/*
|
||
* 函数声明区 - TCP 重传参数设置
|
||
*/
|
||
|
||
/*
|
||
* 函数功能:设置 TCP 重传次数
|
||
* 入口参数:cnt - 重传次数 uint8_t(§5.17:默认 12 次,最大 20,>20 按 20 处理;无 0=默认语义)
|
||
* 限定条件:必须在 ch395f_init() 之前调用
|
||
*/
|
||
void ch395f_set_retrans_count(uint8_t cnt);
|
||
|
||
/*
|
||
* 函数功能:设置 TCP 重传周期
|
||
* 入口参数:period - 重传周期(毫秒) uint16_t
|
||
* 限定条件:必须在 ch395f_init() 之前调用
|
||
*/
|
||
void ch395f_set_retrans_period(uint16_t period);
|
||
|
||
/*
|
||
* 函数声明区 - ARP / TTL / 不可达信息
|
||
*/
|
||
|
||
/*
|
||
* 函数功能:设置 ARP 重传参数
|
||
* 入口参数:period_100ms - ARP 重传周期(单位 100ms,0=默认值=10即1秒) uint8_t
|
||
* cnt - ARP 重传次数(0=默认值=3,255=无限重传) uint8_t
|
||
* 限定条件:应在 ch395f_init() 之后调用
|
||
*/
|
||
void ch395f_set_arp(uint8_t period_100ms, uint8_t cnt);
|
||
|
||
/*
|
||
* 函数功能:设置 Socket TTL
|
||
* 入口参数:sock - Socket 索引 uint8_t 0 - 7
|
||
* ttl - TTL 值 uint8_t 最大 128
|
||
* 限定条件:Socket 已打开,TCP Server 模式下不生效
|
||
*/
|
||
void ch395f_set_ttl(uint8_t sock, uint8_t ttl);
|
||
|
||
/*
|
||
* 函数功能:获取不可达信息(用于调试连接失败原因)
|
||
* 出口参数:p_buf - 8 字节输出缓冲区(类型+协议码+端口+IP)
|
||
* 限定条件:收到 GINT_STAT_UNREACH 中断后调用
|
||
*/
|
||
void ch395f_get_unreach_info(uint8_t *p_buf);
|
||
|
||
/*
|
||
* 函数声明区 - 自愈驱动原语(设计 docs/网络/网络自愈架构设计.md §4.4;
|
||
* 形态定案锚点 同文档 §5.2 E2/E3/E4)
|
||
* E2 实测:单次状态回读 18.1us;LISTEN 可见延迟 100% <=10ms。
|
||
*/
|
||
|
||
/* 类型化状态回读 + 每 Socket 缓存(F-DRV-1/3) */
|
||
#define CH395F_SOCK_STATE_NONE 0xFFU /* open=CLOSED 时 tcp_state 哨兵("无意义") */
|
||
|
||
typedef struct {
|
||
uint8_t open; /* byte0:CH395F_SOCKET_CLOSED / CH395F_SOCKET_OPEN */
|
||
uint8_t tcp_state; /* byte1:CH395F_TCP_*;open=CLOSED 时为 CH395F_SOCK_STATE_NONE */
|
||
} ch395f_sock_state_t;
|
||
|
||
/*
|
||
* 函数功能:主动回读本 Socket 状态并刷新驱动缓存(缓存刷新点之一,另一个
|
||
* 是 net_poll 每轮全量刷新)
|
||
* 入口参数:sn - Socket 索引 uint8_t 0 - 7
|
||
* 返回值:类型化状态;sn>7 返回 {CLOSED, 哨兵} 并计一次边界 fault uint8_t×2
|
||
* 限定条件:芯片已初始化;netTask 上下文(与其它 CH395F 事务串行)
|
||
*/
|
||
ch395f_sock_state_t ch395f_get_sock_state(uint8_t sn);
|
||
|
||
/*
|
||
* 函数功能:读驱动缓存(零 SPI 成本;数据新鲜度取决于刷新点,见上)
|
||
* 入口参数:sn - Socket 索引 uint8_t 0 - 7
|
||
* 返回值:最近一次刷新的状态;sn>7 返回 {CLOSED, 哨兵}
|
||
*/
|
||
ch395f_sock_state_t ch395f_sock_state_cached(uint8_t sn);
|
||
|
||
/*
|
||
* 函数功能:判"本 Socket 正在监听"(读缓存:open=OPEN 且 TCP=LISTEN)
|
||
* 入口参数:sn - Socket 索引 uint8_t 0 - 7
|
||
* 返回值:1=在听 0=不在 int
|
||
*/
|
||
int ch395f_sock_is_listening(uint8_t sn);
|
||
|
||
/*
|
||
* 函数功能:事件护栏——只读本 Socket SINT(0x30,读即清),永不触碰全局寄存器
|
||
* (F-NET-7 收窄:两级预清"先读全局再读本 socket"会清掉其它 Socket 的
|
||
* 事件位;全局寄存器唯一读者=net_poll 写成驱动侧契约)
|
||
* 入口参数:sn - Socket 索引 uint8_t 0 - 7
|
||
* 返回值:SINT 位图;sn>7 返回 0 uint8_t
|
||
*/
|
||
uint8_t ch395f_sock_events(uint8_t sn);
|
||
|
||
/* 复合复位模式(F-DRV-4;两模式都必须排 RX——E4 定案,差异只剩最短等待) */
|
||
typedef enum {
|
||
CH395F_RESET_GRACEFUL = 0, /* 最短等待 100ms(TRAP-NET-18 二阶段实测值) */
|
||
CH395F_RESET_QUARANTINE /* 最短等待 400ms */
|
||
} ch395f_reset_mode_t;
|
||
|
||
/*
|
||
* 函数功能:启动 Socket 复合复位(非阻塞状态机,每 net_poll 步进;内部序列
|
||
* E4 定案:读空 RX -> CLOSE -> 排空事件(quiescent) -> 轮询 byte0=00H)
|
||
* 入口参数:sn - Socket 索引 uint8_t 0 - 7
|
||
* mode - 复位模式 ch395f_reset_mode_t
|
||
* 返回值:0=已启动 -1=参数错或已在运行(调用方逻辑错误) int
|
||
* 限定条件:netTask 上下文;调用前本层已放弃该会话(复位会丢弃 RX 残渣)
|
||
*/
|
||
int ch395f_sock_reset_begin(uint8_t sn, ch395f_reset_mode_t mode);
|
||
|
||
/*
|
||
* 函数功能:复位状态机步进(在 net_poll 或测试循环里周期调用,禁忙等复制)
|
||
* 入口参数:sn - Socket 索引 uint8_t 0 - 7
|
||
* 返回值:0=完成(含未启动,幂等) 1=进行中 -1=失败(超时/参数,槽位已复位可重开) int
|
||
*/
|
||
int ch395f_sock_reset_poll(uint8_t sn);
|
||
|
||
/* 命令完成判据(F-DRV-8;E3 定案=状态回读,GET_CMD_STATUS 对这三条无判别力) */
|
||
typedef enum {
|
||
CH395F_DONE_OPEN = 0, /* open 完成 = byte0 变 05H */
|
||
CH395F_DONE_LISTEN, /* listen 完成 = byte0=05H 且 TCP=01H(E2:<=10ms 可见) */
|
||
CH395F_DONE_CLOSE /* close 完成 = byte0=00H */
|
||
} ch395f_done_what_t;
|
||
|
||
/*
|
||
* 函数功能:非阻塞命令完成查询(单次主动回读 18.1us,E2 背书;勿复制
|
||
* poll_cmd_status 式忙等——E3 实证其对 OPEN/LISTEN/CLOSE 恒白等且无判别力)
|
||
* 入口参数:sn - Socket 索引 uint8_t 0 - 7
|
||
* what - 完成判据 ch395f_done_what_t
|
||
* 返回值:1=已完成 0=未完成 -1=参数错 int
|
||
*/
|
||
int ch395f_cmd_done(uint8_t sn, ch395f_done_what_t what);
|
||
|
||
/* 链路态缓存(F-DRV-13;net_poll 读全局后喂 bit0~3) */
|
||
|
||
/*
|
||
* 函数功能:喂全局中断位(net_poll 读 GET_GLOB_INT_STATUS_ALL 后调用;
|
||
* bit2 PHY_CHANGE 置位时驱动重读 PHY 更新 link_up 缓存 + 变化计数)
|
||
* 入口参数:glob_bits - 全局中断状态低字节语义位图 uint16_t
|
||
*/
|
||
void ch395f_glob_event_feed(uint16_t glob_bits);
|
||
|
||
/*
|
||
* 函数功能:读链路态缓存(首次查询惰性读 PHY 建档)
|
||
* 返回值:1=link up 0=down uint8_t(判据 B9:PHY != DISCONN 即 up)
|
||
*/
|
||
uint8_t ch395f_link_up_cached(void);
|
||
|
||
/*
|
||
* 函数功能:读链路变化计数(net 层订阅用:计数变化 -> 日志/可选重配)
|
||
* 返回值:自建档以来的 PHY 连接状态翻转次数 uint16_t
|
||
*/
|
||
uint16_t ch395f_link_change_count(void);
|
||
|
||
#ifdef __cplusplus
|
||
}
|
||
#endif
|
||
|
||
#endif /* CH395F_H */
|