基于PCI Express总线的雷达数据记录器驱动程序开发
扫描二维码
随时随地手机看文章
在数据采集系统中,大量的数据必须通过总线传到计算机内存中,传统的PCI总线越来越不能满足人们对带宽增长的需要。为解决这一矛盾,PC行业协会和外设厂商一起发布了PCI Express总线[1]规范,并且于2004年在标准台式机上得到应用。该技术可以有效地提高设备至计算机内存的数据传输速率。相对于PCI总线,它最大的特点是实现点到点的数据传输[2],每个设备有自己专用的双向数据通道,数据以包的形式串行传输,每个通道具有单方向250MB/S的数据传输速度。多个通道可以组合在一起形成x1(单通道)、x2、x4、x8、x12、x16和x32的信道以提高带宽。
在合成孔径雷达系统中,大量的回波数据需要实时记录下来以便进行事后成像处理。而PCI Express总线高带宽的优点可以很好的满足高速雷达数据记录的需要,而要充分发挥PCI Express总线的作用,驱动程序设计是关键。本文介绍了在Windows XP系统下,雷达数据记录器中PCI Express总线接口芯片PEX8311的驱动程序开发。
2 雷达数据记录器介绍
雷达数据记录器由一台服务器计算机、PCI Express接口卡、SCSI卡和SCSI硬盘四部分组成,其中PCI Express接口卡的软硬件自行设计,其它部分采用标准的外购件。雷达数据
通过PCI Express接口卡传入计算机内存,计算机再将数据通过SCSI卡写在SCSI硬盘上。
PCI Express接口卡采用美国PLX公司推出的PEX8311作为本地总线和PCI Express总线的接口。PEX8311[3]是一款x1的PCI Express接口芯片,本地端总线频率最高可达66MHZ,数据位宽32bit。PEX8311含有4KB的配置空间,其中前256字节是和PCI设备功能上是兼容的,其余是PCI Express扩展配置空间。本文采用PEX8311的引脚LINTi#接收外部中断信号,使用DMA通道0进行块DMA方式读数据。
接口卡的结构框图如图1所示,利用差分转换芯片先将外部差分信号转换成单端信号,两块FIFO的“乒乓”传输以实现数据的连续传输,单个FIFO容量为512KB。在CPLD的控制下,两块FIFO的数据轮流通过PEX8311的DMA通道0传入计算机。
500)this.style.width=500;" border="0" />
图1 PCI Express接口卡框图
具体工作过程:当其中一个FIFO被写满数据后,在CPLD控制下,外部数据继续写入另一个FIFO,同时,CPLD使PEX8311的LINTi#输入为低电平,这会产生一个LINT#中断,驱动程序响应中断并启动DMA传输读取FIFO中的数据到DMA缓存中。读完后,驱动程序通知应用程序将DMA缓存的数据写到SCSI盘上。
3 WDM驱动程序概述
WDM是一种分层驱动程序模型[4],如图2所示。系统启动时,总线驱动程序枚举总线上的设备,并为每个设备创建一个物理设备对象(PDO);然后PnP管理器根据注册表中的信息查找与这个PDO相关的过滤驱动程序和功能驱动程序,建立的过滤设备对象(FIDO)
500)this.style.width=500;" border="0" />
图2 WDM分层驱动模型
和功能设备对象(FDO),最终,系统完成设备驱动的装入过程。设备扩展对象是与设备对象关联的另一种重要的数据结构,它是一块未分页的内存,I/O管理器自动把它分配给已建立的任何设备扩展对象,可以用它来保存与设备关联的任何信息,驱动程序需要时,只要在设备扩展对象中取出这些资源使用即可。
IRP全名为IO Request Packet,即I/O请求包,是系统创建的一种数据结构。当应用程序对设备操作时,I/O管理器根据具体的请求建立相应的IRP,IRP先被I/O管理器发送到最上层的驱动程序处理,然后依次传递给下层的驱动程序处理。每层驱动程序可以不作任何事情而直接将IRP向下传递,也可以直接将该IRP设置为完成状态。
4 PEX8311驱动程序设计
微软提供的驱动程序开发软件包DDK(Device Driver Kits)提供了用于驱动程序开发的资源文件、编译连接程序、开发技术文档等。第三方开发工具有NuMega公司DriverStudio和Jungo公司的WinDriver,它们对DDK进行了封装,方便用户进行驱动开发。但效率方面不如DDK。考虑到雷达数据记录的数据率较高,所以本文采用DDK开发PEX8311的驱动程序。总线驱动程序由系统提供,过滤驱动程序是可选的。所以本文只设计了PEX8311的功能驱动程序(以下简称驱动程序),它主要由驱动程序初始化、数据传输初始化、数据传输模块三部分组成。其基本思想是:应用程序与驱动程序共享DMA缓存,当驱动程序接收到一个LINT#中断时,启动DMA读取FIFO中的数据存在DMA缓存中,每次读完后,驱动程序通过事件通知应用程序取出DMA缓存中的数据存在SCSI硬盘上。
4.1 驱动程序初始化
DriverEntry是驱动程序的入口函数,负责初始化驱动程序对象。系统启动时,如果检测到PEX8311的存在,I/O管理器会建立一个未初始化的驱动程序对象并将它作为一个参数传给DriverEntry。DriverEntry把驱动程序其它例程的函数指针装入到驱动程序对象里面。当一个IRP被发送到设备时,I/O管理器使用该IRP关联的驱动程序对象找到正确的驱动程序例程处理。初始化的主要函数指针有:AddDevice、DriverUnload、DispatchCreate、DispatchClose、DispatchIoControl、DispatchCleanup、DispatchPnp、DispatchPower。[!--empirenews.page--]
AddDevice是WDM驱动程序另一个入口函数,当DriverEntry初始化成功后,PnP管理器会调用AddDevice创建一个FDO,然后把总线驱动程序创建的PDO连接到FDO上,同时还会创建一个设备扩展对象。本文在设备扩展对象中保存了DMA缓存地址、设备寄存器地址和一些标志位。AddDevice还寄存了一个设备接口,以便应用程序打开设备。
接着,PnP管理器向驱动程序堆栈发送一个PnP启动消息,它是一个主功能代码为IRP_MN_START_DEVICE的IRP。驱动程序并不处理该IRP,只是将它传递给总线驱动程序处理并等待该IRP的处理结果,总线驱动程序将获得的设备资源(中断、DMA通道、内存和I/O资源等)保存在IRP中并通知驱动程序取出这些信息保存在设备扩展对象中。于是,驱动程序就可以根据这些信息对PEX8311进行操作了。
4.2 数据传输初始化
数据传输初始化是在DispatchIoControl派遣例程中实现的。功能驱动程序正常装入后,应用程序就可以发出DeviceIoControl请求初始化数据传输。初始化包括接收用户程序传来的事件句柄、分配DMA缓存、设置中断寄存器。
驱动程序采用事件方式与应用程序进行通信。应用程序中用CreateEvent创建事件hEvent,再调用DeviceIoControl函数将它传给驱动程序,驱动程序响应该请求,从输入缓冲区中取出这个事件句柄存在设备扩展对象中。当驱动程序将该事件设置为信号状态时,应用程序就可以得到通知。
驱动程序通过函数AllocateCommonBuffer分配的一段非分页、连续的DMA缓存,用于缓存从PEX8311传来的雷达数据。为了使应用程序能够直接访问DMA缓存,本文通过函数MmMapLockedPages把这段内存映射到应用程序。每次DMA读取512KB数据,本文分配了60段512KB的连续DMA缓存,驱动程序依次将每次读取的数据存在这些连续的缓存中,而应用程序按相同的顺序取出数据存在SCSI硬盘上。即使应用程序在下次LINT#中断到来时还没及时将缓存中数据写到SCSI硬盘上,驱动程序也会启动DMA将新数据存在下一段缓存中,不会丢失数据。
驱动程序设置PEX8311的中断寄存器,允许LINT#中断和PCI中断。允许LINT#中断可以使LINT#信号处于可用状态,而允许PCI中断可以将LINT#中断和DMA中断路由到计算机系统,操作系统就能调用中断服务程序响应中断。
4.3 数据传输模块
数据传输模块主要包括中断服务例程(ISR)和DPC例程(DpcForIrq)。前者响应LINT#中断和DMA中断,后者启动DMA传输并在数据传完后通知应用程序读取DMA缓存中的数据。因为ISR运行于较高的硬件中断级别[5](DISPATCH_LEVEL),它会阻塞所有的进程,而DpcForIrq运行在软件中断级别,不会阻塞所有进程,所以应该尽量减少ISR的运行时间,而在DpcForIrq中完成耗时的操作。本文在ISR中只判断中断类型,ISR的流程如图3所示:
500)this.style.width=500;" border="0" />
图3 ISR流程图
在调试中发现:当PEX8311的LINT#中断信号有效时间超过8us时,会造成死机。但系统繁忙时,计算机会因为中断有效时间太短而响应不了中断。为解决这一问题,使LINT#的有效时间加长到32us,驱动程序在刚进入ISR时,先禁止PCI中断,LINT#中断便不能传到计算机系统,也就不会造成死机,ISR也有足够的时间读中断寄存器的值进行判断。
数据传输初始化工作完成后,当有LINT#中断时,系统调用ISR。ISR中先判断是LINT#中断,于是将标志m_LINT设置为true,接着调用IoRequestDpc ()将一个DPC对象放入DPC队列中,最后,中断服务程序退出。
然后,系统取出DPC对象,在DISPATCH_LEVEL的级别下执行DpcForIrq。因为m_LINT为true,说明是FIFO存满数据,DpcForIrq设置DMA参数并启动DMA读数据。然后DpcForIrq退出。当PEX8311完成DMA传输后会产生DMA中断,中断服务程序按相同的方式执行,此时m_LINT被设置为false,说明是PEX8311完成DMA传输而产生的DMA中断,驱动程序在DpcFor_Irq中用事件通知应用程序读取DMA缓存中的数据写到SCSI硬盘上。如果应用程序不退出,驱动程序会一直按上述方式循环运行。当应用程序退出时,驱动程序关闭中断并释放DMA缓存。
4.4 驱动程序调试
本文采用Microsoft随DDK一起发布的调试工具WinDbg调试驱动程序。WinDbg是一种内核模式和用户模式调试器,可以用来分析故障转储文件和执行驱动程序代码。调试需要两台计算机:目标机(雷达数据记录器)和主机(运行Windbg的机器),它们用串口线连接,主机控制和监视目标机上的活动。设置好主机和目标机后,通过WinDbg的命令窗口可以设置断点、观察调试输出信息或分析目标机蓝屏后产生的故障转储文件。
测试时:外部中断频率可以提高到200Hz以上,每次中断读取512KB数据。通过分析,测试数据完全正确。经反复测试,记录器稳定记录速度可达100MB/S以上。
由于只采用了两个SCSI硬盘以及系统运行效率的限制,数据记录速度没有达到PEX8311的理论传输速度。若增加SCSI硬盘数量和升级硬件,记录速度还有很大提升空间。
5 总结
本文详细的介绍了基于PCI Express总线的雷达数据记录器驱动程序的开发。本文创新点为:针对雷达数据记录器和PEX8311的特点设计了高效的驱动程序,它具有易操作、移植性强的优点。该驱动程序已成功地应用于某雷达原始数据记录器中。