图1 USB驱动程序模型
USB设备驱动程序是一种典型的WDM(Windows Driver Model)驱动程序,其程序模型如图1所示。用户应用程序工作在Windows操作系统的用户模式层,它不能直接访问USB设备,当需要访问时,通过调用操作系统的API(Application programming interface)函数生成I/O请求信息包(IRP),IRP被传输到工作于内核模式层的设备驱动程序,并通过驱动程序完成与UBS外设通信。设备驱动程序包括两层:函数驱动程序层和总线驱动程序层,函数驱动程序一方面通过IRP及API函数与应用程序通信,另一方面调用相应的总线驱动程序,总线驱动程序完成和外设硬件通信。USB总线驱动程序已经由操作系统提供,驱动程序开发的重点是函数驱动程序。
USB设备驱动程序的设计
使用DriverStudio3.2开发USB设备驱动程序
该驱动程序的主要功能包括:从控制端点0读取规定个数的数据、向端点0发出控制命令、从端点2批量读数据、向端点2批量写数据,驱动程序的开发采用DriverStudio3.2驱动程序开发包及VC++6.0,使用开发包中的向导程序DriverWizard就可以方便的生成驱动程序框架、模块及部分程序源代码,开发者只需要在功能模块中加入自己的实现程序就能完成复杂的USB设备驱动程序设计,下面介绍使用DriverWizard生成ISP1581驱动程序的过程:
1)启动DriverWizard,选择DriverWorks Project创造一个名为USBDIO的VC++项目;
2)在驱动程序类型中选择WDM Driver,WDM Function Driver,在硬件设备所支持的总线类型中选择USB(WDM Only),在USB Vendor ID(厂商识别码)中填写0741,在USB Product ID(产品识别码)中填写0821;
3)增加USB设备端点,设置端点2为批量输入/输出传输方式;
4)在驱动程序支持的功能项中选择Read、Write、Device Control、Cleanup;
5)选择自动产生批量读及批量写程序代码;
6)在I/O请求IRP处理方式中选择None,即IRP不排队;
7)在接口的打开方式中选择Symbolic link:UsbdioDevice,即应用程序以符号链接名打开设备;
8)定义应用程序调用DeviceIoControl函数对WDM驱动程序通信的控制命令,结果如图2所示。
图2 定义控制代码
9)最后选择完成并确认生成新的项目信息,向导程序就会在usbdio目录中生成一个名为USBDIO的项目文件,其中包括了ISP1581驱动程序框架、模块及部分源代码。
USB设备驱动程序的编程
在使用DriverWizard生成驱动程序框架、模块及部分程序源代码后,开发者只需完成图2中三个控制代码所对应的三个功能模块的编程:模块USBDIO_IOCTL_ID_CODE_Handler的功能是从控制端点0读取数据,模块USBDIO_IOCTL_TEST_COMMAND_Handler的功能是向控制端点0发送一个控制命令,模块USBDIO_IOCTL_DMA_COMMAND_Handler的功能是向控制端点0发送一个要求USB设备进行DMA传输的控制命令,下面是第一个模块的编程实例。
NTSTATUS USBDIODevice::USBDIO_IOCTL_ID_CODE_Handler(KIrp I) { NTSTATUS status = STATUS_SUCCESS; t << Entering USBDIODevice::USBDIO_IOCTL_ID_CODE_Handler, << I << EOL; PURB pUrb; ULONG numData; numData=(PUCHAR)I.IoctlBuffer();//设置读取的数据个数 pUrb=m_Lower.BuildVendorRequest( (PUCHAR)I.IoctlBuffer(),//驱动程序存放读取的数据的内存区 numData,//wLength,读取的数据个数 0, 0x0c,//bRequest 0,//wValue TRUE,//input TRUE, NULL, 0x0472,//wIndex,传输到固件程序的读数命令码 URB_FUNCTION_VENDOR_ENDPOINT, NULL ); if(pUrb==NULL) { I.Information() =0; status=STATUS_INSUFFICIENT_RESOURCES; } else { I.Information() =numData; status=m_Lower.SubmitUrb(pUrb,NULL,NULL,0); delete pUrb; } return status; }
对象I包含了应用程序下传的IRP内容,包括命令或数据等参数,函数BuildVendorRequest用来分配并初始化一个用于厂商请求的URB(USB Request Block),该URB将作为下传IRP的一个参数,通过函数SubmitUrb发送给总线驱动程序,以便完成与硬件的通信。
在初始化URB时需要了解USB的传输方式及传输协议,该功能使用了USB的控制传输方式,该方式包括三个阶段:设置阶段、数据阶段和状态阶段,其中数据阶段可选,开发者主要关注设置阶段中的8个关键字节的定义,8字节分成了5个字段,定义了传输请求及相关信息,这8个字节的格式如图3所示。
bmRequestType bRequest wValue wIndex wLength
图3 USB设置数据格式
BmRequestType:1字节,用来指定数据流动的方向,请求的类型,以及接收者。
bRequest:1字节,用来指定请求。
wValue:2字节,主机用来传输信息给设备,开发者可以根据情况自己定义。
wIndex:2字节,主机用来传输信息给设备,开发者可以根据情况自己定义。
wLength:2字节,包含数据阶段中接下来要传输的数据字节数目。
以上字段的应用已经在程序注释中标出,在此不再赘述。
USB设备驱动程序的安装及调用
USB设备驱动程序的安装
驱动程序编译完成后会生成一个名为USBDIO.SYS的文件,即USB设备驱动程序,另外在使用向导程序WizardDriver生成驱动程序时会产生一个名为USBDIO.INF的驱动程序安装程序,对此程序只需稍做修改就能正常使用,具体是将类改为USB,即Class=USB,由于本驱动程序使用符号链接名打开设备,所以删除ClassGUID选项,注意设备标识符必需为:%DeviceDesc%=USBDIO_DDI, USBVID_0471&PID_0821,其中0471是USB控制芯片的厂商识别码,0821是USB设备标识码。
驱动程序安装过程是:将USB设备加电,连入计算机的USB接口,这时候会看到Windows操作系统提示发现新硬件,提问是否安装驱动程序,选择是,然后选择驱动程序所在文件夹,选择文件USBDIO.INF即可完成安装。
USB设备驱动程序的调用
为了完成对驱动程序的调用,笔者使用VC++6.0编写了USB应用程序包,程序包共由五个功能模块组成,用户通过调用这些模块即可方便的完成对USB外设的控制及读写,这些模块如下:
1)int CTRLReadData(unsigned char usbSelect,unsigned char rbuffer,unsigned char numData),主要功能是读取ISP1581控制端点0发来的数据,数据存放在缓冲区rbuffer中。
2)int CTRLSendTestCommand(unsigned char usbSelect,unsigned short int testCommand),主要功能是发送测试命令,变量testCommand定义了测试命令。
3) int CTRLSendDMACommand(unsigned char usbSelect,unsigned char dmaDirection,unsigned char ramSelect,unsigned long dmaLength),主要功能是发送DMA传输命令,变量dmaDirection定义数据传输方向,ramSelect定义将要操作的USB外设的存储器,dmaLength定义了数据传输总数。
4)int DMARead(unsigned char usbSelect,unsigned char rbuffer,int len,int waitTime),主要功能是计算机批量读取ISP1581中的数据,而ISP1581以DMA方式从外部RAM读取数据。
5)int DMAWrite(unsigned char usbSelect, unsigned char rbuffer, int len, int waitTime),主要功能是计算机批量写数据到ISP1581,而ISP1581将以DMA方式写数据到外部RAM。
结语
USB设备驱动程序开发是Windows编程中较难的一个方面,要求开发者不但要有良好的Windows编程知识,还要掌握USB控制芯片工作原理、USB传输协议、USB固件等相关知识,使用DriverStudio3.2进行USB设备驱动程序开发可大大减少工作量和工作难度,本文所设计的USB设备驱动程序,已经应用到某雷达的自动测试设备中,驱动程序在计算机应用程序控制下可以顺利的发送各种测试命令,批量输入或者输出大量数据,达到设计要求。
上一篇:基于PIC的CAN总线超声波测距智能节点设计
下一篇:I²C总线的验证及实现
推荐阅读最新更新时间:2024-05-02 21:28
- 深入东芝参考设计库:夯实您的设计库,让您的设计更出彩
- 【看电源研讨会 抽好礼】 高密度电源系统的PCB布局与散热设计系统
- 了解ADI电网管理、能源计量方案,答题赢Kindle、《新概念模拟电路》【世健的ADI之路主题游 能源站】
- TI E2E™ 中文社区8周年,8本技术合集送给热爱技术的你!
- 逛村田在线云展厅,看干货,闯关赢好礼!
- 速度与激情,为你私人订制。R&S携多功能基础示波器带你身临其境!
- 【已结束】R&S 直播【PCI Express Gen 3 一致性测试(含demo演示)】
- Mentor线上研讨会 | 教你在设计工具中进行DFM分析,轻松兼顾效率、成本和质量
- 有奖直播|围观 普源 全新中国“芯”示波器
- 有奖直播:借助Maxim的模拟技术优化设计
- 大赛作品制作过程中遇到困难怎么办?——致SensorTile参赛小伙伴
- 直流16v转5v
- C2000内置比较器误差来源及校正方法--F28004x, F2807x, F2837x
- Failed to find a range for data of size 354962
- 关于反馈电阻上的前馈电容的补偿作用的讨论
- 【问题反馈】安路TangDynasty ChipWatcher能把人逼疯的排序
- 【2022得捷电子创新设计大赛】7508DK 数控可调电源电源部分更新
- FLASH的擦写寿命问题,擦和写各算一次吗
- 关于SimpliciTI协议的二次开发,高手请进!
- 关于英飞凌“电动汽车充电桩发展趋势及挑战”的评论