2011-06-13 15:56:00 JungoWinDriver 阅读数 1484
  • Cloud Foundry技术新纪元 2017年发展趋势前瞻

    介绍开源CF和Pivotal CF新的一些技术进展,CF在2016年增加了大量的功能,包括行业热点功能:比如采用RunC的容器运行时,对容器的网络和存储插件的支持,也有很多企业级功能,如安全性的增强,支持PCI的安全性等。 PCF已经大规模的在生产系统使用,已经越来越成熟,Pivotal积极收集客户需求,反馈到PCF的功能实现上。

    2137 人正在学习 去看看 CSDN讲师

Q:我欲使用WinDriver开发一个PCI卡的驱动程序来传输图像,但是当我利用WinDriver进行Virtex5 FPGA进行读取和写入动作时,计算机会当机,请问如何解决?


A : 请提供计算机当机时的屏幕显示信息(Minidump),并参阅http://support.microsoft.com/kb/307973。


请同时提供以下数据:
CPU类型、操作系统类型,应用程序


若是因为应用程序当机而非操作系统当机,请提供WinDriver的Debug monitorLog数据,请参阅http://www.jungo.com/st/support/tech_docs/td12.html。

2019-07-08 16:56:14 weixin_43549463 阅读数 77
  • Cloud Foundry技术新纪元 2017年发展趋势前瞻

    介绍开源CF和Pivotal CF新的一些技术进展,CF在2016年增加了大量的功能,包括行业热点功能:比如采用RunC的容器运行时,对容器的网络和存储插件的支持,也有很多企业级功能,如安全性的增强,支持PCI的安全性等。 PCF已经大规模的在生产系统使用,已经越来越成熟,Pivotal积极收集客户需求,反馈到PCF的功能实现上。

    2137 人正在学习 去看看 CSDN讲师
  1. RTX 下操作外设时, 需要把设备从 Windows 移动到 RTX 下面,

具体移植方法可以参考 RTX Help 文档中间 Converting a Windows Device to an RTX Device 一节或者参考附件<<串口设备移植向导.doc>>

  1. PCI驱动程序的特点

在设计驱动程序之前,首先要对欲控制的硬件设备进行细致地分析,更需要详细了解硬件设备的特性。硬件设备的特性会对驱动程序设计产生重大的影响。需要了解的最主要的硬件特性包括:

(1) 设备的总线结构

设备采用什么总线结构非常关键,因为不同的总线类型(如ISA和PCI)在许多硬件工作机制上是不同的,所以驱动程序设计也不同。

(2) 寄存器

要了解设置的控制寄存器、数据寄存器和状态寄存器,以及这些寄存器工作的特性。

(3) 设备错误和状态

要了解如何判断设备的状态和错误信号,这些信号要通过驱动程序返回给用户。

(4) 中断行为

要了解设备产生中断的条件和使用中断的数量。

(5) 数据传输机制

最常见的数据传输机制是通过I/O端口(port),也就是通过CPU进行数据读写。PC的另一种重要的传输机制是DMA,但PCI规范不包括从属DMA的说明。

(6) 设备内存

许多设备自身带有内存,PCI设备大多是采用映射的方式映射到PC系统的物理内存。有的设备还要通过驱动程序设置设备的接口寄存器

  1. RTX 驱动整体架构

使用 RTX Device Driver 开发向导, 选择支持

(1) Interrupt Service Routine (ISR)

(2) Support for Sharing an Interrupt

(3) Basic Port I/O Support

(4) Basic Mapped Memory Support,

即可生成 RTX PCI 设备驱动程序框架。

该程序框架分成两个函数, Driver 文件和 DriverFunc 文件:

Driver 文件主要包括 main 函数,中断服务程序和中断服务线程;

DriverFunc 文件主要是对 PCI 设备的基本操作函数, 包括 PCI 设备搜索, PCI 设备初始化,使能或关闭中断, 处理 PCI 设备共享中断, 以及 PCI 驱动程序资源清理等函数。

  1. 完整的 RTX PCI驱动

