【正点原子FPGA连载】第三十一章基于lwip的echo server实验 摘自【正点原子】DFZU2EG

您所在的位置:网站首页 正点原子lcd白屏 【正点原子FPGA连载】第三十一章基于lwip的echo server实验 摘自【正点原子】DFZU2EG

【正点原子FPGA连载】第三十一章基于lwip的echo server实验 摘自【正点原子】DFZU2EG

2023-03-23 05:49| 来源: 网络整理| 查看: 265

第三十一章基于lwip的echo server实验

随着物联网的兴起,万物互联需要一个强大而又灵活的协议体系,TCP/IP协议得天独厚,而在嵌入式网络设备中,由于硬件资源的限制,需要特殊的实现方式。LWIP作为TCP/IP协议的一种轻量级实现方式,满足了这一要求。本章我们利用VITIS软件自带的lwIP Echo Server例程模板,初步了解lwip的使用。本章包括以下几个部分: 3131.1简介 31.2实验任务 31.3硬件设计 31.4软件设计 31.5下载验证

31.1简介

1)TCP/IP协议简介 TCP/IP协议中文名为传输控制协议/因特网互联协议,又名网络通讯协议,是Internet最基本的协议、Internet国际互联网络的基础,由网络层的IP协议和传输层的TCP协议组成。TCP/IP定义了电子设备如何连入因特网,以及数据如何在它们之间传输的标准。协议采用了4层的层级结构,每一层都呼叫它的下一层所提供的协议来完成自己的需求。通俗而言:TCP负责发现传输的问题,一有问题就发出信号,要求重新传输,直到所有数据安全正确地传输到目的地。而IP是给因特网的每一台联网设备规定一个地址。 TCP/IP协议不是TCP和IP这两个协议的合称,而是指因特网整个TCP/IP协议族。从协议分层模型方面来讲,TCP/IP由四个层次组成:网络接口层、网络层、传输层、应用层。OSI(Open System Interconnection)是开放式系统互连参考模型,该模型将TCP/IP分为七层:物理层、数据链路层、网络层、传输层、会话层、表示层和应用层。TCP/IP模型与OSI模型对比如表32.1.1所示。 表32.1.1 OSI模型与TCP/IP模块 在这里插入图片描述

