optical/NxFuncs/network/ethernet.c
2025-09-04 09:45:08 +08:00

687 lines
14 KiB
C
Raw Permalink 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.

#define _IN_ETHERNET_C
#include "ethernet.h"
#include "inout.h"
#include "delay.h"
#include "tcpserver.h"
#include "tcpclient.h"
#include "udptrans.h"
#include "trigger.h"
#include "cpuid.h"
#include "crc16.h"
//--------------------------------------------------------------------------
//--------------------------------------------------------------------------
//--------------------------------------------------------------------------
void W5500IntConfig(void);
void RegNetCallBack(void);
void LoadDefNetParas(void);
int ChipParaConfig(void);
void NetworkParaConfig(void);
//--------------------------------------------------------------------------
void InitEthernet(void)
{
W5500IntConfig(); // 中断配置
InitWNetSpi(); // 初始化Spi通讯
RegNetCallBack(); // 设置回调函数
LoadDefNetParas(); // 默认参数
InitNetConfig(); // 重启芯片并重新配置
}
void InitNetConfig(void)
{
ChipParaConfig(); // 芯片配置
#if (SERVER_NUM > 0)
InitTcpServer();
SetTcpKeepAlive();
#endif
#if (CLIENT_NUM > 0)
InitTcpClient();
#endif
NetworkParaConfig(); // 网络参数配置
}
//--------------------------------------------------------------------------
// W5500 中断配置
void W5500IntConfig(void)
{
}
//---------------------------------------------------------------------------
// 进入临界区
#define SPI_CrisEnter EnterCritical
// 退出临界区
#define SPI_CrisExit ExitCritical
// 片选信号输出低电平
#define SPI_CS_Select WNetNceOn
// 片选信号输出高电平
#define SPI_CS_Deselect WNetNceOff
#define SPI_ReadByte WNetSpiReadByte
#define SPI_WriteByte WNetSpiWriteByte
void RegNetCallBack(void)
{
// 注册临界区函数
// reg_wizchip_cris_cbfunc(SPI_CrisEnter, SPI_CrisExit);
// 注册SPI片选信号函数
reg_wizchip_cs_cbfunc(SPI_CS_Select, SPI_CS_Deselect);
// 注册读写函数
reg_wizchip_spi_cbfunc(SPI_ReadByte, SPI_WriteByte);
// 注册块读写函数
// reg_wizchip_spiburst_cbfunc(,);
}
//---------------------------------------------------------------------------
void SetNetAddr(u32 ip, u32 mask, u32 gateway, u32 dns)
{
// 源IP地址本地IP
g_netInfo.ip[0] = GETIP1(ip);
g_netInfo.ip[1] = GETIP2(ip);
g_netInfo.ip[2] = GETIP3(ip);
g_netInfo.ip[3] = GETIP4(ip);
// 子网掩码
g_netInfo.sn[0] = GETIP1(mask);
g_netInfo.sn[1] = GETIP2(mask);
g_netInfo.sn[2] = GETIP3(mask);
g_netInfo.sn[3] = GETIP4(mask);
// 网关IP
g_netInfo.gw[0] = GETIP1(gateway);
g_netInfo.gw[1] = GETIP2(gateway);
g_netInfo.gw[2] = GETIP3(gateway);
g_netInfo.gw[3] = GETIP4(gateway);
// DNS服务器IP
g_netInfo.dns[0] = GETIP1(dns);
g_netInfo.dns[1] = GETIP2(dns);
g_netInfo.dns[2] = GETIP3(dns);
g_netInfo.dns[3] = GETIP4(dns);
}
//---------------------------------------------------------------------------
// 通过CPUID生成网卡物理地址
void MakeMacAddr(u8 * mac)
{
CpuId cpuid;
u16 crc;
u8 chrcksum;
GetCpuID(&cpuid);
crc = CalcCrc16(cpuid.buff, CPUID_LEN);
chrcksum = CalcCheckSum(cpuid.buff, CPUID_LEN);
if (mac != NULL)
{
mac[0] = 0x52;
mac[1] = 0x50; // 自定义厂商名 "RP"
mac[2] = 0x4E; // 产品标识N
mac[3] = HIBYTE(crc);
mac[4] = LOBYTE(crc);
mac[5] = chrcksum;
}
}
// 设置默认网络参数
void LoadDefNetParas(void)
{
// 物理层参数
g_phyConfig.by = PHY_CONFBY_SW; // 通过软件配置
g_phyConfig.mode = PHY_MODE_MANUAL; // 手动配置
g_phyConfig.speed = PHY_SPEED_100; // 100
g_phyConfig.duplex = PHY_DUPLEX_FULL; // 全双工
// 网络参数
// 源物理地址
MakeMacAddr(g_netInfo.mac);
g_localIP = LOCAL_IP;
g_netMask = NET_MASK;
g_gateWay = GATE_WAY;
g_dnsIP = DNS_IP;
SetNetAddr(g_localIP, g_netMask, g_gateWay, g_dnsIP);
// DHCP模式
g_netInfo.dhcp = NETINFO_STATIC;
// 时间参数
// ARPTO = time_100us x 0.1ms x (retry_cnt+1)
g_netTimeout.retry_cnt = 3;
g_netTimeout.time_100us = 2000;
// TCPTO = (2000) x 0.1ms // retry_cnt == 0
// (2000 + 4000) x 0.1ms // retry_cnt == 1
// (2000 + 4000 + 8000) x 0.1ms // retry_cnt == 2
// (2000 + 4000 + 8000 + 16000) x 0.1ms // retry_cnt == 3
// (2000 + 4000 + 8000 + 16000 + 32000 + ((retry_cnt - 4) x 64000)) x 0.1ms // retry_cnt >= 4
}
void GetChipConfig(void)
{
ctlwizchip(CW_GET_PHYCONF, (void*)(&g_phyConfig));
printf("after set config, phy config is:\r\n");
if (g_phyConfig.by == PHY_CONFBY_SW)
{
printf("config by software:\r\n");
}
else if(g_phyConfig.by == PHY_CONFBY_HW)
{
printf("config by hardware:\r\n");
}
else
{
printf("config by %d:\r\n", g_phyConfig.by);
}
if (g_phyConfig.mode == PHY_MODE_AUTONEGO)
{
printf("mode is PHY_MODE_AUTONEGO:\r\n");
}
else if (g_phyConfig.mode == PHY_MODE_MANUAL)
{
printf("mode is PHY_MODE_MANUAL:\r\n");
}
else
{
printf("mode is %d:\r\n", g_phyConfig.mode);
}
if (g_phyConfig.speed == PHY_SPEED_100)
{
printf("speed is PHY_SPEED_100:\r\n");
}
else if (g_phyConfig.speed == PHY_SPEED_10)
{
printf("speed is PHY_SPEED_10:\r\n");
}
else
{
printf("speed is %d:\r\n", g_phyConfig.speed);
}
if (g_phyConfig.duplex == PHY_DUPLEX_FULL)
{
printf("duplex is PHY_DUPLEX_FULL:\r\n");
}
else if (g_phyConfig.duplex == PHY_DUPLEX_HALF)
{
printf("duplex is PHY_DUPLEX_HALF:\r\n");
}
else
{
printf("duplex is %d:\r\n", g_phyConfig.duplex);
}
}
// 初始化芯片参数
int ChipParaConfig(void)
{
int rslt;
u8 tmp8;
u16 tmp16;
u8 chipId[6];
u8 memsize[2][8] = {
{2,2,2,2,2,2,2,2},
{2,2,2,2,2,2,2,2},
};
// 复位芯片
ctlwizchip(CW_RESET_WIZCHIP, 0);
DelayMs(10);
// 复位物理层
ctlwizchip(CW_RESET_PHY, 0);
DelayMs(10);
// 配置物理层
ctlwizchip(CW_SET_PHYCONF, (void*)(&g_phyConfig));
DelayMs(10);
// 复位物理层
ctlwizchip(CW_RESET_PHY, 0);
DelayMs(10);
#if (1)
// 读取配置
GetChipConfig();
#endif
// WIZCHIP SOCKET 缓存区初始化
rslt = ctlwizchip(CW_INIT_WIZCHIP, (void*)(memsize));
if(rslt == -1)
{
printf("WIZCHIP Initialized fail.\r\n");
return -1;
}
// 读取电源模式
ctlwizchip(CW_GET_PHYPOWMODE, (void*)(&tmp8));
printf("powermode is %d:\r\n", tmp8);
// 中断屏蔽位配置
tmp16 = 0
| IK_IP_CONFLICT // IP冲突
| IK_DEST_UNREACH // 目标不可达
| IK_PPPOE_TERMINATED // PPPOE连接关闭
| IK_WOL // 网络唤醒
// | IK_SOCK_ALL // 所有的SOCKET中断
| 0;
ctlwizchip(CW_SET_INTRMASK, (void*)(&tmp16));
ctlwizchip(CW_GET_INTRMASK, (void*)(&tmp16));
// 清除中断标志
ctlwizchip(CW_GET_INTERRUPT, (void*)(&tmp16));
tmp16 = 0
| IK_IP_CONFLICT // IP冲突
| IK_DEST_UNREACH // 目标不可达
| IK_PPPOE_TERMINATED // PPPOE连接关闭
| IK_WOL // 网络唤醒
| IK_SOCK_ALL; // 所有的SOCKET中断
ctlwizchip(CW_CLR_INTERRUPT, (void*)(&tmp16));
// 设置中断间隔时间
tmp16 = 25;
ctlwizchip(CW_SET_INTRTIME, (void*)(&tmp16));
ctlwizchip(CW_GET_INTRTIME, (void*)(&tmp16));
printf("intrtime is %d:\r\n", tmp16);
// 读取芯片ID
ctlwizchip(CW_GET_ID, (void*)(&chipId));
printf("chip ID is %x %x %x %x %x %x\r\n", chipId[0],chipId[1],chipId[2],chipId[3],chipId[4],chipId[5]);
// PHY物理层连接状态检查
rslt = ctlwizchip(CW_GET_PHYLINK, (void*)(&tmp8));
if(rslt == -1)
{
printf("Unknown PHY Link stauts.\r\n");
}
else
{
if (tmp8 == PHY_LINK_ON)
{
printf("PHY Link ON.\r\n");
}
else if (tmp8 == PHY_LINK_OFF)
{
printf("PHY Link OFF.\r\n");
}
}
return rslt;
}
// 网络参数配置
void NetworkParaConfig(void)
{
u8 tmp8;
u8 tmpstr[6];
// 网络模式
tmp8 = 0
// | NM_FORCEARP // 强制ARP
// | NM_WAKEONLAN // 网络唤醒
// | NM_PINGBLOCK // ping 阻塞
// | NM_PPPOE // PPPoE 模式
| 0;
ctlnetwork(CN_SET_NETMODE, (void*)(&tmp8));
// 网络参数 包括MAC地址IP地址子网掩码DNSDHCP等
ctlnetwork(CN_SET_NETINFO, (void*)(&g_netInfo));
DelayMs(10);
ctlnetwork(CN_GET_NETINFO, (void*)(&g_netInfo));
ctlwizchip(CW_GET_ID, (void*)(tmpstr));
// 显示网络参数
#if (1)
printf("\r\n=== %s NET CONF ===\r\n",(char*)(tmpstr));
printf("MAC: %X:%X:%X:%X:%X:%X\r\n",g_netInfo.mac[0],g_netInfo.mac[1],g_netInfo.mac[2],
g_netInfo.mac[3],g_netInfo.mac[4],g_netInfo.mac[5]);
printf("SIP: %d.%d.%d.%d\r\n", g_netInfo.ip[0],g_netInfo.ip[1],g_netInfo.ip[2],g_netInfo.ip[3]);
printf("GAW: %d.%d.%d.%d\r\n", g_netInfo.gw[0],g_netInfo.gw[1],g_netInfo.gw[2],g_netInfo.gw[3]);
printf("SUB: %d.%d.%d.%d\r\n", g_netInfo.sn[0],g_netInfo.sn[1],g_netInfo.sn[2],g_netInfo.sn[3]);
printf("DNS: %d.%d.%d.%d\r\n", g_netInfo.dns[0],g_netInfo.dns[1],g_netInfo.dns[2],g_netInfo.dns[3]);
if (g_netInfo.dhcp == 1)
{
printf("alloc ip static\r\n");
}
else if (g_netInfo.dhcp == 2)
{
printf("alloc ip by dhcp\r\n");
}
printf("======================\r\n");
#endif
// 设置时间参数
ctlnetwork(CN_SET_TIMEOUT, (void*)(&g_netTimeout));
}
//-----------------------------------------------------------------------------------------------------
// 中断处理
void EthernetIntProc(void)
{
u16 intr;
// 控制器中断
ctlwizchip(CW_GET_INTERRUPT, &intr); // 读取中断
ctlwizchip(CW_CLR_INTERRUPT, &intr); // 清除中断标志
#if (1)
// 处理中断
if ((intr & IK_WOL) != 0) // 网络唤醒
{
printf("Wake on LAN\r\n");
}
if ((intr & IK_PPPOE_TERMINATED) != 0) // PPPOE连接关闭
{
printf("PPPOE terminated\r\n");
}
if ((intr & IK_DEST_UNREACH) != 0) // 目标不可达
{
printf("Destination Unreachable\r\n");
}
if ((intr & IK_IP_CONFLICT) != 0) // IP冲突
{
printf("IP conflict\r\n");
}
#endif
}
//-----------------------------------------------------------------------------------------------------
int IsSocketErr(int err)
{
int rslt;
rslt = 0;
switch(err)
{
case SOCK_OK:
printf("Result is OK about socket process.\r\n");
break;
case SOCK_BUSY:
printf("Socket is busy on processing the operation. Valid only Non-block IO Mode.\r\n");
break;
case SOCK_FATAL:
printf("Result is fatal error about socket process.\r\n");
break;
case SOCKERR_SOCKNUM:
printf("Invalid socket number\r\n");
rslt = -1;
break;
case SOCKERR_SOCKOPT:
printf("Invalid socket option\r\n");
rslt = -1;
break;
case SOCKERR_SOCKINIT:
printf("Socket is not initialized or SIPR is Zero IP address when Sn_MR_TCP\r\n");
rslt = -1;
break;
case SOCKERR_SOCKCLOSED:
printf("Socket unexpectedly closed.\r\n");
rslt = -1;
break;
case SOCKERR_SOCKMODE:
printf("Invalid socket mode for socket operation.\r\n");
rslt = -1;
break;
case SOCKERR_SOCKFLAG:
printf("Invalid socket flag\r\n");
rslt = -1;
break;
case SOCKERR_SOCKSTATUS:
printf("Invalid socket status for socket operation.\r\n");
rslt = -1;
break;
case SOCKERR_ARG:
printf("Invalid argument.\r\n");
rslt = -1;
break;
case SOCKERR_PORTZERO:
printf("Port number is zero\r\n");
rslt = -1;
break;
case SOCKERR_IPINVALID:
printf("Invalid IP address\r\n");
rslt = -1;
break;
case SOCKERR_TIMEOUT:
printf("Timeout occurred\r\n");
rslt = -1;
break;
case SOCKERR_DATALEN:
printf("Data length is zero or greater than buffer max size.\r\n");
rslt = -1;
break;
case SOCKERR_BUFFER:
printf("Socket buffer is not enough for data communication.\r\n");
rslt = -1;
break;
case SOCKFATAL_PACKLEN:
printf("Invalid packet length. Fatal Error.\r\n");
rslt = -1;
break;
default:
rslt = err;
break;
}
EthernetServiceRun();
return rslt;
}
//-----------------------------------------------------------------------------------------------------
// Ethernet 发送数据
// 功能:发送数据,将数据添加到发送队列中并发送
// 参数: pDatBuf发送数据缓冲区
// len, 发送数据长度
// 返回: >= 0, 实际发送数据
// 返回: -1, 输入参数错误
// -2, 控制结构没有初始化
// -3, 接收缓冲区控制错误
int EthernetSendData(SocketCtrl * pCtrl, u8 * pDatBuf, int len)
{
int rslt, err;
rslt = 0;
if (pCtrl->type == TCP_SERVER || pCtrl->type == TCP_CLIENT)
{
if (pCtrl->status == STA_CONNECT) // 已连接
{
err = send(pCtrl->socket, pDatBuf, len);
rslt = IsSocketErr(err);
}
else
{
printf("socket not connect\r\n");
}
}
#if (UDP_NUM > 0)
else if (pCtrl->type == UDP_COMM)
{
err = UdpTransData(pDatBuf, len); // sendto
rslt = IsSocketErr(err);
}
#endif
else
{
}
return rslt;
}
// 功能:接收数据,将数据从接收缓冲区中取出
// 参数: pDat存放缓冲区
// expectLen希望得到数据的大小
// 返回: >= 0实际得到数据的大小
// -1, 输入参数错误
// -2, 控制器没有初始化
// -3, 接收缓冲区控制错误
int EthernetGetData(SocketCtrl * pCtrl, u8 * pDat, int expectLen)
{
int rslt, err;
rslt = 0;
if (pCtrl->type == TCP_SERVER || pCtrl->type == TCP_CLIENT)
{
if (pCtrl->status == STA_CONNECT) // 已连接
{
err = recv(pCtrl->socket, pDat, expectLen);
rslt = IsSocketErr(err);
}
else
{
printf("socket not connect\r\n");
}
}
#if (UDP_NUM > 0)
else if (pCtrl->type == UDP_COMM)
{
err = UdpRecvData(pDat, expectLen); // recvfrom
rslt = IsSocketErr(err);
}
#endif
else
{
}
return rslt;
}
// Ethernet 已接收数据长度
int EthernetGetRsLen(SocketCtrl * pCtrl)
{
if (pCtrl->status == STA_CONNECT ||
#if (UDP_NUM > 0)
pCtrl->type == UDP_COMM ||
#endif
0 ) // 已连接
{
return getSn_RX_RSR(pCtrl->socket);
}
else
{
// printf("socket not connect\r\n");
return -1;
}
}
// 得到发送缓冲区空闲长度
int EthernetGetSdFreeLen(SocketCtrl * pCtrl)
{
if (pCtrl->status == STA_CONNECT ||
#if (UDP_NUM > 0)
pCtrl->type == UDP_COMM ||
#endif
0 ) // 已连接
{
return getSn_TX_FSR(pCtrl->socket);
}
else
{
// printf("socket not connect\r\n");
return -1;
}
}
SocketCtrl * GetCtrlFromSocketIdx(int sIdx)
{
if (sIdx < UDP_SN_BEG+UDP_NUM)
{
return GetUdpCtrlFromSocketId(sIdx-UDP_SN_BEG);
}
#if (SERVER_NUM > 0)
else if (sIdx < TCP_SERVER_SN_BEG+SERVER_NUM)
{
return GetTcpServerCtrlFromSocketId(sIdx-TCP_SERVER_SN_BEG);
}
#endif
#if (CLIENT_NUM > 0)
else if (sIdx < TCP_CLIENT_SN_BEG+CLIENT_NUM)
{
return GetTcpClientCtrlFromSocketId(sIdx-TCP_CLIENT_SN_BEG);
}
#endif
else
{
return NULL;
}
}
//-------------------------------------------------------------------------------------------------------------------
// 服务运行
void EthernetServiceRun()
{
#if (SERVER_NUM > 0)
TcpServerRun();
#endif
#if (CLIENT_NUM > 0)
TcpClientRun();
#endif
#if (UDP_NUM > 0)
// UdpTransRun();
#endif
}