概述
1)实验平台:正点原子开拓者FPGA 开发板
2)摘自《开拓者 Nios II开发指南》关注官方微信号公众号,获取更多资料:正点原子
3)全套实验源码+手册+视频下载地址:http://www.openedv.com/docs/index.html
第二十一章基于NicheStack的简单Socket服务器实验
随着物联网的兴起,万物互联需要一个强大而又灵活的协议体系,TCP/IP协议成了不二选
择,而在嵌入式网络设备中,由于硬件资源的限制,需要特殊的实现方式。Nios II SBT for
Eclipse包含MicroC/OS-II RTOS和NicheStack TCP/IP协议栈软件组件,使设计人员能够基于
Nios II处理器快速构建嵌入式网络系统应用程序。本章我们基于MicroC/OS-II RTOS和
NicheStack TCP/IP协议栈构建简单的socket服务器实验。本章分为以下几个部分:
21.1 简介
21.2 实验任务
21.3 硬件设计
21.4 软件设计
21.5 下载验证
简介
1) TCP/IP协议简介
TCP/IP中文名为传输控制协议/因特网互联协议,又名网络通讯协议,是Internet最基本
的协议、Internet国际互联网络的基础,由网络层的IP协议和传输层的TCP协议组成。TCP/IP
定义了电子设备如何连入因特网,以及数据如何在它们之间传输的标准。协议采用了4层的层
级结构,每一层都呼叫它的下一层所提供的协议来完成自己的需求。通俗而言:TCP负责发现
传输的问题,一有问题就发出信号,要求重新传输,直到所有数据安全正确地传输到目的地。
而IP是给因特网的每一台联网设备规定一个地址。
TCP/IP协议不是TCP和IP这两个协议的合称,而是指因特网整个TCP/IP协议族。从协议分
层模型方面来讲,TCP/IP由四个层次组成:网络接口层、网络层、传输层、应用层。OSI是传
统的开放式系统互连参考模型,该模型将TCP/IP分为七层:物理层、数据链路层(网络接口层)、
网络层(网络层)、传输层(传输层)、会话层、表示层和应用层(应用层)。TCP/IP模型与
OSI模型对比如表1.1.1所示。
图 21.1.1 OSI模型与TCP/IP模块
2) NicheStack简介
NicheStack是InterNiche从头开始设计的嵌入式TCP/IP协议栈,用于连接嵌入式设备。
NicheStack结合了小尺寸和极高的可移植性与高性能,旨在提供全功能TCP/IP堆栈的同时减少
资源使用。NicheStack的IP层支持各种物理接口,可配置为标准客户端计算机,IP路由器或多
宿主服务器。作为一个综合的设备组网包,标准配置包括FTP,Telnet,DNS,DHCP,IGMPv1和
IGMPv2组件。NicheStack为InterNiche的可选PPP,Web服务器,Web浏览器,DHCP服务器,电
子邮件,SNMP和路由产品提供了经济、可靠的协议平台。
NicheStack TCP/IP协议栈设计用于具有小内存占用的嵌入式系统,其内存要求极低。最
小可以小到12.8KB。带有套接字API的全功能TCP/IP在32位处理器上只要求具有50KB的ROM和RAM空间,适用于Nios II等处理器系统。
对于Nios II处理器,NicheStack TCP/IP协议栈是一个软件包,可通过Nios II软件构建
工具(SBT)将其添加到板级支持包(BSP)。NicheStack TCP/IP协议栈包括以下功能:
•Internet协议(IP),包括通过多个网络接口的数据包转发
•用于网络维护和调试的Internet控制消息协议(ICMP)
•用户数据报协议(UDP)•传输控制协议(TCP)拥塞控制,往返时间(RTT)估计,快速
恢复和重传
•动态主机配置协议(DHCP)
•以太网地址解析协议(ARP)
•标准套接字应用程序接口(API)
实验任务
本章的实验任务是搭建NicheStack应用系统,使用Eclipse自带的NicheStack例程通过
telnet控制led灯的点亮。
硬件设计
在简介部分我们提到了OSI的七层模型,在我们的NicheStack实验中板载的PHY层芯片
RTL8201相当于物理层,而NicheStack提供的就是网络层、传输层的功能,应用层是需要用户
自己根据自己想要的功能去实现的。这里我们使用Qsys的三速以太网IP核作为数据链路层。
新建好工程后,我们打开 Qsys,添加完 nios ii、sdram、epcs(为了和 Eclipse 自带的例
程兼容,我们将 epcs 命名为 ext_flash)、jtag 完成基本系统后,我们现在搭建 NicheStack
应用系统。在搜索框输入 eth 后,出现下图所示结果:
图 21.3.1 搜索三速以太网IP
我们选择Triple-Speed Ethernet,即三速(10/100/100Mbps)以太网,能够和板载的PHY
芯片(支持10/100Mbps)很好的兼容。我们Triple-Speed Ethernet后,弹出下图所示界面:
图 21.3.2 设置MAC配置
在“Core Configuration”栏下将“Core variation”设置为“10/100Mb Small MAC”,“FIFO Option”栏“Depth”设置为512×32 bits,如下图所示:
图 21.3.3 设置FIFO深度
其它选项保持默认即可,单击右下角的“Finish”,并将其命名为tse_mac,即添加三速
以太网IP核到qsys系统中。因为三速以太网IP核的receive和transmit端口为Avalon
Streaming端口,所以这里我们通过Scatter-Gather DMA分别将Streaming信号转换为Memory信
号和Memory信号转换为Streaming信号。在搜索框中输入dma,选择Scatter-Gather DMA
Controller,双击后,弹出图 21.3.4所示界面,在“Transfer mode”中选择“Memory To Stream”,
点击右下角的“Finish”,并将该Scatter-Gather DMA命名为sgdma_tx,将其out端口连接到
三速以太网的transmit端口。同样,我们再添加一个Scatter-Gather DMA将其命名为sgdma_rx,
“Transfer mode”中选择“Stream To Memory”,如图 21.3.5所示:
图 21.3.4 通过SGDMA将Memory转换成Stream
图 21.3.5 通过SGDMA将Stream转换成Memory
将其in端口连接到三速以太网的receive端口。初步完成了Avalon ST到Avalon MM的转换
后,我们添加一个双端口RAM,如下图所示:
图 21.3.6 配置descriptor_memory
将其命名为descriptor_memory,其s1端连接sgdma_tx和sgdma_rx的descriptor_read、
descriptor_write,s2端连接nios2的data_master端。现在我们还需要一个Pipeline桥将SDRAM
和sgdma进行桥接。在搜索框中输入pipeline,选择,如图 21.3.7所示,将其命名为
pb_dma_to_sdram,其s0端连接sgdma_tx的m_read和sgdma_rx的m_write,其m0连接sdram的s1端。
图 21.3.7 配置pb_dma_to_sdram
至此,以太网部分的Qsys硬件就搭建完成了,因为NicheStack是建立在uCos系统上的,所
以我们需要定时器。这里我们添加两个定时器,一个命名为sys_clk_timer,其设置如下:
图 21.3.8 设置sys_clk_timer
另一个命名为high_res_timer,其设置如下:
图 21.3.9 设置high_res_timer
因为本实验是通过telnet控制led的点亮,所示我们还需要PIO用来连接led,添加PIO如下
图所示:
图 21.3.10 设置led PIO
pio命名为led_pio。连接时钟、复位和中断信号,自动分配地址后的结果图截取部分如下:
图 21.3.11 搭建qsys系统
Quartus II工程的顶层代码如下:
1 module qsys_eth(
2 //时钟和复位接口
3 input sys_clk , //系统时钟
4 input sys_rst_n , //按键复位
5
6 //SDRAM 接口
7 output sdram_clk , //SDRAM 芯片时钟
8 output sdram_cke , //SDRAM 时钟有效
9 output sdram_cs_n , //SDRAM 片选
10 output sdram_ras_n, //SDRAM 行有效
11 output sdram_cas_n, //SDRAM 列有效
12 output sdram_we_n , //SDRAM 写有效
13 output [ 1:0] sdram_ba , //SDRAM Bank地址
14 output [12:0] sdram_addr , //SDRAM 行/列地址
15 inout [15:0] sdram_dq , //SDRAM 数据
16 output [ 1:0] sdram_dqm , //SDRAM 数据掩码
17
18 //EPCS Flash 接口
19 output epcs_dclk , //EPCS 时钟信号
20 output epcs_sce , //EPCS 片选信号
21 output epcs_sdo , //EPCS 数据输出信号
22 input epcs_data0 , //EPCS 数据输入信号
23
24 //以太网接口
25 input eth_rx_clk , //MII接收数据时钟
26 input eth_rxdv , //MII输入数据有效信号
27 input eth_tx_clk , //MII发送数据时钟
28 input [3:0] eth_rx_data , //MII输入数据
29 output eth_tx_en , //MII输出数据有效信号
30 output [3:0] eth_tx_data , //MII输出数据
31 output eth_rst_n , //以太网芯片复位信号,低电平有效
32
33 //user interface
34 output [3:0] led //4个LED灯
35 );
36
37 //wire define
38 wire clk_100m;
39 wire pll_locked;
40 wire rst_n;
41
42 //*****************************************************
43 //** main code
44 //*****************************************************
45
46 assign rst_n = sys_rst_n & pll_locked ;
47 //以太网芯片复位信号
48 assign eth_rst_n = rst_n;
49
50 //例化锁相环模块
51 pll u_pll (
52 .inclk0 (sys_clk ),
53 .areset (~sys_rst_n),
54 .c0 (clk_100m), //QSYS 系统时钟
55 .c1 (sdram_clk ), //SDRAM 时钟
56 .locked (pll_locked)
57 );
58
59 //例化Nios2系统模块
60 nios2os u_nios2os(
61 //时钟和复位
62 .clk_clk (clk_100m),
63 .reset_reset_n (rst_n),
64 //EPCS
65 .epcs_flash_dclk (epcs_dclk ),
66 .epcs_flash_sce (epcs_sce ),
67 .epcs_flash_sdo (epcs_sdo ),
68 .epcs_flash_data0 (epcs_data0),
69 //SDRAM
70 .sdram_addr (sdram_addr),
71 .sdram_ba (sdram_ba),
72 .sdram_cas_n (sdram_cas_n),
73 .sdram_cke (sdram_cke),
74 .sdram_cs_n (sdram_cs_n),
75 .sdram_dq (sdram_dq),
76 .sdram_dqm (sdram_dqm),
77 .sdram_ras_n (sdram_ras_n),
78 .sdram_we_n (sdram_we_n),
79 //三速以太网
80 .tse_pcs_tx_clk_clk (eth_tx_clk), //tse_pcs_tx_clk.clk
81 .tse_pcs_rx_clk_clk (eth_rx_clk), //tse_pcs_rx_clk.clk
82 .tse_mac_stu_set_10 (1'b0), //tse_mac_stu.set_10
83 .tse_mac_stu_set_1000 (1'b0), // .set_1000
84 .tse_mac_stu_eth_mode (), // .eth_mode
85 .tse_mac_stu_ena_10 (), // .ena_10
86 .tse_mac_mii_rx_d (eth_rx_data), // tse_mac.mii_rx_d
87 .tse_mac_mii_rx_dv (eth_rxdv), // .mii_rx_dv
88 .tse_mac_mii_rx_err (1'b0), // .mii_rx_err
89 .tse_mac_mii_tx_d (eth_tx_data), // .mii_tx_d
90 .tse_mac_mii_tx_en (eth_tx_en), // .mii_tx_en
91 .tse_mac_mii_tx_err (1'b0), // .mii_tx_err
92 .tse_mac_misc_ff_tx_crc_fwd (1'b0), //tse_mac_misc.ff_tx_crc_fwd
93 .tse_mac_misc_ff_tx_septy (), // .ff_tx_septy
94 .tse_mac_misc_tx_ff_uflow (), // .tx_ff_uflow
95 .tse_mac_misc_ff_tx_a_full (), // .ff_tx_a_full
96 .tse_mac_misc_ff_tx_a_empty (), // .ff_tx_a_empty
97 .tse_mac_misc_rx_err_stat (), // .rx_err_stat
98 .tse_mac_misc_rx_frm_type (), // .rx_frm_type
99 .tse_mac_misc_ff_rx_dsav (), // .ff_rx_dsav
100 .tse_mac_misc_ff_rx_a_full (), // .ff_rx_a_full
101 .tse_mac_misc_ff_rx_a_empty (), // .ff_rx_a_empty
102 //led
103 .led_export (led)
104 );
105
106 endmodule
顶层代码添加了PLL模块,用以产生驱动nios2os系统和SDRAM工作的时钟,例化nios2os系
统,实现信号间的交互。
至此,硬件部分设计完成,下面开始基于 Nios II SBT for Eclipse 的软件部分的设计。
软件设计
打开Nios II SBT for Eclipse后,点击File/New/Nios Application and BSP from Template
选项后进入下图所示界面:
图 21.4.1 创建NicheStack工程
同以往不同的是这次我们在左下方的“Template”栏选择的是“Simple Socket Server”,
Simple Socket Server采用了工业标准的TCP/IP sockets接口。该例程模板显示了如何初始化
NicheStack TCP/IP栈并实现了一个简单的TCP应用服务——telnet,电脑主机通过telnet与
FPGA开发板进行通信。选择完成后,点击“Finish”,工程创建完成后,如下图所示:
图 21.4.2 NicheStack工程结构
其中的C源文件说明如下:
alt_error_handler.c:实现MicroC-OS/II系统调用、网络堆栈系统调用和简单套接字服
务器(simple socket server)应用程序调用错误处理,并打印相应信息。
alt_error_handler.h:定义上述3个错误处理程序。
iniche_init.c:包含main()和SSSInitialTask()以初始化NicheStack,然后在网络正
确初始化后创建其他任务。使用套接字的任务必须使用TK_NEWTASK创建,例如本例中的
SSSSimpleSocketServerTask()。可以通过直接调用MicroC/OS-II API创建任务的函数
OSTaskCreateExt()来创建所有其他任务。
led.c : 包 含 控 制 LED 显 示 的 任 务 LEDManagementTask 和 7 段 数 码 管 显 示 的 任 务
LED7SegLightshowTask。LEDManagementTask从MicroC/OS-II SSSLEDCommandQ Queue队列读取
数据,该队列从SSSSimpleSocketServerTask接收数据。因为我们在Qsys硬件搭建中定义了
led_pio,所以这里我们可以使用LED显示,而不是7段数码管,另外这里默认的LED是8位的,
而我们开拓者开发板是4位的,所以在后面使用时需要注意。
network_utilities.c:包含用于管理寻址的MAC地址和IP地址函数。这些在初始化期间由
NicheStack使用,但是是特定于实现的,所以我们需要对该文件稍作修改——将MAC地址设置
为任何合适的值,后面我们会讲解如何修改。
network_utilities.h:包含函数get_board_mac_addr()的原型。
simple_socket_server.c:simple_socket_server的实现,包括所有必要的套接字调用,
以处理单个套接字连接和处理接收到的命令。
simple_socket_server.h:整个应用程序的定义。此文件后面我们要进行相应修改。
tse_my_system.c:允许通过全局数组初始化自定义tse_mac_device结构。
因为此例程默认使用DHCP客户端,由于我们不需要使用,所以将其关闭。右键点击
qsys_eth_bsp,选择“Nios II/BSP Editor”,进入下图所示界面
图 21.4.3 取消勾选DHCP客户端
在 “ Software Packages” 菜 单 栏下取消勾 选 “enable_dhcp_client” ,然后点击
“Generate”,再点击“Exit”退出,弹出下图所示信息时点击“Yes,Save”。
图 21.4.4 保存修改
为了编译能正确通过,我们再次右键点击qsys_eth_bsp,选择“Nios II/ Generate BSP”。
因 为 不 使 用 DHCP , 所 以 我 们 需 要 设 置 静 态 IP 地 址 。 打 开 qsys_eth 目 录 下 的
simple_socket_server.h文件,修改第113行~121行的宏定义,如下图所示:
图 21.4.5 设置静态IP地址
修改完静态IP地址后,我们还需要修改MAC地址。只需将qsys_eth/network_utilities.c
文件第308行的get_board_mac_addr函数修改成如下形式:
图 21.4.6 添加MAC地址
MAC地址任意设置。
main函数所在的文件为iniche_init.c,具体代码如下:
1 #include <stdio.h>
2
3 /* MicroC/OS-II definitions */
4 #include "includes.h"
5
6 /* Simple Socket Server definitions */
7 #include "simple_socket_server.h"
8 #include "alt_error_handler.h"
9
10 /* Nichestack definitions */
11 #include "ipport.h"
12 #include "libport.h"
13 #include "osport.h"
14
15 /* Definition of task stack for the initial task which will initialize the NicheStack
16 * TCP/IP Stack and then initialize the rest of the Simple Socket Server example tasks.
17 */
18 OS_STK SSSInitialTaskStk[TASK_STACKSIZE];
19
20 /* Declarations for creating a task with TK_NEWTASK.
21 * All tasks which use NicheStack (those that use sockets) must be created this way.
22 * TK_OBJECT macro creates the static task object used by NicheStack during operation.
23 * TK_ENTRY macro corresponds to the entry point, or defined function name, of the task.
24 * inet_taskinfo is the structure used by TK_NEWTASK to create the task.
25 */
26 TK_OBJECT(to_ssstask);
27 TK_ENTRY(SSSSimpleSocketServerTask);
28
29 struct inet_taskinfo ssstask = {
30 &to_ssstask,
31 "simple socket server",
32 SSSSimpleSocketServerTask,
33 4,
34 APP_STACK_SIZE,
35 };
36
37 /* SSSInitialTask will initialize the NicheStack
38 * TCP/IP Stack and then initialize the rest of the Simple Socket Server example
39 * RTOS structures and tasks.
40 */
41 void SSSInitialTask(void *task_data)
42 {
43 INT8U error_code;
44
45 /*
46 * Initialize Altera NicheStack TCP/IP Stack - Nios II Edition specific code.
47 * NicheStack is initialized from a task, so that RTOS will have started, and
48 * I/O drivers are available. Two tasks are created:
49 * "Inet main" task with priority 2
50 * "clock tick" task with priority 3
51 */
52 alt_iniche_init();
53 netmain();
54
55 /* Wait for the network stack to be ready before proceeding.
56 * iniche_net_ready indicates that TCP/IP stack is ready, and IP address is obtained.
57 */
58 while (!iniche_net_ready)
59 TK_SLEEP(1);
60
61 /* Now that the stack is running, perform the application initialization steps */
62
63 /* Application Specific Task Launching Code Block Begin */
64
65 printf("Simple Socket Server starting up");
66
67 /* Create the main simple socket server task. */
68 TK_NEWTASK(&ssstask);
69
70 /*create os data structures */
71 SSSCreateOSDataStructs();
72
73 /* create the other tasks */
74 SSSCreateTasks();
75
76 /* Application Specific Task Launching Code Block End */
77
78 /*This task is deleted because there is no need for it to run again */
79 error_code = OSTaskDel(OS_PRIO_SELF);
80 alt_uCOSIIErrorHandler(error_code, 0);
81
82 while (1); /* Correct Program Flow should never get here */
83 }
84
85 /* Main creates a single task, SSSInitialTask, and starts task scheduler.
86 */
87
88 int main (int argc, char* argv[], char* envp[])
89 {
90
91 INT8U error_code;
92
93 /* Clear the RTOS timer */
94 OSTimeSet(0);
95
96 /* SSSInitialTask will initialize the NicheStack
97 * TCP/IP Stack and then initialize the rest of the Simple Socket Server example
98 * RTOS structures and tasks.
99 */
100 error_code = OSTaskCreateExt(SSSInitialTask,
101 NULL,
102 (void *)&SSSInitialTaskStk[TASK_STACKSIZE],
103 SSS_INITIAL_TASK_PRIORITY,
104 SSS_INITIAL_TASK_PRIORITY,
105 SSSInitialTaskStk,
106 TASK_STACKSIZE,
107 NULL,
108 0);
109 alt_uCOSIIErrorHandler(error_code, 0);
110
111 /*
112 * As with all MicroC/OS-II designs, once the initial thread(s) and
113 * associated RTOS resources are declared, we start the RTOS. That's it!
114 */
115 OSStart();
116
117
118 while(1); /* Correct Program Flow never gets here. */
119
120 return -1;
121 }
Nios II Simple Socket Server使用大写的首字母缩略词前缀来标识每个软件模块的公
共资源,使用带有下划线的小写字母来指示软件模块内部使用的私有资源或函数。下表显示了
软件模块的首字母缩写词标识符及其含义:
图 21.4.7 缩写词及其含义
SSSInitialTask()创建所有MicroC/OS-II资源的实例。初始化NicheStack TCP/IP堆栈和
创建Nios II Simple Socket Server RTOS结构和任务。SSSSimpleSocketServerTask()管理套
接字服务器连接,并调用相关的子例程来管理套接字连接。
基于NicheStack的简单socket服务器实验的数据流程图如下:
图 21.4.8 基于NicheStack的简单socket服务器实验的数据流程图
在主机PC上使用telnet客户端发送以太网数据包与使用NicheStack sockets API的开发
板进行TCP/IP以太网通信,PHY驱动层通过Monitor PHY Task捕获数据包并将其传递给
NicheStack的TCP/IP Task,Nios II Simple Socket Server Task将解析后的数据通过SSS
LED Command队列传递给LED Management Task,LED Blink Task用LED Management Task通过
邮箱传递来的数据控制开发板LED的点亮与熄灭。
下载验证
讲完了软件工程,接下来我们就将该实验下载至我们的开拓者开发板进行验证。
首先我们用一根网线将开发板和电脑进行连接,然后连接JTAG和电源,开发板上电后我们
在Quartus II软件中将qsys_eth.sof文件下载至我们的开拓者开发板,qsys_eth.sof下载完成
后,我们还需要在Nios II SBT for Eclipse软件中将qsys_eth.elf文件下载至我们的开拓者
开发板,qsys_eth.elf下载完成以后,我们的C程序就会执行在我们的开拓者开发板上,此时
在Nios II Console上打印如下信息:
图 21.5.1 Nios II控制台打印信息
从中我们可以看到此处MAC地址(十六进制)与我们设置的相符,IP地址也是我们设置的
静态IP地址192.168.1.234,端口号为30。
我们打开电脑的CMD(按win+r键后输入cmd),输入“telnet 192.168.1.234 30”,如下
图所示:
图 21.5.2 进行telnet连接
回车后,进入下图所示界面:
图 21.5.3 连接成功后的界面
如果回车后出现下图所示界面所示“telnet 不是内部或外部命令,也不是可运行的程序或批
处理文件”,则表明未开启 Windows 的 telnet 客户端功能。
图 21.5.4 未启用telnet客户端时的界面
下面我们介绍一下如何开启Windows的telnet客户端功能。在Win10或Win7系统中,按
“Win+r”快捷键后,在下图所示界面中输入“control”。
图 21.5.5 打开控制面板界面
进入下图所示控制面板界面,将查看方式设置为“类别”,单击“程序”下的“卸载程序”,
如下图所示:
图 21.5.6 点击进入“程序和功能”界面
在弹出的界面中,单击“启用或关闭 Windows 功能”,如下图所示:
图 21.5.7 点击“启用或关闭Windows功能”
在弹出的“Windows 功能”界面中,找到“Telnet Client”,并勾选,如下图所示:
图 21.5.8 勾选telnet client
单击确定后,如果出现“Windows需要重启电脑才能完成安装所请求的更改”字样,重新
启动电脑即可,至此,Windows的telnet客户端服务已启用。
此时我们进行telnet连接会连接成功,但也有部分电脑会出现下图所示现象:
图 21.5.9 无法连接
出现这种情况是因为本地连接(Win10为以太网)设置有问题,需要重新设置。在控制面
板界面,单击“网络和Internet”下的“查看网络状态和任务”,如下图所示:
图 21.5.10 打开“查看网络和状态”
进入下图所示界面:
图 21.5.11 更改适配器设置
点击箭头所指的“更改适配器设置”,进入下图所示界面:
图 21.5.12 打开属性界面
点击“以太网”(或者本地连接,如果有)后出现“更改此连接的设置”,点击“更改此
连接的设置”,进入“属性”界面,点击“Internet协议版本4(TCP/IPv4)”,如下图所示:
图 21.5.13 进入IPv4设置
进入下图所示界面后,按下图的设置进行修改。
图 21.5.14 设置IPv4
成功进入图 21.5.3所示界面后,我们按下0~7之间的数字,可以控制开发板上相应的led
灯,由于开拓者开发板板载4个led灯,所以我们可以通过按下0~3来控制相应的led灯,我们按
下键盘上的“0”并回车后,显示如下:
图 21.5.15 点亮led0
开发板上显示的结果如下:
图 21.5.16 显示结果
led灯DS0点亮,再按一次0,led灯DS0熄灭,按1、2、3分别控制开发板上相应的led灯的
点亮与熄灭。按q键退出,如下图所示:
图 21.5.17 退出telnet连接
最后
以上就是大气雪糕为你收集整理的zigbee组网实验代码_正点原子开拓者NiosII资料连载第二十一章简单服务器实验的全部内容,希望文章能够帮你解决zigbee组网实验代码_正点原子开拓者NiosII资料连载第二十一章简单服务器实验所遇到的程序开发问题。
如果觉得靠谱客网站的内容还不错,欢迎将靠谱客网站推荐给程序员好友。
发表评论 取消回复