2)LWIP简介 LWIP是瑞典计算机科学院(SICS)的Adam Dunkels等开发的一个小型开源的TCP/IP协议栈,是TCP/IP的一种实现方式。LWIP是轻量级IP协议,有无操作系统的支持都可以运行。LWIP实现的重点是在保持TCP协议主要功能的基础上减少对 RAM的占用,它只需十几KB的RAM和40K左右的ROM就可以运行,这使LWIP协议栈适合在低端的嵌入式系统中使用。关于LWIP的详细信息大家可以去http://savannah.nongnu.org/projects/lwip/这个网站去查阅。 LWIP 的主要特性如下: •IGMP 协议,用于网络组管理,可以实现多播数据的接收 •Internet协议(IP),包括 IPv4 和 IPv6,支持 IP 分片与重装,包括通过多个网络接口的数据包转发 •用于网络维护和调试的Internet控制消息协议(ICMP) •用户数据报协议(UDP) •传输控制协议(TCP)拥塞控制,往返时间(RTT)估计,快速恢复和重传 •DNS,域名解析 •SNMP,简单网络管理协议 •动态主机配置协议(DHCP) •以太网地址解析协议(ARP) •AUTOIP,IP 地址自动配置 •PPP,点对点协议,支持 PPPoE 我们本次使用的lwip212_v1_1是一个基于开源lwIP库版本2.1.2构建的库(Vivado 2019.2版本)。lwip212_v1_1库为Ethernetlite(axi_ethernetlite)、TEMAC(axi_ethernet)以及千兆以太网控制器和MAC(GigE)内核提供适配器。该库可以在MicroBlaze、ARM Cortex-A9、ARM Cortex-A53和ARM Cortex-R5处理器上运行。Ethernetlite和TEMAC核心适用于MicroBlaze系统。千兆以太网控制器和MAC(GigE)内核仅适用于ARM Cortex-A9(MPSOC-7000处理器设备)、ARM Cortex-A53和ARM Cortex-R5系统(MPSOC UltraScale+ MPSoC)。 lwip212_v1_1提供二种用户编程接口方式:raw API和socket API。 Raw API:是为高性能和低内存开销而定制的。这种类型的API把网络协议栈和应用程序放在一个进程里,连接网络协议和应用程序的纽带是回调函数,回调函数实际上是一个普通的C函数。为了接收数据,应用程序会首先向协议栈注册一个回调函数,当关联的连接有一个信息到达时,该回调函数就被协议栈调用。这种实现方式即有优点也有缺点。优点是数据的接收和发送不会导致进程的切换,提供了最好的性能,执行速度快,而且消耗的内存资源少;缺点是应用程序无法进行连续运算,因为网络协议的处理和运算是在同一进程中完成的,二者无法并行发生。Raw API是资源较少的嵌入式系统的首选方法,也是在没有操作系统的情况下运行lwIP时唯一可用的API。 Socket API:提供了一个基于open-read-write-close 模块的BSD socket-style接口,需要操作系统。此接口在性能和内存要求方面不如Raw API高效,不适用于小型嵌入式系统,但移植性更好。 本章我们使用无需操作系统(standalone)的RAW API编程接口。 3)PS的千兆以太网控制器 在介绍PS的千兆以太网控制器之前,我们首先了解下MAC与PHY芯片及GMII与RGMII接口。 以太网卡工作在OSI模型的最后两层,物理层和数据链路层,物理层定义了数据传送与接收所需要的电与光信号、线路状态、时钟基准、数据编码和电路等,并向数据链路层设备提供标准接口。物理层的芯片称之为 PHY。此外PHY还提供了和对端设备连接的重要功能并通过LED灯显示出当前的连接的状态和工作状态。当我们给网卡接入网线的时候,PHY不断发出的脉冲信号检测到对端有设备,它们通过一套标准的语言交流,互相协商并确定连接速度、工作模式、是否采用流控等。通常情况下,协商的结果是两个设备中能同时支持的最大速度和最好的双工模式。这个技术被称为AutoNegotiation,即自协商。 数据链路层则提供寻址机构、数据帧的构建、数据差错检查、传送控制、向网络层提供标准的数据接口等功能。以太网卡中数据链路层的芯片称之为MAC控制器。 MAC控制器与PHY通过MII(Medium Independent Interface)接口进行连接。MII接口有很多类型,千兆以太网多使用GMII(Gigabit Medium Independent Interface)或RGMII(Reduced Gigabit Media Independent Interface)接口进行连接。 在这里插入图片描述

图 32.1.1 GMII接口 GMII接口提供了8位数据通道,125MHz的时钟速率,从而具有1000Mbps的数据传输速率。除MDC和MDIO外,有24根接口信号线,如图 32.1.1所示。 GMII接口主要包括四个部分。一是从MAC层到物理层(PHY)的发送数据接口,二是从物理层到MAC层的接收数据接口,三是从物理层到MAC层的状态指示信号,四是MAC 层和物理层之间传送控制和状态信息的MDIO接口。各部分接口信号说明见下表: 表32.1.2 GMII接口信号 在这里插入图片描述

RGMII接口即Reduced GMII,是GMII接口的简化版本。RGMII采用4位数据接口,工作时钟125MHz,并且在上升沿和下降沿同时传输数据,因此传输速率可达1000Mbps。采用 RGMII的目的是降低电路成本,使实现这种接口的器件的引脚数从24个减少到14个(不包括MDC和MDIO),接口信号如下图所示: 在这里插入图片描述

图 32.1.2 RGMII接口 可以看到RGMII接口相对于GMII 接口,在TXD和RXD上总共减少8根数据线。TX_CTL信号线上传送TX_EN和TX_ER两种信息,在TX_CLK的上升沿发送TX_EN,下降沿发送TX_ER;同样的,RX_CTL信号线上传送RX_DV和RX_ER两种信息,在RX_CLK的上升沿发送RX_DV,下降沿发送RX_ER。进一步减少了2根数据线。其他信号同GMII接口。 现在我们来看下PS的千兆以太网控制器(GEM)。PS的千兆以太网控制器实现了与IEEE 802.3-2008标准兼容的10/100/1000 Mb/s以太网MAC,在10/100Mb/s速度下,能够在半双工或全双工模式下运行,在1000Mb/s速度下全双工运行。PS配备四个千兆以太网控制器。每个控制器都可以独立配置,其内部原理图如下: 在这里插入图片描述