基于RTX PCI 设备驱动程序框架, 用户需要添加相应的代码, 下面基于反射内存卡的 RTX 驱动进行分析。

反射内存卡的基本特点:

(1) PCI、PCIe、PMC、VME 外形, 节点之间组成环形连接或通过光纤 Hub 组成星型连接

(2) 节点之间数据确定性的传输延迟, 延迟小于 750us

PCI 反射内存卡的 RTX 驱动也分成 Driver 文件和DriverFunc 文件两个文件。Driver 文件主要包括 main 函数,中断服务程序和中断服务线程, 下面是详细的分析:

(1) Main 函数:

Main 函数并不是 RTX PCI 驱动程序的一部分, 准确的讲它是如何使用 RTX PCI驱动程序的流程。用户需要做的工作:

a. 在 RTX PCI 设备驱动程序框架生成的 main 函数需要在设备初始化 (DeviceInit()) 完成之后与使能 PCI 中断之前添加设备打开(open())函数, 该函数的功能主要是创建信号量和初始化板卡.

b. 使能 PCI 中断之后, 用户即可调用 PCI驱动程序里的读写等函数写一段简单的读写测试程序。

(2) 中断服务程序:

这个函数接收到中断后交给中断服务线程来处理, 用户一般不需要改动。

(3) 中断服务线程:

中断服务线程主要完成读取和记录 PCI 板卡的中断信息, 释放相关的信号量等工作, 一般不完成具体的中断处理工作。PCI 驱动程序一般还提供一个函数来捕捉这些释放的信号量, 完成中断具体含义的解析工作。

DriverFunc 文件主要是对 PCI 设备的基本操作函数, 包括 PCI 设备搜索, PCI 设备初始化,使能或关闭中断, 处理 PCI 设备共享中断, 以及 PCI 驱动程序资源清理, 数据读写, 发送和接收消息类中断等函数。下面是详细的分析:

(1) DeviceSearch 函数

这个函数根据 PCI 设备的 Vendor ID 和 Device ID 搜索 PCI 设备, 返回 PCI 配置信息和 slot Number. 用户修改 Vendor ID 和 Device ID 即可。

(2) DeviceInit 函数

PCI设备初始化函数. 该函数中间调用了两个RTX 系统函数RtTranslateBusAddress() 和 RtMapMemory(), RtTranslateBusAddress() 作用为把 PCI 设备地址转换为 CPU 可以直接访问的物理地址, RtMapMemory() 函数把物理地址映射到虚拟地址。映射到虚拟地址空间后 ring3用户即可以读写 PCI 内存空间或者 I/O 空间了。用户需要关注的是物理地址到虚拟地址映射的地址范围,一般设置为 4K Bytes. RtMapMemory() 函数默认最大可以映射的地址范围为 64M Bytes, 如果需要更大的范围, 可以参考内存管理一节。

(3) Enable/Disable Interrupts On Chip 函数

使能或者关闭 PCI 设备上的中断。用户根据 PCI 设备进行修改。

(4) IsMyInterrupt函数

RTX 下 PCI 设备中断号可以共享。如果有 RTX 下 PCI 设备共享, 需要在该函数中间区分是否是该设备的中断.

(5) DeviceCleanup 函数

该函数释放中断句柄和解除物理地址于虚拟地址之间的映射。用户基本不需要修改该函数。

(6) RFM2gOpen 函数

反射内存功能函数。该函数的功能主要是为 DMA 通道,发送和接收Event(反射内存的一种消息类中断)等硬件功能模块创建信号量和初始化板卡。为了防止对硬件资源的访问冲突, 使用这些硬件资源前需要先拿到信号量, 使用结束后释放这些信号量。

(7) RFM2gEnableEvent函数

反射内存功能函数。使能板卡接收消息类中断。

(8) RFM2gSendEvent 函数

反射内存功能函数。向其它节点发送消息类中断。

