标签:翻译 针对 nbu 不同 top 设备信息 val 字节 编译
原文地址:http://www.cnblogs.com/jacklu/p/6139347.html
正如前几篇博客所说,使用WDF开发PCIe驱动程序是我本科毕业设计的主要工作。在读研的两年,我也分别为所在课题组移植了自己编写的驱动程序,在Windows 32位和64位平台下的PXI、PXIe、PCI、PCIe板卡分别得到了验证。
这篇文章根据自己最新编写的驱动代码(源代码请找博主索取),主要讲述如何为自己的硬件板卡移植驱动程序,并简单讲述如何使用Altera系列FPGA配置PCI IP核,然后对INF文件作简要描述,最后描述如何使用Qt编写上位机软件调用底层驱动。
准备去读博了,这一篇将作为这个系列的完结,之后将把更多精力放到机器学习上来。
所编写的驱动代码程序包括7个源代码文件,分别是Device.h, Driver.h, Public.h, Trace.h, Device.c,Driver.c, Queue.c。其中Device.h 定义了与硬件相关的地址偏移;Public.h定义了DeviceIoControl 用到的用户自定义命令字, 此头文件由上层应用程序和驱动程序共同使用;Queue.c定义了I/O回调例程,分别使用了read、write和I/O Control 三个队列。 除了这三个文件外, 不建议更改其他4个文件的代码。三个源文件函数列表分别如图 1-1、1-2、1-3所示:
什么是 CRA 寄存器组? 打开 quartus 的 sopc builder,可以看到sopc架构如图 2-1 所示,在PCI IP核一栏中有 Control Register Access 寄存器组,地址范围0x00000000-0x00003fff。 里面关键的寄存器地址如图 2-2 所示。 通过读黄色标识的寄存器,可以通过驱动程序调试验证 PCI 核。 关于 CRA 寄存器组的配置说明会在 2.3 节详细说明。
GUID( Globally Unique Identifier) 是微软推出的全局唯一标识符, 通过使用某个特定的算法( 比如根据时间或地点等信息) 生成一组128 位二进制数,来标识某一个实体,比如硬盘上的一张图片。 GUID 广泛应用于微软的产品中, 用于识别接口、文件等对象。开发者可以使用 VS2013 下的工具 GUIDGen.exe 生成 GUID 值, 该 GUID 标识驱动程序, 应用程序根据这个 GUID 值来找到对应的驱动程序。
应用程序总体流程设计为: 首先通过 Win32API 函数 CreateFile 打开设备, 然后调用DeviceIoControl 函数与驱动程序通信,即读写数据,当应用程序退出时,调用CloseHandle函数关闭设备。
应用程序根据底层设置的 GUID 获取设备路径, 从而与指定设备建立连接: 首先调用SetupDiGetClassDevs 函数获得符合传入参数 GUID 的设备信息集合 hDevInfo; 然后根据设备信息集合 hDevInfo 和 GUID 调用 SetupDiEnumDeviceInterfaces 函数枚举设备信息集合中的设备,并输出设备接口数据信息 DeviceInterfaceData ; 再 根 据 hDevInfo和 DeviceInterfaceData 调用 SetupDiGetDeviceInterfaceDetail函数得到保存设备接口详细信息DeviceInterfaceDetailData 的缓冲区大小 ,接着为其开辟空间 , 最后再调用一次SetupDiGetDeviceInterfaceDetail 函数获得设备接口详细信息 pDeviceInterfaceDetailData; 最后根据设备接口详细信息的设备接口路径 pDeviceInterfaceDetailData->DevicePath 调用CreateFile 函数来创建设备句柄。
在测试程序 Source.c 的代码第 62-70 行,完成打开设备句柄功能, 不需要用户改动。
成功打开设备后, 调用 DeviceIoControl 即可通过 IOControl 队列与驱动程序通信, 以读32bit 数据为例, 首先向驱动程序写入需要读的存储单元地址, 如代码第 257-272 行所示,然后向驱动程序传入读数据缓存 outBuffer, 如代码第 274-289 所示, 即可获得FPGA 上对应偏移地址的数据。
成功打开设备后, 调用 DeviceIoControl 即可通过 IOControl 队列与驱动程序通信, 以写32bit 数据为例, 首先向驱动程序写入需要写的存储单元地址, 如代码第 303-317 行所示,然后向驱动程序传入缩写数据缓存 inBuffer, 如代码第 322-336 所示, 即可将数据写入 FPGA上对应偏移地址的内存单元。
通过Win32API 函数ReadFile和WriteFile对设备句柄进行文件读写操作, 在内核驱动中会调用驱动程序的 qd41EvtIoRead和qd41EvtIoWrite,实际的DMA配置在这两个驱动回调例程中实现, ReadFile和WriteFile 只是完成了数据从用户层到内核层的搬运。详细代码在第 340-378 行,不再赘述。
我把C语言编写的应用程序每一个独立的控制命令编译成一个可执行文件,这样Qt可以在新的进程中调用 C 程序编写的命令字读写程序。使用Qt 封装好的进程类 QProcess, 使用其成员函数 start 即可调用一个外部程序。
基于WDF的PCI/PCIe接口卡Windows驱动程序(5)-如何为硬件移植驱动程序
标签:翻译 针对 nbu 不同 top 设备信息 val 字节 编译
原文地址:http://www.cnblogs.com/jacklu/p/6139347.html