图 32.1.3 以太网控制器 DMA控制器通过AXI接口连接到存储器。MAC控制器与FIFO接口的连接为嵌入式处理系统中的分组数据存储提供scatter-gather类型的功能。另外从图 32.1.3中可以看到,如果通过MIO连接至PS端的以太网PHY芯片,则每个控制器使用RGMII接口以节省引脚。如果通过EMIO连接至PL端的以太网PHY芯片,则每个控制器使用GMII接口。 可以通过APB总线访问千兆以太网控制器的寄存器。寄存器用于配置MAC的功能、选择不同的操作模式、以及启用和监控网络管理统计信息。每个控制器为管理PHY芯片提供MDIO接口。

31.2实验任务

本章的实验任务是建立PS的以太网的硬件环境,使用VITIS软件自带的Lwip Echo Server模板了解LWIP的使用。

31.3硬件设计

MPSOC开发板上有一个PS端RJ45以太网接口,用于连接以太网线,其原理图如图 32.3.1所示: 在这里插入图片描述

图 32.3.1 RJ45接口原理图 以太网的数据传输离不开以太网PHY(物理层)芯片的支持。我们的MPSOC开发板上使用的PHY芯片为裕太车通公司的YT8521S,其部分原理图如图 32.3.2所示: 在这里插入图片描述

图 32.3.2 YT8521S原理图 YT8521S是高度集成的以太网收发器,符合10Base-T、100Base-TX和1000Base-T IEEE 802.3标准,提供了所有必要的物理层功能。YT8521S采用最先进的 DSP 技术和模拟前端(AFE),实现了交叉检测和自动校正、极性校正、自适应均衡、串音消除、回声消除、定时恢复和纠错等功能,以提供10Mbps、100Mbps或1000Mbps的强大传输和接收能力。 在图 32.3.2中,YT8521S右侧引脚连接到开发板的RJ45接口,左侧引脚通过RGMII接口与PS端相连接。MDC/MDIO接口用来配置YT8521S。其复位信号与PS的PS_POR_B相连接,在PS的上电复位时同时复位YT8521S,不需要通过MIO来控制。YT8521S与PS的MIO引脚的连接如下图所示,从中可以看到,YT8521S的RGMII接口通过MIO64-75引脚与PS相连接,MDC/MDIO连接到PS的MIO76-77引脚。 在这里插入图片描述

图 32.3.3 PHY芯片同PS接口连接 根据实验任务我们可以画出本次实验的系统框图,如下图所示: 在这里插入图片描述

图 32.3.4 系统框图 在图 32.3.4中,UART用于打印程序相关的信息,千兆以太网控制器GEM通过MIO与外部以太网进行连接。 step1:创建Vivado工程 本次实验的硬件设计可以在《第一章Hello World》实验的基础上进行。 1-1 我们先打开《第一章Hello World》实验的Vivado工程,打开后将工程另存为 “lwip_echo_server”工程,如下图所示,然后点击“OK”按钮。 在这里插入图片描述

图 32.3.5 另存为工程为lwip_echo step2:使用IP Integrator创建Processing System 2-1 在Flow Navigator中,点击IP INTEGRATOR下的Open Block Design,如下图所示: 在这里插入图片描述

图 32.3.6 打开Block Design 2-2 在打开的下图Diagram窗口,双击打开Zynq UltraScale+ MPSOC重定义窗口。 在这里插入图片描述

图 32.3.7 重定义Zynq UltraScale+ MPSOC 2-3 在打开的重定义窗口中,点击左侧的I/O Configuration,在右侧的界面中依次展开High Speed->GEM,勾选“GEM3”并选择“MIO64…75”,同时勾选“MDIO”并选择“MIO76…77”。这里选择“MIO64至MIO77”是为了和开发板硬件对应,如下图所示: 在这里插入图片描述

图 32.3.8 PS以太网接口配置界面 2-4 同样是在刚才界面中,依次展开Low Speed->TTC,勾选TTC0至TTC3,完成后,点击右下角的“OK”,如下图所示: 在这里插入图片描述