(9) RFM2gWaitForEvent函数

反射内存

2015-01-17 12:40:16 dijkstar 阅读数 8837
  • Cloud Foundry技术新纪元 2017年发展趋势前瞻

    介绍开源CF和Pivotal CF新的一些技术进展,CF在2016年增加了大量的功能,包括行业热点功能:比如采用RunC的容器运行时,对容器的网络和存储插件的支持,也有很多企业级功能,如安全性的增强,支持PCI的安全性等。 PCF已经大规模的在生产系统使用,已经越来越成熟,Pivotal积极收集客户需求,反馈到PCF的功能实现上。

    2137 人正在学习 去看看 CSDN讲师

近期在64位Win7下开发一款PCIe接口的多串口卡驱动程序,做个小结:


1. 因为在Win下对WDF不熟悉,加上市面上DDK、WDM书籍较多,故选用WDM框架;


2. 多串口卡的硬件接口为PCIe,因为在软件驱动层面上,PCIe和PCI兼容,直接借用常用的WDM即插即用框架。这里用《Windows驱动开发技术详解(张帆等编写)》第16章Test5中的InitMyPCI函数。该函数枚举了PCI总线的各种资源,如中断、IO口、内存等,直接原封不动的拿来即可用;

① PCI工具PciScope、RW,多多使用;

② WinDriver开发框架虽然简单,但效率不高,做初期验证不错;但随着对PCI等总线的深入了解,发现还不如自己控制来的直接;DriverStudio也是如此;

② 访问一个LONG型的reg,注意内存边界访问方式,:WRITE_REGISTER_ULONG((PULONG)(g_MemBar0+(i * 4) + UART_TX_DATA), dwVal);【这里g_MemBar0是一个unsigned char类型的


3. 该串口卡没有使用中断,底层数据交换都是读写reg实现的。这种机制,驱动开发难度一下子减少了不少,故在内核驱动中启动一个线程,轮询PCIe定义的reg资源,调度线程每次Sleep为1ms(但经测试DebugView测试,实际在15ms左右)。这里和硬件设计人员沟通,每次休息的15ms中,串口卡FPGA中数据缓存足够大,不会丢失。但在串口使用层面看,写入或读出的数据会带来约15ms的延时(忽略其他延时),这是一个需注意的问题;

//延时函数,单位为ms
void MySleep(LONG msec)
{
#define DELAY_ONE_MICROSECOND		(-10)							//1微秒
#define DELAY_ONE_MILLISECOND		(DELAY_ONE_MICROSECOND*1000)	//1毫秒
	
	LARGE_INTEGER	my_interval;
	my_interval.QuadPart = DELAY_ONE_MILLISECOND;
	my_interval.QuadPart *= msec;
	
	KeDelayExecutionThread(KernelMode, 0, &my_interval);
}

由此看来,内核层的1ms睡眠,和Win32的(1)精度一样,不加高精度多媒体库时,都是约15ms。

