版权声明:本文为博主原创文章,未经博主允许不得转载。联系邮箱:zhzhchang@126.com
1.简介
在基础网络建设已趋于完善的今天,使用以太网进行数据传输有着众多优势,不仅传输速度快、传输距离远、传输通道更安全,而且以太网具有一系列标准协议,可以与众多的配套设备互联,可以免费使用众多的软件。
由于网络基础建设的完善,现在越来越多远程测控设备接入了互联网,管理这些分散的远程设备也越来越被人们所重视,其中之一就是设备的程序更新。因此,这里讨论一种利用以太网为数据通道,使用硬件平台提供的在应用编程(IAP)技术进行远程升级的实现方法。TFTP协议为通用协议,上位机端有众多的免费TFTP客户端/服务器可以使用,但小型平台一般不具备文件系统,因此在设备端需要自己来实现TFTP客户端或服务器。本文以NXP公司的lpc1778为例,实现具有以下特性的TFTP服务器:
- 支持标准TFTP(RFC1350)
- 支持扩展TFTP(RFC2347)
- 支持读、写请求
- 支持octet模式(二进制模式)
- 支持-tsize选项(RFC2349)
- 支持-blksize选项(RFC2348),但每包Data限制为512字节
- 支持数据重传功能
- 支持文件名校验功能
- 支持文件大小校验功能
- 支持数据包长度检测功能
由于是在嵌入式设备上实现TFTP服务器,因此这个服务器也有一些限制,如下所示:
- 端口号固定为69
- 单链接
- 不支持netascii模式
2.TFTP协议
TFTP协议全称为简单文件传输协议,它是以UDP为基础的应用层协议。在实现TFTP服务器之前,需要详细理解协议。目前很多介绍TFTP协议的书籍都是参照RFC1350,比如著名的《TCP/IP详解》。然而RFC1350已经被后来RFC2347、RFC2348、RFC2349等所代替,因此我们需要系统的认识一下这些最新的协议。
2.1 TFTP协议简介
1992年,修订版TFTP协议RFC1350发布,这一版本的TFTP协议被广泛使用,《TCP/IP详解卷1》章节15讲解TFTP协议时便是使用的这个版本。
除非一些非常古老的TFTP客户端/服务器软件,目前主流的客户端/服务器软件都会支持TFTP扩展选项,1998年发布的RFC2347定义了TFTP扩展选项。扩展选项可以允许客户端和服务器之间进行协商,以便使用一些额外的功能,比如超时时间、文件大小、数据包大小等等。TFTP扩展选项增加一个新的选项应答(OACK)数据帧,用来应答客户端的选项协商请求,增加一个新的错误码(8),用来指示当进行选项协商出错时,终止数据传输。
1998年颁布的RFC2348定义了数据块大小选项(blksize),同年颁布的RFC2349定义了超时间隔(timeout)和文件大小(tsize)选项。
注:本文所有“字节”均由8bit构成。
2.2 TFTP协议概述
数据传输起始于一个读取或者写入文件的请求,只有客户端才可以发送这种请求。
默认情况下,数据以定长512字节传输,如果服务器支持扩展选项,可以使用blksize选项协商数据长度。每个数据包中仅包含一个数据块。只有收到对方的应答数据包,才会发送下一包数据。
如果一个数据包数据大小小于512字节或小于通过blksize选项协商定的数据长度,表示数据传输结束。
两台机器进行数据传输时,一台为发送方一台为接收方。发送方发送数据并接收应答,接收方发送应答接收数据。
大部分的错误会导致连接中断,错误由一个错误的数据包引起,这个包不会被确认,也不会被重新发送。
2.3 TFTP协议传输模式
TFTP协议支持三种传输模式,分别为:
- netascii:ASCII文本模式
- octet:二进制模式,每字节8位
- mail:现在已经不使用
2.4 TFTP协议数据包种类
TFTP协议支持六种数据包格式,如表2-1所示。
2.4.1读写请求数据包
RFC2347规定的TFTP选项字段附加于读请求和写请求数据帧中。
2.4.1.1常用的选项:blksize
协商数据块大小,默认数据块为512,可以协商的值为8~65464字节(RFC2348)。
2.4.1.2 常用选项:timeout
超时间隔,可以协商的值为1~255秒(RFC2349)
2.4.1.3常用选项:tsize
传输文件的大小(RFC2349)
2.4.2 Data数据包
2.4.3 ACK数据包
2.4.4 ERROR数据包
2.4.5 OACK包格式:
2.5 TFTP客户端/服务器设计注意事项
1) 只能是客户端发送读写请求,读写请求数据包中可能附带选项信息。在读写请求数据包中可能有很多个选项,但一个选项只能出现一次。选项出现的顺序并不重要。
2) 如果服务器支持读写请求数据包中的选项,服务器会使用选项应答(OACK)响应。OACK中包含服务器能够支持的选项以及该选项对应的值,绝对不可以包含客户端没有使用的选项。如果客户端请求的某些选项服务器不支持,则在OACK中忽略这些选项。如果客户端请求的某些选项值服务器不能支持,服务器可以在OACK中将这些选项值替换为自己支持的或者发送一个错误包,错误码为8,以终止数据传输。
3) 如果客户端只请求一个选项,并且该选项没有被服务器应答,客户端必须忽略这个选项,服务器必须表现的像从未收到过这个请求一样。如果客户端请求多个选项,服务器应答了部分请求选项,则客户端必须使用那些服务器已经应答的选项,忽略服务器没有应答的选项。
4) 当客户端向服务器发送带选项的读请求数据包,服务器可能返回三种响应:
- OACK:应答读请求和选项
- DATA:应答读请求,无选项
- ERROR:请求被拒绝
5) 当客户端向服务器发送带选项的写请求数据包,服务器可能返回三种响应:
- OACK:应答写请求和选项
- ACK:应答写请求,无选项
- ERROR:请求被拒绝
6) 如果一个服务器不支持协商选项,它很可能会忽略掉客户端读写请求数据包中的选项字段。在这种情况下,对于读请求,服务器应该返回DATA数据包;对于写请求应该返回ACK数据包。但如果某些服务器返回一个ERROR数据包,客户端应该重新发送一个读写请求,并且这个读写请求中不包含任何选项信息。
7) 客户端应答OACK可能有两种方式,如果是读请求,则以ACK(数据块号设置为0)应答;如果是写请求,则以第一个数据块进行应答,数据块大小适应协商的值。如果客户端要拒绝OACK,它应该发送ERROR数据包,其错误码为8。
8) 服务器应保留发送的数据,直到下一帧正确到来,这样做是为了客户端响应超时后,重发最后一包数据。
注意1:服务器不能请求选项,所有选项由客户端发起。
注意2:如果客户端接收到的OACK中包含未请求的选项,客户端应该发送一个ERROR数据包,错误码为8。
3.boot程序设计
boot程序的设计对于远程升级至关重要,在boot程序中,需要移植一个精简过的lwIP协议栈、实现TFTP服务器、实现在应用编程(IAP)以及各种错误处理机制、超时重传机制。
boot程序设计流程图如图3-1所示。
3.1 Flash区域划分
如图3-2所示,将Flash划分为5个区域,分别是Boot程序区、标志扇区、出厂程序区和其它数据。我们把出厂程序和用户程序统称为应用程序。
1) Boot程序区:包括一个精简的lwIP协议栈、TFTP服务器实现代码、在应用编程(IAP)实现代码以及测试用的调试工具代码。
2) 标志扇区:存储升级标志、升级地址、跳转地址等信息。
3) 出厂程序区:出厂默认程序,此区域的程序升级权限不对非研发人员开放。
4) 用户程序区:出厂时此区域程序为空,在线升级的程序默认放到此区域,更改此区域的程序不会对出厂程序区的程序有任何影响。
3.2 lwIP协议栈移植
TFTP协议属于应用层协议,需要UDP协议作支撑,因此首先应该移植一个完整的TCP/IP协议栈。TCP/IP协议栈选用lwIP1.4.1版本,该协议栈专为嵌入式系统而设计,可在资源匮乏的微控制器上实现完整的可裁剪的TCP/IP协议,在不涉及分包和重组的嵌入式场合极其适用。lwIP的移植涉及的东西比较多,移植本文不作描述。
3.3 TFTP服务器实现
通过本文章节2对TFTP协议的分析可以看出,实现一个可用的TFTP客户端/服务器并无特别之处。但这里我们要实现一个健壮的、具有良好错误提示的TFTP服务器。
TFTP服务器的设计流程图如图3-3所示。
TFTP服务器要有良好的容错能力,对于接收的数据包要有一定的分析能力,能够剔除非法数据、重复数据等。在设计FTFP过程中,需要识别写入的文件名以及文件大小,防止写入非法文件或者过大的文件。过大的文件会覆盖相邻区域的Flash数据,会造成不可恢复的错误。
对于客户端传送过来的读写请求中,可能包含协商选项信息,由于我们事先并不知道客户端会传送多少个协商选项,因此需要将读写请求数据包进行完整的分析。对于支持的tsize选项和blksize选项,会记录选项的值,为校验文件大小以及回送OACK做准备,对于不支持的选项,直接忽略掉。将所有选项分析完成后,需要将支持的选项和选项值放到OACK包中回送给客户端。如果客户端传输来的读写请求中并没有协商选项,则直接返回ACK数据包,其中的数据包号字段设置为0。
对于客户端传送来的Data数据包,则需要校验数据长度和数据包号。校验数据包号可以在客户端发送不正确数据包号时告知客户端下一包应该发送什么样的正确数据包,或者在客户端发送重复数据包时,服务器端不会重复的将数据写入Flash。
考虑到实际现场环境可能非常恶劣,客户端发送的数据或者服务器应答的数据可能会丢失,因此一个健壮的TFTP服务器必须要有超时重传机制。为了在超时后重传最后一包数据,因此服务器必须额外开辟一个缓冲区用来保存最近一次发送的数据。
由于TFTP数据包基于UDP协议,数据包最大不超过560字节,而且以太网底层具有CRC32校验、IP层和UDP层具有累加和校验,这次校验足够将传输过程中的错误数据识别出来,因此在实现TFTP服务器的过程中,并不需要增加额外的校验。
图3-3 TFTP服务器设计流程图
3.4 在应用编程(IAP)
lpc1778芯片内部提供了编程Flash的底层代码,只需构造一个函数指针调用芯片提供的Flash编程代码即可。关于NXP ARM芯片的在应用编程基础知识可以参考我写过的一篇博文: 。
3.5 超时退出Boot程序
Boot程序其实主要有两个作用,一个是上电后如果不需要升级程序,则跳转到出正确的应用程序。二是上电发现需要升级程序则启动TFTP服务器,与TFTP客户端进行文件传输。可以发现,无论是第一个作用还是第二个作用,Boot执行的时间都不可能太长,毕竟真正使用的程序并不在于Boot。但是如果我们设置了升级标志后,又迟迟不给TFTP发送升级文件,这时设备会一直运行Boot程序,因此我们需要一个Boot程序执行超时定时器,来确保Boot程序执行时间到达后,跳转至正确的应用程序。
3.6 Boot程序部分指标
- 吞吐率:≈20KB/S
- 代码使用量:≈16.5KB
- RAM量使用量:≈28.5KB
4.测试
理论上支持RFC1350和RFC2347的TFTP客户端都可以使用,推荐使用Tftpd软件。该软件有两个版本:Tftpd32软件用于32位系统,Tftpd64软件用于64位系统,软件不仅具有TFTP客户端/服务器功能,还具有SNTP服务器、DHCP服务器DNS服务器等功能。本次测试使用Tftpd32和Tftpd64软件作为上位机软件。
4.1 上位机配置
打开Tftp64软件,切换到TftpClient界面,即TFTP客户端配置界面。其中:
1) Host:TFTP服务器IP地址;
2) Port:TFTP服务器器端口号,固定为69
3) Local File:升级文件路径。
4) Remote File:无需配置
5) Block Size:数据块大小,设置为512或者Default。
6) Get按钮:下载服务器上的文件,不需要
7) Put按钮:向服务器上传文件,我们使用这个按钮向服务器传输升级文件
8) Break按钮:终止文件传输
4.2测试流程与测试结果
序号 | 测试方法 | 测试过程 | 符合设计 |
1 | 擦除整个芯片,只烧写Boot程序 | Boot要求更新用户程序区,使用Tftpd客户端软件远程升级用户区程序后,Boot程序成功跳转至用户程序区。 | 符合设计 |
2 | 只烧写Boot和出厂默认程序 | 运行出厂默认程序 | 符合设计 |
3 | 只烧写Boot和用户程序 | Boot要求更新用户程序区,使用ftpd客户端软件远程升级用户区程序后,Boot程序成功跳转至用户程序区。 | 符合设计 |
4 | 运行出厂默认程序时远程升级出厂默认区域 | Boot要求更新出厂程序,使用Tftpd客户端软件远程升级用户区程序后,Boot程序成功跳转至用出厂程序。 | 符合设计 |
5 | 运行出厂默认程序时远程升级用户程序区域 | Boot要求更新用户程序,使用Tftpd客户端软件远程升级用户区程序后,Boot程序成功跳转至用户程序区。 | 符合设计 |
6 | 运行用户程序时远程升级出厂默认程序区域 | Boot要求更新出厂程序,使用Tftpd客户端软件远程升级用户区程序后,Boot程序成功跳转至用出厂程序。 | 符合设计 |
7 | 运行用户程序时远程升级用户程序区域 | Boot要求更新用户程序,使用Tftpd客户端软件远程升级用户区程序后,Boot程序成功跳转至用户程序区。 | 符合设计 |
8 | 升级过程中关闭TFTP客户端软件 | Boot超时重传,当重传次数过多时,跳转到正确的应用程序 | 符合设计 |
9 | 启动远程升级,但不传送任何数据 | Boot运行超时后,自动跳转到正确的应用程序 | 符合设计 |
10 | 启动远程升级,但上传的文件名非法 | 服务器向客户端回送”Bad filename.”错误信息 | 符合设计 |
11 | 启动远程升级,但上传的文件过大 | 服务器向客户端回送“Bad file length.”错误信息 | 符合设计 |
12 | 启动远程升级,使用Get按钮从服务器下载文件 | 服务器向客户端回送”File not fount.“信息 | 符合设计 |
13 | 启动远程升级,模拟数据丢包 | 数据丢包后,Boot程序启动超时重传机制,再次向客户端回送最后一帧数据 | 符合设计
|