图 32.3.9配置三路定时器 2-5 由于不需要添加其它IP,点击Validate Design验证无误后,按Ctrl+S快捷键保存Diagram。此时我们的第二步完成,进入第三步。 step3:生成顶层HDL 在sources面板中,右键点击Block Design设计文件“design_1.bd”,然后执行“Generate Output Products”。因为我们在创建Hello World实验时创建顶层HDL Wrapper使用的是Let Vivado manage wrapper and auto-update选项,所以此处无需再创建顶层HDL Wrapper,Vivado会自动更新顶层HDL Wrapper step4:生成Bitstream文件并导出到VITIS 由于本实验未用到PL部分,所以无需生成Bitstream文件,只需导出到VITIS即可。如果使用到PL,则需要添加引脚约束以及对该系统进行综合、实现并生成Bitstream文件。 4-1 导出硬件。 在菜单栏中选择 File > Export > Export hardware,并在弹出的对话框中,取消勾选“Include bitstream”,直接点击“OK”按钮。将导出的design_1_wrapper.xsa文件放到vitis文件夹中。 4-2 硬件导出完成后,选择菜单Tools->Launch Vitis,启动VITIS开发环境。 31.4软件设计 step5:在VITIS中创建应用工程 5-1 在菜单栏中选择File->New->Application Project, 新建一个VITIS应用工程。 5-2 在弹出的下图所示界面中,输入工程名“lwip_echo_server”。点击“Next”,在接下来的平台(platform)界面中,点击“Create a new platform from hardware(XSA)”标签页,添加硬件平台文件。 在这里插入图片描述

图 32.4.1 创建工程 5-3 继续点击“Next”,在接下来的模板界面中(templates),选择“lwIP Echo Server”工程模版,然后点击“Finish”按钮,完成工程创建,如图 32.4.2所示。 lwIP Echo Server应用程序提供了如何使用轻量级IP堆栈(lwIP)的简单演示。此应用程序将MPSOC开发板MAC地址设置为00:0a:35:00:01:02,默认使用DHCP获取动态IP地址,如果DHCP失败,则使用默认设置的静态IPv4地址192.168.1.10或IPv6地址FE80:0:0:0:20​​A:35FF:FE00:102。服务器在端口7处侦听输入,并简单地回传发送到该端口的任何数据。 这里简单的介绍下DHCP。DHCP(Dynamic Host Configuration Protocol)即动态主机配置协议,通常应用在大型的局域网络环境中,主要作用是集中的管理、分配IP地址,使网络环境中的主机动态的获得IP地址、Gateway地址、DNS服务器地址等信息,并能够提升地址的使用率。 在这里插入图片描述

图 32.4.2 选择“lwIP Echo Server”模版 5-4 展开lwip_echo_server应用工程目录下的src目录,可以看到很多源文件,如图 32.4.4所示,其中大多是平台相关的文件(platform开头的文件)。下面我们简单的介绍下各文件的作用。 echo.c:Echo服务的的主要实现代码。 i2c_access.c:IIC访问PHY的功能实现,本实验不用。 iic_phyreset.c:IIC复位PHY,本实验不用。 main.c:main函数所在文件。 platform_config.h:平台配置相关文件,主要是宏定义所使用的平台。 我们打开“platform_config.h”文件,内容如下: 在这里插入图片描述

图 32.4.3 platform_config.h文件内容 可以看到宏定义了 PLATFORM_ZYNQMP,也就是说本实验是与ZYNQMP平台相关的。所以本实验需要的是platform_zynqmp.c文件,而以下的与其它平台相关的platform_mb.c、platform_ppc.c、platform_zynq.c、platform.c都无需使用。 platform_config.h是基于硬件设计生成的。 sfp.c和si5324.c分别用于sfp PHY和si5324芯片,用于官方特定的开发板,与我们使用的MPSOC开发板不相关。 在这里插入图片描述

图 32.4.4 src目录 5-5 为了方便分析,我们将src文件夹与本实验不相关的平台文件删除,删除后的src文件夹内容如下图所示: 在这里插入图片描述

图 32.4.5 删除不相关文件后的src文件夹内容 5-6 现在我们打开main.c文件,为了方便分析源代码,在main.c文件中将带有下图箭头所指的预编译指令删除。 在这里插入图片描述

图 32.4.6 删除不需要的预编译指令 删除不适用的预编译指令后的main.c代码如下:

1 #include 2 3 #include "xparameters.h" 4 5 #include "netif/xadapter.h" 6 7 #include "platform.h" 8 #include "platform_config.h" 9 #if defined (__arm__) || defined(__aarch64__) 10 #include "xil_printf.h" 11 #endif 12 13 #include "lwip/tcp.h" 14 #include "xil_cache.h" 15 16 #if LWIP_IPV6==1 17 #include "lwip/ip.h" 18 #else 19 #if LWIP_DHCP==1 20 #include "lwip/dhcp.h" 21 #endif 22 #endif 23 24 /* defined by each RAW mode application */ 25 void print_app_header(); 26 int start_application(); 27 int transfer_data(); 28 void tcp_fasttmr(void); 29 void tcp_slowtmr(void); 30 31 /* missing declaration in lwIP */ 32 void lwip_init(); 33 34 #if LWIP_IPV6==0 35 #if LWIP_DHCP==1 36 extern volatile int dhcp_timoutcntr; 37 err_t dhcp_start(struct netif *netif); 38 #endif 39 #endif 40 41 extern volatile int TcpFastTmrFlag; 42 extern volatile int TcpSlowTmrFlag; 43 static struct netif server_netif; 44 struct netif *echo_netif; 45 46 #if LWIP_IPV6==1 47 void print_ip6(char *msg, ip_addr_t *ip) 48 { 49 print(msg); 50 xil_printf(" %x:%x:%x:%x:%x:%x:%x:%x\n\r", 51 IP6_ADDR_BLOCK1(&ip->u_addr.ip6), 52 IP6_ADDR_BLOCK2(&ip->u_addr.ip6), 53 IP6_ADDR_BLOCK3(&ip->u_addr.ip6), 54 IP6_ADDR_BLOCK4(&ip->u_addr.ip6), 55 IP6_ADDR_BLOCK5(&ip->u_addr.ip6), 56 IP6_ADDR_BLOCK6(&ip->u_addr.ip6), 57 IP6_ADDR_BLOCK7(&ip->u_addr.ip6), 58 IP6_ADDR_BLOCK8(&ip->u_addr.ip6)); 59 60 } 61 #else 62 void 63 print_ip(char *msg, ip_addr_t *ip) 64 { 65 print(msg); 66 xil_printf("%d.%d.%d.%d\n\r", ip4_addr1(ip), ip4_addr2(ip), 67 ip4_addr3(ip), ip4_addr4(ip)); 68 } 69 70 void 71 print_ip_settings(ip_addr_t *ip, ip_addr_t *mask, ip_addr_t *gw) 72 { 73 74 print_ip("Board IP: ", ip); 75 print_ip("Netmask : ", mask); 76 print_ip("Gateway : ", gw); 77 } 78 #endif 79 80 int main() 81 { 82 #if LWIP_IPV6==0 83 ip_addr_t ipaddr, netmask, gw; 84 85 #endif 86 /* the mac address of the board. this should be unique per board */ 87 unsigned char mac_ethernet_address[] = 88 { 0x00, 0x0a, 0x35, 0x00, 0x01, 0x02 }; 89 90 echo_netif = &server_netif; 91 #if defined (__arm__) && !defined (ARMR5) 92 #if XPAR_GIGE_PCS_PMA_SGMII_CORE_PRESENT == 1 || XPAR_GIGE_PCS_PMA_1000BASEX_CORE_PRESENT == 1 93 ProgramSi5324(); 94 ProgramSfpPhy(); 95 #endif 96 #endif 97 98 /* Define this board specific macro in order perform PHY reset on ZCU102 */ 99 #ifdef XPS_BOARD_ZCU102 100 if(IicPhyReset()) { 101 xil_printf("Error performing PHY reset \n\r"); 102 return -1; 103 } 104 #endif 105 106 init_platform(); 107 108 #if LWIP_IPV6==0 109 #if LWIP_DHCP==1 110 ipaddr.addr = 0; 111 gw.addr = 0; 112 netmask.addr = 0; 113 #else 114 /* initialize IP addresses to be used */ 115 IP4_ADDR(&ipaddr, 192, 168, 1, 10); 116 IP4_ADDR(&netmask, 255, 255, 255, 0); 117 IP4_ADDR(&gw, 192, 168, 1, 1); 118 #endif 119 #endif 120 print_app_header(); 121 122 lwip_init(); 123 124 #if (LWIP_IPV6 == 0) 125 /* Add network interface to the netif_list, and set it as default */ 126 if (!xemac_add(echo_netif, &ipaddr, &netmask, 127 &gw, mac_ethernet_address, 128 PLATFORM_EMAC_BASEADDR)) { 129 xil_printf("Error adding N/W interface\n\r"); 130 return -1; 131 } 132 #else 133 /* Add network interface to the netif_list, and set it as default */ 134 if (!xemac_add(echo_netif, NULL, NULL, NULL, mac_ethernet_address, 135 PLATFORM_EMAC_BASEADDR)) { 136 xil_printf("Error adding N/W interface\n\r"); 137 return -1; 138 } 139 echo_netif->ip6_autoconfig_enabled = 1; 140 141 netif_create_ip6_linklocal_address(echo_netif, 1); 142 netif_ip6_addr_set_state(echo_netif, 0, IP6_ADDR_VALID); 143 144 print_ip6("\n\rBoard IPv6 address ", &echo_netif->ip6_addr[0].u_addr.ip6); 145 146 #endif 147 netif_set_default(echo_netif); 148 149 /* now enable interrupts */ 150 platform_enable_interrupts(); 151 152 /* specify that the network if is up */ 153 netif_set_up(echo_netif); 154 155 #if (LWIP_IPV6 == 0) 156 #if (LWIP_DHCP==1) 157 /* Create a new DHCP client for this interface. 158 * Note: you must call dhcp_fine_tmr() and dhcp_coarse_tmr() at 159 * the predefined regular intervals after starting the client. 160 */ 161 dhcp_start(echo_netif); 162 dhcp_timoutcntr = 24; 163 164 while(((echo_netif->ip_addr.addr) == 0) && (dhcp_timoutcntr > 0)) 165 xemacif_input(echo_netif); 166 167 if (dhcp_timoutcntr 169 xil_printf("DHCP Timeout\r\n"); 170 xil_printf("Configuring default IP of 192.168.1.10\r\n"); 171 IP4_ADDR(&(echo_netif->ip_addr), 192, 168, 1, 10); 172 IP4_ADDR(&(echo_netif->netmask), 255, 255, 255, 0); 173 IP4_ADDR(&(echo_netif->gw), 192, 168, 1, 1); 174 } 175 } 176 177 ipaddr.addr = echo_netif->ip_addr.addr; 178 gw.addr = echo_netif->gw.addr; 179 netmask.addr = echo_netif->netmask.addr; 180 #endif 181 182 print_ip_settings(&ipaddr, &netmask, &gw); 183 184 #endif 185 /* start the application (web server, rxtest, txtest, etc..) */ 186 start_application(); 187 188 /* receive and process packets */ 189 while (1) { 190 if (TcpFastTmrFlag) { 191 tcp_fasttmr(); 192 TcpFastTmrFlag = 0; 193 } 194 if (TcpSlowTmrFlag) { 195 tcp_slowtmr(); 196 TcpSlowTmrFlag = 0; 197 } 198 xemacif_input(echo_netif); 199 transfer_data(); 200 } 201 202 /* never reached */ 203 cleanup_platform(); 204 205 return 0; 206 }