(关于在Win32下测量Sleep的精度问题,参见我的另一篇文章:http://blog.csdn.net/dijkstar/article/details/23092747,里面有详细的测试方法和测试数据)


4. 驱动层面暴露给Win32的串口COM口,使用《Windows驱动开发技术详解(张帆等编写)》第19章的Virtual_COM示例。

借用这个框架,能看出市面上最常用的串口调试助手“sscom32.exe”,在读取数据时,调用了IOCTL_SERIAL_GET_COMMSTATUS,又调用了IOCTL_SERIAL_WAIT_ON_MASK(对应Win32的WaitCommEvent),所以,自己写的驱动里,必须要处理这两个请求:对第一个IOCTL_SERIAL_GET_COMMSTATUS,简单点处理,要将当前可读的数据个数赋值给AmountInInQueue成员;第二个请求,还用原框架内容:立刻Pending该请求,但要在轮询的线程里,轮询Fifo(后面介绍)发现有数据时,释放到这个请求。这个逻辑查看函数DriverCheckEvent怎么被调用的即可;


5. 如何多个设备dev的创建?传统的WDM是创建一个fdo,附加在底层的pdo之上。灵活改变一下,将第一个fdo创建时,调用IoAttachDeviceToDeviceStack,但第二个、第三个....,不要调用该函数,这样创建后,用DeviceTree查看创建的设备列表,发现他们都是“平行”关系,而不是“Att”关系(只有第一个是);

如此,在Win32应用层CreateFile、ReadFile、WriteFile时,访问的都是“当前”的那个dev,所以,要在驱动层里,自己维护一个全局的设备dev[n]数组;


6. WDM的初始化PCI设备函数是放在IRP_MN_START_DEVICE完成的,而IRP_MN_START_DEVICE又依赖于“某一个dev”的CreateFile完成的,怎么办?使用一个全局变量,当应用层CreateFile时第一个设备时(下标不一定是0),调用初始化PCI设备函数,将全局变量置false,下次再有应用层CreateFile不会调用InitMyPCI;

由此看出,“WDM即插即用”和“传统的NTDriver”并没有区分的那么明显,像上面的思路,就是把两者结合起来使用了;


7. 64位inf生成:只需要将张帆示例的inf添加个NTamd64即可,如下:

[Manufacturer]
%MfgName%=Mfg0,NTamd64

[Mfg0.NTamd64]

; PCI hardware Ids use the form
; PCI\VEN_aaaa&DEV_bbbb&SUBSYS_cccccccc&REV_dd
%DeviceDesc%=YouMark_DDI, PCI\VEN_9999&DEV_9999

8. 64位Win7的驱动需要数字签名,目前没有找到彻底解决办法,暂时:

① 每次启动按F8进入“禁用驱动签名”;

② 进入TestMode:bcdedit/set testsigning on(一定用管理员身份运行),但这样结果导致会出现桌面右下角水印;

③ 使用工具dseo13b.exe(http://www.ngohq.com/?page=dseo);

④ 找网上的“去水印”工具(Windows 7 Watermark Remover);

⑤ 张佩写的签名工具:64Signer V1.2.exe,使用文档、签名原理及下载处:http://www.yiiyee.cn/Blog/64signer/


9. IRP同步问题,做一个假设:假设用户应用程序不会开启两个线程同时调用ReadFile、WriteFile,因此在IRP_MJ_READ、IRP_MJ_WRITE处理里,不考虑STATUS_PENDING的情况,而是直接读写Fifo缓冲区,即为一个非阻塞的操作,无论有无数据都立刻返回。由上层用户启动线程时在调用ReadFile类似的函数时,自己Sleep操作;

如果假设应用层开启两个线程同时ReadFile操作,那么应该使用“串行化处理IRP”(StartIO例程)技术,基本思路是IRP_MJ_READ请求进来后,先Pending挂起该请求,将该请求入队,在StartIO例程里去处理该请求,自己做取舍;


10. 硬件Reg数据的使用:驱动中一个线程高速轮询Reg,不断的读写,读出或写入的数据不是和IRP_MJ_READ、IRP_MJ_WRITE交互,而是首先放到一个Fifo中再交互。这个Fifo要在驱动里自己实现,参见我的另一篇文章:http://blog.csdn.net/dijkstar/article/details/42361805(推荐一个VC下的FIFO实现源码CCircularFifo,附带测试程序),这个程序稍加改造,就可以在驱动层面中使用,记住在内核里创建内存干脆直接用NonPagedPool(非分页内存)吧,现在的机器内存都不少于4G了,没必要为区区一点“交换内存”而引起蓝屏崩溃。



2006-11-09 13:32:00 BuilderChen 阅读数 3658
  • Cloud Foundry技术新纪元 2017年发展趋势前瞻

    介绍开源CF和Pivotal CF新的一些技术进展,CF在2016年增加了大量的功能,包括行业热点功能:比如采用RunC的容器运行时,对容器的网络和存储插件的支持,也有很多企业级功能,如安全性的增强,支持PCI的安全性等。 PCF已经大规模的在生产系统使用,已经越来越成熟,Pivotal积极收集客户需求,反馈到PCF的功能实现上。

    2137 人正在学习 去看看 CSDN讲师
        八、九 月份的时候为一块PCI卡驱动程序增加了bus master DMA和中断服务功能,到现在有一段时间没弄,一些细节有些记不大起来了,赶紧把一些要点记录一下,以免日子久了都忘记了。
        硬件是一块PCI数据采集卡,50MHz,8bit的采集速率,板上使用FPGA(Cyclone II)先对数据进行压缩等处理,然后给上位机。PCI总线用的是PLX公司的PCI9054芯片。原来的驱动不支持DMA,也不支持中断,上位机程序只能不断轮询某个标志位,如果有数据再读取。这作为一块高速的数据采集卡,实在是有点说不过去(原驱动还是出自国内某一流高校之手笔,汗)。
       驱动程序这东西感觉这一点那一点,知识点比较杂,也不知道怎么理出个条理,反正就想到什么记什么了。开发环境:VC++6.0, Win XP DDK, DriverStudio 3.1.0。

1。PCI9054芯片其实就是一个“桥”,一边是PCI总线,另一边是本地总线(local bus)。9054的作用就是把PCI的地址翻译到本地总线的地址。9054有M,C,J三种模式,我的理解就是本地总线的不同,一般用的是C模式。

2。PCI的4个空间要映射到哪个物理地址,是由宿主机器的操作系统或bios动态配置的。宿主系统怎么知道空间的大小呢?方法是系统启动时向PCI配置空间的基地址(PCI base addresss)寄存器写一个全1的32位数,然后立刻读回来,比如说读到0xFFFF0000,后16位是0,说明这个空间有64K。就是说前16位是可写的,被写入1,而后16位是不可写的,值永远是0。然后系统就分配一个基地址,把这个地址写入前16位中,于是基地址寄存器中就保存了分配到的物理基地址。反过来说,如果一个设备要求分配64K内存,那么它就应该实现一个基地址寄存器,其高16位是可读写的,后16位是只读并且为0的(其实最后4位是选项位,可能不为0)。对于中断号的分配也简单,系统把分配的中断号写入到PCI配置空间的Interrup Line寄存器中就ok了,意思就是把PCI卡的中断请求线连接(route)到了中断管理器的几号中断脚上。

3。PCI空间配置好以后,软件通过访问配置空间的基地址寄存器,可以得知空间被映射到了哪个地址。但最先怎么访问配置空间呢?对于PC架构的机器来说,是通过PCI桥来访问的。PCI桥作为PCI总线的管理芯片,可以区别访问不同的PCI插槽。PCI桥的寄存器被固定映射到IO空间的0XCF8,0XCFC,通过操作这两个寄存器,可以访问到各个总线号、设备号、功能号的寄存器了。但开发WDM驱动的时候,这些都不需要我们自己做了,一般我们只要提供Vendor ID和Devcie ID,就可以得到基地址指针了。

4。对于驱动程序,要完成一个事务一般得分成几步,在不同的函数里完成,并且同一个函数里还得根据状态完成不同事务的某个部分。所以采用状态机是个比较适合的选择。例如对于中断的响应,在Isr_irq()里主要是查明中断原因、清除中断源,然后排队一个DpcFor_Irq,尽快返回。因为Isr_irq()是中断级高的环境,运行期间其他中断会被屏蔽,从而降低系统性能。而余下的费时工作,如读数据等操作,则由DpcFor_Irq()来完成。DpcFor_Irq()中断级低,这样在DpcFor_Irq()运行期间Isr_irq()又可以响应其他中断了。

5。DMA传输涉及的步骤比较多,大概的流程是:
        a)SerialRead()收到一个读的IRP,初始化一个KDmaTransfer对象;
        b) KDmaTransfer会调用回调函数OnDmaReady(),在OnDmaReady()里设置硬件寄存器,开始DMA;
        c)硬件DMA完成,触发中断,经Isr_Irq(),到DpcFor_Irq(),在DpcFor_Irq()里调用KDmaTransfer的Continue()函数。这是因为一个IRP请求的数据量可能一次DMA无法完成,需要分成多次。
        d)KDmaTransfer再调用一次OnDmaReady(),OnDmaReady()判断BytesRemaining,看是否需要再启动一次硬件DMA。如果不需要,则调用KDmaTransfer的Terminate(),结束这个Transfer。然后调用PnpNextIrp(),完成这个IRP。
        对于我们的卡,情况比较特殊,在应用程序发出IRP后,还必须等采集卡发出数据就绪中断后,才可以开始DMA。因此我在OnDmaReady()里并不立刻启动硬件DMA,而是在数据就绪中断的DpcFor_Irq()里,先判断是否有Read的IRP在等待处理,再启动硬件DMA。

