USB协议初始化
- 格式:docx
- 大小:18.86 KB
- 文档页数:14
现在非常流行USB设备,时时刻刻都在我们身边,比如使用U盘,使用MP3,使用手机,都需要与PC的USB通讯。
通过USB的接口,使用我们的生活非常方便了,想什么时候听歌,就可以插入MP3到PC机那里,然后再从PC上下载MP3。
这个过程在用户看来是非常的简单,不需要安装驱动程序,不需要断掉PC 机的电源。
真正体现“科技以人为本”的思想。
使用这么方便的U盘或者MP3,那么我们又需要去问个为什么了,为什么会这么方便呢?往往方便的背后,就意味着需要工程师做大量的工作,才会让大家使用USB这么方便。
下面就来详细地分析USB的协议。
USB通讯是非常复杂的,刚刚协议定义就厚厚的一本,要完全地去看完,并且理解它,是很费时间的事情。
希望本文可以提供给你一个非常好的指导,让你深入地理解USB 的协议。
USB的协议是主从协议,在所有通讯里,只有一个主控器,其它都是从设备。
最多能接127个从设备,因为协议里只保留了7bit作为设备地址。
所有的USB数据交流都是由主控器发起,其它从设备进行响应。
现在就以WINDOWS上的USB通讯来学习一下USB的通讯协议,后面所有提到的数据,都是WINDOWS上的USB驱动程序发下来的数据。
为了把所有通讯数据都显示出来,我找到了一个USB的ARM开发板,通过这个开发板,就可以把主控器所有数据打印出来,并作相应的分析。
同时,使用这个开发板,也可以用来调试龙芯的主控器驱动程序的调试。
当USB的开发板加电时,就会先初始化USB的连接,但没有插入PC的连接线,这时开发板就会从串口输出下面的字符:USB SuspendUSB Resume从上面看到,从设备的USB一直不断地挂起和唤醒,直到插入PC的连接线。
当插入连接线到PC时,就会收到主控器发来的信息。
下面的数据,就是开发板与USB主控器交流的数据。
1.收到主控器的获取设备描述符配置包。
Setup m=0,n=0,val=3780 06 00 01 00 00 40 00这是主控器发来第一个配置包数据。
由于主控器不知道USB设备设备描述符有多长,所以包的最后里的长度是0x0040,也就是64个字节长度。
REQUEST_STANDARD=0x6USB_DEVICE_DESCRIPTOR_TYPE(0)根据USB的协议,分析上面的数据,就知道它是获取设备描述符。
为了实现即插即用,就需要对插入来的设备进行获取描述信息,才知道这个USB的设备是什么样的设备,是U盘,还是HID的键盘。
因此,USB设备就返回下面的数据给主控器:USB_DataInStage,cnt=18,EP0Data.Count=1812 01 10 01 00 00 00 40 00 80 00 80 00 01 04 2C 4A 01 这条数据,就是USB的设备描述符,描述了这个设备使用什么USB的协议版本,这里是1.1的版本,还有厂家标识、产品标识,以及厂家、产品和序列号等字符串的偏移地址。
USB_EVT_IN,USB_DataInStageUSB_DataInStage,cnt=0,EP0Data.Count=0USB_EVT_OUT通过设备描述符,就可以让主控器知道这个设备是使用什么版本的USB协议,是高速的设备,还是低速的设备,是谁产生的,是什么产品,然后操作系统就可以通过这些信息去找到相应的驱动程序,如果操作系统没有找到相应的驱动程序,就会提示用户插入光盘,或者其它方来安装相应的驱动程序。
2.收到主控器的设置设备地址配置包。
Setup m=0,n=0,val=3700 05 01 00 00 00 00 00这条数据,根据USB的协议,就可以知道它是设置USB设备的地址配置包。
它的作用,就是分配USB设备的地址,由于USB总线上可以有127个设备,那么每个设备都需要分配一个唯一的地址才通讯,这跟网卡的MAC地址的作用是一样的。
其实,就像分配门牌号,让大家看到那个门牌就知道什么房了。
从下面的数据分析来看,是分配地址为1.REQUEST_STANDARD=0x5USB_DeviceAddress=129USB_EVT_IN,USB_SetAddress(1)3.收到主控器的获取设备描述符配置包。
Setup m=0,n=0,val=3780 06 00 01 00 00 12 00再次收到获取设备描述符的配置包,由于第一次不知道设备描述符有多大,因而总是发送一个最大数据的包,就是64个字节大,现在知道描述符的大小为0x0012个大小了,就把它发送下来了。
所以USB设备再次回应设备描述符就可以了。
REQUEST_STANDARD=0x6USB_DEVICE_DESCRIPTOR_TYPE(1)USB_DataInStage,cnt=18,EP0Data.Count=1812 01 10 01 00 00 00 40 00 80 00 80 00 01 04 2C 4A 01 在这里再次回应设备描述符。
USB_EVT_IN,USB_DataInStageUSB_DataInStage,cnt=0,EP0Data.Count=04.收到配置描述符包Setup m=0,n=0,val=4580 06 00 02 00 00 09 00根据USB协议可以知道,这是一个配置描述符的包,也就是让USB设备发送本设备有多少个配置方式给主控器。
由于USB的设备是多种多样,满足不同的用户需要的。
比如鼠标和键盘,就是不同的设备了。
还有MP3播放器,还有各种数码相机等等,都是不一样的设备了。
就可以通过下面的方式来说明这个配置有多少种方式,主要是通讯的方式。
REQUEST_STANDARD=0x6USB_CONFIGURATION_DESCRIPTOR_TYPE(2)(Offset=0x0) USB_DataInStage,cnt=9,EP0Data.Count=909 02 22 00 01 01 00 01 32这里就是USB设备返回配置描述符给主控器的,它主要说明了这个设备有多少个配置,比如定义端点的类型,端点的传送方式,还有这个设备使用USB 总线的电源多少。
USB_EVT_IN,USB_DataInStageUSB_DataInStage,cnt=0,EP0Data.Count=05.收到字符串描述符包Setup m=0,n=0,val=4580 06 00 03 00 00 FF 00这里收到获取字符串描述符。
由于在设备描述符里已经说明字符串描述符在那里,主要是偏移地址,比如04就是厂家的描述符。
REQUEST_STANDARD=0x6USB_STRING_DESCRIPTOR_TYPE(3)(Offset=0x0)USB_DataInStage,cnt=4,EP0Data.Count=404 03 09 04这里返回偏移地址为0的字符串描述,其实那里是保存字符串描述符的语言描述标识,这里英语的标识,0X0409。
USB_EVT_IN,USB_DataInStageUSB_DataInStage,cnt=0,EP0Data.Count=06.收到字符串描述符包Setup m=0,n=0,val=4580 06 4A 03 09 04 FF 00这时收到获取字符串描述符,根据偏移地址,就知道它是想返回0x4A的字符串,也就是字符串描述符里的偏移地址。
REQUEST_STANDARD=0x6USB_STRING_DESCRIPTOR_TYPE(4)(Offset=0x4A)USB_DataInStage,cnt=36,EP0Data.Count=3624 03 43 00 41 00 49 00 32 00 30 00 30 00 37 00 30 00 33 00 32 00 35 00 20 00 31 00 2E 00 30 00 2E 00 30 00 USB设备返回0x4A的字符串给PC。
这里是我放置的字符串:CAI20070325 1.0.0它作为产品的序列号。
由于采用UNICODE编码,所有高位字节全是0。
由于USB协议是使用小端格式来发送数据,所以都低位在前,高位在后。
这样在PC那里就可以看到USB设备的产品序列号了。
又前进了一步。
USB_EVT_IN,USB_DataInStageUSB_DataInStage,cnt=0,EP0Data.Count=07.收到第二个配置描述符包Setup m=0,n=0,val=4580 06 00 02 00 00 FF 00这里收到是第二个配置描述符包,与第一个的区别是返回长度不同。
第一个配置包返回的长度是9个字节,而这里的长度是255。
REQUEST_STANDARD=0x6USB_CONFIGURATION_DESCRIPTOR_TYPE(5)(Offset=0x0) USB_DataInStage,cnt=34,EP0Data.Count=3409 02 22 00 01 01 00 01 32 09 04 00 00 01 03 00 00 6E 09 21 00 01 00 01 22 24 00 07 05 81 03 40 00 20在这里返回全部配置描述给PC,让PC知道USB设备所有的配置。
在这里包括设备配置,接口配置,端点配置,还有设备特别配置信息。
USB_EVT_IN,USB_DataInStageUSB_DataInStage,cnt=0,EP0Data.Count=08.收到字符串描述符包Setup m=0,n=0,val=4580 06 00 03 00 00 FF 00收到PC的字符串描述符,后面设备就返回。
REQUEST_STANDARD=0x6USB_STRING_DESCRIPTOR_TYPE(6)(Offset=0x0)USB_DataInStage,cnt=4,EP0Data.Count=404 03 09 04返回设备描述符的语言定义。
USB_EVT_IN,USB_DataInStageUSB_DataInStage,cnt=0,EP0Data.Count=09.收到字符串描述符包Setup m=0,n=0,val=4580 06 2C 03 09 04 FF 00收到PC需要产品字符串。
REQUEST_STANDARD=0x6USB_STRING_DESCRIPTOR_TYPE(7)(Offset=0x2C)USB_DataInStage,cnt=30,EP0Data.Count=301E 03 42 00 69 00 67 00 53 00 6C 00 6F 00 70 00 65 00 33 00 44 00 20 00 48 00 49 00 44 00这里USB设备返回产品字符串给PC了。