可以看到代码中有很多的#if LWIP_IPV60和#if LWIP_DHCP1这类预编译指令,这是因为lwip既支持IPv4也支持IPv6,IPv4和DHCP默认支持。如果想重新配置lwip如取消DHCP,可以通过以下方式重配置lwip。 双击硬件平台工程“platform.spr”,在右侧打开的界面中点击psu_cortexa_53_0裸机开发下的板级支持包(Board Support Package),然后在板级支持包界面中选择“Modify BSP Settings”,如下图所示: 在这里插入图片描述

图 32.4.7 Board Support Package Settings 在弹出的界面中点击左侧standalone下的lwip211,右侧就是lwip的配置面板。如下图所示,箭头所指的两处分别是配置启用DHCP和使能IPv6,可以看到,dhcp默认为true,ipv6默认为false。 在这里插入图片描述

图 32.4.8 lwip的配置面板 main函数可以说是使用lwip的一个标准函数,可以在不修改main函数的情况下就可实现其它的应用功能。main函数主要完成以下功能: 1)在代码的88行设置MPSOC开发板的MAC地址为00:0a:35:00:01:02。 2)通过调用init_platform函数配置定时器和建立中断以初始化平台,定时器产生周期性中断。 3)调用lwip_init函数完成对lwip协议栈的初始化,代码第122行。 4)初始化lwIP后,使用xemac_add函数添加以太网MAC到协议栈中。 5)使用platform_enable_interrupts函数使能中断和启动定时器。 6)从代码第156~174行,启动DHCP服务获取动态IP地址,如果超时未获取到动态IP地址,则使用默认的静态IP设置: IP Address: 192.168.1.10 Netmask : 255.255.255.0 Gateway : 192.168.1.1 我们也可以根据需要修改代码第171~173行的值,从而使用不同的静态IP地址。 7)start_application函数是用户应用函数,当我们使用lwip实现不同的应用功能时,可以在保持main函数不变的情况下,修改start_application函数的实现即可。本实验的start_application函数在echo.c文件中定义,该函数创建了一个TCP服务并设定了对应该服务的回调函数。当一个TCP连接请求被接收时,回调函数对客户端发送来的数据原封不动的发送回去,从而实现echo服务器的功能。由于本实验的目的在于初步了解lwip的使用,对于涉及到的TCP协议的使用,我们将在下一章讲解,本实验我们不多做介绍。 8)程序进入while(1)循环执行数据包接收操作,以及它需要执行的任何其他特定于应用程序的操作。TcpFastTmrFlag和TcpSlowTmrFlag是TCP TX处理所必需的,定时器中断分别以250ms和500ms的周期来改变这两个标志位。数据包接收函数xemacif_input处理由中断处理程序接收的数据包,并将它们传递给lwIP,然后lwIP为每个接收到的数据包调用适当的回调处理程序。transfer_data函数无实际意义,可以删除。 5-7 程序修改完成后,按快捷键Ctrl+S保存main.c文件,右击应用工程名选择Build Project进行编译。编译完成后控制台(Console)中会出现提示信息“Build Finished”,同时在应用工程的Binaries目录下可以看到生成的elf文件。