6。PCI总线时序的简单描述:
PCI传送以burst为单位,FRAME#信号指示burst的开始和结束。FRAME#信号使能后的第一个时钟周期是命令周期,以后是数据周期。FRAME#拉高后一个周期传送结束。
PCI master在拉低FRAME#后的第一个时钟上升沿(即命令周期)在AD[31:0}给出地址,在C/BE[3:0]给出命令。命令有I/O r/w, Memory r/w, Configuration r/w等
PCI master第二个上升沿在AD[31:0}给出数据,在C/BE[3:0]给出字节使能。
PCI master拉高FRAME#后的一个上升沿给出最后一个数据和字节使能,一个frame到此结束。
IRDY#和TRDY#用于master(initiator)和slave(target)之间指示是否就绪,如果有一方未就绪,数据周期中间会插入等待周期。


2007-07-25 15:25:00 coloriy 阅读数 2615
  • Cloud Foundry技术新纪元 2017年发展趋势前瞻

    介绍开源CF和Pivotal CF新的一些技术进展,CF在2016年增加了大量的功能,包括行业热点功能:比如采用RunC的容器运行时,对容器的网络和存储插件的支持,也有很多企业级功能,如安全性的增强,支持PCI的安全性等。 PCF已经大规模的在生产系统使用,已经越来越成熟,Pivotal积极收集客户需求,反馈到PCF的功能实现上。

    2137 人正在学习 去看看 CSDN讲师

