1253 lines
35 KiB
C
1253 lines
35 KiB
C
/*
|
|
* 模��称:CH395F SPI Ethernet Protocol Stack Driver
|
|
* 模å�—功能:CH395F 以太网å��è®®æ ˆèŠ¯ç‰‡ SPI 驱动实现,æ��供芯片检测ã€�åˆ�始化ï¿? * 网络å�‚æ•°é…�ç½®ã€�PHY 管ç�†ã€�DHCPã€�Socket 管ç�†å�Šæ•°æ�®æ”¶å�‘功ï¿? * 适用平å�°ï¼šSTM32F4 系列(SPI2 接å�£ï¿? * 作者:王建ï¿? * 创建日期ï¿?026-03-14
|
|
* 修改记录ï¿? * 2026-03-14 王建ï¿? 创建åˆ�始版本,按代ç �规范é‡�æž„
|
|
* 2026-07-18 王建ï¿? 改�?write_send_buf / read_recv_buf 使用 SPI2 DMA 批é‡�ä¼ è¾“
|
|
*/
|
|
|
|
/* 头文件包�区 - 先包�系统头文件,�包�本模�头文件 */
|
|
#include <string.h>
|
|
#include <stdio.h>
|
|
#include "ch395f.h"
|
|
#include "spi.h"
|
|
#include "usart.h"
|
|
|
|
/*
|
|
* 调试输出�置
|
|
*/
|
|
#define DBG_TAG "[CH395]"
|
|
#include "dbg_log.h"
|
|
|
|
/*
|
|
* �有�定义区
|
|
*/
|
|
#define CH395F_CHECK_EXIST_TEST_DATA 0x57U /* 芯片检测测试å—ï¿?*/
|
|
#define CH395F_RESET_DELAY_MS 20U /* å¤�ä½�å�Žç‰å¾…延时(msï¿?*/
|
|
#define CH395F_INIT_TIMEOUT_MS 500U /* �始化超时时间(ms�*/
|
|
#define CH395F_SPI_BEGIN_DELAY_MS 1U /* SPI 事务开始延时(ms�*/
|
|
#define CH395F_DMA_BUF_SIZE 1500U /* DMA 缓冲区最大å—节数 */
|
|
|
|
/*
|
|
* ç§�有å�˜é‡�ï¿?- DMA ä¼ è¾“ç›¸å…³
|
|
*/
|
|
static volatile uint8_t s_spi2_dma_done = 0U; /* DMA ä¼ è¾“å®Œæˆ�æ ‡å¿— */
|
|
|
|
__attribute__((aligned(4)))
|
|
static uint8_t s_spi2_dma_tx_buf[CH395F_DMA_BUF_SIZE]; /* DMA ��缓冲区 */
|
|
__attribute__((aligned(4)))
|
|
static uint8_t s_spi2_dma_rx_buf[CH395F_DMA_BUF_SIZE]; /* DMA 接收缓冲�*/
|
|
|
|
/*
|
|
* �有函数声明� */
|
|
static void ch395f_spi_begin(void);
|
|
static void ch395f_spi_end(void);
|
|
static void ch395f_spi_dma_transfer(uint16_t len);
|
|
|
|
/*
|
|
* �有函数实现� */
|
|
|
|
/*
|
|
* 函数功能:开ï¿?SPI 事务(CS 拉高 -> 拉低ï¿? * 函数说明:手册è¦�ï¿?SPI 模å¼�下å—èŠ‚é—´æ— éœ€é—´éš”ï¿? * CS 拉高å†�拉低满足最å°�片选间隔è¦�ï¿? */
|
|
static void ch395f_spi_begin(void) {
|
|
/* CS 先拉高,确�空闲状�?*/
|
|
HAL_GPIO_WritePin(CH395_SCS_GPIO_Port, CH395_SCS_Pin, GPIO_PIN_SET);
|
|
/* CS 拉低,å�¯åŠ¨äº‹åŠ¡ï¼ˆæ— éœ€é¢�外延时,SPI æ—¶åº�ï¿?SCK 频率决定ï¿?*/
|
|
HAL_GPIO_WritePin(CH395_SCS_GPIO_Port, CH395_SCS_Pin, GPIO_PIN_RESET);
|
|
}
|
|
|
|
/*
|
|
* 函数功能:结�SPI 事务(CS 拉高� */
|
|
static void ch395f_spi_end(void) {
|
|
/* CS 拉高,结�事�*/
|
|
HAL_GPIO_WritePin(CH395_SCS_GPIO_Port, CH395_SCS_Pin, GPIO_PIN_SET);
|
|
}
|
|
|
|
/*
|
|
* 函数功能:DMA å…¨å�Œå·¥ä¼ 输并ç‰å¾…完æˆ�
|
|
* å…¥å�£å�‚数:len - ä¼ è¾“å—节ï¿? uint16_t
|
|
* 函数说明:å�‘ï¿?s_spi2_dma_tx_buf,接收到 s_spi2_dma_rx_bufï¿? * 阻塞ç‰å¾… DMA 完æˆ�回调置ä½�æ ‡å¿—
|
|
*/
|
|
static void ch395f_spi_dma_transfer(uint16_t len) {
|
|
HAL_StatusTypeDef status;
|
|
uint32_t tickstart;
|
|
volatile uint32_t loop_cnt = 0U;
|
|
|
|
s_spi2_dma_done = 0U;
|
|
status = HAL_SPI_TransmitReceive_DMA(&hspi2, s_spi2_dma_tx_buf, s_spi2_dma_rx_buf, len);
|
|
if (status != HAL_OK) {
|
|
DBG_ERROR("HAL_SPI_TransmitReceive_DMA FAIL: %d, SPI_State=%d, SPI_Error=0x%lX, DMA_State=%d",
|
|
(int)status,
|
|
(int)hspi2.State,
|
|
hspi2.ErrorCode,
|
|
(int)hspi2.hdmarx->State);
|
|
return;
|
|
}
|
|
|
|
tickstart = HAL_GetTick();
|
|
while (s_spi2_dma_done == 0U) {
|
|
loop_cnt++;
|
|
if ((HAL_GetTick() - tickstart) > 1000U) {
|
|
DBG_ERROR("TIMEOUT after 1s, len=%d, loop=%lu, SPI_State=%d, SPI_Error=0x%lX",
|
|
(int)len, loop_cnt,
|
|
(int)hspi2.State,
|
|
hspi2.ErrorCode);
|
|
DBG_ERROR(" DMA_RX: State=%d, Dir=%lu, CNT=%lu",
|
|
(int)hspi2.hdmarx->State,
|
|
hspi2.hdmarx->Init.Direction,
|
|
__HAL_DMA_GET_COUNTER(hspi2.hdmarx));
|
|
DBG_ERROR(" DMA_TX: State=%d, Dir=%lu, CNT=%lu",
|
|
(int)hspi2.hdmatx->State,
|
|
hspi2.hdmatx->Init.Direction,
|
|
__HAL_DMA_GET_COUNTER(hspi2.hdmatx));
|
|
DBG_ERROR(" SPI2_CR1=0x%lX, CR2=0x%lX, SR=0x%lX",
|
|
SPI2->CR1, SPI2->CR2, SPI2->SR);
|
|
/* 强制å¤�ä½� SPI2 DMA 状æ€�,é�¿å…�æ»é”� */
|
|
HAL_SPI_Abort(&hspi2);
|
|
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);
|
|
}
|
|
}
|
|
|
|
/*
|
|
* 函数功能:SPI 收�完�回调
|
|
* 函数说明:由 HAL SPI 驱动ï¿?DMA TX+RX 完æˆ�å�Žè°ƒç”¨ï¼ˆHAL_SPI_TransmitReceive_DMA 触å�‘æ¤å›žè°ƒï¼‰
|
|
*/
|
|
void HAL_SPI_TxRxCpltCallback(SPI_HandleTypeDef *hspi) {
|
|
if (hspi->Instance == SPI2) {
|
|
s_spi2_dma_done = 1U;
|
|
}
|
|
}
|
|
|
|
/*
|
|
* 函数功能:SPI 错误回调
|
|
* 函数说明:由 HAL SPI 驱动ï¿?DMA ä¼ è¾“å‡ºé”™æ—¶è°ƒç”¨ï¼Œé‡Šæ”¾ç‰å¾…
|
|
*/
|
|
void HAL_SPI_ErrorCallback(SPI_HandleTypeDef *hspi) {
|
|
if (hspi->Instance == SPI2) {
|
|
s_spi2_dma_done = 1U;
|
|
}
|
|
}
|
|
|
|
/*
|
|
* 公共函数实现� */
|
|
|
|
/*
|
|
* 函数功能:å�‘ CH395 写入命令å—节
|
|
* 入��数:cmd - 命令� uint8_t 0x00 - 0xFF
|
|
* 返回值:命令ç �回显�? uint8_t
|
|
* �定�件:需�ch395f_spi_begin() �ch395f_spi_end() 之间调用
|
|
* 函数说明:SPI 模å¼�下命令与数æ�®ä¹‹é—´æ— 需间隔
|
|
*/
|
|
uint8_t ch395f_write_cmd(uint8_t cmd) {
|
|
uint8_t rx_data;
|
|
|
|
/* 通过 SPI ��命令并接收回显 */
|
|
HAL_SPI_TransmitReceive(&hspi2, &cmd, &rx_data, 1, HAL_MAX_DELAY);
|
|
return rx_data;
|
|
}
|
|
|
|
/*
|
|
* 函数功能:å�‘ CH395 写入数æ�®å—节
|
|
* å…¥å�£å�‚数:data - æ•°æ�®å—节 uint8_t 0x00 - 0xFF
|
|
* 返回值:数�回显� uint8_t
|
|
* �定�件:需�ch395f_spi_begin() �ch395f_spi_end() 之间调用
|
|
*/
|
|
uint8_t ch395f_write_data(uint8_t data) {
|
|
uint8_t rx_data;
|
|
|
|
/* 通过 SPI ��数�并接收回显 */
|
|
HAL_SPI_TransmitReceive(&hspi2, &data, &rx_data, 1, HAL_MAX_DELAY);
|
|
return rx_data;
|
|
}
|
|
|
|
/*
|
|
* 函数功能:从 CH395 读å�–æ•°æ�®å—节
|
|
* 返回值:接收到的数æ�®å—节 uint8_t
|
|
* �定�件:需�ch395f_spi_begin() �ch395f_spi_end() 之间调用
|
|
*/
|
|
uint8_t ch395f_read_data(void) {
|
|
uint8_t tx_dummy = 0xFFU;
|
|
uint8_t rx_data;
|
|
|
|
/* ��?0xFF 作为时钟�,读�芯片返回的数�*/
|
|
HAL_SPI_TransmitReceive(&hspi2, &tx_dummy, &rx_data, 1, HAL_MAX_DELAY);
|
|
return rx_data;
|
|
}
|
|
|
|
/*
|
|
* 函数功能:检ï¿?CH395 芯片是å�¦å˜åœ¨ä¸”通信æ£å¸¸
|
|
* 返回值:CH395F_STATUS_OK - 检测到芯片,CH395F_STATUS_NOT_DETECTED - 未检测到
|
|
* é™�定æ�¡ä»¶ï¼šSPI2 å·²æ£ç¡®åˆ�始化
|
|
* 函数说明:å�‘ï¿?CMD_CHECK_EXIST (0x06) å�Šæµ‹è¯•å—ï¿?0x57ï¿? * 芯片应返回按ä½�å�–å���?0xA8
|
|
*/
|
|
ch395f_status_t ch395f_check_exist(void) {
|
|
uint8_t test_data = CH395F_CHECK_EXIST_TEST_DATA;
|
|
uint8_t reply_data;
|
|
|
|
/* 开�SPI 事务 */
|
|
ch395f_spi_begin();
|
|
|
|
/* ��检测命�*/
|
|
ch395f_write_cmd(CH395F_CMD_CHECK_EXIST);
|
|
|
|
/* ��测试数�*/
|
|
ch395f_write_data(test_data);
|
|
|
|
/* 读�芯片回� */
|
|
reply_data = ch395f_read_data();
|
|
|
|
/* 结� SPI 事务 */
|
|
ch395f_spi_end();
|
|
|
|
/* 验�回�是�为测试数�的按��� */
|
|
if (reply_data == (uint8_t)(~test_data)) {
|
|
return CH395F_STATUS_OK;
|
|
}
|
|
|
|
return CH395F_STATUS_NOT_DETECTED;
|
|
}
|
|
|
|
/*
|
|
* 函数功能:读ï¿?CH395 芯片版本ï¿? * 返回值:版本å—节(bit5:0 为版本å�·ï¼‰uint8_t
|
|
* �定�件:芯片已通过 ch395f_check_exist() 检� */
|
|
uint8_t ch395f_get_version(void) {
|
|
uint8_t version;
|
|
|
|
/* 开�SPI 事务 */
|
|
ch395f_spi_begin();
|
|
|
|
/* ��版本读�命�*/
|
|
ch395f_write_cmd(CH395F_CMD_GET_IC_VER);
|
|
|
|
/* 读�版本�*/
|
|
version = ch395f_read_data();
|
|
|
|
/* 结� SPI 事务 */
|
|
ch395f_spi_end();
|
|
|
|
return version;
|
|
}
|
|
|
|
/*
|
|
* 函数功能:获�远�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) {
|
|
uint8_t i;
|
|
|
|
/* 检查输入�数�法�?*/
|
|
if (p_buf == NULL) {
|
|
return;
|
|
}
|
|
|
|
/* 开�SPI 事务 */
|
|
ch395f_spi_begin();
|
|
|
|
/* ��获�远�IP 和端�命�*/
|
|
ch395f_write_cmd(CH395F_CMD_GET_REMOT_IPP_SN);
|
|
|
|
/* ��?Socket 索引 */
|
|
ch395f_write_data(sock);
|
|
|
|
/* 读å�– 4 å—节 IP 地å�€ */
|
|
for (i = 0; i < 4; i++) {
|
|
p_buf[i] = ch395f_read_data();
|
|
}
|
|
|
|
/* 读å�– 2 å—节端å�£ï¿?*/
|
|
for (i = 4; i < 6; i++) {
|
|
p_buf[i] = ch395f_read_data();
|
|
}
|
|
|
|
/* 结� SPI 事务 */
|
|
ch395f_spi_end();
|
|
}
|
|
|
|
/*
|
|
* 函数功能:设�CH395 功能�数
|
|
* å…¥å�£å�‚数:para - 4 å—节功能å�‚æ•° uint32_t
|
|
* �定�件:必须在 ch395f_init() 之�调用
|
|
*/
|
|
void ch395f_set_fun_para(uint32_t para) {
|
|
/* 开�SPI 事务 */
|
|
ch395f_spi_begin();
|
|
|
|
/* ��设置功能�数命�*/
|
|
ch395f_write_cmd(CH395F_CMD_SET_FUN_PARA);
|
|
|
|
/* å�‘�?4 å—节å�‚数(低å—节在å‰�ï¿?*/
|
|
ch395f_write_data((uint8_t)(para));
|
|
ch395f_write_data((uint8_t)(para >> 8));
|
|
ch395f_write_data((uint8_t)(para >> 16));
|
|
ch395f_write_data((uint8_t)(para >> 24));
|
|
|
|
/* 结� SPI 事务 */
|
|
ch395f_spi_end();
|
|
}
|
|
|
|
/*
|
|
* 函数功能:设�TCP MSS
|
|
* 入��数:mss - MSS � uint16_t 60~1460
|
|
* �定�件:必须在 ch395f_init() 之�调用
|
|
*/
|
|
void ch395f_set_tcp_mss(uint16_t mss) {
|
|
/* 开�SPI 事务 */
|
|
ch395f_spi_begin();
|
|
|
|
/* ��设�TCP MSS 命令 */
|
|
ch395f_write_cmd(CH395F_CMD_SET_TCP_MSS);
|
|
|
|
/* å�‘�?2 å—节 MSS 值(低å—节在å‰�) */
|
|
ch395f_write_data(mss & 0xFFU);
|
|
ch395f_write_data((mss >> 8) & 0xFFU);
|
|
|
|
/* 结� SPI 事务 */
|
|
ch395f_spi_end();
|
|
}
|
|
|
|
/*
|
|
* 函数功能:设�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) {
|
|
/* 开�SPI 事务 */
|
|
ch395f_spi_begin();
|
|
|
|
/* ��设置接收缓冲区命令 */
|
|
ch395f_write_cmd(CH395F_CMD_SET_RECV_BUF);
|
|
|
|
/* ��?Socket 索引 */
|
|
ch395f_write_data(sock);
|
|
|
|
/* ��起始�地� */
|
|
ch395f_write_data(start_block);
|
|
|
|
/* ���个数 */
|
|
ch395f_write_data(block_count);
|
|
|
|
/* 结� SPI 事务 */
|
|
ch395f_spi_end();
|
|
}
|
|
|
|
/*
|
|
* 函数功能:设�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) {
|
|
/* 开�SPI 事务 */
|
|
ch395f_spi_begin();
|
|
|
|
/* ��设置��缓冲区命令 */
|
|
ch395f_write_cmd(CH395F_CMD_SET_SEND_BUF);
|
|
|
|
/* ��?Socket 索引 */
|
|
ch395f_write_data(sock);
|
|
|
|
/* ��起始�地� */
|
|
ch395f_write_data(start_block);
|
|
|
|
/* ���个数 */
|
|
ch395f_write_data(block_count);
|
|
|
|
/* 结� SPI 事务 */
|
|
ch395f_spi_end();
|
|
}
|
|
|
|
/*
|
|
* 函数功能:清�Socket 接收缓冲� * 入��数:sock - Socket 索引 uint8_t 0 - 7
|
|
* �定�件:Socket 已打开
|
|
*/
|
|
void ch395f_clear_recv_buf(uint8_t sock) {
|
|
/* 开�SPI 事务 */
|
|
ch395f_spi_begin();
|
|
|
|
/* ��清空接收缓冲区命令 */
|
|
ch395f_write_cmd(CH395F_CMD_CLEAR_RECV_BUF_SN);
|
|
|
|
/* ��?Socket 索引 */
|
|
ch395f_write_data(sock);
|
|
|
|
/* 结� SPI 事务 */
|
|
ch395f_spi_end();
|
|
}
|
|
|
|
/*
|
|
* 函数功能:设�TCP KeepAlive 空闲时间
|
|
* 入��数:time - 空闲时间(秒� uint32_t
|
|
* �定�件:必须在 ch395f_init() 之�调用
|
|
*/
|
|
void ch395f_set_keepalive_idle(uint32_t time) {
|
|
/* 开�SPI 事务 */
|
|
ch395f_spi_begin();
|
|
|
|
/* ��设�KeepAlive 空闲时间命令 */
|
|
ch395f_write_cmd(CH395F_CMD_SET_KEEPALIVE_IDLE);
|
|
|
|
/* å�‘�?4 å—节时间值(低å—节在å‰�) */
|
|
ch395f_write_data((uint8_t)(time));
|
|
ch395f_write_data((uint8_t)(time >> 8));
|
|
ch395f_write_data((uint8_t)(time >> 16));
|
|
ch395f_write_data((uint8_t)(time >> 24));
|
|
|
|
/* 结� SPI 事务 */
|
|
ch395f_spi_end();
|
|
}
|
|
|
|
/*
|
|
* 函数功能:设�TCP KeepAlive 探测间隔
|
|
* 入��数:time - 间隔时间(秒� uint32_t
|
|
* �定�件:必须在 ch395f_init() 之�调用
|
|
*/
|
|
void ch395f_set_keepalive_intvl(uint32_t time) {
|
|
/* 开�SPI 事务 */
|
|
ch395f_spi_begin();
|
|
|
|
/* ��设�KeepAlive 探测间隔命令 */
|
|
ch395f_write_cmd(CH395F_CMD_SET_KEEPALIVE_INTVL);
|
|
|
|
/* å�‘�?4 å—节时间值(低å—节在å‰�) */
|
|
ch395f_write_data((uint8_t)(time));
|
|
ch395f_write_data((uint8_t)(time >> 8));
|
|
ch395f_write_data((uint8_t)(time >> 16));
|
|
ch395f_write_data((uint8_t)(time >> 24));
|
|
|
|
/* 结� SPI 事务 */
|
|
ch395f_spi_end();
|
|
}
|
|
|
|
/*
|
|
* 函数功能:设�TCP KeepAlive 探测次数
|
|
* 入��数:cnt - 探测次数 uint8_t
|
|
* �定�件:必须在 ch395f_init() 之�调用
|
|
*/
|
|
void ch395f_set_keepalive_cnt(uint8_t cnt) {
|
|
/* 开�SPI 事务 */
|
|
ch395f_spi_begin();
|
|
|
|
/* ��设�KeepAlive 探测次数命令 */
|
|
ch395f_write_cmd(CH395F_CMD_SET_KEEPALIVE_CNT);
|
|
|
|
/* ��探测次�*/
|
|
ch395f_write_data(cnt);
|
|
|
|
/* 结� SPI 事务 */
|
|
ch395f_spi_end();
|
|
}
|
|
|
|
/*
|
|
* 函数功能:���用指定 Socket �KeepAlive
|
|
* 入��数:sock - Socket 索引 uint8_t 0 - 7
|
|
* enable - 1 �用� �用 uint8_t
|
|
* �定�件:Socket 已打开
|
|
*/
|
|
void ch395f_set_keepalive_enable(uint8_t sock, uint8_t enable) {
|
|
/* 开�SPI 事务 */
|
|
ch395f_spi_begin();
|
|
|
|
/* ��设�KeepAlive 使能命令 */
|
|
ch395f_write_cmd(CH395F_CMD_SET_KEEPALIVE_SN);
|
|
|
|
/* ��?Socket 索引 */
|
|
ch395f_write_data(sock);
|
|
|
|
/* å�‘é€�ä½¿èƒ½æ ‡ï¿?*/
|
|
ch395f_write_data(enable);
|
|
|
|
/* 结� SPI 事务 */
|
|
ch395f_spi_end();
|
|
}
|
|
|
|
/*
|
|
* 函数功能:设ï¿?TCP é‡�ä¼ æ¬¡æ•°
|
|
* å…¥å�£å�‚数:cnt - é‡�ä¼ æ¬¡æ•° uint8_tï¿?=使用默认ï¿?ï¿? * é™�定æ�¡ä»¶ï¼šå¿…须在 ch395f_init() 之å‰�调用
|
|
*/
|
|
void ch395f_set_retrans_count(uint8_t cnt) {
|
|
/* 开�SPI 事务 */
|
|
ch395f_spi_begin();
|
|
|
|
/* å�‘é€�设置é‡�ä¼ æ¬¡æ•°å‘½ï¿?*/
|
|
ch395f_write_cmd(CH395F_CMD_SET_RETRAN_COUNT);
|
|
|
|
/* å�‘é€�é‡�ä¼ æ¬¡ï¿?*/
|
|
ch395f_write_data(cnt);
|
|
|
|
/* 结� SPI 事务 */
|
|
ch395f_spi_end();
|
|
}
|
|
|
|
/*
|
|
* 函数功能:设ï¿?TCP é‡�ä¼ å‘¨æœŸ
|
|
* å…¥å�£å�‚数:period - é‡�ä¼ å‘¨æœŸï¼ˆæ¯«ç§’ï¼‰ uint16_t
|
|
* �定�件:必须在 ch395f_init() 之�调用
|
|
*/
|
|
void ch395f_set_retrans_period(uint16_t period) {
|
|
/* 开�SPI 事务 */
|
|
ch395f_spi_begin();
|
|
|
|
/* å�‘é€�设置é‡�ä¼ å‘¨æœŸå‘½ï¿?*/
|
|
ch395f_write_cmd(CH395F_CMD_SET_RETRAN_PERIOD);
|
|
|
|
/* å�‘�?2 å—节周期值(低å—节在å‰�) */
|
|
ch395f_write_data(period & 0xFFU);
|
|
ch395f_write_data((period >> 8) & 0xFFU);
|
|
|
|
/* 结� SPI 事务 */
|
|
ch395f_spi_end();
|
|
}
|
|
|
|
/*
|
|
* 函数功能:软件��CH395
|
|
* 返回值:CH395F_STATUS_OK
|
|
* é™�定æ�¡ä»¶ï¼šSPI2 å·²æ£ç¡®åˆ�始化
|
|
* 函数说明:��耗时�15ms(TE0),函数内部已包�延� */
|
|
ch395f_status_t ch395f_reset(void) {
|
|
/* 开�SPI 事务 */
|
|
ch395f_spi_begin();
|
|
|
|
/* ����命�*/
|
|
ch395f_write_cmd(CH395F_CMD_RESET_ALL);
|
|
|
|
/* 结� SPI 事务 */
|
|
ch395f_spi_end();
|
|
|
|
/* ç‰å¾…å¤�ä½�完æˆ�(TE0 = 15ms 典型值,ç‰å¾… 20msï¿?*/
|
|
HAL_Delay(CH395F_RESET_DELAY_MS);
|
|
|
|
return CH395F_STATUS_OK;
|
|
}
|
|
|
|
/*
|
|
* 函数功能:查询命令执行状ï¿? * 返回值:状æ€�å—节(CH395F_ERR_SUCCESS / CH395F_ERR_BUSY / ...)uint8_t
|
|
* �定�件:仅在长执行命令(如�始化)�调� */
|
|
uint8_t ch395f_get_cmd_status(void) {
|
|
uint8_t status;
|
|
|
|
/* 开�SPI 事务 */
|
|
ch395f_spi_begin();
|
|
|
|
/* ��状�查询命�*/
|
|
ch395f_write_cmd(CH395F_CMD_GET_CMD_STATUS);
|
|
|
|
/* 读å�–状æ€�å—ï¿?*/
|
|
status = ch395f_read_data();
|
|
|
|
/* 结� SPI 事务 */
|
|
ch395f_spi_end();
|
|
|
|
return status;
|
|
}
|
|
|
|
/*
|
|
* 函数功能:轮询ç‰å¾…命令执行完ï¿? * å…¥å�£å�‚数:timeout_ms - 超时时间(毫秒) uint32_t
|
|
* 返回值:命令执行状æ€�ç �(CH395F_ERR_SUCCESS ï¿?CH395F_CMD_RET_ABORTï¿? * é™�定æ�¡ä»¶ï¼šåœ¨å�‘é€�长执行命令å�Žè°ƒï¿? * 函数说明:æ¯� 20ms 查询一次,直到命令完æˆ�或超ï¿? */
|
|
uint8_t ch395f_poll_cmd_status(uint32_t timeout_ms) {
|
|
uint8_t status;
|
|
uint32_t retry_count = 0U;
|
|
uint32_t max_retries = (timeout_ms + 20U - 1U) / 20U;
|
|
|
|
while (1) {
|
|
HAL_Delay(20U);
|
|
status = ch395f_get_cmd_status();
|
|
|
|
if (status != CH395F_ERR_BUSY) {
|
|
return status;
|
|
}
|
|
|
|
if (++retry_count >= max_retries) {
|
|
return CH395F_ERR_BUSY; /* è¶…æ—¶ */
|
|
}
|
|
}
|
|
}
|
|
|
|
/*
|
|
* 函数功能:åˆ�始化 CH395(包ï¿?MACã€�PHYã€�TCP/IP å��è®®æ ˆï¼‰
|
|
* 返回值:CH395F_STATUS_OK - �功,CH395F_STATUS_TIMEOUT - 超时失败
|
|
* �定�件:芯片已通过 ch395f_reset() ��
|
|
* 函数说明:阻塞ç‰å¾…åˆ�始化完æˆ�或超时(芯片需è¦�约 200msï¼Œè¿™é‡Œç‰æœ€ï¿?4sï¿? */
|
|
ch395f_status_t ch395f_init(void) {
|
|
uint8_t status;
|
|
|
|
ch395f_spi_begin();
|
|
ch395f_write_cmd(CH395F_CMD_INIT_CH395);
|
|
ch395f_spi_end();
|
|
|
|
status = ch395f_poll_cmd_status(4000U);
|
|
|
|
if (status == CH395F_ERR_SUCCESS) {
|
|
return CH395F_STATUS_OK;
|
|
}
|
|
|
|
return (status == CH395F_ERR_BUSY) ? CH395F_STATUS_TIMEOUT : CH395F_STATUS_ERROR;
|
|
}
|
|
|
|
/*
|
|
* 函数功能:设ï¿?CH395 IP 地å�€ï¼ˆä½Žå—节在å‰�ï¿? * å…¥å�£å�‚数:p_ip - 4 å—节 IP 地å�€æŒ‡é’ˆ uint8_t*
|
|
* �定�件:指针�空,芯片已�始化
|
|
*/
|
|
void ch395f_set_ip_addr(uint8_t *p_ip) {
|
|
uint8_t i;
|
|
|
|
/* 检查输入�数�法�?*/
|
|
if (p_ip == NULL) {
|
|
return;
|
|
}
|
|
|
|
/* 开�SPI 事务 */
|
|
ch395f_spi_begin();
|
|
|
|
/* ��设�IP 命令 */
|
|
ch395f_write_cmd(CH395F_CMD_SET_IP_ADDR);
|
|
|
|
/* é€�å—节å�‘ï¿?IP 地å�€ */
|
|
for (i = 0; i < 4; i++) {
|
|
ch395f_write_data(p_ip[i]);
|
|
}
|
|
|
|
/* 结� SPI 事务 */
|
|
ch395f_spi_end();
|
|
}
|
|
|
|
/*
|
|
* 函数功能:设置网ï¿?IP 地å�€ï¼ˆä½Žå—节在å‰�ï¿? * å…¥å�£å�‚数:p_gwip - 4 å—节网关 IP 指针 uint8_t*
|
|
* �定�件:指针�空,芯片已�始化
|
|
*/
|
|
void ch395f_set_gwip_addr(uint8_t *p_gwip) {
|
|
uint8_t i;
|
|
|
|
/* 检查输入�数�法�?*/
|
|
if (p_gwip == NULL) {
|
|
return;
|
|
}
|
|
|
|
/* 开�SPI 事务 */
|
|
ch395f_spi_begin();
|
|
|
|
/* ��设置网关命�*/
|
|
ch395f_write_cmd(CH395F_CMD_SET_GWIP_ADDR);
|
|
|
|
/* é€�å—节å�‘é€�网ï¿?IP */
|
|
for (i = 0; i < 4; i++) {
|
|
ch395f_write_data(p_gwip[i]);
|
|
}
|
|
|
|
/* 结� SPI 事务 */
|
|
ch395f_spi_end();
|
|
}
|
|
|
|
/*
|
|
* 函数功能:设置å�网掩ç �(低å—节在å‰�)
|
|
* å…¥å�£å�‚数:p_mask - 4 å—节å�网掩ç �指针 uint8_t*
|
|
* �定�件:指针�空,芯片已�始化
|
|
*/
|
|
void ch395f_set_mask_addr(uint8_t *p_mask) {
|
|
uint8_t i;
|
|
|
|
/* 检查输入�数�法�?*/
|
|
if (p_mask == NULL) {
|
|
return;
|
|
}
|
|
|
|
/* 开�SPI 事务 */
|
|
ch395f_spi_begin();
|
|
|
|
/* å�‘é€�设置掩ç �命ï¿?*/
|
|
ch395f_write_cmd(CH395F_CMD_SET_MASK_ADDR);
|
|
|
|
/* é€�å—节å�‘é€�å�网掩ï¿?*/
|
|
for (i = 0; i < 4; i++) {
|
|
ch395f_write_data(p_mask[i]);
|
|
}
|
|
|
|
/* 结� SPI 事务 */
|
|
ch395f_spi_end();
|
|
}
|
|
|
|
/*
|
|
* 函数功能:设ï¿?MAC 地å�€ï¼ˆä½Žå—节在å‰�,å˜å‚¨äºŽ EEPROMï¿? * å…¥å�£å�‚数:p_mac - 6 å—节 MAC 地å�€æŒ‡é’ˆ uint8_t*
|
|
* �定�件:指针�空,芯片已�始化
|
|
* 函数说明:执行耗时�30us(TE5� */
|
|
void ch395f_set_mac_addr(uint8_t *p_mac) {
|
|
uint8_t i;
|
|
|
|
/* 检查输入�数�法�?*/
|
|
if (p_mac == NULL) {
|
|
return;
|
|
}
|
|
|
|
/* 开�SPI 事务 */
|
|
ch395f_spi_begin();
|
|
|
|
/* ��设�MAC 命令 */
|
|
ch395f_write_cmd(CH395F_CMD_SET_MAC_ADDR);
|
|
|
|
/* é€�å—节å�‘ï¿?MAC 地å�€ */
|
|
for (i = 0; i < 6; i++) {
|
|
ch395f_write_data(p_mac[i]);
|
|
}
|
|
|
|
/* 结� SPI 事务 */
|
|
ch395f_spi_end();
|
|
}
|
|
|
|
/*
|
|
* 函数功能:从 CH395 读� MAC 地�
|
|
* 出å�£å�‚数:p_mac - 6 å—节 MAC 地å�€ç¼“冲区指ï¿? uint8_t*
|
|
* �定�件:指针�� */
|
|
void ch395f_get_mac_addr(uint8_t *p_mac) {
|
|
uint8_t i;
|
|
|
|
/* 检查输入�数�法�?*/
|
|
if (p_mac == NULL) {
|
|
return;
|
|
}
|
|
|
|
/* 开�SPI 事务 */
|
|
ch395f_spi_begin();
|
|
|
|
/* ��读�MAC 命令 */
|
|
ch395f_write_cmd(CH395F_CMD_GET_MAC_ADDR);
|
|
|
|
/* é€�å—节读ï¿?MAC 地å�€ */
|
|
for (i = 0; i < 6; i++) {
|
|
p_mac[i] = ch395f_read_data();
|
|
}
|
|
|
|
/* 结� SPI 事务 */
|
|
ch395f_spi_end();
|
|
}
|
|
|
|
/*
|
|
* 函数功能:读ï¿?IP ä¿¡æ�¯ï¼ˆIP + 掩ç � + DNS,共 20 å—节ï¿? * 出å�£å�‚数:p_buf - 20 å—节缓冲区指ï¿? uint8_t*
|
|
* �定�件:指针�� */
|
|
void ch395f_get_ip_inf(uint8_t *p_buf) {
|
|
uint8_t i;
|
|
|
|
/* 检查输入�数�法�?*/
|
|
if (p_buf == NULL) {
|
|
return;
|
|
}
|
|
|
|
/* 开�SPI 事务 */
|
|
ch395f_spi_begin();
|
|
|
|
/* ��读�IP 信�命令 */
|
|
ch395f_write_cmd(CH395F_CMD_GET_IP_INF);
|
|
|
|
/* é€�å—节读ï¿?IP ä¿¡æ�¯ï¼ˆå…± 20 å—节ï¿?*/
|
|
for (i = 0; i < 20; i++) {
|
|
p_buf[i] = ch395f_read_data();
|
|
}
|
|
|
|
/* 结� SPI 事务 */
|
|
ch395f_spi_end();
|
|
}
|
|
|
|
/*
|
|
* 函数功能:获ï¿?PHY 连接状�? * 返回值:PHY 状æ€�ç �(CH395F_PHY_DISCONNã€�CH395F_PHY_10M_FULL ç‰ï¼‰uint8_t
|
|
* �定�件:芯片已�始� */
|
|
uint8_t ch395f_get_phy_status(void) {
|
|
uint8_t status;
|
|
|
|
/* 开�SPI 事务 */
|
|
ch395f_spi_begin();
|
|
|
|
/* ��读�PHY 状�命�*/
|
|
ch395f_write_cmd(CH395F_CMD_GET_PHY_STATUS);
|
|
|
|
/* 读� PHY 状�?*/
|
|
status = ch395f_read_data();
|
|
|
|
/* 结� SPI 事务 */
|
|
ch395f_spi_end();
|
|
|
|
return status;
|
|
}
|
|
|
|
/*
|
|
* 函数功能:设�PHY 连接模�
|
|
* 入��数:phystat - 连接模�� uint8_t 0x20 = 自动�商
|
|
* �定�件:芯片已�始� */
|
|
void ch395f_set_phy(uint8_t phystat) {
|
|
/* 开�SPI 事务 */
|
|
ch395f_spi_begin();
|
|
|
|
/* ��设�PHY 命令 */
|
|
ch395f_write_cmd(CH395F_CMD_SET_PHY);
|
|
|
|
/* ��连接模���*/
|
|
ch395f_write_data(phystat);
|
|
|
|
/* 结� SPI 事务 */
|
|
ch395f_spi_end();
|
|
}
|
|
|
|
/*
|
|
* 函数功能:使ï¿?å…³é— CH395 å“�应 PING
|
|
* å…¥å�£å�‚数:enable - 1 使能 PING å“�应ï¿? å…³é—
|
|
* �定�件:芯片已�始� * 函数说明:手�5.37 CMD_PING_ENABLE,默认关� */
|
|
void ch395f_ping_enable(uint8_t enable) {
|
|
/* 开�SPI 事务 */
|
|
ch395f_spi_begin();
|
|
|
|
/* ��?PING 使能命令 */
|
|
ch395f_write_cmd(CH395F_CMD_PING_ENABLE);
|
|
|
|
/* å�‘é€�ä½¿èƒ½æ ‡ï¿?*/
|
|
ch395f_write_data(enable);
|
|
|
|
/* 结� SPI 事务 */
|
|
ch395f_spi_end();
|
|
}
|
|
|
|
/*
|
|
* 函数功能:���用 DHCP
|
|
* 入��数:enable - 1 �用� �用 uint8_t
|
|
* �定�件:芯片已�始� */
|
|
void ch395f_set_dhcp(uint8_t enable) {
|
|
/* 开�SPI 事务 */
|
|
ch395f_spi_begin();
|
|
|
|
/* ��?DHCP 使能命令 */
|
|
ch395f_write_cmd(CH395F_CMD_DHCP_ENABLE);
|
|
|
|
/* �����用�数 */
|
|
ch395f_write_data(enable);
|
|
|
|
/* 结� SPI 事务 */
|
|
ch395f_spi_end();
|
|
}
|
|
|
|
/*
|
|
* 函数功能:获�DHCP 状�? * 返回值:0 = �功,��= 错误/超时 uint8_t
|
|
* �定�件:芯片已�始化且 DHCP 已�� */
|
|
uint8_t ch395f_get_dhcp_status(void) {
|
|
uint8_t status;
|
|
|
|
/* 开�SPI 事务 */
|
|
ch395f_spi_begin();
|
|
|
|
/* ��读�DHCP 状�命�*/
|
|
ch395f_write_cmd(CH395F_CMD_GET_DHCP_STATUS);
|
|
|
|
/* 读� DHCP 状�?*/
|
|
status = ch395f_read_data();
|
|
|
|
/* 结� SPI 事务 */
|
|
ch395f_spi_end();
|
|
|
|
return status;
|
|
}
|
|
|
|
/*
|
|
* 函数功能:设�Socket �议类型
|
|
* 入��数:sock - Socket 索引 uint8_t 0 - 3
|
|
* proto - �议类型 uint8_t CH395F_PROTO_TYPE_xxx
|
|
* �定�件:Socket 未打开
|
|
*/
|
|
void ch395f_set_proto_type(uint8_t sock, uint8_t proto) {
|
|
/* 开�SPI 事务 */
|
|
ch395f_spi_begin();
|
|
|
|
/* ��设置�议类型命�*/
|
|
ch395f_write_cmd(CH395F_CMD_SET_PROTO_TYPE_SN);
|
|
|
|
/* ��?Socket 索引 */
|
|
ch395f_write_data(sock);
|
|
|
|
/* ���议类�*/
|
|
ch395f_write_data(proto);
|
|
|
|
/* 结� SPI 事务 */
|
|
ch395f_spi_end();
|
|
}
|
|
|
|
/*
|
|
* 函数功能:设ï¿?Socket ç›®æ ‡ IP 地å�€
|
|
* 入��数:sock - Socket 索引 uint8_t 0 - 3
|
|
* p_ip - 4 å—èŠ‚ç›®æ ‡ IP 指针 uint8_t*
|
|
* �定�件:指针�� */
|
|
void ch395f_set_des_ip(uint8_t sock, uint8_t *p_ip) {
|
|
uint8_t i;
|
|
|
|
/* 检查输入�数�法�?*/
|
|
if (p_ip == NULL) {
|
|
return;
|
|
}
|
|
|
|
/* 开�SPI 事务 */
|
|
ch395f_spi_begin();
|
|
|
|
/* ��设置目�IP 命令 */
|
|
ch395f_write_cmd(CH395F_CMD_SET_IP_ADDR_SN);
|
|
|
|
/* ��?Socket 索引 */
|
|
ch395f_write_data(sock);
|
|
|
|
/* é€�å—节å�‘é€�ç›®ï¿?IP */
|
|
for (i = 0; i < 4; i++) {
|
|
ch395f_write_data(p_ip[i]);
|
|
}
|
|
|
|
/* 结� SPI 事务 */
|
|
ch395f_spi_end();
|
|
}
|
|
|
|
/*
|
|
* 函数功能:设ï¿?Socket ç›®æ ‡ç«¯å�£ï¼ˆå°�端åº�ï¿? * å…¥å�£å�‚数:sock - Socket 索引 uint8_t 0 - 3
|
|
* port - ç›®æ ‡ç«¯å�£ uint16_t
|
|
* é™�定æ�¡ä»¶ï¼šæ—
|
|
*/
|
|
void ch395f_set_des_port(uint8_t sock, uint16_t port) {
|
|
/* 开�SPI 事务 */
|
|
ch395f_spi_begin();
|
|
|
|
/* å�‘é€�è®¾ç½®ç›®æ ‡ç«¯å�£å‘½ï¿?*/
|
|
ch395f_write_cmd(CH395F_CMD_SET_DES_PORT_SN);
|
|
|
|
/* ��?Socket 索引 */
|
|
ch395f_write_data(sock);
|
|
|
|
/* å�‘é€�端å�£ä½Žå—节 */
|
|
ch395f_write_data(port & 0xFFU);
|
|
|
|
/* å�‘é€�端å�£é«˜å—节 */
|
|
ch395f_write_data((port >> 8) & 0xFFU);
|
|
|
|
/* 结� SPI 事务 */
|
|
ch395f_spi_end();
|
|
}
|
|
|
|
/*
|
|
* 函数功能:设�Socket �端�(�端�)
|
|
* 入��数:sock - Socket 索引 uint8_t 0 - 3
|
|
* port - �端� uint16_t
|
|
* é™�定æ�¡ä»¶ï¼šæ—
|
|
*/
|
|
void ch395f_set_sour_port(uint8_t sock, uint16_t port) {
|
|
/* 开�SPI 事务 */
|
|
ch395f_spi_begin();
|
|
|
|
/* ��设置�端�命令 */
|
|
ch395f_write_cmd(CH395F_CMD_SET_SOUR_PORT_SN);
|
|
|
|
/* ��?Socket 索引 */
|
|
ch395f_write_data(sock);
|
|
|
|
/* å�‘é€�端å�£ä½Žå—节 */
|
|
ch395f_write_data(port & 0xFFU);
|
|
|
|
/* å�‘é€�端å�£é«˜å—节 */
|
|
ch395f_write_data((port >> 8) & 0xFFU);
|
|
|
|
/* 结� SPI 事务 */
|
|
ch395f_spi_end();
|
|
}
|
|
|
|
/*
|
|
* 函数功能:打开 Socket
|
|
* 入��数:sock - Socket 索引 uint8_t 0 - 7
|
|
* 返回值:命令执行状æ€�ç �(CH395F_ERR_SUCCESS 表示æˆ�功ï¿? uint8_t
|
|
* �定�件:�议类型�目�IP�端�已设置
|
|
*/
|
|
uint8_t ch395f_open_socket(uint8_t sock) {
|
|
ch395f_spi_begin();
|
|
ch395f_write_cmd(CH395F_CMD_OPEN_SOCKET_SN);
|
|
ch395f_write_data(sock);
|
|
ch395f_spi_end();
|
|
|
|
return ch395f_poll_cmd_status(4000U);
|
|
}
|
|
|
|
/*
|
|
* 函数功能:关�Socket
|
|
* 入��数:sock - Socket 索引 uint8_t 0 - 7
|
|
* 返回值:命令执行状æ€�ç �(CH395F_ERR_SUCCESS 表示æˆ�功ï¿? uint8_t
|
|
* �定�件:Socket 已打开
|
|
*/
|
|
uint8_t ch395f_close_socket(uint8_t sock) {
|
|
ch395f_spi_begin();
|
|
ch395f_write_cmd(CH395F_CMD_CLOSE_SOCKET_SN);
|
|
ch395f_write_data(sock);
|
|
ch395f_spi_end();
|
|
|
|
return ch395f_poll_cmd_status(4000U);
|
|
}
|
|
|
|
/*
|
|
* 函数功能:��TCP 监�模�
|
|
* 入��数:sock - Socket 索引 uint8_t 0 - 7
|
|
* 返回值:命令执行状æ€�ç �(CH395F_ERR_SUCCESS 表示æˆ�功ï¿? uint8_t
|
|
* �定�件:Socket 已打开且�议类型为 TCP
|
|
*/
|
|
uint8_t ch395f_tcp_listen(uint8_t sock) {
|
|
ch395f_spi_begin();
|
|
ch395f_write_cmd(CH395F_CMD_TCP_LISTEN_SN);
|
|
ch395f_write_data(sock);
|
|
ch395f_spi_end();
|
|
|
|
return ch395f_poll_cmd_status(4000U);
|
|
}
|
|
|
|
/*
|
|
* 函数功能:��TCP 连接
|
|
* 入��数:sock - Socket 索引 uint8_t 0 - 7
|
|
* 返回值:命令执行状æ€�ç �(CH395F_ERR_SUCCESS 表示æˆ�功ï¿? uint8_t
|
|
* �定�件:Socket 已打开且�议类型为 TCP
|
|
*/
|
|
uint8_t ch395f_tcp_connect(uint8_t sock) {
|
|
ch395f_spi_begin();
|
|
ch395f_write_cmd(CH395F_CMD_TCP_CONNECT_SN);
|
|
ch395f_write_data(sock);
|
|
ch395f_spi_end();
|
|
|
|
return ch395f_poll_cmd_status(4000U);
|
|
}
|
|
|
|
/*
|
|
* 函数功能:æ–å¼€ TCP 连接
|
|
* 入��数:sock - Socket 索引 uint8_t 0 - 7
|
|
* 返回值:命令执行状æ€�ç �(CH395F_ERR_SUCCESS 表示æˆ�功ï¿? uint8_t
|
|
* �定�件:TCP 已建立连� */
|
|
uint8_t ch395f_tcp_disconnect(uint8_t sock) {
|
|
ch395f_spi_begin();
|
|
ch395f_write_cmd(CH395F_CMD_TCP_DISCONNECT_SN);
|
|
ch395f_write_data(sock);
|
|
ch395f_spi_end();
|
|
|
|
return ch395f_poll_cmd_status(4000U);
|
|
}
|
|
|
|
/*
|
|
* 函数功能:å�‘ Socket å�‘é€�缓冲区写入数æ�®ï¼ˆDMA 批é‡�ä¼ è¾“ï¿? * å…¥å�£å�‚数:sock - Socket 索引 uint8_t 0 - 3
|
|
* p_data - 数�指针 uint8_t*
|
|
* len - 数�长度 uint16_t
|
|
* �定�件:指针�空,长度大于 0,TCP 已连接或 UDP 已打开
|
|
* 函数说明:将命令头和数æ�®æ‰“包ï¿?DMA 缓冲区,一ï¿?SPI DMA ä¼ è¾“å®Œæˆ�
|
|
*/
|
|
void ch395f_write_send_buf(uint8_t sock, uint8_t *p_data, uint16_t len) {
|
|
uint16_t total;
|
|
|
|
/* 检查输入�数�法�?*/
|
|
if (p_data == NULL) {
|
|
return;
|
|
}
|
|
|
|
/* 计算总长度:1(cmd) + 1(sock) + 2(len) + data */
|
|
total = 4U + len;
|
|
if (total > CH395F_DMA_BUF_SIZE) {
|
|
return;
|
|
}
|
|
|
|
/* 打包命令头到 DMA ��缓冲区 */
|
|
s_spi2_dma_tx_buf[0] = CH395F_CMD_WRITE_SEND_BUF_SN;
|
|
s_spi2_dma_tx_buf[1] = sock;
|
|
s_spi2_dma_tx_buf[2] = len & 0xFFU;
|
|
s_spi2_dma_tx_buf[3] = (len >> 8) & 0xFFU;
|
|
|
|
/* 拷�用户数��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);
|
|
ch395f_spi_end();
|
|
}
|
|
|
|
/*
|
|
* 函数功能:从 Socket 接收缓冲区读å�–æ•°æ�®ï¼ˆDMA 批é‡�ä¼ è¾“ï¿? * å…¥å�£å�‚数:sock - Socket 索引 uint8_t 0 - 3
|
|
* p_data - 输出缓冲区指� uint8_t*
|
|
* len - 待读�数�长� uint16_t
|
|
* é™�定æ�¡ä»¶ï¼šæŒ‡é’ˆé�žç©ºï¼Œé•¿åº¦å¤§äºŽ 0,接收缓冲区有数ï¿? * 函数说明:命令头打包到å�‘é€�缓冲区(数æ�®éƒ¨åˆ†å¡« 0xFF 作时钟)ï¿? * 一ï¿?SPI DMA å…¨å�Œå·¥ä¼ 输,有效数æ�®ä»ŽæŽ¥æ”¶ç¼“冲区å��ç§» 4 å—节处拷ï¿? */
|
|
void ch395f_read_recv_buf(uint8_t sock, uint8_t *p_data, uint16_t len) {
|
|
uint16_t total;
|
|
|
|
/* 检查输入�数�法�?*/
|
|
if (p_data == NULL) {
|
|
return;
|
|
}
|
|
|
|
/* 计算总长度:1(cmd) + 1(sock) + 2(len) + data */
|
|
total = 4U + len;
|
|
if (total > CH395F_DMA_BUF_SIZE) {
|
|
return;
|
|
}
|
|
|
|
/* 命令头打包到 DMA ��缓冲区 */
|
|
s_spi2_dma_tx_buf[0] = CH395F_CMD_READ_RECV_BUF_SN;
|
|
s_spi2_dma_tx_buf[1] = sock;
|
|
s_spi2_dma_tx_buf[2] = len & 0xFFU;
|
|
s_spi2_dma_tx_buf[3] = (len >> 8) & 0xFFU;
|
|
|
|
/* 数�部分填充 0xFF(SPI 时钟驱动用) */
|
|
memset(&s_spi2_dma_tx_buf[4], 0xFFU, len);
|
|
|
|
/* CS 拉低 -> DMA å…¨å�Œå·¥ä¼ 输(å�‘命令头 + æ”¶æ•°æ�®ï¼‰ -> CS 拉高 */
|
|
ch395f_spi_begin();
|
|
ch395f_spi_dma_transfer(total);
|
|
ch395f_spi_end();
|
|
|
|
/* ï¿?DMA 接收缓冲区å��ï¿?4 å—节处拷è´�有效数æ�®åˆ°ç”¨æˆ·ç¼“冲ï¿?*/
|
|
memcpy(p_data, &s_spi2_dma_rx_buf[4], len);
|
|
}
|
|
|
|
/*
|
|
* 函数功能:获�Socket 接收缓冲区数�长� * 入��数:sock - Socket 索引 uint8_t 0 - 3
|
|
* 返回值:接收数�长度 uint16_t
|
|
* �定�件:Socket 已打开
|
|
*/
|
|
uint16_t ch395f_get_recv_len(uint8_t sock) {
|
|
uint16_t recv_len;
|
|
|
|
/* 开�SPI 事务 */
|
|
ch395f_spi_begin();
|
|
|
|
/* ��获�接收长度命�*/
|
|
ch395f_write_cmd(CH395F_CMD_GET_RECV_LEN_SN);
|
|
|
|
/* ��?Socket 索引 */
|
|
ch395f_write_data(sock);
|
|
|
|
/* 读å�–长度低å—ï¿?*/
|
|
recv_len = ch395f_read_data();
|
|
|
|
/* 读å�–长度高å—节并组å�ˆ */
|
|
recv_len |= (uint16_t)ch395f_read_data() << 8;
|
|
|
|
/* 结� SPI 事务 */
|
|
ch395f_spi_end();
|
|
|
|
return recv_len;
|
|
}
|
|
|
|
/*
|
|
* 函数功能:获å�–免局䏿–状�? * è¿”å›žå€¼ï¼šä¸æ–状æ€�å—ï¿? uint8_t
|
|
* �定�件:芯片已�始� */
|
|
uint8_t ch395f_get_glob_int_status(void) {
|
|
uint8_t status;
|
|
|
|
/* 开�SPI 事务 */
|
|
ch395f_spi_begin();
|
|
|
|
/* å�‘é€�读å�–免局䏿–状æ€�命ï¿?*/
|
|
ch395f_write_cmd(CH395F_CMD_GET_GLOB_INT_STATUS);
|
|
|
|
/* 读å�–䏿–状�?*/
|
|
status = ch395f_read_data();
|
|
|
|
/* 结� SPI 事务 */
|
|
ch395f_spi_end();
|
|
|
|
return status;
|
|
}
|
|
|
|
/*
|
|
* 函数功能:获å�–免局䏿–状æ€�(2 å—节版,支æŒ� Socket 0~7ï¿? * è¿”å›žå€¼ï¼šä¸æ–状�?uint16_t(低å—节=Socket 0~3 + PHY/DHCP,高å—节=Socket 4~7 + DHCPv6ï¿? * é™�定æ�¡ä»¶ï¼šèŠ¯ç‰‡å·²åˆ�å§‹ï¿? */
|
|
uint16_t ch395f_get_glob_int_status_all(void) {
|
|
uint16_t status;
|
|
|
|
ch395f_spi_begin();
|
|
ch395f_write_cmd(CH395F_CMD_GET_GLOB_INT_STATUS_ALL);
|
|
status = (uint16_t)ch395f_read_data();
|
|
status |= ((uint16_t)ch395f_read_data() << 8U);
|
|
ch395f_spi_end();
|
|
|
|
return status;
|
|
}
|
|
|
|
/*
|
|
* 函数功能:获ï¿?Socket 䏿–状�? * å…¥å�£å�‚数:sock - Socket 索引 uint8_t 0 - 7
|
|
* 返回值:Socket 䏿–状æ€�å—ï¿? uint8_t
|
|
* �定�件:芯片已�始� */
|
|
uint8_t ch395f_get_sock_int_status(uint8_t sock) {
|
|
uint8_t status;
|
|
|
|
/* 开�SPI 事务 */
|
|
ch395f_spi_begin();
|
|
|
|
/* å�‘é€�读ï¿?Socket 䏿–状æ€�命ï¿?*/
|
|
ch395f_write_cmd(CH395F_CMD_GET_INT_STATUS_SN);
|
|
|
|
/* ��?Socket 索引 */
|
|
ch395f_write_data(sock);
|
|
|
|
/* 读å�–䏿–状�?*/
|
|
status = ch395f_read_data();
|
|
|
|
/* 结� SPI 事务 */
|
|
ch395f_spi_end();
|
|
|
|
return status;
|
|
}
|
|
|
|
/*
|
|
* 函数功能:获ï¿?Socket 状æ€�(2 å—节输出ï¿? * å…¥å�£å�‚数:sock - Socket 索引 uint8_t 0 - 7
|
|
* status - 2 å—节输出缓冲ï¿?[0]=Socket状�? [1]=TCP状�? * é™�定æ�¡ä»¶ï¼šèŠ¯ç‰‡å·²åˆ�å§‹ï¿? */
|
|
void ch395f_get_socket_status(uint8_t sock, uint8_t *p_status) {
|
|
ch395f_spi_begin();
|
|
ch395f_write_cmd(CH395F_CMD_GET_SOCKET_STATUS_SN);
|
|
ch395f_write_data(sock);
|
|
p_status[0] = ch395f_read_data();
|
|
p_status[1] = ch395f_read_data();
|
|
ch395f_spi_end();
|
|
}
|
|
|
|
/*
|
|
* 函数功能:设ï¿?ARP é‡�ä¼ å�‚æ•°
|
|
* å…¥å�£å�‚数:period_100ms - ARP é‡�ä¼ å‘¨æœŸï¼ˆå�•ï¿?100msï¿?=默认ï¿?10ï¿?秒) uint8_t
|
|
* cnt - ARP é‡�ä¼ æ¬¡æ•°ï¿?=默认ï¿?3ï¿? uint8_t
|
|
* �定�件:应�ch395f_init() 之�调用
|
|
* 函数说明:周期最大值约 25.5 秒,255 è¡¨ç¤ºæ— é™�é‡�ä¼
|
|
*/
|
|
void ch395f_set_arp(uint8_t period_100ms, uint8_t cnt) {
|
|
ch395f_spi_begin();
|
|
ch395f_write_cmd(CH395F_CMD_SET_ARP);
|
|
ch395f_write_data(period_100ms);
|
|
ch395f_write_data(cnt);
|
|
ch395f_spi_end();
|
|
}
|
|
|
|
/*
|
|
* 函数功能:设�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) {
|
|
ch395f_spi_begin();
|
|
ch395f_write_cmd(CH395F_CMD_SET_TTL);
|
|
ch395f_write_data(sock);
|
|
ch395f_write_data(ttl);
|
|
ch395f_spi_end();
|
|
}
|
|
|
|
/*
|
|
* 函数功能:获å�–ä¸�å�¯è¾¾ä¿¡æ�¯ï¼ˆç”¨äºŽè°ƒè¯•è¿žæŽ¥å¤±è´¥åŽŸå› ï¼‰
|
|
* 出å�£å�‚数:p_buf - 8 å—节输出缓冲区(类型+å��è®®ï¿?端å�£+IPï¿? * é™�定æ�¡ä»¶ï¼šæ”¶ï¿?GINT_STAT_UNREACH 䏿–å�Žè°ƒï¿? */
|
|
void ch395f_get_unreach_info(uint8_t *p_buf) {
|
|
uint8_t i = 0;
|
|
|
|
ch395f_spi_begin();
|
|
ch395f_write_cmd(CH395F_CMD_GET_UNREACH_IPPT);
|
|
for (i = 0; i < 8; i++) {
|
|
p_buf[i] = ch395f_read_data();
|
|
}
|
|
ch395f_spi_end();
|
|
}
|
|
|
|
|