31.5下载验证

首先将下载器与开发板上的JTAG接口连接,下载器另外一端与电脑连接。再使用USB连接线将USB_UART(开发板PS PORT)接口与电脑连接,用于串口通信。使用网线一端连接开发板的PS以太网接口(PS_ETH),另一端与电脑或路由器连接。最后连接开发板的电源,给开发板上电,如下图所示: 在这里插入图片描述

图 32.5.1 MPSOC开发板实物图 现在进入最后一步。 step6:板级验证 6-1打开Vitis Terminal终端,设置并连接串口。 6-2 下载程序。 6-3 可以看到串口打印的结果如下: 在这里插入图片描述

图 32.5.2 显示打印结果 在打印出“link speed for phy address 7: 1000”后要等一段时间进行DHCP服务。因为我们将开发板的以太网接口与电脑进行连接,所以出现了DHCP Timeout,开发板的IP地址为默认设置的静态IP地址192.168.1.10。如果和路由器进行连接,开发板的IP则是由DHCP获取的动态IP设置。TCP应答服务的端口号为7。另外需要说明的是串口打印的“TCP packets sent to port 6001 will be echoed back”可能是该模板最初版本使用的是6001端口,后面更新的时候使用了端口7,而该语句没有修改或删除,所以这是无意义的语句,可以找到print_app_header函数从而删除该语句。 在打印信息的第三行出现一个警告,这是因为lwip模板默认phy芯片是Marvell、TI或Realtek Ethernet这三家的,而我们开发板上使用的是其它厂家的,不影响正常工作,所以这个地方的警告忽略就可以了。 在使用静态IP地址时,需要确保同网段内没有主机使用192.168.1.10 的IP地址,否则会造成IP冲突。可以在开发板未上电前或未下载程序前在CMD里输入“ping 192.168.1.10”命令查看是否能ping通,如果能ping通,说明网络中有此IP地址,此时需要更改静态IP地址为其他值,如192.168.1.123等。 6-4 使用网络调试助手发送数据。在使用网络助手调试之前需要按照本章实验的步骤6-7设置网络适配器。设置完后在电脑端打开网络调试助手,设置协议类型为:TCP Client,服务器IP地址为串口打印的地址,此处为:192.168.1.10,服务器端口号为:7,然后点击连接,即可连上开发板的TCP Sever,如下图所示: 在这里插入图片描述