八、九 月份的时候为一块PCI卡驱动程序增加了bus master DMA和中断服务功能,到现在有一段时间没弄,一些细节有些记不大起来了,赶紧把一些要点记录一下,以免日子久了都忘记了。 硬件是一块PCI数据采集卡,50MHz,8bit的采集速率,板上使用FPGA(Cyclone II)先对数据进行压缩等处理,然后给上位机。PCI总线用的是PLX公司的PCI9054芯片。原来的驱动不支持DMA,也不支持中断,上位机程序只能不断轮询某个标志位,如果有数据再读取。这作为一块高速的数据采集卡,实在是有点说不过去(原驱动还是出自国内某一流高校之手笔,汗)。 驱动程序这东西感觉这一点那一点,知识点比较杂,也不知道怎么理出个条理,反正就想到什么记什么了。

开发环境:VC++6.0, Win XP DDK, DriverStudio 3.1.0。

 1。PCI9054芯片其实就是一个“桥”,一边是PCI总线,另一边是本地总线(local bus)。9054的作用就是把PCI的地址翻译到本地总线的地址。9054有M,C,J三种模式,我的理解就是本地总线的不同,一般用的是C模式。 

2。PCI的4个空间要映射到哪个物理地址,是由宿主机器的操作系统或bios动态配置的。宿主系统怎么知道空间的大小呢?方法是系统启动时向PCI配置空间的基地址(PCI base addresss)寄存器写一个全1的32位数,然后立刻读回来,比如说读到0xFFFF0000,后16位是0,说明这个空间有64K。就是说前16位是可写的,被写入1,而后16位是不可写的,值永远是0。然后系统就分配一个基地址,把这个地址写入前16位中,于是基地址寄存器中就保存了分配到的物理基地址。反过来说,如果一个设备要求分配64K内存,那么它就应该实现一个基地址寄存器,其高16位是可读写的,后16位是只读并且为0的(其实最后4位是选项位,可能不为0)。对于中断号的分配也简单,系统把分配的中断号写入到PCI配置空间的Interrup Line寄存器中就ok了,意思就是把PCI卡的中断请求线连接(route)到了中断管理器的几号中断脚上。 

