摘 要:随着嵌入式技术在军工、信息家电中的应用,如何在嵌入式实时系统下对网卡进行驱动程序的设计以及实现网络通信和管理,成为非常重要的技术。本文首先从整体上VxWorks网络系统得基本原理和与结构,然后以Intel82557网卡驱动为例,着重介绍网络设备驱动程序设计与实现过程。本文对所有基于MUX机制下的VxWorks网络设备驱动程序开发者具有参考价值.
Abstract:As Embedded system are the most popular technology applied in war industry, information appliances ,it has become an important technology how to design the device drivers and implement network communications and management under embedded system. At first, this article analyzes the base principle of network driver in VxWorks and its architecture. Then it mainly illustrates how to develop the enhanced network device driver by example of Intel82557 the enhanced network driver 。It has a reference value for other network device driver developers.
引言
VxWorks 是一个具有微内核、可裁剪的高性能强实时操作系统,它以其良好的可靠性和卓越的实时性被广泛地应用在通信、军事、航空、航天等高精尖技术及实时性要求极高的领域中。我校研制的综合导航显控台采用VxWorks操作系统,它作为舰船导航系统的核心设备实时为导航、通信、驾控系统提供各种信息。当需要更改海图模块硬盘中一些及时需要修改的数据、程序和电子海图等信息时,为避免拆卸设备,可以通过网络传输来解决上述问题。可以本文以Intel82557网卡为例 ,给出了基于VxWorks的网络设备驱动程序的开发方法和实现流程。
1 VxWorks的网络结构
VxWorks提供了与其他TCP/IP网络系统间“透明”的存取方式、BSD Socket兼用的编程接口,远程过程调用(RPC),远程文件存取等。网络驱动程序和上层网络协议栈可以有两种实现形式:BSD方式和MUX方式。在VxWorks中, MUX与END合称 SENS驱动(可裁剪增强型网络驱动)。网卡驱动程序的层次结构使网卡驱动程序的实现和移植更加方便。而且VxWorks为编写网卡增强型驱动程序(SENS)提供了很好的接口和规范。下图是VxWorks的网络系统。
图1 VxWorks的网络系统
2 END驱动概述
2.1 MUX与END
VxWorks网络协议栈可以分为以下几层:应用层 、传输层、IP层、MUX层、数据链路层和物理层。如图2所示。
图2、VxWorks网络协议栈分层结构示意图
从上图看出,与其他TCP/IP 协议相比VxWorks网络协议栈增加一层MUX层。MUX层是VxWorks为方便在网络接口硬件上实现多种协议而增加的一层 。它主要用于管理底层的多种硬件的设备驱动,向上层不同协议提供统一的接口,降低了上层协议与底层物理硬件的藕合,使得网络驱动和上层协议彼此保持独立,既方便在现有硬件基础上实现新的上层协议,也利于用新的硬件支持原有的上层协议。
MUX与END的交互是通过提供一套可供底层调用接口服务来实现的,实现END驱动必须遵循这套接口关系。如图3所示
图 3、MUX与END 的接口关系
上图中右边框中列出的函数是驱动需要实现的函数,供MUX 层调用在必要的时间调用,如当上层使用该网卡发送数据时,MUX 会调用该网卡END 驱动提供的Send函数,将数据提交给网卡芯片硬件。
2.2缓冲池数据结构
网络设备驱动与上层协议进行数据交换需要相应的内存缓冲,并且管理这些缓冲也需要相应的函数。VxWorks提供了netBufLib函数库用于创建和管理网络设备用到的内存缓冲池,网络设备驱动可以直接使用也可以在此基础上设计自己特定的内存缓冲池。数据以簇的形式保存,数据结构mBlks(内存块)和clBlks(簇块)形成的数据链结构则用于指定各个簇。
在clBlk之上是mBlk结构。该结构存储一个到clBlk的连接,也可以存储一个到另一个mBlk的连接。通过mBlk的连接,可以引用任意数量的数据,如图4所示
图4 mBlks和clBlks的数据结构
3 END驱动实现
3.1 END 设备驱动程序装载过程
END设备驱动程序装载过程实际上是分三个步骤完成的。即指定END设备、装载END设备和启动END 设备。
3.1.1指定END 设备
网络设备的驱动程序安装时通过修改相应的BSP实现。在修改BSP之前,首先看一下BSP中的END设备驱动程序入口表END_TBL_ENTRY的结构。在BSP的configNet.h文件中定义着 END_TBL_ENTRY结构的数组endDevTbl[],其结构原型如下所示:
END_TBL_ENTRY endDevTbl[]= { ----- #ifdef INCLUDE_FEI_END {0,FEI82557_LOAD_FUNC,FEI82557_LOAD_ STRING,FEI82557_BUFF_LOAN,NULL,FALSE}, #endif /*INCLUDE_FEI_END*/ #ifdef INCLUDE_ELT_3C509_END {0,END_3C509_LOAD_FUNC,END_3C509_LOAD_STRING,END_3C509_BUFF_LOAN,NULL,FALSE} #endif /*INCLUDE_ELT_3C509_END*/ ----- };
该数组描述了系统中的所有网络设备的装载函数入口点及其相关参数。将网络设备驱动程序的装载函数fei82557EndLoad()入口点及相关参数添加到网络设备表endDevTbl[] 中,而后在config.h中加入“#define INCLUDE_END”以使系统准备初始化MUX并通过MUX装载网络设备驱动程序。
在VxWorks网络驱动程序的编程规范中,为了系统的高移植性、兼容性和可裁剪型等,通常在configNet.h文件中对系统支持的INTEL82557网络设备定义一些宏,其编写规范如下所示:
#ifdef INCLUDE_FEI_END #define FEI82557_LOAD_FUNC fei82557EndLoad /*设备驱动程序装载函数*/ #define FEI82557_BUFF_LOAN 1/*允许缓冲借出*/ /* *fei82557End初始化字符串格式: *::::<user—Flags> */ #define FEI82557_LOAD_STRING“-1:0x00:0x20:0x20:0x00” IMPORT END_OBJ*FEI82557_LOAD_FUNC(char*, void*); #endif /*INCLUDE_FEI_END*/
3.1.2装载及启动END 设备
装载及启动END设备的系统函数主要用到以下几个:
(1).muxDevLoad()
该函数装载指定设备的驱动程序装载函数。如果要装载END 设备,系统必须调用muxDevLoad()函数。
(2).muxDevStart()启动设备函数
(3).muxBind()
muxBind()可以将协议绑定到指定的END 设备上。其调用过程是系统调用ipAttach()函数,而该函数调用muxBind()函数,绑定协议堆栈到MUX上的一个指定的网络接口。当一个网络接口被关闭时,ipAttach()函数将释放网络接口所关联的TCP/IP堆栈模块。
装载及启动END设备驱动程序的流程如下:
使用指定的END 设备驱动程序的BSP 引导VxWorks系统时,在引导过程中,系统将执行任务tUsrRoot 来完成如下各项:
- 初始化网络任务的工作队列;
- 创建tNetTask任务来处理网络任务工作队列的条目;
- 调用muxDevLoad()装载指定的网络驱动程序;
- 调用muxDevStart()启动指定的网络驱动程序。
tUsrRoot任务调用MUX设备装载函数muxDevLoad()和设备启动函数muxDevStart(),通过这两个函数来装载和启动设备驱动程序。
muxDevLoad()函数会根据网络设备表endDevTbl[]中的定义逐一调用各网络设备的装载函数,其中这个函数是muxDevLoad()的一个输入参数。muxDevStart()函数也会根据endDevTbl[]逐一调用网络设备所定义的设备开始函数。至此MUX的歘石化以及END 驱动程序的初始化工作已经完成。但是网络设备还是不可以使用,因为还需要将协议绑定到指定的END 指定的设备上,这一步需要用muxBind()函数实现。
在VxWorks中,系统通过usrRoot()函数调用usrNetInit()函数完成MUX的初始化、装载网络设备表endDevTbl[]中描述的所有设备并将IP协议绑定到网络引导设备上等工作。
网络设备驱动程序的安装过程即下图所示的网络初始化顺序
图5 网络初始化顺序
3.3、发送数据
在VxWorks网络系统中,发送数据的流程如图
通过对上图分析,主要包含以下几个处理。
- 用户调用write()函数,通过套接字访问网络。
- 网络协议拷贝需要发送的数据到网络缓 区中,并调用协议驱动程序的发送程序。
- 协议驱动程序调用muxSend()启动发送循环。
- muxSend()通过调用send()回调函数,把缓冲区传递给END。
- 数据发送程序把数据拷贝到设备缓冲区中,并 把它放置到设备的发送队列中。
- 当产生发送中断时,驱动程序的中断服务程序调度程序丢弃已发送的数据包,彻底清理发送队列。
3.4、接收数据
在VxWorks网络系统中,接收数据的流程如图
通过对上图进行分析,它主要包含以下几个处理。
(1)设备接收到数据包后直接把数据存放到预先分配的簇中。
(2)当接收到中断时,驱动程序的中断服务程序调度任务级接收程序进行如下操作。
①clBlk结构和簇连接;mBlk和clBlk连接;最后构成缓冲区。
②通过调用receiveRtn()函数,把缓冲区传递给更高级别的协议。
(3)muxReceive()调用协议的stackRcvRtn()函数,把成列的缓冲区传递给应用。用户使用read()函数,通过套接字访问网络中的成列缓冲区
3.5、驱动程序的中断处理
中断处理函数fei82557INT处理设备中断。当网络接口产生中断时,系统调用用户驱动程序注册的中断服务程序。中断程序主要完成将数据包从本地网络设备送出的操作。为了排列任务级的包接收处理工作,网络驱动程序中断服务程序必须调用netJobAdd()函数。在调用netJobAdd()函数时,应当指定任务级处理数据包的驱动程序入口。然后由netJobAdd()把函数指派到网络系统任务——tNetTask的工作队列中。VxWorks通过tNetTask处理任务级的网络处理。
tNetTask调用队列中处理程序如下:
- 包接收程序:把接收到的数据包上传到网络缓冲区的堆栈中,通过一个调用上传给MUX。
- 释放所有发送帧程序:程序调用netClFree()函数释放发送缓冲区中所有已经发送的数据帧。
4、结束语
本文分析了VxWorks下网卡驱动程序的原理,并以Intel82557网卡为例具体说明了网卡驱动的设计开发过程。 主要就VxWorks下网卡驱动程序的共性做了阐述, 比如VxWorks下网卡驱动的在结构、在整个系统中的位置,中断处理,收发包存储空间分配等。
参考文献:
- 周启平、张扬,VxWorks下设备驱动程序及BSP开发指南.[M]中国电力出版社.2004.
- 孔祥营、张保山、俞烈彬,VxWorks驱动及分布式编程. [M]中国电力出版社.2007.
- Wind River Systems, Inc. VxWorks Network Protocol Toolkit Users Guide[ K]. California: Wind River, 1999.
- 王守林、苏建华,VxWorks下PCI网卡驱动程序结构与实现.[J] 工业控制计算机.2005
- 景琦,基于VxWorks的设备驱动和网络通信.[D]西安科技大学.2006.