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.4 在应用编程(IAP) lpc1778芯片内部提供了编程Flash的底层代码,只需构造一个函数指针调用芯片提供的Flash编程代码即可。关于NXP ARM芯片的在应用编程基础知识可以参考我写过的一篇博文:基于IAP和Keil MDK的远程升级设计 。
3.5 超时退出Boot程序
Boot程序其实主要有两个作用,一个是上电后如果不需要升级程序,则跳转到出正确的应用程序。二是上电发现需要升级程序则启动TFTP服务器,与TFTP客户端进行文件传输。可以发现,无论是第一个作用还是第二个作用,Boot执行的时间都不可能太长,毕竟真正使用的程序并不在于Boot。但是如果我们设置了升级标志后,又迟迟不给TFTP发送升级文件,这时设备会一直运行Boot程序,因此我们需要一个Boot程序执行超时定时器,来确保Boot程序执行时间到达后,跳转至正确的应用程序。 3.6 Boot程序部分指标
- 吞吐率:≈20KB/S
- 代码使用量:≈16.5KB
- RAM量使用量:≈28.5KB
|