Files
STM32F4-Base/Drivers/BSP/CH395F/ch395f.h
T
wandering1 4c0a0af9f8 fix(net): N34 阶段0 零风险清理 9 条(注释债/死码/三处小逻辑门)
纯注释/死码(零行为变更):
- 0-1 pump 注释 50ms→100ms(宏真值源 100U,net_socket.c)
- 0-2 D10 give-up 文案改"retry budget exhausted, pump takes over"
  (旧文案夸大永久失效语义,pump 100ms 仍周期认领重建)
- 0-7 IP 字节序注释更正:set_ip/gw/mask 实为点分十进制序(调用方
  parse_ip_string 数组直传、芯片按首段接受、台架多年实证);
  set_des_ip 补"与 get_remot_ipp 输出同序"往返注(ch395f.h/.c)
- 0-8 Trap 13 注释降级为"未证实历史观察"(对齐 2026-10-11 Trap 13
  复核注,与手册 §5.34 相左):DMA 定容理由改"接收缓冲 2KB 整缓冲
  单读=Trap 25 排空契约形态";net_socket.c 四处引用改写
- 0-9 删死声明:GET_GLOB_INT_STATUS(0x29)/ENTER_SLEEP/EEPROM×3/
  GPIO×2/SPI_BEGIN_DELAY_MS/GINT_STAT_SOCK0..3(全仓零引用核实)

小逻辑(台架冒烟实证):
- 0-3 U12 对称:TCP_LISTEN 失败补 close 两处(net_relisten_locked /
  net_listen_locked)——防芯片 Socket 卡"OPEN 无监听"、下轮 open
  恒返 USE(U12 同源事故形态)
- 0-4 retry_tick 状态门:仅 LISTENING/CLOSED 才重试;已转 ESTABLISHED
  (新会话抢先)清陈旧登记,防 open→close 摧毁活连接(认领口径同 pump)
- 0-5 FUN_PARA 裸 0x08 → CH395F_FUN_PARA_SOCKET_CLOSE(复用既有宏
  (1UL<<3),注释补 §5.52/版本/红线口径;曾重复定义触发 9 警告,
  已并入原宏块)
- 0-6 版本门控:ver<0x46 拒置 bit3 并 [ERR] 留痕(防芯片批次漂移;
  本台架 ≥0x46 行为不变,fun_para 日志改打实际值)

验证:@build 全量重编 0 错 0 警(Code=209580,RW/ZI 不变);@test
PASS(回读无差异);冒烟 n30 0/20、:21 @0ms 20/20、:7003 20/20、
ftp_regression 11/11。

门禁说明:doc-links 工作树 junction 伪影按既定口径 SKIP;mem-budget
分支 .map 漂移同前;cppcheck/coding-standard 手跑 Passed。
2026-10-13 05:54:42 +08:00

755 lines
27 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 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,见 Trap 21)——维持 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 20)。 */
#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 25,
* bit3=1 残数据由 MCU 读出)的形态本身就是整缓冲单读。
* (历史注记:旧注释把定容理由归给"Trap 13 部分读致剩余数据不可见",该机理
* 2026-10-11 复核**未证实**且与手册 §5.34 相左,已降级为未证实历史观察,
* 见 Trap 记录 Trap 13 复核注;定容不依赖该观察。)
* 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
/* N34 阶段0-9:EEPROM(0xE9..0xEB)/GPIO(0xEC/0xED)/SLEEP(0x03) 命令宏与
* GET_GLOB_INT_STATUS(0x29,只有 2 字节版 0x19 有实现) 死声明已删除——
* 全仓零引用核实于 2026-10-13;需要时按手册 §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,N34 阶段0-6);
* bit1 TCP_SERVER 多连接模式——本项目单连接模型不用(红线,勿置 1);
* bit0 保留必须为 0(Trap 18 定案更正:0x09→0x08)
*/
#define CH395F_FUN_PARA_TCP_SERVER (1UL << 1) /* TCP Server 多连接模式 */
#define CH395F_FUN_PARA_SOCKET_CLOSE (1UL << 3) /* Socket 关闭控制(0=芯片自动,1=外部控制;Trap 25 排空契约) */
#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 单列宏已删(N34 阶段0-5,
* 全仓零引用;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;
* N34 阶段0-7 更正旧注"低字节在前"——调用方 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 直传其输出,
* 台架出站连接往返实证;N34 阶段0-7 补注)
*/
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)
* 限定条件:芯片已初始化
*/
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);
#ifdef __cplusplus
}
#endif
#endif /* CH395F_H */