1)实验平台:正点原子领航者ZYNQ开发板
2)平台购买地址:https://item.taobao.com/item.htm?&id=606160108761
3)全套实验源码+手册+视频下载地址:http://www.openedv.com/thread-301505-1-1.html
4)对正点原子FPGA感兴趣的同学可以加群讨论:905624739 点击加入群聊:
5)关注正点原子公众号,获取最新资料更新
第三十一章 基于lwip的echo server实验
随着物联网的兴起,万物互联需要一个强大而又灵活的协议体系,TCP/IP协议得天独厚,而在嵌入式网络设备中,由于硬件资源的限制,需要特殊的实现方式。LWIP作为TCP/IP协议的一种轻量级实现方式,满足了这一要求。本章我们利用SDK软件自带的lwIP Echo Server例程模板,初步了解lwip的使用。本章包括以下几个部分: 1 1.1 简介 1.2 实验任务 1.3 硬件设计 1.4 软件设计 1.5 下载验证 1.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模型对比如表1.1.1所示。 表 33.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 地址自动配置 • PP,点对点协议,支持 PPPoE 我们本次使用的lwip202_v1_2是一个基于开源lwIP库版本2.0.2构建的SDK库(Vivado 2018.3版本)。lwip202_v1_2库为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(Zynq-7000处理器设备)、ARM Cortex-A53和ARM Cortex-R5系统(Zynq UltraScale+ MPSoC)。 lwip202_v1_2提供二种用户编程接口方式: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(MediumIndependent Interface)接口进行连接。MII接口有很多类型,千兆以太网多使用GMII(Gigabit Medium Independent Interface)或RGMII(Reduced Gigabit Media IndependentInterface)接口进行连接。
GMII接口提供了8位数据通道,125MHz的时钟速率,从而具有1000Mbps的数据传输速率。除MDC和MDIO外,有24根接口信号线,如图33.1.1所示。 GMII接口主要包括四个部分。一是从MAC层到物理层(PHY)的发送数据接口,二是从物理层到MAC层的接收数据接口,三是从物理层到MAC层的状态指示信号,四是MAC 层和物理层之间传送控制和状态信息的MDIO接口。各部分接口信号说明见下表: 表 33.1.2 GMII接口信号 RGMII接口即Reduced GMII,是GMII接口的简化版本。RGMII采用4位数据接口,工作时钟125MHz,并且在上升沿和下降沿同时传输数据,因此传输速率可达1000Mbps。采用 RGMII的目的是降低电路成本,使实现这种接口的器件的引脚数从24个减少到14个(不包括MDC和MDIO),接口信号如下图所示:
可以看到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的千兆以太网控制器实现了与IEEE802.3-2008标准兼容的10/100/1000 Mb/s以太网MAC,能够以上述三种速度在半双工或全双工模式下运行。PS配备两个千兆以太网控制器。每个控制器都可以独立配置,其内部原理图如下:
DMA控制器通过AHB总线接口连接到存储器。MAC控制器与FIFO接口的连接为嵌入式处理系统中的分组数据存储提供scatter-gather类型的功能。另外从图 33.1.3中可以看到,如果通过MIO连接至PS端的以太网PHY芯片,则每个控制器使用RGMII接口以节省引脚。如果通过EMIO连接至PL端的以太网PHY芯片,则每个控制器使用GMII接口。 可以通过APB总线访问千兆以太网控制器的寄存器。寄存器用于配置MAC的功能、选择不同的操作模式、以及启用和监控网络管理统计信息。控制器为管理PHY芯片提供MDIO接口,可以从MDIO接口控制PHY芯片。 1.2 实验任务本章的实验任务是建立PS的以太网的硬件环境,使用SDK软件自带的Lwip Echo Server模板了解LWIP的使用。 1.3 硬件设计领航者ZYNQ底板上有一个RJ45以太网接口,用于连接以太网线,其原理图如图 33.3.1所示:
以太网的数据传输离不开以太网PHY(物理层)芯片的支持。我们的领航者ZYNQ开发板上使用的PHY芯片为Realtek公司的RTL8211E,其原理图如图 33.3.2所示:
Realtek RTL8211E是高度集成的以太网收发器,符合 10Base-T、100Base-TX和1000Base-T IEEE 802.3标准,提供了所有必要的物理层功能。RTL8211E采用最先进的 DSP 技术和模拟前端(AFE),实现了交叉检测和自动校正、极性校正、自适应均衡、串音消除、回声消除、定时恢复和纠错等功能,以提供10Mbps、100Mbps或1000Mbps的强大传输和接收能力。 在图 33.3.2中,RTL8211E右侧引脚连接到底板的RJ45接口,左侧引脚通过RGMII接口与PS端相连接。MDC/MDIO接口用来配置RTL8211E。其复位信号与PS的PS_POR_B相连接,在PS的上电复位时同时复位RTL8211E,不需要通过MIO来控制。RTL8211E与PS的MIO引脚的连接如图 33.3.3所示。从图 33.3.3可以看到,RTL8211E的RGMII接口通过MIO16-27引脚与PS相连接,MDC/MDIO连接到PS的MIO52-53引脚。
根据实验任务我们可以画出本次实验的系统框图,如下图所示:
在图 33.3.4中,UART用于打印程序相关的信息,千兆以太网控制器和MAC(GigE)内核通过MIO与外部以太网进行连接。 step1:创建Vivado工程 本次实验的硬件设计可以在《第一章 Hello World》实验的基础上进行。 1-1 我们先打开《第一章Hello World》实验的Vivado工程,打开后将工程另存为“lwip_echo_server”工程,如下图所示,然后点击“OK”按钮。
step2:使用IP Integrator创建Processing System 2-1 在Flow Navigator中,点击IP INTEGRATOR下的Open Block Design,如下图所示: 2-2 在打开的下图Diagram窗口,双击打开ZYNQ7 Processing System重定义窗口。
图33.3.7 重定义ZYNQ7 Processing System 2-3 在打开的重定义窗口中,点击左侧的MIO Configuration,在右侧的界面中展开“I/O Peripherals”。勾选“ENET 0”和其下的“MDIO”,在“IO”列选择ENET 0的IO为MIO16…27,MDIO的IO为MIO52…53。因为MIO的Bank1即原理图中的BANK501为1.8V,所以我们选择Bank1 I/O Voltage为LVCOMS 1.8V。另外设置Speed列的速度为“fast”,如下图所示,完成后,点击右下角的“OK”。
2-4 由于不需要添加其它IP,按Ctrl+S快捷键保存Diagram。此时我们的第二步完成,进入第三步 step3:生成顶层HDL 在sources面板中,右键点击Block Design设计文件“system.bd”,然后依次执行“Generate Output Products”和“Create HDLWrapper”。 step4:生成Bitstream文件并导出到SDK 由于本实验未用到PL部分,所以无需生成Bitstream文件,只需导出到SDK即可。如果使用到PL,则需要添加引脚约束以及对该系统进行综合、实现并生成Bitstream文件。 4-1 导出硬件。 在菜单栏中选择 File> Export > Export hardware。 并在弹出的对话框中,取消勾选“Includebitstream”,直接点击“OK”按钮。 因为是在前一工程的基础上建立的,还保留着前一工程的结果,所以会弹出“Module Already Exported”对话框,我们点击“Yes”按钮。 4-2 硬件导出完成后,选择菜单File->Launch SDK,启动SDK开发环境。 1.4 软件设计首先删除前一实验的工程。下面我们开始第五步——创建应用工程。 step5:在SDK中创建应用工程 5-1 在菜单栏中选择File->New->Application Project, 新建一个SDK应用工程。 5-2 在弹出的图 33.4.1所示界面中,输入工程名“lwip_echo_server”。 在该页面中,我们需要确认HardwarePlatform一栏中选择的是本次实验所导出的硬件平台system_wrapper_hw_platform_1。另外,为了方便以后能在此工程的基础上创建其他工程,我们将创建的BSP工程名称修改为一个不与应用工程相关的名称,此处修改“Create New”后面的方框内容为“lwip _server_bsp”,其它选项保持默认,点击“Next”。
5-3 选择“lwIP Echo Server”工程模版,然后点击“Finish”按钮,如图 33.4.2所示。 lwIP Echo Server应用程序提供了如何使用轻量级IP堆栈(lwIP)的简单演示。此应用程序将领航者开发板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服务器地址等信息,并能够提升地址的使用率。
图 33.4.2 选择“lwIP Echo Server”模版 5-4 展开lwip_echo_server应用工程目录下的src目录,可以看到很多源文件,如图33.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”文件,内容如下:
图33.4.3 platform_config.h文件内容 可以看到宏定义了 PLATFORM_ZYNQ,也就是说本实验是与ZYNQ平台相关的。所以本实验需要的是platform_zynq.c文件,而以下的与其它平台相关的platform_mb.c、platform_ppc.c、platform_zynqmp.c、platform.c都无需使用。 platform_config.h是基于硬件设计生成的。 sfp.c和si5324.c分别用于sfp PHY和si5324芯片,用于官方特定的开发板,与我们使用的领航者开发板不相关。
5-5 为了方便分析,我们将src文件夹与本实验不相关的平台文件删除,删除后的src文件夹内容如下图所示:
图33.4.5 删除不相关文件后的src文件夹内容 5-6 现在我们打开main.c文件,为了方便分析源代码,在main.c文件中将带有下图箭头所指的预编译指令删除。
删除不适用的预编译指令后的main.c代码如下: - #include <stdio.h>
- #include "xparameters.h"
- #include "netif/xadapter.h"
- #include "platform.h"
- #include "platform_config.h"
- #include "xil_printf.h"
- #include "lwip/tcp.h"
- #include "xil_cache.h"
- #if LWIP_IPV6==1
- #include "lwip/ip.h"
- #else
- #if LWIP_DHCP==1
- #include "lwip/dhcp.h"
- #endif
- #endif
- //函数声明
- void print_app_header();
- int start_application();
- int transfer_data();
- void tcp_fasttmr(void);
- void tcp_slowtmr(void);
- void lwip_init();
- #if LWIP_IPV6==0
- #if LWIP_DHCP==1
- extern volatile int dhcp_timoutcntr;
- err_t dhcp_start(struct netif *netif);
- #endif
- #endif
- extern volatile int TcpFastTmrFlag;
- extern volatile int TcpSlowTmrFlag;
- static struct netif server_netif;
- struct netif *echo_netif;
- #if LWIP_IPV6==1
- void print_ip6(char *msg, ip_addr_t *ip)
- {
- print(msg);
- xil_printf("%x:%x:%x:%x:%x:%x:%x:%x\n\r",
- IP6_ADDR_BLOCK1(&ip->u_addr.ip6),
- IP6_ADDR_BLOCK2(&ip->u_addr.ip6),
- IP6_ADDR_BLOCK3(&ip->u_addr.ip6),
- IP6_ADDR_BLOCK4(&ip->u_addr.ip6),
- IP6_ADDR_BLOCK5(&ip->u_addr.ip6),
- IP6_ADDR_BLOCK6(&ip->u_addr.ip6),
- IP6_ADDR_BLOCK7(&ip->u_addr.ip6),
- IP6_ADDR_BLOCK8(&ip->u_addr.ip6));
- }
- #else
- void print_ip(char *msg, ip_addr_t *ip)
- {
- print(msg);
- xil_printf("%d.%d.%d.%d\n\r", ip4_addr1(ip), ip4_addr2(ip),
- ip4_addr3(ip), ip4_addr4(ip));
- }
- void print_ip_settings(ip_addr_t *ip, ip_addr_t *mask, ip_addr_t *gw)
- {
- print_ip("BoardIP: ", ip);
- print_ip("Netmask: ", mask);
- print_ip("Gateway: ", gw);
- }
- #endif
- int main()
- {
- #if LWIP_IPV6==0
- ip_addr_t ipaddr, netmask, gw;
- #endif
- //设置领航者开发板的MAC地址
- unsignedchar mac_ethernet_address[] =
- { 0x00, 0x0a, 0x35, 0x00, 0x01, 0x02 };
- echo_netif = &server_netif;
- init_platform();
- #if LWIP_IPV6==0
- #if LWIP_DHCP==1
- ipaddr.addr = 0;
- gw.addr = 0;
- netmask.addr = 0;
- #else
- //设置静态IP地址
- IP4_ADDR(&ipaddr, 192, 168, 1, 10);
- IP4_ADDR(&netmask, 255, 255, 255, 0);
- IP4_ADDR(&gw, 192, 168, 1, 1);
- #endif
- #endif
- print_app_header();
- lwip_init();
- #if (LWIP_IPV6 == 0)
- //添加以太网MAC
- if (!xemac_add(echo_netif, &ipaddr, &netmask,
- &gw, mac_ethernet_address,
- PLATFORM_EMAC_BASEADDR)) {
- xil_printf("Erroradding N/W interface\n\r");
- return -1;
- }
- #else
- if (!xemac_add(echo_netif, NULL, NULL, NULL, mac_ethernet_address,
- PLATFORM_EMAC_BASEADDR)) {
- xil_printf("Erroradding N/W interface\n\r");
- return -1;
- }
- echo_netif->ip6_autoconfig_enabled = 1;
- netif_create_ip6_linklocal_address(echo_netif, 1);
- netif_ip6_addr_set_state(echo_netif, 0, IP6_ADDR_VALID);
- print_ip6("\n\rBoardIPv6 address ", &echo_netif->ip6_addr[0].u_addr.ip6);
- #endif
- netif_set_default(echo_netif);
- //启用中断
- platform_enable_interrupts();
- //指定网络是否已启动
- netif_set_up(echo_netif);
- #if (LWIP_IPV6 == 0)
- #if (LWIP_DHCP==1)
- //创建新的DHCP客户端。
- dhcp_start(echo_netif);
- dhcp_timoutcntr = 24;
- while(((echo_netif->ip_addr.addr) == 0) && (dhcp_timoutcntr > 0))
- xemacif_input(echo_netif);
- if (dhcp_timoutcntr <= 0) {
- if ((echo_netif->ip_addr.addr) == 0) {
- xil_printf("DHCPTimeout\r\n");
- xil_printf("Configuringdefault IP of 192.168.1.10\r\n");
- IP4_ADDR(&(echo_netif->ip_addr), 192, 168, 1, 10);
- IP4_ADDR(&(echo_netif->netmask), 255, 255, 255, 0);
- IP4_ADDR(&(echo_netif->gw), 192, 168, 1, 1);
- }
- }
- ipaddr.addr = echo_netif->ip_addr.addr;
- gw.addr = echo_netif->gw.addr;
- netmask.addr = echo_netif->netmask.addr;
- #endif
- print_ip_settings(&ipaddr, &netmask, &gw);
- #endif
- //启动应用程序
- start_application();
- //接收和处理数据包
- while (1) {
- if (TcpFastTmrFlag) {
- tcp_fasttmr();
- TcpFastTmrFlag = 0;
- }
- if (TcpSlowTmrFlag) {
- tcp_slowtmr();
- TcpSlowTmrFlag = 0;
- }
- xemacif_input(echo_netif);
- transfer_data();
- }
- cleanup_platform();
- return 0;
- }
复制代码
可以看到代码中有很多的#if LWIP_IPV6==0和#if LWIP_DHCP==1这类预编译指令,这是因为lwip即支持IPv4也支持IPv6,IPv4和DHCP默认支持。如果想重新配置lwip如取消DHCP,可以通过以下方式重配置lwip。 鼠标右键点击“lwip_server_bsp”,在弹出的菜单中选择“Board Support Package Settings”,如下图所示:
图33.4.7 Board Support Package Settings 在弹出的界面中点击左侧standalone下的lwip202,右侧就是lwip的配置面板。如下图所示,箭头所指的两处分别是配置启用DHCP和使能IPv6,可以看到,dhcp默认为true,ipv6默认为false。
main函数可以说是使用lwip的一个标准函数,可以在不修改main函数的情况下就可实现其它的应用功能。main函数主要完成以下功能: 1) 在代码的73行设置领航者开发板的MAC地址为00:0a:35:00:01:02。 2) 通过调用init_platform函数配置定时器和建立中断以初始化平台,定时器产生周期性中断,周期为250ms。 3) 调用lwip_init函数完成对lwip协议栈的初始化,代码第93行。 4) 初始化lwIP后,使用xemac_add函数添加以太网MAC到协议栈中。 5) 使用platform_enable_interrupts函数使能中断和启动定时器。 6) 从代码第125~139行,启动DHCP服务获取动态IP地址,如果超时未获取到动态IP地址,则使用默认的静态IP设置: IP Address: 192.168.1.10 Netmask : 255.255.255.0 Gateway : 192.168.1.1 我们也可以根据需要修改代码第135~137行的值,从而使用不同的静态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文件,工具会自动进行编译。编译完成后控制台(Console)中会出现提示信息“Build Finished”,同时在应用工程的Binaries目录下可以看到生成的elf文件。 1.5 下载验证首先我们将下载器与领航者底板上的JTAG接口连接,下载器另外一端与电脑连接。然后使用Mini USB连接线将USB UART接口与电脑连接,用于串口通信。使用网线一端连接领航者开发板的以太网接口,另一端与电脑或路由器连接。最后连接开发板的电源,并打开电源开关。如下图所示:
现在进入最后一步。 step6:板级验证 6-1 在SDK软件的下方的SDK Terminal窗口中点击右上角的加号连接串口。 6-2 下载程序。 6-3 可以看到串口打印的结果如下:
在打印出“link speedfor phy address 1: 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函数从而删除该语句。 在使用静态IP地址时,需要确保同网段内没有主机使用192.168.1.10 的IP地址,否则会造成IP冲突。可以在开发板未上电前或未下载程序前在CMD里输入“ping 192.168.1.10”命令查看是否能ping通,如果能ping通,说明网络中有此IP地址,此时需要更改静态IP地址为其他值,如192.168.1.123等。 6-4 我们在电脑端打开网络调试助手,设置协议类型为:TCP Client,服务器IP地址为串口打印的地址,此处为:192.168.1.10,服务器端口号为:7,然后点击连接,即可连上开发板的 TCP Sever,如下图所示:
图33.5.3 电脑端网络调试助手TCP Client测试界面 6-5 本实验除了可以使用网络调试助手软件外,还可以使用telnet。 我们打开电脑的CMD(按win+r键后输入cmd),输入“telnet192.168.1.10 7”,如下图所示:
回车后,进入下图所示界面:
如果回车后出现像下图所示界面所示“telnet不是内部或外部命令,也不是可运行的程序或批处理文件”,则表明未开启Windows的telnet客户端功能,开启方式见6-5。
此时我们按键盘上的字母和数字键,如123abc,控制台显示如下:
可以看到除了1只有一个外,其它字符都显示两个,一个是我们按下的,另一个是开发板的lwip echo server应答的。可见功能基本正确,不过从使用上看还是有问题的,一是第一次按下的字符没有回显;二是不能输入字符串,这些问题主要是windows自带的telnet的问题。如果使用第三方提供的telnet工具,例如使用Win10系统的读者可以开启WSL,从而使用linux系统提供的telnet功能进行连接,如下图(通过WSL使用Ubuntu系统):
可以看到一点问题也没有。按“Ctrl+]”可以退出输入界面,然后输入“quit”即可退出telnet连接。 注:Telnet 协议是TCP/IP 协议族中的一员,是 Internet 远程登录服务的标准协议和主要方式。它为用户提供了在本地计算机上完成远程主机工作的能力。在终端使用者的电脑上使用telnet 程序,用它连接到服务器。终端使用者可以在telnet程序中输入命令,这些命令会在服务器上运行,就像直接在服务器的控制台上输入一样。可以在本地就能控制服务器。 6-6 下面我们介绍一下如何开启Windows的telnet客户端功能。在Win10或Win7系统中,按“Win+r”快捷键后,在下图所示界面中输入“control”。
进入下图所示控制面板界面,将查看方式设置为“类别”,单击“程序”下的“卸载程序”,如下图所示:
在弹出的界面中,单击“启用或关闭Windows功能”,如下图所示:
图33.5.11 点击“启用或关闭Windows功能” 在弹出的“Windows功能”界面中,找到“Telnet Client”,并勾选,如下图所示:
单击确定后,如果出现“Windows需要重启电脑才能完成安装所请求的更改”字样,重新启动电脑即可,至此,Windows的telnet客户端服务已启用。 此时我们进行telnet连接会连接成功,但也有部分电脑会出现下图所示现象:
出现这种情况是因为本地连接(Win10为以太网)设置有问题,需要重新设置。在控制面板界面,单击“网络和Internet”下的“查看网络状态和任务”,如下图所示:
进入下图所示界面:
点击箭头所指的“更改适配器设置”,进入下图所示界面: 图33.5.16 打开属性界面 点击“以太网”(或者本地连接,如果有)后出现“更改此连接的设置”,点击“更改此连接的设置”,进入“属性”界面,点击“Internet协议版本4(TCP/IPv4)”,如下图所示:
进入下图所示界面后,按下图的设置进行修改。
经过这些设置后,基本上就可以使用telnet了。 至此,本实验完成。
|