DSP

LwIP实例代码分析

2019-07-13 20:47发布

//开发环境IAR int APP_Main(void) { #if C_USE_MCU_STM32F4xx  /* Ethernet configuration --------------------------------------*/ Ethernet_Initial(); while(1) {    Ethernet_Handler();     } #endif  /*end C_USE_MCU_STM32F4xx */ } /** @param  netif: the network interface//网络接口*/ void Ethernet_Initial(void) {     /* config the Ethernet Reset Pin*///配置以太网复位引脚     Ethernet_Reset_Config();  /* config the Ethernet Link interrupt*///配置以太网链路中断     Ethernet_Config();     /* Initilaize the LwIP stack */ //初始化LwIP堆栈     lwip_init();     //netif_remove(&gnetif);     /* Configure the Network interface */ //配置网络接口     Netif_Config();     /* Notify user about the network interface config *///通知用户有关网络接口配置     User_notification(&gnetif);     /*Connects to the TCP echo server*///连接到TCP echo服务器     tcp_echoclient_connect(); } void Ethernet_Reset_Config(void) {   GPIO_Set_Mode(ETHERNET_RST_CTRL_PORT,ETHERNET_RST_CTRL_PIN,GPIO_MODE_OUTPUT_PP, GPIO_NOPULL);  //PA4     GPIO_RESET(ETHERNET_RST_CTRL_PORT, ETHERNET_RST_CTRL_PIN);     delay_cycles_ms(1);     GPIO_SET(ETHERNET_RST_CTRL_PORT, ETHERNET_RST_CTRL_PIN);     delay_cycles_ms(10); } void Ethernet_Config(void) {     //congig the ETH_INT 需要配置,断网自动联网机制     GPIO_InitTypeDef GPIO_InitStructure;     /* Enable PX.x to IT mode: Ethernet Link interrupt */     ETHERNET_MII_INT_CLK_ENABLE();     GPIO_InitStructure.Pin = ETHERNET_MII_INT_PIN;     GPIO_InitStructure.Mode = GPIO_MODE_IT_FALLING;     GPIO_InitStructure.Pull = GPIO_NOPULL ;     HAL_GPIO_Init(ETHERNET_MII_INT_PORT, &GPIO_InitStructure);      //PB9  /* Enable EXTI Line interrupt for ETH MII pin */     HAL_NVIC_SetPriority(ETHERNET_MII_INT_IRQ , 0x5, 0x0);     HAL_NVIC_EnableIRQ(ETHERNET_MII_INT_IRQ); } void lwip_init(void) {   stats_init();   mem_init();//将堆归零并初始化start,end和free-free   memp_init();//将memp_memory划分为每个池类型的链接列表。   pbuf_init();//初始化pbuf模块   netif_init();// 网络接口 netif   udp_init();//清除UDP PCB列表。   tcp_init();//清除TCP PCB列表并清除一些内部定时器。注:在这个初始化函数之后,你必须按预先确定的每个周期内调用       tcp_fasttmr() 和 tcp_slowtmr()函数。   sys_timeouts_init();//初始化lwip超时时间限制 } void Netif_Config(void) {     struct ip_addr ipaddr;     struct ip_addr netmask;     struct ip_addr gw;     uint8_t temp_addr[4]; //自动获取IP     if(g_Config.Ethernet.DHCP[0] == 0x01)     {         ipaddr.addr = 0;         netmask.addr = 0;         gw.addr = 0;     }else{         //IP4_ADDR(&ipaddr, IP_ADDR0, IP_ADDR1, IP_ADDR2, IP_ADDR3);         if(F_Conver_IP_Addr(g_Config.Ethernet.LocalIP, temp_addr))         {             IP4_ADDR(&ipaddr, temp_addr[0], temp_addr[1], temp_addr[2], temp_addr[3]);         }else{//格式错误使用默认参数             IP4_ADDR(&ipaddr, IP_ADDR0, IP_ADDR1, IP_ADDR2, IP_ADDR3);         }         //IP4_ADDR(&netmask, NETMASK_ADDR0, NETMASK_ADDR1 , NETMASK_ADDR2, NETMASK_ADDR3);         if(F_Conver_IP_Addr(g_Config.Ethernet.NetMask, temp_addr))         {             IP4_ADDR(&netmask, temp_addr[0], temp_addr[1], temp_addr[2], temp_addr[3]);         }else{//格式错误使用默认参数             IP4_ADDR(&netmask, NETMASK_ADDR0, NETMASK_ADDR1, NETMASK_ADDR2, NETMASK_ADDR3);         }         //IP4_ADDR(&gw, GW_ADDR0, GW_ADDR1, GW_ADDR2, GW_ADDR3);         if(F_Conver_IP_Addr(g_Config.Ethernet.GateWay, temp_addr))         {             IP4_ADDR(&gw, temp_addr[0], temp_addr[1], temp_addr[2], temp_addr[3]);         }else{//格式错误使用默认参数             IP4_ADDR(&gw, GW_ADDR0, GW_ADDR1, GW_ADDR2, GW_ADDR3);         }     }     /* Add the network interface */     netif_add(&gnetif, &ipaddr, &netmask, &gw, NULL, ðernetif_init, ðernet_input);     /* Registers the default network interface */     netif_set_default(&gnetif);//注册默认网络接口     if (netif_is_link_up(&gnetif))     {         /*  Creates a new DHCP client for this interface on the first call.         Note: you must call dhcp_fine_tmr() and dhcp_coarse_tmr() at         the predefined regular intervals after starting the client.         You can peek in the netif->dhcp struct for the actual DHCP status.*/         if(g_Config.Ethernet.DHCP[0] == 0x01)         {            dhcp_start(&gnetif);          }         /* When the netif is fully configured this function must be called */         netif_set_up(&gnetif);     }     else     {         /* When the netif link is down this function must be called */         netif_set_down(&gnetif);     }     /* Set the link callback function, this function is called on change of link status */     netif_set_link_callback(&gnetif, ethernetif_update_config); } void tcp_echoclient_connect(void) {     struct ip_addr DestIPaddr;     uint8_t temp_addr[4];     if(echoclient_pcb != NULL)     {//只创建一个TCP Client         tcp_echoclient_connection_close(echoclient_pcb, echoclient_es);         tcp_pcb_remove(&tcp_active_pcbs, echoclient_pcb);         memp_free(MEMP_TCP_PCB, echoclient_pcb);         echoclient_pcb = NULL;         echoclient_es = NULL;     }     echoclient_pcb = tcp_new();     if (echoclient_pcb != NULL)     {//new an echoclient_pcb Success         //IP4_ADDR( &DestIPaddr, DEST_IP_ADDR0, DEST_IP_ADDR1, DEST_IP_ADDR2, DEST_IP_ADDR3 );         if(F_Conver_IP_Addr(g_Config.Net.Server1_IP, temp_addr))         {             IP4_ADDR(&DestIPaddr, temp_addr[0], temp_addr[1], temp_addr[2], temp_addr[3]);         }else{//格式错误使用默认参数             IP4_ADDR(&DestIPaddr, DEST_IP_ADDR0, DEST_IP_ADDR1, DEST_IP_ADDR2, DEST_IP_ADDR3);         }         /* connect to destination address/port */         //tcp_connect(echoclient_pcb,&DestIPaddr,DEST_PORT,tcp_echoclient_connected);         tcp_connect(echoclient_pcb, &DestIPaddr,(uint16_t)F_Conver_PORT_Addr(g_Config.Net.Server1_Port),                     tcp_echoclient_connected);     }     else     {//new an echoclient_pcb fail         /* deallocate the pcb */         memp_free(MEMP_TCP_PCB, echoclient_pcb);     } } void Ethernet_Handler(void) {     /* Check TCP Connect */     Check_TCP_Client_Connect();//检查客户端是否与服务器相连     /* Read a received packet from the Ethernet buffers and send it     to the lwIP for handling */ //从以太网缓冲区读取接收到的数据包并发送到lwIP进行处理     ethernetif_input(&gnetif);     /* Handle timeouts *///超时处理     sys_check_timeouts();     //LwIP定时处理任务(心跳、收发)     LwIP_Periodic_Handle(Ethernet_LocalTime); } struct tcp_pcb *Check_TCP_Client_Connect(void) {//检查客户端是否与服务器相连     struct tcp_pcb *cpcb = NULL;     err_t err;     cpcb = tcp_active_pcbs;     if(cpcb != NULL)//     {//设备连接成功         g_TCPLinkClient_Timeout = 300;         if( g_TCPLinkCheck_Cnt == 0 )         {//超时未收到数据             tcp_echoclient_connect();//重新连接             g_TCPLinkCheck_Cnt = 100;             //g_TCPLinkCheck_Cnt = g_EthTcp_Proto.HeartInterval_Set+60;   //断网检测时间         }else{         }         return cpcb;     }else{//连接断开或者未连接         //-----------------------------------------         if((g_TCPLinkConnect_flag == 0) && (g_TCPLinkCheck_Cnt == 0))         {             tcp_echoclient_connect();//重新连接             g_TCPLinkCheck_Cnt = 20;//60;         }else if(g_TCPLinkConnect_flag == 1) {             /* send data */             //通过发送一组数据来侦测remote 是否断开             //sprintf((char*)data, "message %d", (int)message_count);             sprintf((char*)data, "");             err = tcp_write(cpcb, data, strlen((char*)data), TCP_WRITE_FLAG_MORE);//ecoh 数据             if(err == ERR_OK)             {//server 意外断开,而client 没有侦测到,重新连接                 g_TCPLinkCheck_Cnt = 5;                 g_TCPLinkConnect_flag = 0;             }             else             {//server 意外断开,重新连接                 g_TCPLinkCheck_Cnt = 15;                 g_TCPLinkConnect_flag = 0;             }         }         return cpcb;     } } /**   * @brief This function should be called when a packet is ready to be read   * from the interface. It uses the function low_level_input() that   * should handle the actual reception of bytes from the network   * interface. Then the type of the received packet is determined and   * the appropriate input function is called. 当数据包准备好被读取时,应调用此函数    *来自界面。 它使用函数low_level_input()    *应该处理来自网络的实际字节接收    *界面。 然后确定接收分组的类型    *调用适当的输入函数。   *   * @param netif the lwip network interface structure for this ethernetif   */ void ethernetif_input(struct netif *netif) {   err_t err;   struct pbuf *p;   /* move received packet into a new pbuf */ / *将收到的数据包移动到新的pbuf * /   p = low_level_input(netif);   /* no packet could be read, silently ignore this *// *无法读取数据包,默默忽略此* /   if (p == NULL) return;   /* entry point to the LwIP stack */ / * LwIP堆栈的入口点* /   err = netif->input(p, netif);   if (err != ERR_OK)//输入错误   {     LWIP_DEBUGF(NETIF_DEBUG, ("ethernetif_input: IP input error "));     pbuf_free(p);     p = NULL;   } } / ** * @brief LwIP定期任务 * @param localtime当前的LocalTime值 * @retval没有 * / void LwIP_Periodic_Handle(__ IO uint32_t localtime) {     / *每250毫秒TCP周期性过程* /     if(localtime - TCPTimer> = TCP_TMR_INTERVAL)     {         TCPTimer = localtime;         tcp_tmr();     }     / *每5秒ARP周期进程* /     if((localtime - ARPTimer)> = ARP_TMR_INTERVAL)     {         ARPTimer = localtime;         etharp_tmr();     }     if(g_Config.Ethernet.DHCP [0] == 0x01)     {         / *每500ms精细DHCP定期进程* /         if(localtime - DHCPfineTimer> = DHCP_FINE_TIMER_MSECS)         {             DHCPfineTimer = localtime;             dhcp_fine_tmr();             if((DHCP_state!= DHCP_ADDRESS_ASSIGNED)&&(DHCP_state!= DHCP_TIMEOUT))             {                 / *切换LED1以指示DHCP正在进行的过程* /                 // STM_EVAL_LEDToggle(LED1);                 / *进程DHCP状态机* /                 LwIP_DHCP_Process_Handle();             }         }         / * DHCP每60秒进行一次粗略周期过程* /         if(localtime - DHCPcoarseTimer> = DHCP_COARSE_TIMER_MSECS)         {             DHCPcoarseTimer = localtime;             dhcp_coarse_tmr();         }     }