USB协议与Windows USB设备驱动程序笔记

USB概述

USB是分层的星形拓扑结构(不超过7层,包括根集线器),USB主控制器包含了root hub,一起构成了层的起点。USB是主从架构,通常电脑是总线主控,设备是从机。USB主控制器负责数据处理,USB根集线器(ROOT HUB)提供一个连接USB主控制器与USB设备之间的接口和通路。USB集线器(USB HUB)可以对原有的USB端口在数量上进行扩展。一个USB主控制器下面一定有一个USB根集线器,而USB根集线器下面可以有0个或多个USB集线器或USB设备。多个USB设备共享一个USB主控制器的带宽。所以一个USB根集线器下面连接了多个USB设备的系统,与一个USB根集线器下面只连接了一个USB设备的系统相比,后者USB设备将工作地更快。USB集线器中包括上行端口和下行端口(也称上游端口和下游端口),上行端口连接主机或集线器的下行端口,下行端口连接USB设备或集线器的上行端口。USB设备地址是7位,理论上一个USB主控制器下面可以接128个USB设备,地址范围为0~127,其中地址0作为刚接入系统的USB设备的默认地址。

USB低速传输是在USB全速传输环境中实现的。USB1.0为低速;USB1.1为全速,所有的USB HUB都支持全速;USB2.0为高速,于2001年引出,所有的USB高速设备都能退回到全速传输。USB2.0是半双工,有4根信号线;USB3.0是全双工,有9根信号线,其中包括USB2.0的信号线。USB高速设备在全速下枚举,当主机和设备都同意高速时,设备就切换到高速传输,这个协商过程发生在USB复位过程中,通过Chirp协议协商。

一个具体的端点,只能工作在一种传输模式下。通常把工作在什么模式下的端点,叫做什么端点。例如,控制端点,批量(bulk)传输端点等。

USB一次传输(如一次bulk读)包括1个或多个事务,1个事务包括3个包:令牌包、数据包、握手包(等时传输没有)。USB传输包括控制传输、批量(bulk)传输、中断传输、等时传输。一次控制传输分为3个过程:建立过程、可选的数据过程、状态过程。这里只提建立过程和状态过程。建立过程为一个事务,其令牌包的类型为SETUP,数据包类型为DATA0,握手包类型为ACK(出错则不应答,而不能使用NAK或STALL来应答)。状态过程为一个事务,其令牌包类型为IN或OUT,其数据包类型为DATA1。低速和全速USB每隔1ms传输一帧,高速USB每隔125us传输一帧。每个帧以PID为SOF的令牌包作为起始包。每个帧可以容纳多个事务,注意事务中的令牌包的PID只能是IN、OUT或SETUP。

USB传输:控制传输、bulk传输、iso传输、中断传输;

USB一个传输可以分为多个事务,而一个事务分为3个Packet:令牌包(Token)、数据包、握手包,对于iso传输,没有握手包;

一个packet由同步域(SOP+SYNC)、包内容、包结束符(EOP)组成;

包内容=PID(8位)+目的地址域(11位)+帧号域(11位)+数据域+CRC(5位),不同类型的包,其内容有所不同;

PID=OUT/IN/SETUP时,该包为令牌包(Token),没有帧号和数据,令牌包总是由主机发出,PID为SETUP的令牌包仅用于控制传输;

PID=DATA0/DATA1/DATA2/DATAM时,为数据包,没有地址域和帧号域;

PID=ACK/NAK/STALL/NYET/ERR时,为握手包,只有PID域;

PID=SOF时,为SOF包,没有地址域、数据域;

目的地址=设备地址(7位)+端点地址(4位),LS设备最多3个端点,FS/HS设备最多16个端点;

为了防止USB总线设备挂起,需要每隔一段时间就发送SOF包,主机每发一帧,帧号就加1,当帧号达到7FFH时,帧号归零,重新计数;

不同的USB传输,包内容中的数据的最大长度不同:

握手包中:

ACK:传输正确完成;

NAK:设备暂时没有准备好接收数据,或没有准备好发送数据;

STALL:设备不能进行传输;

NYET/ERR:仅用于高速传输,设备没有准备好或出错;

关于数据包中的DATA0和DATA1,举例如下:

发送方:DATA0-DATA1-DATA0-DATA1-DATA0......

接收方:DATA0-DATA1-DATA0-DATA1-DATA0......

上面是发送方和接收方都没有出错的情况,这里DATA0到DATA1的切换被称为toggle;

如果发送方发送DATA0,而接收方没有正确收到数据,于是接收方响应NAK,发送方收到NAK的握手包后,会重新发送DATA0;如果接收方正确收到了DATA0,则响应ACK,则发送方收到ACK后,就会发送DATA1;

设备描述符:

配置描述符:

接口描述符:

端点描述符:

Windows USB设备驱动程序

USB设备驱动程序高度依赖USB总线驱动程序(在Windows系统中USB总线驱动程序是USBD.sys)而不直接使用HAL函数与硬件通信。USB设备驱动程序为了向其硬件设备发送一个请求,首先创建一个USB请求块(URB),然后把URB提交到USB总线驱动程序。例如,为了配置一个USB设备,USB设备驱动程序需要提交几个URB来读取各种描述符或发送命令,最后由总线驱动程序把请求送到总线上。 

USB主控制器与其它I/O设备接口一样直接连接到系统总线(PCI总线)上。操作系统与USB主控制器通信使用I/O口或内存寄存器(即USB主控制器映射到I/O空间或内存空间,CPU通过I/O指令或内存访问指令与USB主控制器通信),通过普通的中断信号,系统可以接受USB主控制器的事件通知。USB主控制器连接一棵USB设备树。一种称为hub的设备作为其它设备的连接点。多个hub能以菊链方式连接,可以连接到USB规范中定义的最大深度。其它设备,如照相机、麦克风、键盘等等,直接连到hub上。为了精确地表达概念,USB使用术语function来描述非hub设备。 

当一个USB设备第一次接入时,它使用默认的设备地址(0)。然后,某个电子信号通知USB总线驱动程序有一个新设备插入总线,于是USB总线驱动程序找出一个未用的设备地址并发送一个控制事务告诉“0号设备”什么才是它的真实地址。这之后,设备就放弃使用默认地址0,而用真实地址来应答。

当客户程序通过USB管道发送或接收数据时,它首先调用Win32 API,调用最终将使function的驱动程序(即USB设备驱动程序)收到一个IRP。而驱动程序的工作就是把客户的请求引导到有正确端点的管道上。它把请求提交到总线驱动程序,总线驱动程序再把请求分解成多个事务(transaction),然后这些事务被送往总线。

与传统PC总线(如PCI总线)设备的驱动程序相比,USB设备驱动程序从不直接与硬件对话。相反,它仅靠创建URB(USB请求块)并把URB提交到USB总线驱动程序就可完成硬件操作。因而,在USB设备驱动程序的IRP_MN_START_DEVICE处理函数中,我们不需要写与硬件资源有关的代码,而只需要配置USB设备。

USB配置提供一个或多个接口,每个接口具有零个或多个端点描述符。接口描述符和端点描述符始终作为配置描述符的一部分返回,无法使用GET_DESCRIPTOR或SET_DESCRIPTOR请求直接访问接口描述符或端点描述符。接口可以包括备用设置(Alternate Setting),接口描述符中的bAlternateSetting字段用于在同一个接口中的多个描述符中进行切换,以实现在配置设备之后改变端点或它们的特性。接口的默认设置始终为备用设置0。

如果一个接口具有两个备用设置,则具有两个接口描述符。配置描述符后面是一个接口描述符,其中bInterfaceNumber和bAlternateSetting字段为0,然后是该设置的端点描述符,后跟另一个接口描述符及其关联的端点描述。第二个接口描述符的bInterfaceNumber字段也为0,但第二个接口描述符的bAlternateSetting字段为1。如下图所示:

 如果接口仅使用端点0,则接口描述符后面不会紧接有端点描述符。在这种情况下,接口描述符中的bNumEndpoints字段必须设置为0。接口描述符永远不包括端点数量中的端点0。

FX3 CYUSB3014学习笔记

FX3官方文档有以下叙述:

AN76405,Page12: In the transfer execution entry command, the bootloader will turn off all the interrupts and disconnect the USB.

FX3_Programmers_Manual,Page66: The next step in the initialization sequence is USB enumeration. After descriptor and endpoint configuration, the Connect API is issued to the USB driver. This enables the USB PHY and the pull-up on the D+ pin. This makes the USB device visible to a connected USB host and the enumeration continues.

FX3_Programmers_Manual 的 5.2.1.1节很重要。

Host PC端的USB设备驱动程序一开始会获取USB设备的设备描述符和配置描述符,然后发送SET_CONFIGURATION请求。USB设备端一上电就会配置好各个端点,在收到SET_CONFIGURATION请求之前,FX2/FX3的USB接口已经配置好了。

FX3的USB通过DMA传输时,在手动DMA中,如果FX3固件未调用CyU3PDmaChannelCommitBuffer,则上位机读端点函数(比如DeviceIoControl或WinUsb_ReadPipe)将一直阻塞等待;只有FX3固件调用了CyU3PDmaChannelCommitBuffer,上位机的读端点函数才会返回,固件提交了多少数据(可以是0个字节,此时就是所谓的ZLP),上位机就读多少数据;FX3固件提交了N次,读操作函数就要调用并返回N次。

  • 1
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值