/* * net_function.c * * Created on: 2025年5月21日 * Author: cc */ #include "includes.h" #include #include uint8_t MACAddr[6]; //MAC address uint8_t IPAddr[4] = {172, 16, 4, 100}; //IP address uint8_t GWIPAddr[4] = {172, 16, 4, 254}; //Gateway IP address uint8_t IPMask[4] = {255, 255, 0, 0}; //subnet mask uint8_t DESIP[4] = {172, 16, 4, 55}; //destination IP address uint16_t desport = 1000; //destination port uint16_t srcport = 1000; //source port uint8_t SocketId; uint8_t socket[WCHNET_MAX_SOCKET_NUM]; //Save the currently connected socket uint8_t SocketRecvBuf[WCHNET_MAX_SOCKET_NUM][RECE_BUF_LEN]; //socket receive buffer //设备的网络信息 WCHNET_INFO_T g_netinfo = { .device_ip = {192,168,1,200}, .gateway = {192,168,1,1}, .subnet = {255,255,0,0}, .mac_addr = {0x34,0xD0,0xB8,0x11,0x11,0x11}, .SocketId = {0,0,0,0}, }; DEVICE_NET_APPINFO server_info = { .net_sta = 0, }; TFTP_LOG tftp_log; void ETH_IRQHandler(void) __attribute__((interrupt("WCH-Interrupt-fast"))); void TIM2_IRQHandler(void) __attribute__((interrupt("WCH-Interrupt-fast"))); /******************************************************************************* * Function Name : mStopIfError * Description : check if error. * Input : * iError - error constants. *******************************************************************************/ void mStopIfError(uint8_t iError) { if (iError == WCHNET_ERR_SUCCESS) return; printf("Error: %X\r\n", (uint16_t) iError); } /******************************************************************************* * Function Name : TIM2_Init * Description : Initializes TIM2. *******************************************************************************/ __attribute__((section(".non_0_wait"))) void TIM2_Init(void) { TMR2_ClrCurrentCount(); R32_TMR2_CNT_END = SystemCoreClock / 1000 * WCHNETTIMERPERIOD; R8_TMR2_CTRL_MOD = RB_TMR_COUNT_EN; TMR2_ITCfg(ENABLE, RB_TMR_IE_CYC_END); NVIC_EnableIRQ(TIM2_IRQn); } /******************************************************************************* * Function Name : ETH_IRQHandler * Description : This function handles ETH exception. *******************************************************************************/ void ETH_IRQHandler(void) { WCHNET_ETHIsr(); } /******************************************************************************* * Function Name : TIM2_IRQHandler * Description : This function handles TIM2 exception. *******************************************************************************/ void TIM2_IRQHandler(void) { WCHNET_TimeIsr(WCHNETTIMERPERIOD); TMR2_ClearITFlag(RB_TMR_IF_CYC_END); } /******************************************************************************* * Function Name : WCHNET_CreateUdpSocket * Description : 创建UDP套接字 * Input : * S - socket索引值 * SourPort - socket源端口 * cb - socket回调函数 * Return : None *******************************************************************************/ __attribute__((section(".non_0_wait"))) void WCHNET_CreateUdpSocket(uint8_t* S, uint16_t SourPort, pSockRecv cb) { uint8_t i; SOCK_INF TmpSocketInf; /* 创建临时socket变量 */ memset((void *)&TmpSocketInf,0,sizeof(SOCK_INF)); /* 库内部会将此变量复制,所以最好将临时变量先全部清零 */ TmpSocketInf.IPAddr[0] = 0xFF; TmpSocketInf.IPAddr[1] = 0xFF; TmpSocketInf.IPAddr[2] = 0xFF; TmpSocketInf.IPAddr[3] = 0xFF; TmpSocketInf.DesPort = SourPort; /* 设置目的端口 */ TmpSocketInf.SourPort = SourPort; /* 设置源端口 */ TmpSocketInf.ProtoType = PROTO_TYPE_UDP; /* 设置socket类型 */ TmpSocketInf.RecvBufLen = RECE_BUF_LEN; /* 设置socket 接收缓冲区长度 */ TmpSocketInf.AppCallBack = cb; /* 设置接收回调函数 */ i = WCHNET_SocketCreat(S, &TmpSocketInf); /* 创建socket,将返回的socket索引保存在SocketId中 */ mStopIfError(i); WCHNET_ModifyRecvBuf(SocketId, (uint32_t) SocketRecvBuf[SocketId], RECE_BUF_LEN); Dbg_Println(DBG_BIT_NET_STATUS_bit,"%s - %d",__func__, *S); } /******************************************************************************* * Function Name : WCHNET_CreateTcpSocket * Description : 创建TCP套接字 * Input : * S - socket索引值 * Return : None *******************************************************************************/ __attribute__((section(".non_0_wait"))) void WCHNET_CreateTcpSocket(uint8_t* S) { uint8_t i; SOCK_INF TmpSocketInf; memset((void *) &TmpSocketInf, 0, sizeof(SOCK_INF)); memcpy((void *) TmpSocketInf.IPAddr, DESIP, 4); TmpSocketInf.DesPort = desport; TmpSocketInf.SourPort = srcport; TmpSocketInf.ProtoType = PROTO_TYPE_TCP; TmpSocketInf.RecvStartPoint = (uint32_t) SocketRecvBuf[0]; TmpSocketInf.RecvBufLen = RECE_BUF_LEN; i = WCHNET_SocketCreat(S, &TmpSocketInf); printf("TCP SocketId %d\r\n", *S); mStopIfError(i); i = WCHNET_SocketConnect(*S); //make a TCP connection mStopIfError(i); } void UDPSocket1_AppCallBack( struct _SOCK_INF * SocketInf,uint32_t ipaddr,uint16_t port,uint8_t *buff,uint32_t len) { uint8_t ip[4]; ip[0] = ipaddr; ip[1] = ipaddr>>8; ip[2] = ipaddr>>16; ip[3] = ipaddr>>24; Dbg_Println(DBG_BIT_NET_STATUS_bit,"ip:%d.%d.%d.%d, port:%d",ip[0], ip[1], ip[2], ip[3], port); Dbg_Println(DBG_BIT_NET_STATUS_bit,"Socket1 len:%ld",len); Dbg_Print_Buff(DBG_BIT_NET_STATUS_bit,"data :",buff,len); //Udp_Internal_Analysis(buff, len, ip, port); if(buff[0] == 0xAA) { switch(buff[1]) { case 0x55: //旧的服务器协议 //Udp_Internal_Analysis(buff, len, ip, port); break; case 0x66: //UDP服务协议 - 2022-05-31 //UDP_NetServer_Data_Analysis(buff, len, ip, port); break; } } } /******************************************************************************* * Function Name : WCHNET_DataLoopback * Description : Data loopback function. * Input : * id - socket id. * Return : None *******************************************************************************/ __attribute__((section(".non_0_wait"))) void WCHNET_DataLoopback(uint8_t id) { uint8_t i; uint32_t len; uint32_t endAddr = SocketInf[id].RecvStartPoint + SocketInf[id].RecvBufLen; //Receive buffer end address if ((SocketInf[id].RecvReadPoint + SocketInf[id].RecvRemLen) > endAddr) { //Calculate the length of the received data len = endAddr - SocketInf[id].RecvReadPoint; } else { len = SocketInf[id].RecvRemLen; } i = WCHNET_SocketSend(id, (uint8_t *) SocketInf[id].RecvReadPoint, &len); //send data if (i == WCHNET_ERR_SUCCESS) { WCHNET_SocketRecv(id, NULL, &len); //Clear sent data } } /******************************************************************************* * Function Name : WCHNET_HandleSockInt * Description : Socket Interrupt Handle * Input : * socketid - socket id. * intstat - interrupt status * Return : None *******************************************************************************/ __attribute__((section(".non_0_wait"))) void WCHNET_HandleSockInt(uint8_t socketid, uint8_t intstat) { uint8_t i; if (intstat & SINT_STAT_RECV) //receive data { WCHNET_DataLoopback(socketid); //Data loopback } if (intstat & SINT_STAT_CONNECT) //connect successfully { #if KEEPALIVE_ENABLE WCHNET_SocketSetKeepLive(socketid, ENABLE); #endif for (i = 0; i < WCHNET_MAX_SOCKET_NUM; i++) { if (socket[i] == 0xff) { //save connected socket id socket[i] = socketid; //需要注意要是套接字ID 超出数组范围的话,无需重新分配接收缓冲区 // if(socketid < WCHNET_MAX_SOCKET_NUM) // { // WCHNET_ModifyRecvBuf(socketid, (uint32_t) SocketRecvBuf[socketid], RECE_BUF_LEN); // } break; } } printf("TCP Connect Success\r\n"); printf("socket id: %d\r\n", socket[i]); } if (intstat & SINT_STAT_DISCONNECT) //disconnect { for (i = 0; i < WCHNET_MAX_SOCKET_NUM; i++) { //delete disconnected socket id if (socket[i] == socketid) { socket[i] = 0xff; break; } } printf("TCP Disconnect\r\n"); } if (intstat & SINT_STAT_TIM_OUT) //timeout disconnect { for (i = 0; i < WCHNET_MAX_SOCKET_NUM; i++) { //delete disconnected socket id if (socket[i] == socketid) { socket[i] = 0xff; break; } } printf("TCP Timeout\r\n"); } } /******************************************************************************* * Function Name : WCHNET_Get_PHY_Linked_Status * Description : 获取PHY链路状态 * Return :返回PHY状态: 0x00 - PHY Link Succ,0x01 - PHY Link Fail *******************************************************************************/ __attribute__((section(".non_0_wait"))) uint8_t WCHNET_Get_PHY_Linked_Status(void) { uint16_t rev = 0; rev = WCHNET_GetPHYStatus(); if(rev & PHY_Linked_Status) return 0x00; return 0x01; } /******************************************************************************* * Function Name : WCHNET_HandleGlobalInt * Description : Global Interrupt Handle *******************************************************************************/ __attribute__((section(".non_0_wait"))) void WCHNET_HandleGlobalInt(void) { uint8_t intstat; uint16_t i; uint8_t socketint; intstat = WCHNET_GetGlobalInt(); //get global interrupt flag if (intstat & GINT_STAT_UNREACH) //Unreachable interrupt { printf("GINT_STAT_UNREACH\r\n"); } if (intstat & GINT_STAT_IP_CONFLI) //IP conflict { printf("GINT_STAT_IP_CONFLI\r\n"); } if (intstat & GINT_STAT_PHY_CHANGE) //PHY status change { i = WCHNET_GetPHYStatus(); if (i & PHY_Linked_Status) Dbg_Println(DBG_BIT_NET_STATUS_bit,"PHY Link Success"); else{ //网线已拔出 Dbg_Println(DBG_BIT_NET_STATUS_bit,"PHY断开,需重新初始化网络"); server_info.init_flag = 0; //PHY断开,需重新初始化网络 LOG_SYS_PHY_Change_Record(0x00); //网线拔出 } } if (intstat & GINT_STAT_SOCKET) { //socket related interrupt for (i = 0; i < WCHNET_MAX_SOCKET_NUM; i++) { socketint = WCHNET_GetSocketInt(i); if (socketint) WCHNET_HandleSockInt(i, socketint); } } } /******************************************************************************* * Function Name : WCHNET_DHCPCallBack * Description : DHCPCallBack * Input : status - status returned by DHCP arg - Data returned by DHCP * Return : DHCP status *******************************************************************************/ uint8_t WCHNET_DHCPCallBack(uint8_t status, void *arg) { uint8_t *p; uint8_t tmp[4] = {0, 0, 0, 0}; if(!status) { p = arg; Dbg_Println(DBG_BIT_NET_STATUS_bit,"DHCP Success"); /*If the obtained IP is the same as the last IP, exit this function.*/ if(!memcmp(g_netinfo.device_ip, p ,sizeof(IPAddr))) { Dbg_Println(DBG_BIT_NET_STATUS_bit,"DHCP 获取IP与当前IP相同!"); return ETH_SUCCESS; } /*Determine whether it is the first successful IP acquisition*/ if(memcmp(g_netinfo.device_ip, tmp ,sizeof(IPAddr))){ /*The obtained IP is different from the last value, * then disconnect the last connection.*/ Dbg_Println(DBG_BIT_NET_STATUS_bit,"DHCP 获取IP与当前IP不同 断开TCP链接\r\n"); WCHNET_SocketClose(SocketId, TCP_CLOSE_NORMAL); //特别强调,该释放套接字与DHCP网络底层操作有关,删除会导致出现网络异常 } memcpy(g_netinfo.device_ip, p, 4); memcpy(g_netinfo.gateway, &p[4], 4); memcpy(g_netinfo.subnet, &p[8], 4); Dbg_Println(DBG_BIT_NET_STATUS_bit,"IPAddr = %d.%d.%d.%d ", g_netinfo.device_ip[0], g_netinfo.device_ip[1], g_netinfo.device_ip[2], g_netinfo.device_ip[3]); Dbg_Println(DBG_BIT_NET_STATUS_bit,"GWIPAddr = %d.%d.%d.%d ", g_netinfo.gateway[0], g_netinfo.gateway[1], g_netinfo.gateway[2], g_netinfo.gateway[3]); Dbg_Println(DBG_BIT_NET_STATUS_bit,"IPMask = %d.%d.%d.%d ", g_netinfo.subnet[0], g_netinfo.subnet[1], g_netinfo.subnet[2], g_netinfo.subnet[3]); Dbg_Println(DBG_BIT_NET_STATUS_bit,"DNS2: %d.%d.%d.%d ", p[16], p[17], p[18], p[19]); WCHNET_DHCPStop(); //关闭DHCP功能 server_info.net_retry_num = 0; server_info.net_sta = NET_SOCKET_WAIT; server_info.wait_cot = SysTick_1ms; return ETH_SUCCESS; } else { /*DHCP获取失败 */ Dbg_Println(DBG_BIT_NET_STATUS_bit,"DHCP Fail %02x ", status); /*Determine whether it is the first successful IP acquisition*/ if(memcmp(IPAddr, tmp ,sizeof(IPAddr))){ /*The obtained IP is different from the last value*/ //WCHNET_SocketClose(SocketId, TCP_CLOSE_NORMAL); } return ETH_ERROR; } } /******************************************************************************* * Function Name : WCHNET_DNSCallBack_1 * Description : 解析云端服务器域名回调函数 * Input : name - DNS解析域名 ipaddr - DNS解析域名的IP * Return : DHCP status *******************************************************************************/ __attribute__((section(".non_0_wait"))) void WCHNET_DNSCallBack_1(const char *name, uint8_t *ipaddr, void *callback_arg) { if(ipaddr == NULL) { server_info.net_retry_num++; if(server_info.net_retry_num >= 3) { server_info.net_retry_num = 0; server_info.net_sta = NET_TFTP; //解析失败,下一个 WCHNET_DNSStop(); //stop DNS,and release socket } Dbg_Print(DBG_BIT_NET_STATUS_bit,"DNS Fail\r\n"); return; } server_info.dis_ip[0] = ipaddr[0]; server_info.dis_ip[1] = ipaddr[1]; server_info.dis_ip[2] = ipaddr[2]; server_info.dis_ip[3] = ipaddr[3]; Dbg_Print(DBG_BIT_NET_STATUS_bit,"Host Name = %s\r\n", name); Dbg_Print(DBG_BIT_NET_STATUS_bit,"IP= %d.%d.%d.%d\r\n", ipaddr[0], ipaddr[1], ipaddr[2], ipaddr[3]); if(callback_arg != NULL) { Dbg_Print(DBG_BIT_NET_STATUS_bit,"callback_arg = %02x\r\n", (*(uint8_t *)callback_arg)); } WCHNET_DNSStop(); //stop DNS,and release socket server_info.server_dns_flag = 0x01; //解析成功标志位 server_info.net_sta = NET_TFTP; //解析成功,下一个 } /******************************************************************************* * Function Name : WCHNET_DNSCallBack_2 * Description : 解析TFTP服务器域名回调函数 - 网络启动时解析域名 * Input : name - DNS解析域名 ipaddr - DNS解析域名的IP * Return : DHCP status *******************************************************************************/ __attribute__((section(".non_0_wait"))) void WCHNET_DNSCallBack_2(const char *name, uint8_t *ipaddr, void *callback_arg) { if(ipaddr == NULL) { server_info.net_retry_num++; if(server_info.net_retry_num >= 3) { server_info.net_retry_num = 0; server_info.net_sta = NET_COMPLETE; server_info.init_flag = 0x01; } Dbg_Print(DBG_BIT_NET_STATUS_bit,"DNS Fail\r\n"); return; } server_info.tftp_ip[0] = ipaddr[0]; server_info.tftp_ip[1] = ipaddr[1]; server_info.tftp_ip[2] = ipaddr[2]; server_info.tftp_ip[3] = ipaddr[3]; Dbg_Print(DBG_BIT_NET_STATUS_bit,"Host Name = %s\r\n", name); Dbg_Print(DBG_BIT_NET_STATUS_bit,"IP= %d.%d.%d.%d\r\n", ipaddr[0], ipaddr[1], ipaddr[2], ipaddr[3]); if(callback_arg != NULL) { Dbg_Print(DBG_BIT_NET_STATUS_bit,"callback_arg = %02x\r\n", (*(uint8_t *)callback_arg)); } WCHNET_DNSStop(); //stop DNS,and release socket server_info.tftp_dns_flag = 0x01; //解析成功标志位 server_info.net_sta = NET_COMPLETE; server_info.init_flag = 0x01; } /******************************************************************************* * Function Name : WCHNET_DNSCallBack_3 * Description : 解析TFTP服务器域名回调函数 - TFTP发生前解析域名 * Input : name - DNS解析域名 ipaddr - DNS解析域名的IP * Return : DHCP status *******************************************************************************/ __attribute__((section(".non_0_wait"))) void WCHNET_DNSCallBack_3(const char *name, uint8_t *ipaddr, void *callback_arg) { if(ipaddr == NULL) { server_info.net_retry_num++; if(server_info.net_retry_num >= 3) { server_info.net_retry_num = 0; } Dbg_Print(DBG_BIT_NET_STATUS_bit,"DNS Fail\r\n"); return; } server_info.tftp_ip[0] = ipaddr[0]; server_info.tftp_ip[1] = ipaddr[1]; server_info.tftp_ip[2] = ipaddr[2]; server_info.tftp_ip[3] = ipaddr[3]; Dbg_Print(DBG_BIT_NET_STATUS_bit,"Host Name = %s\r\n", name); Dbg_Print(DBG_BIT_NET_STATUS_bit,"IP= %d.%d.%d.%d\r\n", ipaddr[0], ipaddr[1], ipaddr[2], ipaddr[3]); if(callback_arg != NULL) { Dbg_Print(DBG_BIT_NET_STATUS_bit,"callback_arg = %02x\r\n", (*(uint8_t *)callback_arg)); } WCHNET_DNSStop(); //stop DNS,and release socket server_info.tftp_dns_flag = 0x01; //解析成功标志位 } /******************************************************************************* * Function Name : is_valid_domain * Description : 判断域名 * Input : domain - 需要判断的域名 * Return : 0x00:合格域名,0x01:非法域名 *******************************************************************************/ __attribute__((section(".non_0_wait"))) uint8_t is_valid_domain(const char *domain) { const char *c = domain; int parts = 0; int dashes = 0; //Dbg_Println(DBG_BIT_NET_STATUS_bit,"is_valid_domain_0:%s",domain); // 检查是否有连续的点或连字符 if (strstr(domain, "..") || strstr(domain, "--")) { Dbg_Println(DBG_BIT_NET_STATUS_bit,"is_valid_domain_1"); return 0x01; } // 检查每个字符 while (*c) { if (isalpha(*c) || isdigit(*c) || *c == '-' || *c == '.') { if (*c == '-') { // 不允许在开头或结尾出现连字符 if (c == domain || *(c + 1) == '\0' || dashes == 0) { Dbg_Println(DBG_BIT_NET_STATUS_bit,"is_valid_domain_2"); return 0x01; } dashes = 0; } else { dashes = 1; } } else { // 非法字符 Dbg_Println(DBG_BIT_NET_STATUS_bit,"is_valid_domain_3:%c",*c); return 0x01; } if (*c == '.') { parts++; // 分隔符计数 if (c == domain || *(c + 1) == '\0') { // 不允许在开头、结尾或者在两个点之间为空 Dbg_Println(DBG_BIT_NET_STATUS_bit,"is_valid_domain_4"); return 0x01; } } c++; } // 至少需要两个部分(例如 example.com) Dbg_Println(DBG_BIT_NET_STATUS_bit,"is_valid_domain_5:%d",parts); if(parts > 1) { return 0x00; //合格域名 }else { return 0x01; //非法域名 } } /******************************************************************************* * Function Name : NetWork_Parameter_Get * Description : 网络任务 获取网络初始化参数以及网络初始化功能 * Input : None * Output : None * Return : None * 用 法 : 初始化调用 *******************************************************************************/ __attribute__((section(".non_0_wait"))) void NetWork_Parameter_Get(void) { uint8_t Arge_Flag = 0; uint32_t temp = 0; /*判断网络是否使用设置参数为默认IP地址*/ Arge_Flag = SRAM_Read_Byte(SRAM_Register_Start_ADDRESS + Register_NetInfo_EN_OFFSET + 1); if(Arge_Flag == 0x01) { Dbg_Println(DBG_BIT_NET_STATUS_bit,"NET 网络参数使用PC设置参数!"); SRAM_DMA_Read_Buff(g_netinfo.device_ip, 4, SRAM_Register_Start_ADDRESS + Register_NetIP_OFFSET); SRAM_DMA_Read_Buff(g_netinfo.gateway,4,SRAM_Register_Start_ADDRESS + Register_NetGateway_OFFSET); SRAM_DMA_Read_Buff(g_netinfo.subnet,4,SRAM_Register_Start_ADDRESS + Register_NetMask_OFFSET); SRAM_DMA_Read_Buff(g_netinfo.dns_server_ip,4,SRAM_Register_Start_ADDRESS + Register_DNSServerIP_OFFSET); }else { Dbg_Println(DBG_BIT_NET_STATUS_bit,"NET 网络参数使用本机默认参数!"); //MCU初始化IP g_netinfo.device_ip[0] = 192; g_netinfo.device_ip[1] = 168; g_netinfo.device_ip[2] = MACAddr[4]; g_netinfo.device_ip[3] = MACAddr[5]; //MCU初始网关 g_netinfo.gateway[0] = 192; g_netinfo.gateway[1] = 168; g_netinfo.gateway[2] = MACAddr[4]; g_netinfo.gateway[3] = 1; //MCU初始子网掩码 g_netinfo.subnet[0] = 255; g_netinfo.subnet[1] = 255; g_netinfo.subnet[2] = 0; g_netinfo.subnet[3] = 0; //MCU DNS地址 g_netinfo.dns_server_ip[0] = 223; g_netinfo.dns_server_ip[1] = 5; g_netinfo.dns_server_ip[2] = 5; g_netinfo.dns_server_ip[3] = 5; } /*启用DHCP*/ if(SRAM_Read_Byte(SRAM_Register_Start_ADDRESS + Register_NetInfo_EN_OFFSET) != 0x02) { Dbg_Println(DBG_BIT_NET_STATUS_bit,"DHCP功能使能!"); server_info.dhcp_en = 0x01; }else{ /*不启用*/ Dbg_Println(DBG_BIT_NET_STATUS_bit,"不启用DHCP功能!"); server_info.dhcp_en = 0x00; } /*判断当前使用本地服务器还是云端服务器*/ temp = SRAM_Read_Byte(SRAM_Register_Start_ADDRESS + Register_NetInfo_EN_OFFSET + 2); if(temp == 0x01) //使用本地端服务器 { server_info.server_select = 0x01; Dbg_Println(DBG_BIT_NET_STATUS_bit,"使用本地端服务器"); }else //使用云端端服务器 { server_info.server_select = 0x00; Dbg_Println(DBG_BIT_NET_STATUS_bit,"使用云端端服务器"); } memset(&tftp_log,0,sizeof(TFTP_LOG)); SRAM_DMA_Read_Buff((uint8_t*)&tftp_log.Time,2,SRAM_Register_Start_ADDRESS + Register_TFTPLOGTime_OFFSET); SRAM_DMA_Read_Buff((uint8_t*)&tftp_log.Port,2,SRAM_Register_Start_ADDRESS + Register_TFTPLOGPort_OFFSET); Dbg_Println(DBG_BIT_NET_STATUS_bit,"tftp log port:%d time:%dh",tftp_log.Port,tftp_log.Time); if((tftp_log.Port == 0xFFFF) || (tftp_log.Port == 0x00)) { tftp_log.Port = TFTP_Destination_Port; Dbg_Println(DBG_BIT_NET_STATUS_bit,"tftp log default port:%d",tftp_log.Port); } if((tftp_log.Time == 0x00) || (tftp_log.Time > 720)) { tftp_log.Time = 720; //1个月 Dbg_Println(DBG_BIT_NET_STATUS_bit,"tftp log default time:%dh",tftp_log.Time); } tftp_log.DN_Lens = SRAM_Read_Byte(SRAM_Register_Start_ADDRESS + Register_TFTPDmLens_OFFSET); Dbg_Println(DBG_BIT_NET_STATUS_bit,"tftp log domain name lens:%d",tftp_log.DN_Lens); if(tftp_log.DN_Lens < DOMAINNAME_MAX) { SRAM_DMA_Read_Buff((uint8_t*)tftp_log.DomainName,tftp_log.DN_Lens,SRAM_Register_Start_ADDRESS + Register_TFTPDmName_OFFSET); tftp_log.DomainName[tftp_log.DN_Lens] = '\0'; } if((tftp_log.DN_Lens == 0x00) || (is_valid_domain(tftp_log.DomainName) != 0x00)) //域名不合法使用默认 { tftp_log.DN_Lens = sizeof(TFTPSERVER_NAME_DNS); if(tftp_log.DN_Lens < DOMAINNAME_MAX) { memcpy(tftp_log.DomainName,(char*)TFTPSERVER_NAME_DNS,sizeof(TFTPSERVER_NAME_DNS)); tftp_log.DomainName[tftp_log.DN_Lens] = '\0'; } Dbg_Println(DBG_BIT_NET_STATUS_bit,"tftp domain name err,use default:%s",tftp_log.DomainName); } //读取服务器离线判定时间 server_info.udp_online_time = SRAM_Read_DW(SRAM_Register_Start_ADDRESS + Register_NetOfflineTime_OFFSET); if( (server_info.udp_online_time < 1000) || (server_info.udp_online_time > 7200000) ) { server_info.udp_online_time = 600000; } //读取UDP 定期上报时间间隔 temp = SRAM_Read_DW(SRAM_Register_Start_ADDRESS + Register_UDPPeriodicTime_OFFSET); if( (temp < 10000) || (temp > 7200000) ) { server_info.udp_periodic_time = 60; }else { server_info.udp_periodic_time = temp / 1000; } //读取服务器域名与端口 temp = SRAM_Read_DW(SRAM_Register_Start_ADDRESS + Register_WebServerPort_OFFSET); if( (temp == 0x00) || (temp >= 0xFFFF) ) { //服务器端口不合法,使用默认端口 3339 server_info.dis_port = SERVER_COMM_Port; }else { server_info.dis_port = temp & 0xFFFF; } temp = SRAM_Read_Byte(SRAM_Register_Start_ADDRESS + Register_BLVServerDmName_OFFSET); Dbg_Println(DBG_BIT_NET_STATUS_bit,"BLVServerDmName lens:%d",temp); if(temp < DOMAINNAME_MAX) { memset(server_info.ServerDename,0,sizeof(server_info.ServerDename)); SRAM_DMA_Read_Buff((uint8_t*)server_info.ServerDename,temp,SRAM_Register_Start_ADDRESS + Register_BLVServerDmName_OFFSET); server_info.ServerDename[temp] = '\0'; } if((temp == 0x00) || (is_valid_domain((char *)server_info.ServerDename) != 0x00)) //域名不合法使用默认 { temp = sizeof(SERVER_NAME_DNS); if(temp < DOMAINNAME_MAX) { memcpy(server_info.ServerDename,(char*)SERVER_NAME_DNS,sizeof(SERVER_NAME_DNS)); server_info.ServerDename[temp] = '\0'; } Dbg_Println(DBG_BIT_NET_STATUS_bit,"BLVServerDmName err,use default:%s",server_info.ServerDename); } Dbg_Println(DBG_BIT_NET_STATUS_bit,"MCU初始IP地址 : %d.%d.%d.%d",g_netinfo.device_ip[0],g_netinfo.device_ip[1],g_netinfo.device_ip[2],g_netinfo.device_ip[3]); Dbg_Println(DBG_BIT_NET_STATUS_bit,"MCU初始网关 : %d.%d.%d.%d",g_netinfo.gateway[0],g_netinfo.gateway[1],g_netinfo.gateway[2],g_netinfo.gateway[3]); Dbg_Println(DBG_BIT_NET_STATUS_bit,"MCU初始子网掩码 : %d.%d.%d.%d",g_netinfo.subnet[0],g_netinfo.subnet[1],g_netinfo.subnet[2],g_netinfo.subnet[3]); Dbg_Println(DBG_BIT_NET_STATUS_bit,"MCU DNS地址 : %d.%d.%d.%d",g_netinfo.dns_server_ip[0],g_netinfo.dns_server_ip[1],g_netinfo.dns_server_ip[2],g_netinfo.dns_server_ip[3]); Dbg_Println(DBG_BIT_NET_STATUS_bit,"TFTP Log Domain name:%s ",tftp_log.DomainName); Dbg_Println(DBG_BIT_NET_STATUS_bit,"BLVServerDmName : %s:%d ",server_info.ServerDename,server_info.dis_port); Dbg_Println(DBG_BIT_NET_STATUS_bit,"online_time:%d periodic_time:%d",server_info.udp_online_time,server_info.udp_periodic_time); LOG_SYS_NET_Argc_Init_Record(g_netinfo.device_ip,g_netinfo.gateway,g_netinfo.subnet,g_netinfo.dns_server_ip,Arge_Flag,server_info.dhcp_en,server_info.server_select); } /******************************************************************************* * Function Name : WCHNET_SocketInf_Printf * Description : WCH网络库 套接字 参数信息打印 *******************************************************************************/ __attribute__((section(".non_0_wait"))) void WCHNET_SocketInf_Printf(void) { for(uint8_t i=0;i 30000) { Dbg_Println(DBG_BIT_NET_STATUS_bit,"网络PHY协商失败,准备重新初始化网络"); server_info.net_sta = NET_WAIT_MAC_RESTART; } break; }else { Dbg_Println(DBG_BIT_NET_STATUS_bit,"网线插入已插入,创建直连套接字"); WCHNET_CreateUdpSocket(&g_netinfo.SocketId[SocketIdnex_BLVSeriver], 3341, UDPSocket1_AppCallBack); //创建套接字,局域网等待接收升级或配置发布等命令 server_info.online_state = 1; //2023-10-07 server_info.wait_cot = SysTick_1ms; server_info.net_sta = NET_CON_WAIT; LOG_SYS_PHY_Change_Record(0x01); //网线插入 } break; case NET_WAIT_MAC_RESTART: if(SysTick_1ms - server_info.wait_cot > 2000) { server_info.wait_cot = SysTick_1ms; Dbg_Println(DBG_BIT_NET_STATUS_bit,"重启网络中"); server_info.net_sta = NET_INIT; } break; case NET_CON_WAIT: if(SysTick_1ms - server_info.wait_cot > 200) { server_info.wait_cot = SysTick_1ms; if(server_info.dhcp_en == 0x01) { server_info.net_sta = NET_DHCP; }else { server_info.net_sta = NET_DNS; } } break; case NET_DHCP: //启动DHCP分配ip Dbg_Println(DBG_BIT_NET_STATUS_bit,"启动DHCP分配..."); WCHNET_DHCPSetHostname("BLV_RCU"); WCHNET_DHCPStart(WCHNET_DHCPCallBack); /* 启动DHCP */ server_info.wait_cot = SysTick_1ms; server_info.net_sta = NET_DHCP_WAIT; break; case NET_DHCP_WAIT: if(SysTick_1ms - server_info.wait_cot >= 20000) { Dbg_Println(DBG_BIT_NET_STATUS_bit,"DHCP 耗时:%dms", SysTick_1ms - server_info.wait_cot); server_info.wait_cot = SysTick_1ms; Dbg_Println(DBG_BIT_NET_STATUS_bit,"DHCP获取失败!"); WCHNET_DHCPStop(); server_info.net_retry_num++; server_info.net_sta = NET_DHCP; if(server_info.net_retry_num >= 3) { server_info.net_retry_num = 0; Dbg_Println(DBG_BIT_NET_STATUS_bit,"DHCP重试次数已达上限!"); server_info.net_sta = NET_INIT; //DHCP分配失败,直接重新初始化网络; WCHNET_SocketClose(g_netinfo.SocketId[SocketIdnex_BLVSeriver],0x00); } } /* 如果再次期间拔出网线,PHY链接断开,需重新初始化网络 * - 在重新初始化网络前,需要停止DHCP操作 * */ break; case NET_SOCKET_WAIT: if(SysTick_1ms - server_info.wait_cot >= 200) { Dbg_Print(DBG_BIT_NET_STATUS_bit,"DHCP成功,重新创建通讯套接字\n"); WCHNET_CreateUdpSocket(&g_netinfo.SocketId[SocketIdnex_BLVSeriver], 3341, UDPSocket1_AppCallBack); //创建套接字,局域网等待接收升级或配置发布等命令 WCHNET_SocketInf_Printf(); server_info.net_sta = NET_DNS; } break; case NET_DNS: if(server_info.server_select == 0x00) { /*解析服务器域名 */ Dbg_Print(DBG_BIT_NET_STATUS_bit,"启动DNS域名解析:%s Flag:%d...\n",server_info.ServerDename,server_info.net_retry_flag); //Set DNS server IP address, and DNS server port is 53 if(server_info.net_retry_flag == 0x00) { Dbg_Print(DBG_BIT_NET_STATUS_bit,"DNS解析服务器:%d.%d.%d.%d\n",g_netinfo.dns_server_ip[0],\ g_netinfo.dns_server_ip[1],\ g_netinfo.dns_server_ip[2],\ g_netinfo.dns_server_ip[3]); WCHNET_InitDNS(g_netinfo.dns_server_ip, Net_DNS_Port); }else if(server_info.net_retry_flag == 0x01) { Dbg_Print(DBG_BIT_NET_STATUS_bit,"DNS解析服务器:%d.%d.%d.%d\n",g_netinfo.dns_server2_ip[0],\ g_netinfo.dns_server2_ip[1],\ g_netinfo.dns_server2_ip[2],\ g_netinfo.dns_server2_ip[3]); WCHNET_InitDNS(g_netinfo.dns_server2_ip, Net_DNS_Port); } server_info.dns_sta = 0x01; WCHNET_HostNameGetIp(server_info.ServerDename, RemoteIp, WCHNET_DNSCallBack_1, NULL); //Start DNS server_info.wait_cot = SysTick_1ms; server_info.net_sta = NET_DNS_WAIT; }else if(server_info.server_select == 0x01) { /*采用本地服务器 - 直接设置服务器IP地址,跳过解析服务器域名这一步,解析域名标志位暂时没用上*/ server_info.dis_ip[0] = SRAM_Read_Byte(SRAM_Register_Start_ADDRESS + Register_WebServerIP_OFFSET + 0); server_info.dis_ip[1] = SRAM_Read_Byte(SRAM_Register_Start_ADDRESS + Register_WebServerIP_OFFSET + 1); server_info.dis_ip[2] = SRAM_Read_Byte(SRAM_Register_Start_ADDRESS + Register_WebServerIP_OFFSET + 2); server_info.dis_ip[3] = SRAM_Read_Byte(SRAM_Register_Start_ADDRESS + Register_WebServerIP_OFFSET + 3); server_info.server_dns_flag = 0x00; server_info.net_sta = NET_TFTP; Dbg_Println(DBG_BIT_NET_STATUS_bit,"采用本地服务器:%d.%d.%d.%d",server_info.dis_ip[0],server_info.dis_ip[1],server_info.dis_ip[2],server_info.dis_ip[3]); } break; case NET_TFTP: Dbg_Print(DBG_BIT_NET_STATUS_bit,"启动DNS域名解析:%s Flag:%d...\n",tftp_log.DomainName,server_info.net_retry_flag); //Set DNS server IP address, and DNS server port is 53 if(server_info.net_retry_flag == 0x00) { Dbg_Print(DBG_BIT_NET_STATUS_bit,"DNS解析服务器:%d.%d.%d.%d\n",g_netinfo.dns_server_ip[0],\ g_netinfo.dns_server_ip[1],\ g_netinfo.dns_server_ip[2],\ g_netinfo.dns_server_ip[3]); WCHNET_InitDNS(g_netinfo.dns_server_ip, Net_DNS_Port); }else if(server_info.net_retry_flag == 0x01) { Dbg_Print(DBG_BIT_NET_STATUS_bit,"DNS解析服务器:%d.%d.%d.%d\n",g_netinfo.dns_server2_ip[0],\ g_netinfo.dns_server2_ip[1],\ g_netinfo.dns_server2_ip[2],\ g_netinfo.dns_server2_ip[3]); WCHNET_InitDNS(g_netinfo.dns_server2_ip, Net_DNS_Port); } server_info.dns_sta = 0x02; WCHNET_HostNameGetIp(tftp_log.DomainName, RemoteIp, WCHNET_DNSCallBack_2, NULL); //Start DNS server_info.wait_cot = SysTick_1ms; server_info.net_sta = NET_DNS_WAIT; break; case NET_DNS_WAIT: if(SysTick_1ms - server_info.wait_cot >= 5000) { server_info.wait_cot = SysTick_1ms; switch(server_info.dns_sta) { case 0x01: if(server_info.net_retry_num >= 3) { server_info.net_retry_num = 0; if(server_info.net_retry_flag == 0x00) { //换个DNS服务器测试一下 server_info.net_retry_flag = 0x01; server_info.net_sta = NET_DNS; }else { //还是解析不出来,那算了,下一个 server_info.net_retry_flag = 0x00; server_info.net_sta = NET_TFTP; } WCHNET_DNSStop(); //stop DNS,and release socket }else { server_info.net_retry_num++; server_info.net_sta = NET_DNS; WCHNET_DNSStop(); //stop DNS,and release socket } break; case 0x02: if(server_info.net_retry_num >= 3) { server_info.net_retry_num = 0; if(server_info.net_retry_flag == 0x00) { //换个DNS服务器测试一下 server_info.net_retry_flag = 0x01; server_info.net_sta = NET_TFTP; }else { //还是解析不出来,那算了 server_info.net_retry_flag = 0x00; server_info.net_sta = NET_COMPLETE; server_info.init_flag = 0x01; WCHNET_SocketInf_Printf(); } WCHNET_DNSStop(); //stop DNS,and release socket }else { server_info.net_retry_num++; server_info.net_sta = NET_TFTP; WCHNET_DNSStop(); //stop DNS,and release socket } break; default: //如果还有其他域名解析依次向后添加即可 break; } } /* 如果再次期间拔出网线,PHY链接断开,需重新初始化网络 * - 在重新初始化网络前,需要停止DNS操作 * */ break; case NET_COMPLETE: Internal_TFTP_Task(); //TFTP 任务 BLV_UDP_Comm_Task(); //BLV UDP通讯任务 //Udp_Internal_Task(); //内网处理任务(升级,发布配置) if(SysTick_1s - server_info.con_tick > 10) { //测试使用 server_info.con_tick = SysTick_1s; Dbg_Println(DBG_BIT_NET_STATUS_bit,"网络处理中...\n"); } /* -该用于网络直连超时后,重启网络 * -处于网络直连状态下,PC工具会向主机定期发送查询数据 * */ if(server_info.con_flag==0x01) { if(SysTick_1s - server_info.con_tick > 10) { server_info.con_flag = 0x00; server_info.con_tick = SysTick_1s; server_info.init_flag = 0x00; Dbg_Print(DBG_BIT_NET_STATUS_bit,"直连超时,重启网络\n"); } } if(server_info.init_flag == 0x00) //网络需要重新初始化 { Dbg_Print(DBG_BIT_NET_STATUS_bit,"网络需要重新初始化,关闭MAC\n"); server_info.online_state = 0; server_info.wait_cot = SysTick_1ms; server_info.net_sta = NET_WAIT_MAC_RESTART; /*释放套接字*/ Dbg_Println(DBG_BIT_NET_STATUS_bit,"释放套接字"); WCHNET_SocketClose(g_netinfo.SocketId[SocketIdnex_BLVSeriver],0x00); } break; } }