文献标识码: A
文章编号: 0258-7998(2014)04-0126-04
在高科技研究以及工业、医疗、交通、航空等众多领域中,对高帧率和高分辨率的图像数据需求逐渐加大,例如航天和军工中高速物体运动轨迹的捕捉、3D动漫、视频定位和测量、高速公路交通监控等。然而,连续的高帧率和高分辨率图像采集将产生巨大的数据量,例如以10 f/s帧率传输分辨率为4 928 V×3 280H的视频图像时,总线上的数据速率高达1.23 Gb/s;以500 f/s帧率传输分辨率为640 V×480 H的视频图像时,总线上的数据速率也高达1.18 Gb/s。为了实现1 Gb/s以上的传输速度且满足实时性和长距离传输的要求,选用光纤技术和PCI Express(简称PCI-E)总线技术设计了PCI-E总线光纤接口卡。
光纤具有频带宽、传输距离长、损耗低、抗干扰能力强等优点[1],适用于大量数据的远程传输。PCI-E总线采用了串行点对点通信技术,使传输速率大幅度提高,PCI-E 1.0标准的单通道单向速率高达2.5 Gb/s,且最大支持32通道[2]。PCI-E 3.0标准单通道单向速率可达8 Gb/s,是传输高速、大数据量总线的首选,具有研究和应用价值。
本文基于Spartan-6芯片设计的PCI Express光纤接口卡的驱动程序,完成的功能有:(1)驱动程序对光纤接口卡硬件资源的获取; (2)光纤接口卡能够将大量数据及时发送到计算机内存中; (3)合理的中断机制能够满足处理高速图像的需要; (4)计算机可以向光纤接口卡发送参数命令。
1 PCI Express接口卡的硬件结构
PCI Express接口卡基于Xilinx公司的Spartan-6 LTX系列FPGA设计,完成图像数据收发、数据缓存以及PCI-E协议等工作,并将采集到的图像数据通过PCI-E总线传输给计算机。Spartan-6 LTX系列FPGA内部包含一个PCI-E端点硬核,完整实现了PCI-E1.0标准协议中的数据链路层和物理层的功能,可以完成1链路的PCI-E总线传输[3]。光纤接口卡采用单片高性能FPGA设计,具有系统集成度高、硬件设计简洁且便于扩展的特点。末端利用计算机对采集的图像进行显示、存储以及回放等操作。PCI Express接口卡的硬件结构如图1所示。
利用ISE中的IP核生成工具CORE Generator对PCIE端点硬核进行定制:设备ID采用默认值,Vendor ID = 0x10EE,Device ID = 0x0007,这是驱动程序识别该硬件的厂商号和设备号; 基址寄存器的类型选择为Memory,开辟一个32 位寻址的1 KB大小的存储器空间;中断设置为采用INTA的传统中断类型。
基址寄存器设计是实现接口卡功能关键内容,按照偏移地址将1 KB的存储器空间划分成功能不同的寄存器,部分定义如表1所示。
2 PCI Express接口卡的驱动程序
2.1 开发工具Windows DDK简介
Windows DDK是微软提供的驱动程序开发工具包,包括了设备驱动开发的文档、头文件和库文件、调试工具和程序示例。先将Windows DDK导入VC++软件开发工具,然后用C语言编写驱动程序代码,编译后再用Windows DDK中的调试软件调试,生成可执行的驱动程序。使用Windows DDK能够开发出真正意义上的核心态驱动程序,它所开发的驱动程序效率也是最高的,但必须详细了解操作系统的内核工作方式,开发难度较大[4]。
常用开发工具还有WinDriver和DriverStudio,为了获得最大的驱动程序效率,选择采用Windows DDK来设计PCI Express接口卡的驱动程序。
2.2 WDM启动程序的结构
通常WDM驱动程序都是基于分层的结构设计,由功能驱动函数、总线驱动程序和过滤器驱动程序三部分组成。完成一个设备的操作,至少要有两个驱动设备共同完成[5],一个是总线驱动程序生成的物理设备对象(PDO),另一个是功能驱动程序生成的功能设备对象(FDO)。
Windows XP系统检测到PCI-E接口卡插入主板卡槽时,总线驱动会自动创建出一个PDO。但是PDO不能单独操作设备,还需要将实现功能的FDO挂载在总线驱动生成的PDO上,即相当于功能驱动程序挂载到了指定的硬件设备上[6],实现驱动程序对硬件设备的控制。
2.3 接口卡发送数据
为了提高接口卡的传输效率,采用DMA的传输方式将图像数据通过PCI-E总线发送到计算机。在DMA传输过程中,PCI-E接口卡作为DMA传输的主控器,数据的传输速度基本由PCI-E总线的传输速度决定[7]。
2.3.1 获取接口卡的资源信息
接口卡发送图像数据之前,驱动程序要将DMA传输的目标地址以及数据负载的大小发送给接口卡,驱动程序需要先获取接口卡上的硬件资源,如接口卡端点内存的物理地址等。
首先根据设备类型和设备扩展的大小,利用函数IoCreateDevice生成并初始化一个FDO;其次利用函数IoAttachDeviceToDeviceStack将生成的FDO附加在系统生成的PDO上;然后向PDO转发一个IRP_MN_START_DEVICE类型的I/O 请求包(IRP),PDO会根据设备的类型自动枚举该设备的所有资源。为了使FDO能够得到底层PDO处理IRP的结果,需要同时将一个同步事件发送给底层PDO。PDO处理完IRP后立刻激发同步事件,通知FDO查询此次IRP的结果; PDO完成了对IRP_
MN_START_DEVICE命令的响应后,将获取到的接口卡设备资源存储在IRP中名为IO_STACK_LOCATION结构的设备堆栈中[8],流程如图2所示。
利用函数IoGetCurrentIrpStackLocation可以获得该IO_STACK_LOCATION结构,主要包含接口卡的中断信息、端点内存寄存器资源以及接口卡的物理地址等设备硬件资源。
2.3.2 分配内存空间并实现乒乓操作
为了尽可能提高计算机内存资源利用率,驱动程序分配的内存空间大小与每次DMA传输的图像数据大小需保持一致。先利用函数IoGetDmaAdapter获取一个DMA适配器,包含了开辟内存空间的函数AllocateCommonBuffer,调用此函数获得一段指定大小的连续物理内存,保存物理内存的逻辑地址作为DMA传输的目标地址。
预先在计算机中分配了多块内存空间,使计算机可以在处理一块写满了图像数据的内存缓冲区的同时,用另一块闲置的内存缓冲区接收DMA传输的图像数据,从而实现乒乓操作,提高传输效率[9]。
接收到DMA传输开始的指令后,PCI-E接口卡会根据分配好的内存空间地址和设定好的DMA传输负载长度,不断地向计算机发送带有图像数据的TLPs数据包[10]。每次DMA传输结束后,驱动程序都会根据是否希望继续进行DMA传输选择轮转一块新的内存地址发送给接口卡或者释放相关资源。DMA传输操作流程图如图3所示。
2.4 驱动程序的中断处理
驱动程序接收到PCI-E接口卡产生的中断信号,表明PCI-E接口卡已经向计算机指定的内存空间完成了一次DMA传输,要通知应用层程序对内存中的数据进行访问,完成显示、存储等功能。先利用函数IoConnectInterrupt将中断例程与设备产生的中断信号绑定。根据计算机中断优先级的规则,硬件中断会得到操作系统的优先响应[11]。
计算机操作系统检测到PCI-E接口卡的中断信号来临时,立即进入中断服务例程(ISR)。由于接口卡采用的传统中断是一种电平中断信号,还需要驱动程序在ISR中进一步完成对中断来源的判断和清除中断的操作。
采用同步事件方式实现中断信号的同步处理,先在应用程序中定义一个与驱动程序共享的同步事件,并通过DeviceIoControl函数把该事件句柄传递给驱动程序,等待事件触发之后再进行读数据操作。驱动程序根据所传递的这个事件句柄创建一个相应的内核事件[12]。中断发生时驱动程序调用KeSetEvent函数将同步事件设置为激发态,通知应用程序中断已经发生。尽量减少ISR程序的运行时间,将激发同步事件的动作设计发生在拥有较低中断等级的延迟过程调用例程(DPC)中[13]。中断处理流程如图4所示。
2.5 驱动程序向接口卡发送指令
指令发送可以分为两个子过程,首先应用程序与驱动程序实现交互,然后驱动程序再根据交互获得的参数,修改PCI-E接口卡端点内存中寄存器的值[14]。
用函数IoRegisterDeviceInterface将一个名为GUID的128位二进制数字标识符与PDO绑定在一起。应用程序利用函数OpenDeviceByGuid获取被绑定的驱动程序的设备句柄,再利用这个设备句柄和函数DeviceIoControl完成应用程序与驱动程序之间的通信与交互。DeviceIoControl函数可以将指定字节数量的数据传入驱动程序,同时也可以接收驱动程序返回的数据。
下面举例给出一个发送光纤相机帧的行大小的参数指令代码:
#define IOCTL_LINE CTL_CODE (// 定义控制码
FILE_DEVICE_UNKNOWN,//对象类型0x828,//驱动程序定义的IOCTL码METHOD_BUFFERED, //操作模式FILE_
ANY_ACCESS) // 访问权限
hDevice = OpenDeviceByGuid(// 打开驱动
(LPGUID) &GuidDriver); //接口卡设备句柄
ULONG value=0; //初始化输出缓冲区
value = (m_Line<<16)|0x03; //光纤相机帧的行大小
DeviceIoControl (//发送相机参数命令到驱动程序
hDevice, //上文打开设备后返回的句柄
IOCTL_LINE //控制代码名称
&value //输入缓冲区地址
sizeof(value) //输入缓冲区大小
NULL,//返回缓冲区地址
NULL 0 //返回缓冲区大小为0
&nOutput // 记录返回的数据大小
NULL)// 默认为NULL
…
switch (ioStack->Parameters.DeviceIoControl
.IoControlCode) // 驱动程序获取IOCTL码
case IOCTL_LINE: // 驱动程序接收到命令
address=(ULONG)deviceExtension->
MemoryStart[FPGA]+LINE; //设定PIO传输的目标地址
WRITE_REGISTER_ULONG((PULONG)address,
*pBuffer); //写接口卡寄存器
应用层将相机参数和指令一同发送给了驱动程序,驱动程序利用在获取PCI-E接口卡硬件资源时,保存接口卡物理地址和端点内存的寄存器偏移地址,完成对寄存器中数据的修改,实现对前端相机的控制。
利用FPGA内的计数器不断产生数据,使PCI-E接口卡不停地进行DMA传输。应用程序使用QueryPerformanceFrequency获取处理器频率,使用QueryPerformanceCounter查询定时器计数值。经多次反复测试,系统实际最大有效传输速度为1.5 Gb/s,高于利用DriverStudio工具开发的驱动程序实现的720 Mb/s有效传输速度[15]。
PCI-E总线采用8b/10b编码, 因此使用1.0标准的PCI-E总线的理论有效输速度为2.0 Gb/s[16],分析实际有效传输速度没能达到理论值的原因是: (1)驱动程序基于Windows XP系统设计,该操作系统不支持MSI中断方式,在响应DMA传输的传统中断时会占用一定时间; (2)发起DMA传输前需要设置FPGA内相关寄存器,这也需要一定的时间。
经安装光纤相机后测试,能够清晰、流畅地显示图像大小为1 280 H×720 V、帧率为120 f/s、传输速率为842 Mb/s的图像数据。驱动程序工作稳定,并且可满足多种数据类型的传输。
参考文献
[1] 吴德明.光纤通信原理与技术[M].北京:科学出版社, 2004.
[2] 王齐.PCI Express体系结构导读[M].北京:机械工业出版社,2010.
[3] XILINX. Xilinx solutions guide for PCI express user guide [EB/OL].[2009-09-16]. Http://www.xilinx.com/.
[4] 李忠辉,张志文.PCI设备驱动程序的开发和应用[J].西安工业学院学报,2005,25(1):8-11.
[5] 张帆,史彩成. Windows驱动开发技术形式详解[M]. 北京:电子工业出版社,2008.
[6] 蹇红梅,居锦武,王兰英. Windows设备驱动程序的开发[J]. 四川理工学院学报(自然科学版), 2007(4):11-13.
[7] 席华伟.基于Verilog语言的DMA控制器的设计与仿真[D]. 西安:西安电子科技大学,2007.
[8] 武安河.Windows 2000/XP WDM设备驱动程序开发[M]. 北京:电子工业出版社,2003.
[9] 何柳,陈勇,吴斌.PCI/PCI-E高速实时DMA传输驱动设计[J].电子技术应用,2012,38(11):143-145.
[10] 董永吉,陈庶樵,李玉峰,等.Xilinx PCI-Express核总线接口设计与实现[J].电子技术应用,2011,37(8):135-138.
[11] 田泽, 刘娟, 王琦卉.基于WDM的PCIE驱动设计和实现[J]. 软件导刊,2010,9(4):9-10.
[12] 司刚,付少锋,周利华.WDM驱动程序中设备事件通知技术研究[J].计算机技术与发展,2006,16(4):144-146.
[13] 梁国龙,何昕,魏仲慧,等.PCIE数据采集系统的驱动程序开发[J].计算机工程与应用,2009,45(31):63-65.
[14] Peng Yu, Li Bo, Liu Datong, et al. A High Speed DMA transaction method for PCI express devices[J]. Journal of Electronic Science and Technology of China, 2009,7(4):380-384.
[15] 王维,蒋景宏,刘垚.基于PCI Express总线光纤采集卡WDM驱动程序设计[J].计算机测量与控制,2013,21(1):272-275.
[16] PCI-SIG. PCI Express card electromechanical specification revision 1.0[S].2002.