基于CPCI的伺服卡的DMA和中断研究关保青1,2,李岩1,王鹤淇1,2(1.中国科学院长春光学精密机械与物理研究所吉林长春130033;2.中国科学院研究生院北京100039)摘要:为简化当前光电设备电子学系统的结构,本文提出了基于CPCI总线,以DSP和FPGA为控制核心的伺服控制卡结构,来取代原来的控制子系统;在Windows2000下,利用DriverStudio为其开发的WDM驱动程序,采用DMA结合中断的数据传输方式,使其与上位机的通信速率在突发模式下能达到26.3Mbytes/s,满足了系统对伺服控制器的实时性要求。关键字:CPCI总线;WDM;DMA;中断;PCI9054中图分类号:TP336;TP316文献标识码:AImplementationofDMAandinterruptofServocontrolcardbasedonCPCIbusGuanBaoqing1,2,LiYan1,WangHeqi1,2(1.ChangchunInstituteofOptics,FineMechanicsandPhysics,ChineseAcademyofSciencesJilinChangchun130033;2.GraduateSchoolofChineseAcademyofSciencesBeijing100039)Abstract:Tosimplifythestructureofthecurrentoptic-electronicsystem,thispaperproposedaServocontrolcardstructure,whichisbasedonCPCIbusandusetheDSPandFPGAasthecontrolcore,toreplacetheformercontrolsubsystem.WDMdriverforthecardwasdevelopedwithDriverStudioasthedevelopingtoolinWindows2000.ByusingDMAandinterruptwiththeburstmodel,thedataspeedcanreach26.3Mbytes/s,whichcansatisfytherealtimerequirementoftheservocontrolcard.Keyword:CPCIbus;WDM;DMA;interrupt;PCI9054引言在当前光电子学系统中,以PC104作为伺服控制分系统,体积庞大,不便于系统管理。开发具有伺服控制能力的处理卡,用一块板卡替代原来的系统,能简化系统结构,提高系统的集成度,使电子学系统昀终成为一个高度集成的控制平台。CPCI(CompactPCI)总线在PCI总线基础之上,采用了欧洲卡结构,抛弃金手指式互连方式,改用2mm密度的针孔连接器,并具有可热插拔性,使其具有了更高的可靠性和开放性,并且能适应恶劣的工作环境,在工业控制、航空航天等领域得到广泛应用。自行开发的伺服控制卡基于CPCI总线,以DSP作为卡上控制CPU,与FPGA结合实现控制。本论文以该伺服控制卡为依托,在概述其硬件平台结构的基础上,介绍了在Windows2000下CPCI设备驱动程序的设计与开发,重点阐述了桥接芯片PCI9054的DMA数据传输实现及中断处理机制。1.伺服控制卡的系统结构与硬件实现方案伺服控制卡以TI公司的TMS320F2812DSP作为核心处理器,与FPGA结合来实现整个板卡的控制功能,通过CPCI总线完成与上位PC机的通信,其系统功能框图如图1所示:图1伺服控制卡硬件结构图FPGA选用Altera公司的EPF10K30A,它内嵌1536Byte的RAM,此RAM为主机与DSP共享,用于上位机与DSP之间的高速数据缓冲,FPGA负责接收上位机传递的命令和参数等数据,经处理后发送给DSP进行相应的控制操作,同时反馈信息给上位机。TMS32F2812的主要任务就是完成复杂的伺服控制算法,特别是位置控制和速度控制。FPGA通过2812的外部中断XINT1和XINT2来触发2812接收控制命令和参数,2812接收到命令后,根据自身定义的工作协议进入相应的工作状态。系统设计中采用PLX公司的PCI9054作为总线接口芯片,实现CPCI局部总线与FPGA的通信。PCI9054采用C模式,在该模式下,PCI的数据线与地址线是非复用的,设计时只需关注9054的本地端总线。2.WDM驱动程序设计在Windows环境下,位于用户态的应用程序不能之间访问硬件资源,而要通过执行核心态的驱动程序来间接完成对硬件资源的访问,因此,对于上位机上的应用程序,要对伺服控制卡进行访问,必须要为其开发驱动程序。WDM驱动程序是一种Pnp驱动程序,它能够实现Windows98与Windows2000、WindowsXP之间的源代码级兼容。Windows2000性能稳定,在调试自行开发的板卡时,仍然是首选的操作系统。在Windows2000中,所有对驱动程序的I/O请求都转化为I/O请求包(IRP)来表示,IRP是I/O管理器在响应I/O请求时从非分页系统内存中分配的一个可变大小的数据结构,I/O管理器负责产生代表一次I/O操作的IRP,并将IRP传至正确的设备驱动程序,并通过分层的驱动程序传递给物理设备。设备驱动程序则接收IRP,执行相应的操作,完成后再将IRP传送回I/O管理器,表示I/O操作的完成或者通过I/O管理器将其传递给其他的驱动程序进行进一步的处理。3.伺服控制卡的WDM驱动程序设计与实现驱动程序的开发环境常用的有微软的DDK、Jungo的WinDriver和Numega的DriverStudio。DriverStudio把DDK封装成类,包含完善的代码生成和调试工具,并且提供对WDM驱动的完全支持,利用它开发的核心态驱动程序运行效率也很高。本系统在VC环境下利用DriverStudio开发驱动程序。接口芯片PCI9054支持主模式、从模式和DMA模式三种数据传输方式。DMA传输不通过处理器,直接进行数据交换,可以节省CPU资源;并且DMA模式还支持CPCI总线与本地总线之间的高效突发。3.1DMA数据传输实现PCI9054集成了两个互相独立的DMA通道,每一个通道由一个DMA控制器和一个专用双向FIFO组成,都支持块DMA和分散/集中DMA操作,这里选用DMA通道0,采用块DMA方式实现传输。在DriverWorks中提供了三个类来实现DMA传输,分别是KDmaAdapter类、KDmaTransfer类和KCommonDmaBuffer类。3.1.1.DMA适配器对于DMA传输,驱动程序需要创建一个DMA适配器,来表明一个DMA通道的特性和提供串行化访问的服务。KDmaAdapter类实现对DMA适配器的操作。在它的初始化函数Initialize(PDEVICE_DESCRIPTIONpDesc,PDEVICE_OBJECTpPdo)中第一个参数是一个DEVICE_DESCRIPTION结构的指针,这个参数用于对DMA通道的属性进行设置。3.1.2.DMA控制器采用DMA方式时,CPU要放弃对系统总线的使用权,主存储器和外部设备是被控制的对象,它们之间没有相互控制的能力,需要利用DMA控制器来代替CPU完成控制功能。在用DriverWorks开发驱动时,KDmaTransfer类用于控制DMA的传输;它可以启动一个DMA传输,指定DMA传输的方向,DMA传输数据缓冲区的物理地址和要传输的字节数。KDmaTransfer类的Initiate()函数用于初始化一个KDmaTransfer对象;在成功初始化一个KDmaTransfer类对象后,将会调用DMA准备就绪回调例程OnDmaReady,在该例程中获取要传输的内存的地址和字节数,并调用StartDMA例程开始DMA传输。与中断结合的DMA传输在一次传输结束后会再次调用KDmaTransfer类的Continue()函数发起下一次的DMA传输操作,直到传输完成。3.1.3.DMA公共缓冲区在DriverWorks中KCommonDmaBuffer类实现对公用缓冲区的操作。在实际使用时,声明一个KCommonDmaBuffer类对象并初始化。在传输结束后,释放公共缓冲区,以防止内存丢失。3.1.4.寄存器设置PCI9054在DMA模式下传输,驱动程序要通过I/O指令设置DMA控制器内部的寄存器以实现两总线间的数据传送,需要设置的内部寄存器及其具体功能如下表1所示:表1:DMA传输的寄存器功能描述名称偏移量功能DMAMODE0PCI:0x80设置局部总线工作模式DMAPADR0PCI:0x84CPCI局部总线上的地址,物理地址DMALADR0PCI:0x88存储空间在本地总线的地址DMASIZ0PCI:0x8C需传输的数据大小DMADPR0PCI:0x90设置数据传输方向等DMACSR0PCI:0xA8使能和启动DMA通道0传输3.2驱动开发中的中断处理机制及实现本系统的驱动程序采用块DMA与中断结合的方式来实现主机与伺服控制卡之间的数据传输。以读操作为例,每次DMA传输完后,都会产生一个DMA中断,中断处理程序应答中断,并获取公共缓冲区中的数据,通知主机端有数据到达;可以看出,高效的DMA处理依赖于高效的中断处理过程。中断处理完成CPU与I/O设备之间的信息交换,在为硬件板卡开发驱动程序时需要为中断配置相应的驱动处理。在处理中断之前要对中断资源进行配置,首先定义并初始化一个中断对象,在初始化阶段,提取IRP资源中的中断级别、中断模式、中断向量、共享模式等信息。利用上面获得的参数来连接中断,连接中断操作的主要目的是注册设备驱动的中断服务例程(ISR),以便在中断发生后中断服务例程能够被调用。在DriverWorks中用KInterrupt类实现对硬件中断的处理。status=m_Irq.InitializeAndConnect(pResListTranslated,LinkTo(Isr_Irq),this)当硬件发生中断时,硬件抽象层(HAL)把中断级别(IRQL)提升到合适的中断级别,然后调用中断服务例程(ISR)。CPCI总线是中断共享的,因此,ISR首先确定是哪一个设备发生了中断,如果不是当前设备的中断,立即返回FALSE,以便HAL把中断发送给其他设备的驱动程序。如果是当前设备的中断,则在清除该中断,并做相应的处理。中断处理的整个过程如下图2所示:ISR执行在高于DISPATCH_LEVEL的IRQL上,它冻结了其CPU上所有低于或等于该IRQL上的其他活动,为了提高系统性能,ISR例程应该尽可能快的完成;此外,ISR中使用的所有代码和数据必须存在于非分页内存中,能调用的内核模式函数也十分有限。图2:中断处理流程图Windows2000提供了延迟过程调用(DPC)机制来解决这个问题,ISR决定当前请求的完成并请求一个DPC,之后,内核在DISPATCH_LEVEL级上调用这个DPC例程。当有当前设备的中断到来时,把一个DPC插入到DPC队列中。实现代码如下:m_DpcFor_Irq.Setup(LinkTo(DpcFor_Irq),this);//创建一个DPCm_DpcFor_Irq.Request(NULL,NULL)//把一个DPC插入到DPC队列等待执行4.应用程序与驱动程序的通信4.1通信的实现策略应用程序采用Win32事件通知的方式与驱动程序进行通信:应用程序调用API函数CreatFile打开设备,调用CreateEvent创建事件句柄hEvent并置为无信号态,把hEvent作为函数DeviceIoControl的参数传递给驱动程序,同时调用CreateThread创建等待线程;WDM驱动程序接收事件句柄hEven,初始化KEvent类对象m_hEvent,当中断发生时,在DPC中执行m_hEvent-Set(),将事件设置为信号态,唤醒应用程序中的等待线程,然