根据pci总线的实时测频卡wdm驱动程序设计策略
pci总线是一种与cpu无关的32/64位地址数据复用总线,工作频率为33 mhz/66 mhz,它支持突发传输,具有即插即用、电源管理等功能。pci总线以其优良性能和可适应性成为现代微机的主流总线。在开发pci设备的过程中,需要为pci设备写驱动程序。windows驱动程序模型(wdm)是microsoft公司力推的全新驱动程序模式,它支持php、电源管理和wmi等技术。在windows操作平台上,wdm已成为主流的驱动模型。这里主要介绍根据工程背景开发的基于pci总线的实时测频卡的wdm驱动程序设计。
1实时测频卡硬件系统结构
实时测频卡的主要功能是实时测定信号频率,实时识别信号调制方式。系统的电路框图如图1所示。外部待测信号通过sma接口进入实时测频卡的adc。adc输出的数字信号在fpga中缓存后进入dsp。在dsp内对信号进行粗估,然后通过emif接口把转化为频率和相位控制字的粗估结果发给ddc。ddc做出调整后,通过fpga把移频和降采样后的信号输入给dsp。 dsp依据粗估结果和ddc的数据进行实时测频。测频完毕后,通过pci总线向pc机发出中断信号。pc机响应中断,读取dsp内指定位置内存处的测频数据。为简化pci接口电路设计,选用带有pci接口电路的dsp芯片tms320c6416。
2 tms320c6416的pci接口介绍
实时测频卡通过tms320c6416的pci接口和主机进行通信。该接口符合pci 2.2规范,能提供33 mhz总线时钟,32 b数据宽度,可达到峰值132 mb/s的数据带宽。pci接口包括配置寄存器、i/o寄存器和存储器映射寄存器。图2给出了部分pci配置寄存器。配置寄存器的主要功能如下:
(1)设备的识别、控制和状态指示。将供应商id域、设备id域、版本域、配置头类型域、分类代码域这五个域用于识别设备。所有的pci设备必须设置这些域,配置软件可利用它们来确定系统中可用的pci总线设备。对于tms320c6416芯片而言,供应商id为104ch;设备id为a106h;其他三个域随不同的应用会有所改变。命令寄存器为发出和响应pci总线命令提供粗略的控制。状态寄存器用于记录pci总线有关操作的状态信息。
(2)中断引脚寄存器的功能。01h~04h值对应于pci中断请求引脚inta#~intd#。
(3)基地址寄存器的功能。其功能是为pci设备指定存储空间。pci存储空间分为独立寻址的memory空间和i/o空间两类。memory空间适用于设备功能寄存器较多或数据流量较大的场合,i/o空间适用于设备功能寄存器较少或数据流量较小的场合。pci接口拥有3个基地址寄存器bar用于保存指向pci存储空间的指针。图2为部分pci配置寄存器。
①base 0基地址寄存器(bar0)。确定一个4 mb可预取的pc机内存地址空间。将dsp存储空间中不同的4 mb空间都映射到pc机内存相同的4 mb空间中。由dsp页寄存器(dspp)设置该区域在。dsp存储空间中的映射位置;用bar0访问dsp内部的ram和外挂的通过emifa和emifb访问的存储器空间。访问时每次最多只能读取dsp存储空间的4 mb内容,并且需要定义dspp寄存器,以指定访问空间的起始地址。访问支持数据突发传输模式。这种映射方式只适用于dsp处于从模式。
②base 1基地址寄存器(bar1):确定一个8 mb不可预取的访问区间。对dsp芯片而言,其访问地址固定在0180000h~0200000h的范围内。用barl来访问dsp内部所有的操作命令控制寄存器。
③base 2基地址寄存器(bar2):定义一个16 b的pc机i/o空间,用于访问pci的i/o寄存器。bar2加偏移00h,访问主机状态寄存器hsr;bar2加偏移04h,访问主机对dsp控制寄存器hdcr;bar2加偏移08h,访问dsp页寄存器dspp。
3 wdm概述
wdm(windows driver model)是一种遵循即插即用协议的内核模式驱动程序,它是微软的全新驱动程序模式,旨在通过提供一种灵活的方式来简化驱动程序的开发,在实现对新硬件支持的基础上,减少并降低必须开发的驱动程序数量和复杂性。在wdm中,采用图3所示的分层驱动程序体系结构。
在wdm模型中,每个硬件设备至少有两个驱动程序:总线驱动程序和功能驱动程序。总线驱动程序由操作系统实现,它在最底层直接与设备打交道,负责管理硬件与计算机的连接;负责发现总线上所有的设备,并检测设备何时添加到总线上或何时从总线上删除。设备功能驱动程序在上层通过与低层驱动程序打交道,进行硬件操作,以实现pci设备的功能。中间还可以有类过滤驱动程序或设备过滤驱动程序用于修改和监视irp(i/o请求包),实现数据的过滤或转换。一般在特殊的情况下才需要编写。在实际开发中,只需要开发一个设备功能驱动程序即可。
wdm还引入了功能设备对象(functional deviceobject,fdo)与物理设备对象(physical device object,pdo)来描述硬件。一个pdo对应一个真实的硬件,一个硬件只允许有一个pdo,却可以有多个fdo。在驱动程序中直接操作的不是硬件而是相应的pdo与fdo。当应用程序与wdm驱动程序进行通信时,系统为每一个用户请求打包,形成一个i/o请求包(irp)结构,将其发送到驱动程序,并通过识别irp中的pdo来区别是发送给哪一个设备。irp从驱动程序堆栈栈顶进入,每层驱动再把i/o请求划分成更简单的请求,以传给更下层的驱动执行,最底层的驱动程序在收到irp后,通过硬件抽象层hal与硬件发生作用,从而完成i/o请求工作。内核通常通过发送irp来运行驱动程序中的代码。
4测频卡wdm驱动程序实现
在微软公司ddk工具的支持下,compuware nu-mega公司提供driver studio工具包中的driverworks将wdm驱动程序编写所需的对内核及对硬件的访问封装成类库,加上驱动程序代码生成向导driverlwizard,极大地简化了驱动程序的开发难度。本文选择driverworks作为wdm驱动程序的开发工具。
测频卡驱动程序的主要功能是为用户读取所测信号的频率参数,包括载频、调制方式、码元速率等。同时用户还能通过驱动程序发送命令对测频卡的工作方式进行控制。由此可知,驱动程序要重点处理好硬件访问和中断处理工作。
4.1i/o访问
类kiorange封装了对i/o端口的操作。本卡中pci配置寄存器中的base 2基地址寄存器定义了i/o空间。在onstartdevice例程中取得i/o资源,并初始化,其函数实现如下:
完成初始化后,可以用成员函数inb,inw,ind从i/o端口读一个(多个)字节、字、双字的数据;outb,outw,outd向i/o端口写一个(多个)字节、字、双字的数据。
4.2内存访问
在windows系统中,内存分为分页内存和非分页内存。在wdm驱动程序中,对于硬件的内存映射一般需要用非分页内存。因为在一些较高级别的例程中,使用分页内存会造成系统产生缺页中断,从而引起死锁。使用非分页内存无需太多的转换,非常安全,效率也高。类kmemoryrange封装了对pci设备映射内存的操作。类kmemoryrange成员函数的读/写操作同类kiorange。由pci配置寄存器中的base 0和base 1基地址寄存器分别定义了两个内存空间。在onstartdevice例程中取得内存资源并初始化,其函数实现如下:
status=m_memoryrange0.initialize(preslisttranslated,preslistraw,pciconfig.baseaddresslndextoordinal(0));
status=m_memoryrangel.initialize(preslisttranslated,preslistraw,peiconfig.baseaddresslndextoordinal(1));
4.3中断处理
中断处理一般需要声明两种类实例:klnterrupt和kdeferredcall。kinterrupt类用于实现硬件中断处理;kdeferredcall类用于实现延时过程调用。首先创建一个klnterrupt类实例m_irq,将此实例作为设备类的成员变量,然后创建一个kdeferredcall类实例m_dpcfor_irq。m_irq对应的中断服务例程和m_dpcfor_irq对应的延时过程调用例程也需要在实例中声明。这两个实例m_irq和m_dpcfor_irq都是在onstartdevice例程中初始化的,代码如下:
status=m_irq.inifializeandconnect(preslisttranslated,linkto(isr_irq),this);
m_dpcfor_irq.setup(linkto(dpefor_irq),this);
中断服务例程的处理时间应尽量短,对于一些耗时,但不需要立即处理的任务,中断服务程序会调用一个低于中断服务程序dirql级别的延迟过程调用程序dpc,在dispatch_level上完成处理,这个级别上的限制较少,函数调用也相对比较方便。在中断服务例程中,首先判断中断是否是自己设备产生的,若不是,返回false;若是,进行必要的处理,请求一个dpc(延时过程调用),然后返回true。关键代码如下:
在延时过程调用例程dpcfor_irq中,读取所测信号的频率参数:
5驱动程序与应用程序之间的通信
虽然驱动程序是为设备的硬件层编程服务的,但同样需要提供和应用程序进行通信的能力,从而最终达到应用程序控制设备的目的。应用程序与驱动程序之间的通信通过调用win32 api来实现,应用程序用creatfile函数通过已经定义的设备接口来获取驱动程序文件句柄,然后将文件句柄作为其他win32 api函数的一个参数,对驱动程序的进行数据操作。调用devicelocontrol进行数据量较小的,如控制指令传输或端口、寄存器访问;调用readfile,writefile等函数进行数据量较大的传输,如内存读/写等。驱动程序与应用程序的通信有devicecontrol异步完成、共享win32事件通知两种方式。win32事件通知是由应用程序创建了一个事件后,设置事件的状态为unsignal,然后直接将该事件句柄传递给驱动程序,等待驱动程序发送事件通知。驱动程序通过类kevent获取这个事件的一个对象指针后,在irql≤dispatch_level级别的例程中设置事件信号状态为signal来通知应用程序进行后续处理。
6结语
基于上述的硬件结构和驱动程序设计方法,成功开发了一款实时测频卡,在实际中得到了很好的应用,板卡工作正常,达到了预期效果。实践证明,driverworks是一款功能强大,使用方便的驱动程序开发工具,利用它可以方便快捷地构造pci设备的驱动程序框架,大大加快了开发周期,提高了开发效率。
比特币的起源谜团
当AI开始保护TA
伺服电机十大故障分析(二)
万用表能否测量nA级别信号
德州仪器推出在线工具WEBENCH系统电源建筑师
根据PCI总线的实时测频卡WDM驱动程序设计策略
虚拟现实技术都用在了哪些方面
微软新款 Xbox 外接硬盘要求公布:USB 3.0,128GB
LPC553x/S3x MCU系列功能简介
Supermicro 在北京 IDF 上展示新的 Twin
北京移动携手华为在北京师范大学成功开通首个5G基站
复合式盐雾试验箱的日常维护与保养
八个常用Shell脚本编写详解及注意事项
苹果macOS真的很安全吗?定期进行病毒查杀非常有必要
AIGC将产生数万亿美元经济价值,云从科技已有所布局!
区块链技术正式开始应用于能源电力行业
关于VR一体机的性能分析和介绍
AR说丨Ifgames钱清泉:虚空的力量比想象中更强
微流控技术助力细胞迁移的研究与应用
中国广电入局5G给通信行业带来了深远的影响