基于cPCI的一次性指令通信卡驱动程序设计
2014-09-26王煊
王 煊
(中国空空导弹研究院 河南 洛阳 471009)
一次性指令通信卡通过cPCI接口和PCI总线进行通讯,对外部使用通用的输入输出接口。通过一次性指令控制卡,测试设备可以像飞控系统施加激励信号,同时接受飞控输出的一次性指令,数据汇总到测试设备的处理器,可以对飞控系统进行分析处理。所以,一次性指令通信卡在飞控系统静态测试设备中扮演非常重要的角色。
一次性指令通信卡是一个综合性的设备,对它的设计包括硬件和软件的部分。硬件设计包括芯片选择、板卡布线以及控制逻辑。软件设计包括DLL调用接口、上层应用程序以及在选定平台下的驱动程序软件。本文着重研究软件尤其是驱动程序的设计。
作者所要完成的工作是cPCI一次性指令通信卡在Windows 2K/XP下的驱动程序设计。具体内容有:深入了解Windows NT系列32位操作系统的内部原理,以及开发驱动程序的原理和方法;理解和掌握目标cPCI板卡的内部结构、板上资源和指令;编写该cPCI一次性指令通信卡的驱动程序,同时开发对应的DLL函数库;编写一个简易的测试程序。
1 cPCI一次性指令通信卡硬件结构
cPCI是CompactPCI的简称,是工业计算机的一种互联总线,是欧标连接方式和PCI信号协议的结合产物。cPCI板卡有3U和6U两个尺寸标准,多块板卡通过一块背板互联。接口管脚定义由欧美PICMG 组织制定。
cPCI原本上是为了支持PCI信号协议而制定的。和PCI标准相比,cPCI提供两倍的插槽,并提供热插拔机制更适合工业应用。从协议上看,cPCI与PCI完全等效,驱动和上层程序完全兼容。
图1 测试程序界面Fig. 1 Test program interface
PCI9054是美国PLX公司继PCI9052之后推出的又一低成本PCI总线接口芯片,低功耗,PQFP 172pins封装,它采用了先进的PLX数据管道结构技术,可以使局部总线快速转换到PCI总线上[1]。PCI9054的主要特性如下:
1)符合PCI 2.2版本规范,32位,33 MHz总线
2)普通主总线接口,包含两个DMA引擎
3)支持PCI双地址周期
4)可编程中断产生器
5)6个可编程并且零等待突发操作的FIFO
6)串行EEPROM接口
PCI的配置空间是编写驱动程序的基础。
PCI9054的许多功能都是通过配置寄存器来控制的。其中的部分寄存器是由系统上电时由EEPROM自动按厂商预定的映射方式填入,主要包括Vender ID、device ID、基本的中断设置和部分本地配置寄存器。
1)作为重要的控制本地地址空间映射到PCI地址空间的寄存器有3个,以Space 0 为例:
LAS0RR:本地地址空间0大小寄存器,32位
LAS0BA:本地地址空间基地址寄存器,表示映射前的本地地址空间相对于自身的基地址和映射后本地地址空间在PCI总线空间上的物理基地址之间的对应关系。
PCIBAR2:PCI基地址寄存器,在从模式下,用来保存系统加电后BIOS为本地地址空间映射到PCI空间后的总线物理基地址。在驱动程序中,系统会发一个资源分配的数据请求包(IRP)。在响应这个IRP的例程中,可以得到PCI基地址寄存器中的值,经过转换为内核模式下的系统虚拟地址才能为驱动程序所访问。
2)中断先寄存器(PCIILR)
中断线寄存器为8位,改寄存器的值说明PCI设备的中断引脚连接到系统中断控制器的哪个中断上。该寄存器的值由系统上电期间从EEPROM装入。
3)中断引脚寄存器(PCIIPR)
该寄存器说明设备使用PCI总线上的哪一个中断引脚,PCI总线一共有4个中断引脚。PCI9054仅支持#INTA,故本设计中该寄存器的值为01H。
图2 Windows 2000 操作系统组件框图Fig. 2 Windows 2000 OS component diagram
以上这几个寄存器才开发PCI板卡时,以及编写PCI板卡驱动时,是十分重要的[2]。可以通过EEPROM方式事先固化PCI配置寄存器中的值。EEPROM内容的固化可以设计响应的烧写电路并使用通过PlxMon工具将配置值固化到EEPROM中,烧写之前必须保证EEPROM中的值全为0xFFFFFFFF,否则烧写电路驱动程序将不能识别该硬件。
2 测试系统软件设计
2.1 Windows2000内核模式环境组成
内核模式环境实际上已经实现了一个通用操作系统的底层软件平台。内核模式环境主要由3个代码模块组成[3]。
1)硬件抽象层(HAL, Hardware Abstract Layer)
硬件抽象层是一个薄层软件,它是硬件与操作系统其他部分的接口,是物理硬件资源的一种抽象。硬件抽象层通过动态链接库实现,使用硬件抽象层例程的设备驱动程序可以在有相同CPU体系的平台上实现二进制代码兼容。
2)内核(Kernel)
如果说硬件抽象层代表了硬件平台的抽象化,那么内核便是整个操作系统的神经中枢。它提供管理以下功能的机制:中断和异常处理、线程调度和同步、多处理机同步、定时控制、内核对象。通过这些内核服务,操作系统的上层部分可以忽略底层CPU的体系结构[4]。内核提供了一个基于对象的界面。内核对象可以分为调度者对象和控制对象两大类。内核提供了一个基于对象的界面。由于调度者对象主要负责同步性能并改变或影响线程调度,故设备很少使用到这类对象。但是却经常用到以某种方式控制操作系统的行为控制对象。
3)执行体(Executive)
执行体由几个不同的软件模块组成,它们是完全独立的,只通过定义好的接口来通讯。执行体为用户模式进程及它们之间的通信提供服务。执行体包含的重要的模块有:系统服务接口、进程管理器、I/O管理器、即插即用管理器、电源管理器。
2.2 设备驱动程序的主要内容
1)初始化例程
和动态链接库类似,它向操作系统显露一个名为DriverEntry的例程,每次启动驱动程序[5]的时候,操作系统将调用这个入口。DriverEntry除了做一些必要的设备初始化工作外,还初始化一些Dispatch例程入口。使I/O管理器能知道当用户的打开、关闭、读写等请求到来时各应调用哪些过程来处理。同时要初始化设备对象,申请软硬件资源。
2)调度例程
调度例程(Dispatch)是设备驱动程序提供的主要函数,可以完成打开、关闭、读取、写入以及设备文件系统或网络支持的任何其它功能。当被调用去执行一个I/O操作时,I/O管理器产生一个I/O请求包(IRQ),并且通过某个驱动程序的调度例程调用驱动程序。
3)Start I/O例程
串行化处理I/O请求,提高程序执行效率。驱动程序可以使用Start I/O例程来初始化与设备之间的数据传输。在开始设备操作时,I/O管理器调用驱动程序的Start I/O例程,分配处理该请求所需的任何资源,并设置设备运行。
4)中断服务例程(ISR)
当一个设备中断时,内核的中断调度程序把控制权转交给这个例程。ISR例程运行在高级别的IRQL上,所以他越简单越好,以避免对低优先级中断产生不希望的阻塞。ISR可以把剩余的大多数工作推迟到低中断优先级的延迟过程调用(DPC)中实现。
5)延迟过程调用(DPC)
用于处理中断响应的大多数工作,在ISR例程用排队并得到调用。
2.3 开发PCI设备驱动程序要了解的硬件特性
1)设备的总线结构。设备采用什么样的总线结构非常关键,因为不同的总线在硬件工作机制上存在很大的不同,所以驱动程序的设计也不同。
2)要了解设置的控制寄存器、状态寄存器和数据寄存器,以及这些寄存器工作的特性。
3)要了解设备寄存器返回的状态和错误信号,这些信号要通过驱动程序返回用户。
4)要了解设备产生中断的调节和中断是数量
5)数据传输机制:最常用的数据传输机制,是通过IO指令和硬件设备进行数据读写。
6)许多设备带有内存,PCI设备大多采用内存映射的方式映射到系统的物理内存。有的设备还要通过驱动程序来设置接口的寄存器。
3 驱动程序的讨论和实现
NuMega公司的DriverStudio是一套简化Windows驱动程序开发、调试及测试的工具包。其中包括:开发普通设备WDM驱动程序的DriverWorks、创建DDK支持的纯C语言的WDM驱动程序框架、支持网络设备驱动程序开发的DriverNetWorks及Windows内核单击调试工具SoftICE。DriverWorks以面向对象的方式将编写WDM驱动程序所需要的内核及访问硬件的函数封装成类。这样,驱动开发者只要在工程向导的指引下逐步设置必要的参数,最后就可以得到WDM驱动程序框架。然后根据特定设备的访问请求,想类中添加新的类对象和代码即可。DriverWorks是基于VC或者VC.net工程的,经过编译以后即可以得到设备驱动程序。它所用到的函数只不过是对DDK提供的库函数的封装,不会影响代码的执行效率。
使用DriverStudio驱动生成向导建立驱动程序的步骤是[6]:
1)输入路径和工程名;
2)选择要生成的驱动程序框架的类型,这里选择WDM Driver;
3)选择WDM驱动程序的类型,这里选择WDM Function Driver;
4)选择驱动程序所对应的硬件设备类型,选择PCI,并填入对应的厂商编号和设备编号;
5)添加硬件资源,并选中“Use Interrupts”;
6)选择驱动程序支持的功能项;
7)添加I/O控制;
8)添加注册表中装载的标志参数,这里不需要添加;
9)选择电源管理选项;
10)选择是否添加WMI属性;
11)选择安装选项;
12)选择其他选项。
3.1 硬件资源分配例程OnStartDevice例程设计
前面讲过PCI设备实现硬件操作时是将设备空间映射到计算机系统空间中实现的,因此一个很重要的设计就是在系统启动时,保存系统给板卡分配的基地址空间,因为对硬件板卡的全部操作将会依赖于这些基地址。当然这些基地址是根据总线上的设备以及设备资源要求来分配的。由于系统启动发现硬件板卡并给其分派好资源后,操作系统会给驱动程序发送一个代码为IRP_MN_START_DEVICE的IRP,该IRP保函了系统分配的资源信息列表,因此在驱动程序中需要设计相应的例程来解析该资源列表。KIoRange和KMemoryRange两个类分别用来实现对IO映射芯片的访问和对内存映射芯片的访问。根据得到的资源来调用者两个类的成员函数即可实现对PCI9054寄存器和本地空间的访问。
3.2 响应中断的代码设计
PCI板卡对软件产生中断,该中断在DriverStudio生成的框架中会调用Irp()函数。可以在Device类中定义一个KEvent成员变量。首先注册事件变量,获取应用程序传入的事件句柄后,对KEvent事件变量进行注册。在Irp()中可以关闭中断,以免中断多次响应。然后在Isr_dpc()函数中开启中断,并且记录中断源,清除中断,并对KEvent对象进行Set()操作。
3.3 访问硬件例程的实现
DriverStudio向导生成的工程框架对每个IO控制接口都专门生成一个单独的函数,在对应的函数中取出缓冲区数据,写入对应Memory Resource或IO Resource的自定义地址中,或者从资源地址中取出数据,写入输出缓冲区,并报告数据区在缓冲区的长度。
4 驱动程序的应用程序接口
驱动程序仅仅实现对硬件设备的操作,那么要实现人为的控制对设备的操作应该实现用户程序和内核驱动程序的某种连接,这样才会有更大的实际价值。
通常的板卡控制流程如下:使用CreateFile去打开板卡,然后使用DeviceIOControl去和驱动程序进行通信或者利用其读写少量的数据,进行大数据量连续的数据传输则考虑使用ReadFile和WriteFile的DMA方式去实现,当操作完成以后,直接使用CloseHandle去关闭设备。这种对应关系如表1所示。
表1 Win32函数与IRP例程关系对应表Tab.1 Correspondence between Win32 function and IRP routine
5 结束语
经过了艰苦的努力,这套一次性指令卡的驱动终于开发完成。在开发测试过程中,综合使用了驱动设计过程中的各种技术。无论从理论上还是实践上都有极为重要的研究意义。
[1]PCI 9054 Data Book Version 2.1,PCI 9054 Data Book[S].U.S:PLX, 2000.
[2]孟楠, 刘文怡. 基于PXI总线的数字量IO卡设计[J].科学技术与工程, 2013, 13(2):507-511.
MENG Nan, LIU Wen-yi.A Design of Digital IO Card Based on PXI Bus[J]. Science Technology and Engineering, 2013,13(2)):507-511.
[3]DDK,Microsoft Driver Development Kits[S].U.S:Microsoft Press,1997.
[4]吴海箐, 吴江, 吴瑛. Windows NT4.0环境下数据采集卡设备驱动程序的设计[J]. 信息工程大学学报, 2001, 2(3)):19-23.
WU Hai-jing, WU Jiang, WU Ying. The Design of Data Acquisition Card' s Driving Program in Windows NT4.0[J].JournalofInformation EngineeringUniversity, 2001, 2(3):19-23.
[5]Oney.W Programming the Microsoft Windows Driver Model[M].U.S:Microsoft Press,1999.
[6]武安河.Windows2000/XP WDM设备驱动程序开发[M].2版.北京:电子工业出版社,2005.