图 32.5.3 电脑端网络调试助手TCP Client测试界面 6-5 本实验除了可以使用网络调试助手软件外,还可以使用telnet。 我们打开电脑的CMD(按win+r键后输入cmd),输入“telnet 192.168.1.10 7”,如下图所示: 在这里插入图片描述

图 32.5.4 进行telnet连接 回车后,进入下图所示界面: 在这里插入图片描述

图 32.5.5 连接成功后的界面 如果回车后出现像下图所示界面所示“telnet不是内部或外部命令,也不是可运行的程序或批处理文件”,则表明未开启Windows的telnet客户端功能,开启方式见6-6。 在这里插入图片描述

图 32.5.6 未启用telnet客户端时的界面 此时我们按键盘上的字母和数字键,如123abc,控制台显示如下: 在这里插入图片描述

图 32.5.7 控制台显示 可以看到除了1只有一个外,其它字符都显示两个,一个是我们按下的,另一个是开发板的lwip echo server应答的。可见功能基本正确,不过从使用上看还是有问题的,一是第一次按下的字符没有回显;二是不能输入字符串,这些问题主要是windows自带的telnet的问题。如果使用第三方提供的telnet工具,例如使用Win10系统的读者可以开启WSL,从而使用linux系统提供的telnet功能进行连接,如下图(通过WSL使用Ubuntu系统): 在这里插入图片描述

图 32.5.8 功能完全正常 可以看到一点问题也没有。按“Ctrl+]”可以退出输入界面,然后输入“quit”即可退出telnet连接。 注:Telnet协议是TCP/IP协议族中的一员,是Internet远程登录服务的标准协议和主要方式。它为用户提供了在本地计算机上完成远程主机工作的能力。在终端使用者的电脑上使用telnet程序,用它连接到服务器。终端使用者可以在telnet程序中输入命令,这些命令会在服务器上运行,就像直接在服务器的控制台上输入一样。可以在本地就能控制服务器。 6-6 下面我们介绍一下如何开启Windows的telnet客户端功能。在Win10或Win7系统中,按“Win+r”快捷键后,在下图所示界面中输入“control”。 在这里插入图片描述

图 32.5.9 打开控制面板界面 进入下图所示控制面板界面,将查看方式设置为“类别”,单击“程序”下的“卸载程序”,如下图所示: 在这里插入图片描述

图 32.5.10 点击进入“程序和功能”界面 在弹出的界面中,单击“启用或关闭Windows功能”,如下图所示: 在这里插入图片描述

图 32.5.11 点击“启用或关闭Windows功能” 在弹出的“Windows功能”界面中,找到“Telnet Client”,并勾选,如下图所示: 在这里插入图片描述

图 32.5.12 勾选telnet client 单击确定后,如果出现“Windows需要重启电脑才能完成安装所请求的更改”字样,重新启动电脑即可,至此,Windows的telnet客户端服务已启用。 此时我们进行telnet连接会连接成功,但也有部分电脑会出现下图所示现象: 在这里插入图片描述

图 32.5.13 无法连接 出现这种情况是因为本地连接(Win10为以太网)设置有问题,需要重新设置。 6-7 更改适配器设置。在控制面板界面,单击“网络和Internet”下的“查看网络状态和任务”,如下图所示: 在这里插入图片描述

图 32.5.14 打开“查看网络和状态” 进入下图所示界面: 在这里插入图片描述

图 32.5.15 更改适配器设置 点击箭头所指的“更改适配器设置”,进入下图所示界面: 在这里插入图片描述

图 32.5.16 打开属性界面 点击“以太网”(或者本地连接,如果有)后出现“更改此连接的设置”,点击“更改此连接的设置”,进入“属性”界面,点击“Internet协议版本4(TCP/IPv4)”,如下图所示: 在这里插入图片描述

图 32.5.17 进入IPv4设置 进入下图所示界面后,按下图的设置进行修改。 在这里插入图片描述

图 32.5.18 设置IPv4 经过这些设置后,基本上就可以使用telnet了。 至此,本实验完成。



【本文地址】


今日新闻


推荐新闻


CopyRight 2018-2019 办公设备维修网 版权所有 豫ICP备15022753号-3