引言
随着人们对信息化程度的要求不断提高, 设备上网已经成为一个趋势。32位机资源丰富,上网方案也较为成熟,但成本相对较高,因而价位偏低的8位机上网方案成为研究的热点。但是,8位机资源有限,因此在实现8位机以太网连接时,一定要考虑周全。本文介绍在VRS51L3074上实现TCP/IP协议栈uIP的移植,成功实现了socket通信。
硬件平台
本方案的硬件平台主要由VRS51L3074和CS8900A组成,经网络变压器的隔离,CS8900A与网络接口RJ-45连接上,这样整个系统就可以连接到Ethernet。数据输入可由串口传递给系统。硬件平台如图1。
图1 硬件平台(略)
VRS51L3074简介
VRS51L3074是Ramtron公司最新推出的单周期、基于8051内核、功能丰富的SOC单片机,是全球第一款集成FRAM的高性能单片机。CPU最高处理速度可达40MIPS,内置64kB Flash存储器支持ISP、IAP功能、4kB+256B的SRAM以及8kB的FRAM,带有完全可配置的I2C接口和SPI接口等片内外设,支持JTAG下载和非侵入式在线调试。VRS51系列单片机和8051完全兼容,支持SDCC、Keil等C编译器,编译和下载时需要一些特殊的配置。Versa Ware JTAG软件是VRS51系列单片机的下载工具,和Keil uVision配合使用时需要一些配置。
CS8900A简介
CS8900A是CIRRUS LOGIC公司的一种低价位、高集成度、低功耗、全双工的16bit以太网控制器,是一款专门为嵌入式系统设计优化的以太网控制器。该芯片的突出特点就是使用灵活,其物理层接口、数据传输模式、工作模式都能根据需要而进行动态配置,可通过内部寄存器的配置来适应不同的应用环境。CS8900A有三种工作模式:I/O模式、存储器模式和DMA模式。
CS8900A基本工作原理是:在收到由主机发来的数据报后,侦听网络线路。如果线路忙,它就等到线路空闲为止,否则立即发送该数据帧 。发送过程中,首先它添加以太网帧头(包括先导字段和帧开始标志),然后生成CRC校验码,最后将此数据帧发送到以太网上。接收时,它将从以太网收到的数据帧在经过解码、去掉帧头和地址检验等步骤后缓存在片内。通过CRC校验后,它会根据初始化配置情况,通知主机CS8900A收到了数据帧,最后用某种传输模式传到主机的存储区中。
嵌入式TCP/IP协议栈uIP
TCP/IP是一个协议族,它是一个四层协议模型,包括应用层、传输层、网络层和网络接口层。应用层定义清晰的会话过程,HTTP、FTP、Telnet和SMTP等都属于应用层协议;传输层提供端到端的通信,该协议有传输控制协议(TCP)和用户数据报协议(UDP);网络层负责数据打包和逻辑寻址,IP、ICMP和ARP等协议都属于网络层;网络接口层负责在源和目的节点间线路上进行无差错的传输数据,具有流量控制等功能。
TCP/IP协议较为复杂,实现起来非常困难,一般都采用现有的TCP/IP协议栈来实现。本系统就是采用源码开放的免费嵌入式TCP/IP协议栈uIP来实现TCP/IP协议的。
uIP是专门为8位和16位嵌入式微控制器设计的微型TCP/IP协议栈 , 它是由瑞典计算机学院的Adam Dunkels开发的免费开源软件,最新版本为uIP1.0。uIP完全是由C语言编写的,因此可移植到各种不同的CPU结构和操作系统上。uIP提供了网络通信所必须的协议,本身代码和占用的内存数都非常少,uIP的源代码只有几kB,RAM仅占用几百字节。uIP具有如下特点:
1)完整的说明文档和公开的源代码,全部由C编写,并附有详细的注释,便于移植。
2)极少的代码占用量和RAM资源要求,尤其适合于8/16位单片机。
3)支持IP、ARP、TCP、ICMP和UDP等基本功能。
4)高度的可配置性以适应不同资源条件和应用场合。
5)支持多个主动连接和被动连接并发,支持连接的动态分配和释放。
6)简易的应用层接口和设备驱动层接口。
7)完善的示例程序和协议实现范例。
为了节省资源占用,简化应用接口,uIP1.0在内部实现上做了特殊处理。
1)注意各模块的融合,减少处理函数的个数和调用次数,提高代码复用率以减少ROM占用。
2)基于单一全局数组的收发数据缓冲区,不支持内存动态分配,由应用负责处理收发的数据。
3 )基于事件驱动的应用程序接口,各并发连接采用轮循处理,仅当网络事件发生时,由uIP内核唤起应用程序处理,这样uIP用户只须关注特定应用就可以了。传统的TCP/IP实现一般要基于多任务处理环境,而大多数8位机系统不具备这个条件。
4)应用程序主动参与部分协议栈功能的实现(如TCP的重发机制,数据包分段和流量控制),由uIP内核设置重发事件,应用程序重新生成数据提交发送,免去了大量内部缓存的占用。基于事件驱动的应用接口使得这些实现较为简单。
uIP实现了TCP/IP协议族的四个基本协议:ARP(地址解析协议),IP(网际协议),ICMP(因特网信息控制协议)和TCP(传输控制协议),UDP协议是可选模块。
IP(Internet Protocol网际协议)是TCP/IP协议族中最为核心的协议,提供不可靠的无连接的数据报传送服务。所有的TCP、UDP、ICMP及IGMP数据都是以IP数据报格式传输的。uIP的IP协议主要负责封装TCP帧、验证输入包IP头的正确性、接受IP数据报进行处理并向上层协议提交以及TCP与ICMP之间的复用数据包。为了节省占用空间,uIP1.0只支持一个数据报的分片和重组。
TCP(Transmission Control Protocol)协议是传输层的协议之一,它提供高可靠性的数据通信。TCP的主要工作是把应用程序交给的数据分成适当的小块交给下面的网络层,确认收到的分组,设置发送最后确认分组的超时时钟等。TCP是uIP重点实现的协议。为了减少存储器空间占用,uIP没有实现TCP发送和接收数据的窗口调整,且不会缓存收到的TCP段,而是立即交给应用程序处理。重发也是由应用程序实现的。在输出数据时,每一个连接只能有一个正在传输的TCP段。
ICMP(Internet控制报文协议)用来传递差错报文以及其他需要注意的信息。uIP只实现了echo。
ARP(Address Resolution Protocol)为IP地址到对应的硬件地址之间提供动态映射。ARP协议是把目标IP地址解析为以太网MAC地址,当一个IP包要在以太网上发送时,先查询ARP表,找出要发送的MAC地址。如果在表里找不到对应的IP地址,就会广播ARP请求包,以获取给出IP地址所对应的MAC地址。目的主机收到请求包后发出一个ARP回应包,给出自己的MAC地址和IP地址。ARP表每十秒更新一次。ARP协议是uIP的可选模块。
UDP(User Datagram Protocol)协议是一个简单的、面向数据报的传输层协议。UDP协议是uIP可选模块。
uIP是一个专为8位和16位单片机设计的小型简易的TCP/IP协议栈,简单易用、占用资源少是其设计特点。为了占用较少的资源,uIP只保留了基本的通信功能而把全功能协议栈中那些不常用的功能去掉,其重点是在IP、TCP和ICMP的实现上,而把ARP和UDP作为可选模块。uIP体系结构如图2。
图2 uIP体系结构(略)
uIP处于网络通信的中间,其上层协议是应用程序层,其下层硬件或固件称为网络设备驱动层。uIP并不仅仅是为以太网设计的,它与媒体无关。
uIP的设备驱动程序接口
uIP中需要底层驱动支持的函数有:uip_input( )和uip_periodic( )。uip_input( )函数是用来处理网络层和设备驱动层之间的传送数据的,当设备驱动程序从网络层收到一个数据包时会调用此函数,设备驱动程序会事先把数据包存放在uip_buf[ ]缓冲区里,而把数据长度放到uip_len,然后交给uip_input( )函数处理。当函数返回时,如果uip_len不为0,则表明带有数据。如果需要ARP支持时,则要考虑更新ARP 表或者发送ARP请求和回应。
uip_periodic( )用于内部时钟事件计时,当周期定时激发时,每一个 TCP连接应该调用uip_periodic( )函数。这个函数用于uIP内核对各连接的定时轮循,因此需要一个硬件支持的定时程序周期性地用它轮循各连接,一般用于检查主机是否有数据要发送,如果需要则构造IP包。
从本质上来说,uip_input( )和uip_periodic( )在内部是一个函数,即uip_process ( )。UIP的设计者将uip_process(UIP_DATA)定义成uip_input( ),而将uip_process(UIP_TIMER)定义成uip_periodic( ),因此从代码实现上来说是完全复用的。
uIP应用程序接口
uIP在接受到底层传来的数据包后,如需送上层应用程序处理,就会调UIP_APPCALL( ),同时uIP设置UIP_CONN结构体指针指向当前连接。UIP_CONN记录一条TCP连接的所有相关信息。为了将用户的应用程序挂接到uIP中,必须将宏UIP_APPCALL( )定义成实际的应用程序函数名,这样每当某个uIP事件发生时,内核就会调用该应用程序进行处理。如果要加入应用程序状态的话,必须将宏UIP_APPSTATE_SIZE定义成应用程序状态结构体的长度。
uIP在VRS51L3074上的应用和简单Socket通信
本硬件平台是网络POS机的一部分,它的工作原理是:由扫描枪采集的数据经串口送入网卡内,然后经网络发送到远端主机。
本系统的软件部分包括网络设备驱动程序、TCP/IP协议栈实现以及简单的Socket通信程序。
CS8900主要包括三个部分:EtherDevInit()函数完成CS8900A网络芯片的初始化,包括初始化寄存器等,使之进入服务状态;EtherDevSend()实现把以太网数据包发送到网络中;EtherDevRecv()完成数据的接受。在CS8900的头文件中设置了MAC地址以及其他的一些参数。
网络设备驱动程序通过两个全局变量与uIP协议栈进行接口:uip_buf为收发缓冲区,uip_len为数据的长度。EtherDevSend( )函数把uip_buf里的数据发送到网络中,EtherDevRecv( )函数把接受到的数据存储到uip_buf缓冲区中,同时修改uip_len的值。
uIP协议栈承担网络通信功能,一方面与底层链路层通信实现数据收发,另一方面为上层应用程序提供了简单的API接口。uIP基本实现了IP、TCP、ARP、UDP以及ICMP(ping)等协议,它包括uip.c、uip_arch.c、uip_arp.c、uip.h、uipopt.h、uip_arch.h、uip_arp.h等文件。uip.c完成主要TCP/IP功能,主要是IP和TCP协议,UDP是可选模块;uip_arp.c完成地址解析;uip_arch.c完成校验;uipopt.h是uIP配置文件,它以宏的形式定义便于修改,用户可根据自己的需要设置本地的物理地址、IP地址、网关地址、收发缓冲区大小、支持的最大连接数以及ARP表大小等选项。
VRS51L3074有3个16-bit的定时器,可以选择一个为TCP/IP协议中与事件有关的事件定时。uIP中需要定时的事件有:为uip_periodic( )函数的执行提供基准和ARP表更新。uip_periodic( )函数每0.5秒执行一次,ARP表每10秒更新一次。
添加了必需的模块,进行了正确的配置后,需要编写主程序和应用程序。主程序流程图如图3。
图3 主程序流程图(略)
初始化包括定时器初始化、串口初始化、网卡芯片初始化、uIP协议栈初始化、用户应用程序初始化等,主程序初始化完成后,进入不停查询的状态,如果有数据到来,则交给uip_input( )进行处理,如果没有则由uip_periodic( )来处理定时事件。为了将应用程序挂接到uIP中,必须把UIP_APPCALL( )定义为实际的应用 程序函数名,这样每当某个uIP事件发生时,内核就会调用该应用程序进行处理。本应用程序定义 #define UIP_APPCALL socket_appcall。
结束语
本方案成功地把嵌入式TCP/IP协议栈uIP移植到VRS51单片机上,实现了网络通信。该方案是网络POS机的一部分,目前已经正在运行,且状态良好。本方案采用的单片机和网络芯片不但性能良好而且价格低廉,uIP是一个性能优良的免费小型TCP/IP协议栈,因此本系统运行速度快、稳定可靠且价位较低。本方案可广泛应用于远程数据采集、传输,远程监控,远程抄表以及 信息家电等领域。 |