涉及 lwip 库文件及 ZYNQ 配置相关可参考以下文章:
【ZYNQ】裸机 PS + PL 双网口实现之 LWIP 库文件修改
【ZYNQ】裸机 PS + PL 双网口实现之 ZYNQ 配置
工程配置
- 启动 SDK ,创建模板工程,配置 BSP。
- 勾选 lwip141 库。
- 对 lwip 做如下配置,如没有此选项请先参考【ZYNQ】裸机 PS + PL 双网口实现之 lwip 库文件修改。
将 use_axieth_on_zynq 和 use_emaclite_on_zynq 设为 0。将 use_gmii2rgmii_core_on_eth1 设置为 true,GMII to RGMII IP 核对应的 PHY 地址为 8,即 gmii2rgmii_core_address_on_eth1 设为 8。ETH0 不使用 EMIO,因此 use_gmii2rgmii_core_on_eth0 为 false,gmii2rgmii_core_address_on_eth0 无需进行设置。
程序设计
- 添加定时器,用来调用 tcp 服务,其中,250ms 和 500ms 是必须的。相关代码如下:
- main.c
/** * Copyright (c) 2022-2023,HelloAlpha * * Change Logs: * Date Author Notes */ #include "platform_config.h" #include "service/timer/app_timer.h" #define USING_ULOG #include "ulog.h" #define _EXPORT_FUNC(function) \ do \ { \ extern int function(void); \ function(); \ } while (0) int lwip_tcp_init(void); int app_timer_init(void); int func_doing_always(void) { static timer_flag_t *_timer_flag = &g_timer_flag; #ifdef USING_ETHERNET_TCP _EXPORT_FUNC(tcp_func_always); #endif if(_timer_flag->timer_flag_250ms == 1) { _timer_flag->timer_flag_250ms = 0; #ifdef USING_ETHERNET_TCP _EXPORT_FUNC(tcp_func_per_250ms); #endif } if(_timer_flag->timer_flag_500ms) { _timer_flag->timer_flag_500ms = 0; #ifdef USING_ETHERNET_TCP _EXPORT_FUNC(tcp_func_per_500ms); #endif } if(_timer_flag->timer_flag_1s == 1) { _timer_flag->timer_flag_1s = 0; #ifdef USING_ETHERNET_TCP _EXPORT_FUNC(tcp_func_per_1s); #endif } return 0; } int main(void) { ULOG("\r\n------ Main Function Running ------\r\n"); app_timer_init(); #ifdef USING_ETHERNET_TCP _EXPORT_FUNC(lwip_tcp_init); #endif while(1) { func_doing_always(); } return 0; }
- 基于 LWIP 创建网卡,这里配置为静态 IP,代码如下:
- lwip_tcp.c
/** * Copyright (c) 2022-2023,HelloAlpha * * Change Logs: * Date Author Notes */ #include "tcp_config.h" #ifdef USING_ETHERNET_TCP #include "lwip/init.h" #include "lwip/err.h" #include "netif/xadapter.h" #define USING_ULOG #include "ulog.h" err_t accept_callback(void *arg, struct tcp_pcb *newpcb, err_t err); static void print_ip(char *msg, struct ip_addr *ip) { kprintf(msg); kprintf("%d.%d.%d.%d\r\n", ip4_addr1(ip), ip4_addr2(ip), ip4_addr3(ip), ip4_addr4(ip)); } void tcp_node_printf(char *tcp_node_name, tcp_node_t *tcp_node) { kprintf("------------- %s -------------\r\n", tcp_node_name); print_ip("local addr: ", &(tcp_node->local_addr)); kprintf("local port: %d \r\n" ,tcp_node->local_port); print_ip("target addr: ", &(tcp_node->target_addr)); kprintf("remote port: %d \r\n", tcp_node->remote_port); kprintf("-------------------------------------\r\n"); } static void print_app_header() { kprintf("\n\r----- lwIP TCP ------\r\n"); } /** * @brief * * @return err_t */ err_t start_tcp_application(tcp_node_t *tcp_node) { err_t err; if(!tcp_node) { ULOG("TCP node is empty!\r\n"); return ERR_ARG; } /* create pcb */ tcp_node->pcb_obj = tcp_new(); if (!tcp_node->pcb_obj) { ULOG("Error creating PCB. Out of Memory!\r\n"); return ERR_MEM; } /* bind to specified @port */ err = tcp_bind(tcp_node->pcb_obj, &(tcp_node->local_addr), tcp_node->local_port); if (err != ERR_OK) { ULOG("Unable to bind to port %d: err = %d!\r\n", tcp_node->local_port, err); return ERR_ABRT; } /* we do not need any arguments to callback functions */ tcp_arg(tcp_node->pcb_obj, NULL); /* listen for connections */ tcp_node->pcb_obj = tcp_listen(tcp_node->pcb_obj); if (!tcp_node->pcb_obj) { ULOG("Out of memory while tcp_listen!\r\n"); return ERR_MEM; } /* specify callback to use for incoming connections */ tcp_accept(tcp_node->pcb_obj, accept_callback); return err; } #ifdef USING_ETHERNET0 static int ethernet0_init(void) { err_t err; struct netif *echo_netif0 = &server_netif0; struct ip_addr ipaddr0, netmask0, gw0; /* the mac address of the board. this should be unique per board */ unsigned char mac_ethernet_address0[] = { 0x00, 0x0a, 0x35, 0x00, 0x01, 0x02 }; /* initliaze IP addresses to be used */ IP4_ADDR(&ipaddr0, 192, 168, 6, 10); IP4_ADDR(&netmask0, 255, 255, 255, 0); IP4_ADDR(&gw0, 192, 168, 1, 1); /* Add network interface to the netif_list, and set it as default */ if (!xemac_add(echo_netif0, &ipaddr0, &netmask0, &gw0, mac_ethernet_address0, PLATFORM_EMAC_BASEADDR)) { kprintf("ENET0 Error adding N/W interface!\r\n"); return -1; } netif_set_default(echo_netif0); /* specify that the network if is up */ netif_set_up(echo_netif0); /* initialize TCP0 node */ tcp_node_t *tcp0_node = &g_tcp0_node; /* local IP */ tcp0_node->local_addr.addr = ipaddr0.addr; /* local port */ tcp0_node->local_port = DEFAULT_PORT0; /* target IP */ IP4_ADDR(&(tcp0_node->target_addr), 192,168,6,81); /* target port */ tcp0_node->remote_port = 8080; /* clear the connection flag */ tcp0_node->connected_flag = 0; /* start the application */ err = start_tcp_application(tcp0_node); if(err != ERR_OK) { kprintf("Start TCP0 application failed!\r\n"); return -1; } else { tcp_node_printf("TCP0 Node", tcp0_node); } return 0; } #endif #ifdef USING_ETHERNET1 static int ethernet1_init(void) { err_t err; struct netif *echo_netif1 = &server_netif1; struct ip_addr ipaddr1, netmask1, gw1; /* the mac address of the board. this should be unique per board */ unsigned char mac_ethernet_address1[] = { 0x00, 0x0a, 0x35, 0x00, 0x01, 0x03 }; /* initliaze IP addresses to be used */ IP4_ADDR(&ipaddr1, 192, 168, 6, 20); IP4_ADDR(&netmask1, 255, 255, 255, 0); IP4_ADDR(&gw1, 192, 168, 1, 1); if (!xemac_add(echo_netif1, &ipaddr1, &netmask1, &gw1, mac_ethernet_address1, PLATFORM_EMAC1_BASEADDR)) { kprintf("ENET1 Error adding N/W interface!\r\n"); return -1; } netif_set_default(echo_netif1); /* specify that the network if is up */ netif_set_up(echo_netif1); /* initialize TCP1 node */ tcp_node_t *tcp1_node = &g_tcp1_node; /* local IP */ tcp1_node->local_addr.addr = ipaddr1.addr; /* local port */ tcp1_node->local_port = DEFAULT_PORT1; /* target IP */ IP4_ADDR(&(tcp1_node->target_addr), 192,168,6,81); /* target port */ tcp1_node->remote_port = 8081; /* clear the connection flag */ tcp1_node->connected_flag = 0; /* start the application */ err = start_tcp_application(tcp1_node); if(err != ERR_OK) { kprintf("Start TCP1 application failed!\r\n"); return -1; } else { tcp_node_printf("TCP1 Node", tcp1_node); } return 0; } #endif int lwip_tcp_init(void) { print_app_header(); lwip_init(); #ifdef USING_ETHERNET0 ethernet0_init(); #endif #ifdef USING_ETHERNET1 ethernet1_init(); #endif return 0; } #endif
- tcp_service.c 主要实现一些功能服务。
- tcp_service.c
/** * Copyright (c) 2022-2023,HelloAlpha * * Change Logs: * Date Author Notes */ #include "tcp_config.h" #ifdef USING_ETHERNET_TCP #include "lwip/err.h" #include <string.h> #define USING_ULOG #include "ulog.h" #ifdef USING_ETHERNET0 static tcp_node_t *tcp0_node = &g_tcp0_node; #endif #ifdef USING_ETHERNET1 static tcp_node_t *tcp1_node = &g_tcp1_node; #endif /** * @brief TCP data sending function * * @return err_t */ err_t tcp_transfer_data(struct tcp_pcb *tpcb, const uint8_t *pData, int plen) { err_t err; static struct pbuf *tcp_pbuf = NULL; static int tcp_len = 0; /* If parameter length bigger than tcp_len, reallocate memory space */ if(plen > tcp_len) { if(tcp_pbuf) { /* free pbuf */ pbuf_free(tcp_pbuf); } tcp_len = plen; /* allocate memory space to pbuf */ tcp_pbuf = pbuf_alloc(PBUF_TRANSPORT, tcp_len, PBUF_RAM); if(!tcp_pbuf) { ULOG("pbuf_alloc %d fail!\r\n", tcp_len); tcp_len = 0; return ERR_BUF; } } /* copy data to pbuf payload */ memcpy(tcp_pbuf->payload, pData, plen); tcp_pbuf->len = plen; tcp_pbuf->tot_len = plen; /* Start to send udp data */ err = tcp_write(tpcb, (tcp_pbuf->payload), (tcp_pbuf->len), TCP_WRITE_FLAG_COPY | TCP_WRITE_FLAG_MORE); if (err != ERR_OK) { ULOG("Error on tcp_write: %d!\r\n", err); return err; } err = tcp_output(tpcb); if (err != ERR_OK) { ULOG("Error on tcp_output: %d!\r\n", err); return err; } return err; } /** * @brief TCP data sending function * * @return err_t */ err_t tcp_send(tcp_node_t *tcp_node, tcp_msg_t *tcp_msg) { err_t err; if(!tcp_node) { ULOG("Empty TCP node!\r\n"); return ERR_ARG; } else if(!tcp_msg) { ULOG("Empty TCP message!\r\n"); return ERR_ARG; } else if(!tcp_node->connected_flag) { ULOG("TCP%d is not currently connected!\r\n", (tcp_node->local_port == DEFAULT_PORT0) ? 0 : 1); tcp_msg->tx_vflag = 0; return ERR_CONN; } else if(!tcp_msg->tx_vflag) { ULOG("Flag indicates message is not ready!\r\n"); return ERR_ARG; } else { err = tcp_transfer_data(tcp_node->pcb_obj, (uint8_t *)tcp_msg->tx_pdata, tcp_msg->tx_plen); tcp_msg->tx_vflag = 0; } return err; } /** * @brief close the TCP connection * * @return int */ static int tcp_connection_close(struct tcp_pcb *tpcb) { tcp_close(tpcb); tcp_arg(tpcb, NULL); tcp_recv(tpcb, NULL); tcp_sent(tpcb, NULL); tcp_poll(tpcb, NULL, 0); tcp_err(tpcb, NULL); #ifdef USING_ETHERNET0 if(tpcb->local_port == DEFAULT_PORT0) { if(tcp0_node->connected_flag == 1) { /* reset the connection flag */ tcp0_node->connected_flag = 0; } } #endif #ifdef USING_ETHERNET1 if (tpcb->local_port == DEFAULT_PORT1) { if(tcp1_node->connected_flag == 1) { /* reset the connection flag */ tcp1_node->connected_flag = 0; } } #endif return ERR_OK; } /** * @brief TCP data receiving callback function * * @return err_t */ static err_t recv_callback(void *arg, struct tcp_pcb *tpcb, struct pbuf *p_rx, err_t err) { /* do not read the packet if we are not in ESTABLISHED state */ if (!p_rx) { tcp_connection_close(tpcb); return ERR_OK; } /* indicate that the packet has been received */ tcp_recved(tpcb, p_rx->len); /* the data is processed here. */ { #ifndef USING_TCP_LOOKBACK #ifdef USING_ETHERNET0 static tcp_msg_t *tcp0_msg = &g_tcp0_msg; if(tpcb->local_port == DEFAULT_PORT0) { if(!tcp0_msg->rx_vflag) { tcp0_msg->rx_pdata = tcp0_msg->rx_pdata_buf; memcpy(tcp0_msg->rx_pdata, (char *) p_rx->payload, p_rx->len); tcp0_msg->rx_plen = p_rx->len; tcp0_msg->rx_vflag = 1; } } #endif #ifdef USING_ETHERNET1 static tcp_msg_t *tcp1_msg = &g_tcp1_msg; if(tpcb->local_port == DEFAULT_PORT1) { if(!tcp1_msg->rx_vflag) { tcp1_msg->rx_pdata = tcp1_msg->rx_pdata_buf; memcpy(tcp1_msg->rx_pdata, (char *) p_rx->payload, p_rx->len); tcp1_msg->rx_plen = p_rx->len; tcp1_msg->rx_vflag = 1; } } #endif #else char TcpSend[] = "> LookBack Test Running... \r\n> Rec Data: "; tcp_transfer_data(tpcb, (uint8_t *)TcpSend, strlen(TcpSend)); /* echo back the payload */ /* in this case, we assume that the payload is < TCP_SND_BUF */ if (tcp_sndbuf(tpcb) > p_rx->len) { err = tcp_write(tpcb, p_rx->payload, p_rx->len, 1); } else { ULOG("No space in tcp_sndbuf...\n\r"); } #endif } /* free the received pbuf */ pbuf_free(p_rx); return ERR_OK; } /** * @brief TCP Callback function for successful TCP data sending * * @return err_t */ static err_t tcp_sent_callback(void *arg, struct tcp_pcb *tpcb, u16_t len) { #ifdef USING_ETHERNET0 static uint32_t tcp0_trans_cnt = 0; if(tpcb->local_port == DEFAULT_PORT0) { ULOG("TCP0 Send Success Count: %d \r\n", tcp0_trans_cnt++); } #endif #ifdef USING_ETHERNET1 static uint32_t tcp1_trans_cnt = 0; if (tpcb->local_port == DEFAULT_PORT1) { ULOG("TCP1 Send Success Count: %d \r\n", tcp1_trans_cnt++); } #endif return ERR_OK; } static err_t tcp_poll_callback(void *arg, struct tcp_pcb *tpcb) { /* it is executed every 500ms */ #ifdef USING_ETHERNET0 if(tpcb->local_port == DEFAULT_PORT0) { tcp0_node->connected_count++; } #endif #ifdef USING_ETHERNET1 if(tpcb->local_port == DEFAULT_PORT1) { tcp1_node->connected_count++; } #endif return ERR_OK; } static void tcp_err_callback(void *arg, err_t err) { LWIP_UNUSED_ARG(err); ULOG("TCP error: %x \r\n", (uint32_t)arg); if(NULL != arg) { } } /** * @brief When TCP is in LISTEN state, listen for a new connection * and execute this function * * @return err_t */ err_t accept_callback(void *arg, struct tcp_pcb *newpcb, err_t err) { static int connection = 1; /* set the receive callback for this connection */ tcp_recv(newpcb, recv_callback); /* set the sent callback for this connection */ tcp_sent(newpcb, tcp_sent_callback); tcp_poll(newpcb, tcp_poll_callback, 1); tcp_err(newpcb, tcp_err_callback); { ULOG("\r\n----- TCP Connection -----\r\n"); ULOG(" Local IP: %d.%d.%d.%d, Local Port: %d \r\n", (newpcb->local_ip.addr) & 0xff, (newpcb->local_ip.addr >> 8) & 0xff, (newpcb->local_ip.addr >> 16) & 0xff, (newpcb->local_ip.addr >> 24) & 0xff, newpcb->local_port); ULOG(" Remote IP: %d.%d.%d.%d, Remote Port: %d \r\n", (newpcb->remote_ip.addr) & 0xff, (newpcb->remote_ip.addr >> 8) & 0xff, (newpcb->remote_ip.addr >> 16) & 0xff, (newpcb->remote_ip.addr >> 24) & 0xff, newpcb->remote_port); #ifdef USING_ETHERNET0 if(newpcb->local_port == DEFAULT_PORT0) { if(tcp0_node->connected_flag == 0) { /* set the connection flag */ tcp0_node->connected_flag = 1; tcp0_node->pcb_obj = newpcb; } } #endif #ifdef USING_ETHERNET1 if (newpcb->local_port == DEFAULT_PORT1) { if(tcp1_node->connected_flag == 0) { /* set the connection flag */ tcp1_node->connected_flag = 1; tcp1_node->pcb_obj = newpcb; } } #endif } /* just use an integer number indicating the connection id as the callback argument */ tcp_arg(newpcb, (void*)(UINTPTR)connection); /* increment for subsequent accepted connections */ connection++; return ERR_OK; } #ifdef USING_TCP_STATUS #ifdef USING_ETHERNET0 static int tcp0_check_connect_status(void) { static uint32_t last_tcp0_count = 0; static uint8_t tcp0_status = 0; if(tcp0_node->connected_count > last_tcp0_count) { if(tcp0_status == 0) { tcp0_status = 1; ULOG("Tcp0 Connected!\r\n"); } if(tcp0_node->connected_count > 65530) { tcp0_node->connected_count = 1; } last_tcp0_count = tcp0_node->connected_count; } else { tcp0_node->connected_flag = 0; if(tcp0_status == 1) { tcp0_status = 0; ULOG("Tcp0 Disconnected!\r\n"); } } return 0; } #endif #ifdef USING_ETHERNET1 static int tcp1_check_connect_status(void) { static uint32_t last_tcp1_count = 0; static uint8_t tcp1_status = 0; if(tcp1_node->connected_count > last_tcp1_count) { if(tcp1_status == 0) { tcp1_status = 1; ULOG("Tcp1 Connected!\r\n"); } if(tcp1_node->connected_count > 65530) { tcp1_node->connected_count = 1; } last_tcp1_count = tcp1_node->connected_count; } else { tcp1_node->connected_flag = 0; if(tcp1_status == 1) { tcp1_status = 0; ULOG("Tcp1 Disconnected!\r\n"); } } return 0; } #endif /** * @brief Check TCP connect status * */ int tcp_check_connect_status(void) { #ifdef USING_ETHERNET0 tcp0_check_connect_status(); #endif #ifdef USING_ETHERNET1 tcp1_check_connect_status(); #endif return 0; } #endif #endif
- tcp_config.h 实现了一些定义及配置。
- tcp_config.h
/** * Copyright (c) 2022-2023,HelloAlpha * * Change Logs: * Date Author Notes */ #ifndef __TCP_CONFIG_H__ #define __TCP_CONFIG_H__ #include "xparameters.h" /** * TCP config begin * @{ */ #define USING_ETHERNET_TCP #if defined USING_ETHERNET_TCP #define USING_ETHERNET0 #define USING_ETHERNET1 #define USING_TCP_STATUS //#define USING_TCP_LOOKBACK //#define USING_TCP_PRINT_MSG //#define USING_TCP_TEST_CMD #endif #ifdef USING_ETHERNET0 #define PLATFORM_EMAC_BASEADDR XPAR_XEMACPS_0_BASEADDR #endif #ifdef USING_ETHERNET1 #define PLATFORM_EMAC1_BASEADDR XPAR_XEMACPS_1_BASEADDR #endif /**@}*/ #ifdef USING_ETHERNET_TCP #include "lwip/tcp.h" /* default IP port */ #define DEFAULT_PORT0 7 #define DEFAULT_PORT1 8 #define MAX_SEND_LEN 64 #define TCP_MSG_MSG_LEN 256 struct tcp_msg { char rx_pdata_buf[TCP_MSG_MSG_LEN]; char *rx_pdata; uint16_t rx_plen; uint8_t rx_vflag; char tx_pdata_buf[TCP_MSG_MSG_LEN]; char *tx_pdata; uint16_t tx_plen; uint8_t tx_vflag; }; typedef struct tcp_msg tcp_msg_t; struct tcp_node { struct tcp_pcb *pcb_obj; struct ip_addr local_addr; uint16_t local_port; struct ip_addr target_addr; uint16_t remote_port; uint8_t connected_flag; struct tcp_msg *msg; uint32_t connected_count; }; typedef struct tcp_node tcp_node_t; #ifdef USING_ETHERNET0 struct netif server_netif0; /* definition TCP node */ tcp_node_t g_tcp0_node; /* definition TCP message node*/ tcp_msg_t g_tcp0_msg; #endif #ifdef USING_ETHERNET1 struct netif server_netif1; /* definition TCP node */ tcp_node_t g_tcp1_node; /* definition TCP message node*/ tcp_msg_t g_tcp1_msg; #endif err_t tcp_transfer_data(struct tcp_pcb *tpcb, const uint8_t *pData, int plen); err_t tcp_send(tcp_node_t *tcp_node, tcp_msg_t *tcp_msg); void tcp_node_printf(char *tcp_node_name, tcp_node_t *tcp_node); int lwip_tcp_init(void); #endif #endif
- tcp_cmd.c 实现了 tcp 的功能调用等。
- tcp_cmd.c
/** * Copyright (c) 2022-2023,HelloAlpha * * Change Logs: * Date Author Notes */ #include "tcp_config.h" #ifdef USING_ETHERNET_TCP #include "netif/xadapter.h" #define USING_ULOG #include "ulog.h" /* defined by each RAW mode application */ void tcp_fasttmr(void); void tcp_slowtmr(void); #ifdef USING_TCP_STATUS int tcp_check_connect_status(void); #endif #ifdef USING_TCP_PRINT_MSG void tcp_print_msg(void) { #ifdef USING_ETHERNET0 static tcp_msg_t *tcp0_msg = &g_tcp0_msg; if(tcp0_msg->rx_vflag == 1) { kprintf("> Eth0 Rec: \r\n"); kprintf("> Data: %s\r\n", tcp0_msg->rx_pdata); kprintf("> Size: %d\r\n", tcp0_msg->rx_plen); tcp0_msg->rx_vflag = 0; } #endif #ifdef USING_ETHERNET1 static tcp_msg_t *tcp1_msg = &g_tcp1_msg; if(tcp1_msg->rx_vflag == 1) { kprintf("> Eth1 Rec: \r\n"); kprintf("> Data: %s\r\n", tcp1_msg->rx_pdata); kprintf("> Size: %d\r\n", tcp1_msg->rx_plen); tcp1_msg->rx_vflag = 0; } #endif } #endif #ifdef USING_TCP_TEST_CMD int tcp_test_cmd(void) { static uint16_t count = 0; static char tcp_buff[32]; count++; sprintf(tcp_buff, "Hello! TCP Count: %d \r\n", count); kprintf("size: %d data: %s", strlen(tcp_buff), tcp_buff); #ifdef USING_ETHERNET0 static tcp_node_t *tcp0_node = &g_tcp0_node; static tcp_msg_t *tcp0_msg = &g_tcp0_msg; if(tcp0_msg->tx_vflag == 0) { tcp0_msg->tx_pdata = tcp_buff; tcp0_msg->tx_plen = strlen(tcp_buff); tcp0_msg->tx_vflag = 1; kprintf("TCP0 tcp_send: %d \r\n", tcp_send(tcp0_node, tcp0_msg)); } #endif #ifdef USING_ETHERNET1 static tcp_node_t *tcp1_node = &g_tcp1_node; static tcp_msg_t *tcp1_msg = &g_tcp1_msg; if(tcp1_msg->tx_vflag == 0) { tcp1_msg->tx_pdata = tcp_buff; tcp1_msg->tx_plen = strlen(tcp_buff); tcp1_msg->tx_vflag = 1; kprintf("TCP1 tcp_send: %d \r\n", tcp_send(tcp1_node, tcp1_msg)); } #endif return 0; } #endif int tcp_func_per_250ms(void) { tcp_fasttmr(); return 0; } int tcp_func_per_500ms(void) { tcp_slowtmr(); return 0; } int tcp_func_per_1s(void) { #ifdef USING_TCP_STATUS tcp_check_connect_status(); #endif #ifdef USING_TCP_TEST_CMD tcp_test_cmd(); #endif return 0; } int tcp_func_always(void) { /* receive and process packets */ #ifdef USING_ETHERNET0 static struct netif *echo_netif0 = &server_netif0; xemacif_input(echo_netif0); #endif #ifdef USING_ETHERNET1 static struct netif *echo_netif1 = &server_netif1; xemacif_input(echo_netif1); #endif #ifdef USING_TCP_PRINT_MSG tcp_print_msg(); #endif return 0; } #endif
功能验证
- 创建网卡
- ping 指令测试
- 回环测试
tcp_config.h 中定义使用 tcp 回环测试
使用网络调试助手连接网络
进行回环测试
源码获取
相关代码也可以从此处获取 GitHub。