#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地址,子网掩码,DNS,DHCP等 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 }