3。PCI空间配置好以后,软件通过访问配置空间的基地址寄存器,可以得知空间被映射到了哪个地址。但最先怎么访问配置空间呢?对于PC架构的机器来说,是通过PCI桥来访问的。PCI桥作为PCI总线的管理芯片,可以区别访问不同的PCI插槽。PCI桥的寄存器被固定映射到IO空间的0XCF8,0XCFC,通过操作这两个寄存器,可以访问到各个总线号、设备号、功能号的寄存器了。但开发WDM驱动的时候,这些都不需要我们自己做了,一般我们只要提供Vendor ID和Devcie ID,就可以得到基地址指针了。 

4。对于驱动程序,要完成一个事务一般得分成几步,在不同的函数里完成,并且同一个函数里还得根据状态完成不同事务的某个部分。所以采用状态机是个比较适合的选择。例如对于中断的响应,在Isr_irq()里主要是查明中断原因、清除中断源,然后排队一个DpcFor_Irq,尽快返回。因为Isr_irq()是中断级高的环境,运行期间其他中断会被屏蔽,从而降低系统性能。而余下的费时工作,如读数据等操作,则由DpcFor_Irq()来完成。DpcFor_Irq()中断级低,这样在DpcFor_Irq()运行期间Isr_irq()又可以响应其他中断了。

 5。DMA传输涉及的步骤比较多,大概的流程是: 

a)SerialRead()收到一个读的IRP,初始化一个KDmaTransfer对象;

 b) KDmaTransfer会调用回调函数OnDmaReady(),在OnDmaReady()里设置硬件寄存器,开始DMA;

 c)硬件DMA完成,触发中断,经Isr_Irq(),到DpcFor_Irq(),在DpcFor_Irq()里调用KDmaTransfer的Continue()函数。这是因为一个IRP请求的数据量可能一次DMA无法完成,需要分成多次。

 d)KDmaTransfer再调用一次OnDmaReady(),OnDmaReady()判断BytesRemaining,看是否需要再启动一次硬件DMA。如果不需要,则调用KDmaTransfer的Terminate(),结束这个Transfer。然后调用PnpNextIrp(),完成这个IRP。 对于我们的卡,情况比较特殊,在应用程序发出IRP后,还必须等采集卡发出数据就绪中断后,才可以开始DMA。因此我在OnDmaReady()里并不立刻启动硬件DMA,而是在数据就绪中断的DpcFor_Irq()里,先判断是否有Read的IRP在等待处理,再启动硬件DMA。 

6。PCI总线时序的简单描述: PCI传送以burst为单位,FRAME#信号指示burst的开始和结束。FRAME#信号使能后的第一个时钟周期是命令周期,以后是数据周期。FRAME#拉高后一个周期传送结束。 PCI master在拉低FRAME#后的第一个时钟上升沿(即命令周期)在AD[31:0}给出地址,在C/BE[3:0]给出命令。命令有I/O r/w, Memory r/w, Configuration r/w等 PCI master第二个上升沿在AD[31:0}给出数据,在C/BE[3:0]给出字节使能。 PCI master拉高FRAME#后的一个上升沿给出最后一个数据和字节使能,一个frame到此结束。 IRDY#和TRDY#用于master(initiator)和slave(target)之间指示是否就绪,如果有一方未就绪,数据周期中间会插入等待周期。

没有更多推荐了,返回首页