目录
链接快速定位
前沿
本小节主要围绕USB2.0的概述、设备的识别、描述符、传输类型、复位及唤醒机制讲解。
1 概述
1.1 特点及应用范围
USB2.0分为低速、全速和高速系列,不同速度的应用场景有所不同,具体见下图。
1.2 拓扑结构
USB总线基于分层的星状拓扑结构,拓扑结构有以下特点:
- 以Hub为中心,连接周围设备
- 总线上最多可连接127个设备
- Hub串联数量最多5个
- 线缆长度最长5米
下图是USB的拓扑结构实例。
1.3 电气特性
USB使用差分传输模式,标准的USB连接线使用4芯电缆:5V电源线(VBUS)、差分数据线负(DM)、差分数据线正(DP)和地线(GND)。在USB OTG中,使用5芯线缆,比标准的USB多了一条身份识别线(ID)。
1.4 线缆
USB线缆分为很多种,这里展示常见的5种线缆,分别是Mini-USB、USB-TypeA、USB-TypeB、USB-TypeC、Micro-USB接口。
2 设备的识别
2.1 插入检测和速度检测
下图展示了全速和低速设备的检测机制,主机端的DM、DP信号线下拉15K的电阻,当有设备接入的时候,DM和DP信号线会呈现不同的电平。
当DP上拉1.5K电阻接入主机的时候,DP为1,DM为0,此时设备被识别为全速设备;当DM上拉1.5K电阻接入主机的时候,DM为1,DP为0,此时设备被识别为低速设备。
高速设备首先被检测为全速设备,然后通过成为“chirp sequence”的总线握手机制检测高速的能力。
2.2 枚举过程
USB主机在检测到USB设备插入后,就要对设备进行枚举了。为什么要枚举呢?枚举就是从设备读取各种描述符信息,这样主机就可以根据这些信息来加载合适的驱动程序,从而知道设备是什么类型的设备,如何进行通讯等。调试USB设备,很重要的一点就是USB的枚举过程,只要枚举成功了,剩下的工作就不多了。
枚举的过程可以用下图来简单的概括。
以下是一个简单的枚举过程,帮助大家理解软件层面的协议。
Host [ 80 06 00 01 00 00 40 00 ] 主机:你是什么设备? |
Device [ 12 01 00 02 0A 00 00 40 70 34 08 00 00 02 01 02 03 01 ] 设备:我是CDC设备 |
Host [ 00 05 21 00 00 00 00 00 ] 主机设置唯一设备地址(地址只能从0-127),以后使用此地址和设备通讯 |
Host [ 80 06 00 01 00 00 12 00 ] 主机:你是什么设备? |
Device [ 12 01 00 02 02 02 02 40 70 34 08 00 00 02 01 02 03 01 ] 设备:我是CDC设备 |
Host [ 80 06 00 02 00 00 FF 00 ] 主机:你有几个接口?每个接口使用了哪几个端点? |
Device [ 09 02 43 00 02 01 00 C0 32 09 04 00 00 01 02 02 01 00 05 24 00 10 01 05 24 01 00 01 04 24 02 02 05 24 06 00 01 07 05 82 03 08 00 FF 09 04 01 00 02 0A 00 00 00 07 05 03 02 40 00 00 07 05 81 02 ] |
Device [ 40 00 00 ] 设备:我有2个接口,一个接口使用了输入端点2,一个接口使用了输入端点1和输出端点3 |
Host [ 80 06 00 03 00 00 FF 00 ] 主机:你的字符串使用的是什么编码格式? |
Device [ 04 03 09 04 ] 设备:我使用的美国的编码格式 |
Host [ 80 06 02 03 09 04 FF 00 ] 主机:你的产品名称是什么? |
Device [ 32 03 53 00 54 00 4D 00 33 00 32 00 20 00 56 00 69 00 72 00 74 00 75 00 61 00 6C 00 20 00 43 00 4F 00 4D 00 20 00 50 00 6F 00 72 00 74 00 20 00 20 00 ] 设备:我的产品名称是… |
Host [ 80 06 03 03 09 04 FF 00 ] 主机:你的设备UID是什么? |
Device [ 1A 03 35 00 43 00 44 00 45 00 35 00 38 00 34 00 30 00 33 00 32 00 33 00 30 00 ] 设备:我的 UID是.... |
以下是USB2.0协议的截图,USB2.0资料下载,主要讲解了枚举过程的SETUP指令的含义,这里举个请求设备描述符(80 06 00 01 00 00 40 00)的例子:
命令格式 | bmRequestType | bRequest | wValue | wIndex | wLength |
命令数据 | 80 | 06 | 0100 | 0000 | 0040 |
含义 | Data transfer direction: Device-to-host Type: Standard Recipient: Device | GET_DESCRIPTOR | Descriptor Descriptor | 0 | Descriptor |
3 各类描述符解析
这里主要讲解设备端回复的描述符,主机端请求的类型需要参考USB2.0手册根据具体请求回复具体的命令。
3.1 设备描述符
Offset | Field | Size | Value | 描述 | 备注 |
0 | bLength | 1 | 数字 | 该描述子包含的字节数目 | 一般都是18 |
1 | bDescripotorType | 1 | 常数 | 设备描述符的类型常数 | 1 |
2 | bcdUSB | 2 | BCD | 该设备符合遵循的USB协议版本号 | |
4 | bDeviceClass | 1 | Class | 由USB-IF分配的,能在 | |
5 | bDeviceSubClass | 1 | SubClass | ||
6 | bDeviceProtocol | 1 | Protocol | ||
7 | bMaxPacketSize0 | 1 | 数字 | EPO的最大包长 | HS必须是64 |
8 | idVendor | 2 | ID | USB-IF分配的 | 0x3470 |
10 | iProduct | 2 | ID | 厂家分配的 | 0x0008 |
12 | bcdDevice | 2 | BCD | 该设备自身的版本号 | |
14 | iManufacturer | 1 | Index | 各自在众多字符串描述符中的序号 | |
15 | iProduct | 1 | Index | ||
16 | iSerialNumber | 1 | index | ||
17 | bNumConfigurations | 1 | 数字 | 该设备在当前速度下支持多少种configuration |
Virtual_Com_Port_DeviceDescriptor[ ] =
{
0x12, /* 整个Descriptor的长度:18字节 */
0x01, /* Descriptor的类别:Device Descriptor(0x01) */
0x00, 0x02, /* 设备所遵循的USB协议的版本号:2.00 */
0x0A, /* 设备所实现的类:CDC Class*/
0x00, /* 设备所实现的子类:*/
0x00, /* 设备所遵循的协议类别:*/
0x40, /* 端点0的最大数据包长度:64字节*/
0x70, 0x34, /* IDVendor: 0x3470 */
0x08, 0x00, /* IDProduct: 0x0008 */
0x00, 0x02, /* bcdDevice: 2.00*/
1, /* 用于描述生产厂商的字符描述符的索引号 */
2, /* 用于描述产品的字符描述符的索引号*/
3, /* 用于描述产品系列号的字符描述符的索引号*/
0x01 /* 设备所支持的配置数目:1*/
}
bDeviceClass、bDeviceSubClass和bDeviceProtocol可在USB官网进行查询,idVendor是向USB机构申请的,需要支付一笔费用,如果针对开发者,可以选择芯片厂商的idVendor进行开发。
3.2 配置描述符
Offset | Field | Size | Value | 描述 | 备注 |
0 | bLength | 1 | 数字 | 该描述子包含的字节数目 | 一般都是9 |
1 | bDescripotorType | 1 | 常数 | 配置描述符的类型常数 | 2 |
2 | wTotalLength | 2 | 数字 | 包含了所有描述子的长度(配置、接口、端点、类相关、厂商相关) | 当主机要求配置描述符时,所有相关的接口、端点描述符都要返回 |
4 | bNumInterfaces | 1 | 数字 | 该配置包含几个接口 | |
5 | bConfigurationValue | 1 | 数字 | 选择该配置时,传递给SetConfiguration0的参数 | |
6 | iConfiguration | 1 | index | 在众多字符串描述符中的序号 | |
7 | bmAttributes | 1 | 位图 | D7:保留为1是否由总线供电 D6:是否支持远程唤醒 D5:D4~D0:保留为0 | |
8 | bMaxPower | 1 | mA | 该设备在该configuration下全速工作时需要从总线获取的电流(以2mA为单位) |
Virtual_Com_Port_ConfigDescriptor[ ] =
{
0x09, /* 描述符的长度:9字节 */
0x02, /* 描述符的类型: 0x02 配置描述符 */
VIRTUAL_COM_PORT_SIZ_CONFIG_DESC, 0x00, /* 完整的描述 符包括接口描述符、 端点描述符和类描述符的长度 */
0x02, /* 配置所支持的接口数目:2*/
0x01, /* 用SetConfiguration选择此配置时所指定的配置号*/
0x00, /* 用于描述此配置的字符描述符的索引号:0 */
0xC0, /* 供电配置:B7(1 保留), B6(自供电), B5(远程唤醒), B4- B0(0 保留) */
0x32, /* 最大功耗,以2mA为单位计算:0x32表示 100mA */
}
3.3 接口描述符
Offset | Field | Size | Value | 描述 | 备注 |
0 | bLength | 1 | 数字 | 该描述子包含的字节数目 | 一般都是9 |
1 | bDescripotorType | 1 | 常数 | 接口描述符的类型常数 | 4 |
2 | bInterfaceNumber | 1 | 数字 | 该接口的序号:在该配置所支持的众多接口中的序号 | 从0开始 |
3 | bAlternateSetting | 1 | 数字 | 用来选择该接口的某个setting | |
4 | bNumEndpoints | 1 | 数字 | 该接口支持多少个非0的EP | 如果此项为0则该接口使用默认的控制通道 |
5 | blnterfaceClass | 1 | Class | 由USB-IF分配 | |
6 | bInterfaceSubClass | 1 | SubClass | ||
7 | blnterfaceProtocol | 1 | Protocol | ||
8 | ilnterface | 1 | index | 在众多字符串描述符中的序号 |
Virtual_Com_Port_InterfaceDescriptor[ ] =
{
0x09, /* 描述符的长度:9字节 */
4, /* 描述符的类型:0x04接口描述符(Interface) */
0x00, /* 选择此接口的索引号,从0开始计算:0 */
0x00, /* 用于选择此设置的索引号:0 */
0x02, /* 实现此接口需要使用的端点数目:2 */
0x0A, /* 此接口所遵循的类:CDC Class */
0x00, /* 此接口所遵循的子类:*/
0x00, /* 此接口所支持的协议:*/
0, /* 用于描述此接口的字符描述符的索引号 */
}
3.4 端点描述符
Offset | Field | Size | Value | 描述 | 备注 |
0 | bLength | 1 | 数字 | 该描述子包含的字节数目 | 一般都是7 |
1 | bDescripotorType | 1 | 常数 | 端点描述符的类型常数 | 5 |
2 | bEndpointAddress | 1 | 端点 | Bit7: 方向 (0-OUT; 1-IN) Bit6~4:保留为0 Bit3~0:端点号 | |
3 | bmAttributes | 1 | 位图 | 传输类型 | |
4 | wMaxPacketSize | 2 | 数字 | 该端点的最大包长 | |
6 | bInterval | 1 | 数字 | 主机查询EP的间隔,以帧或微帧为单位 FS/HS的ISO EP:取值1~16,间隔是2(bInterval-1)6bInterval数字 FS/LS的INTR EP: 取值1~255 HS的INTR EP:取值在1~16,间隔是2(bInterval1) HS的BULK/CTRL OUT EP:设定了设备的最大NAK率(即每个微帧最多回几个NAK) ; 取值0~255 |
Virtual_Com_Port_InterfaceDescriptor[ ] =
{
0x07, /* 描述符长度:7字节 */
5, /* 描述符类型:端点描述符*/
0x81, /* 端点的特性:B3-B0(端点号), B6-B4(0), B7(1=IN, 0=OUT)
0x81:Endpoint1/ IN */
0x02, /* 端点的类型:B1-B0(00=控制 01=同步 10=大容量 11=中断) 0x02:大容量端点 */
0x40, 0x00 /* 此端点的最大有效数据长度:64 字节 */
0x00, /* 主机查询此端点数据的间隔时间:大容量端点,忽略此值*/
}
3.5 字符串描述符
字符串描述符包括以下:
- 字符串语言ID描述符
Offset | Field | Size | Value | 描述 | 备注 |
0 | bLength | 1 | 常数 | 该描述子包含的字节数目 | 一般为4 |
1 | bDescripotorType | 1 | 常数 | 字符串描述符的类型常数 | 3 |
2 | LangID | 2 | 数字 | 语言ID码 |
- 其它字符串描述符
Offset | Field | Size | Value | 描述 | 备注 |
0 | bLength | 1 | N+2 | 该描述子包含的字节数目 | |
1 | bDescripotorType | 1 | 常数 | 字符串描述符的类型常数 | 3 |
2 | WLANGID[O] | 2 | 数字 | 语言编号编码0 | |
… | … | … | … | … | … |
n | WLANGID[x] | 2 | 数字 | 语言编号编码n |
3.6 其它描述符
4 Packet
4.1 Packet的组成
Packet主要由下面四部分组成:
- SOP:起始帧,从DILE状态(J状态)切换到K状态
- SYNC:同步域,3个重复的KJ状态切换,后跟随2个位时间的K状态
- Packet Connent:内容域,主要包括以下内容:
- PID:包标识
- 地址:设备地址
- 帧号:11位帧号
- 数据:通信的数据
- CRC:校验
- EOP:结束帧,持续2个位时间的SE0信号,后跟随1个位时间的J状态
接下来重点讲解一下Packet Connent域里面的内容。
状态 | 速度 | 差分值 |
J状态 | LS | 差分0 |
FS | 差分1 | |
K状态 | LS | 差分1 |
FS | 差分0 |
4.2 Packet的内容
4.2.1 Packet包的内容--PID域
PID:Packet Identifier,包标识,LSB在前,前4个字节为PID码,后四个字节是前四个字节的取反。
PID0(LSB) | PID1 | PID2 | PID3 | PID0 | PID1 | PID2 | PID3 (MSB) |
以下是PID的类型码。
PID类型 | PID名 | PID[3:0] | 说明 |
令牌类 | OUT | 0001B | 通知设备将要输出数据 |
IN | 1001B | 通知设备将要输入数据 | |
SOF | 0101B | 通知设备这是一个帧起始包 | |
SETUP | 1101B | 通知设备将要开始一个控制传输 | |
数据类 | DATA0 | 0011B | 不同类型的数据包 |
DATA1 | 1011B | ||
DATA2 | 0111B | ||
MDATA | 1111B | ||
握手类 | ACK | 0010B | 确认 |
NAK | 1010B | 不确认 | |
STALL | 1110B | 挂起 | |
NYET | 0110B | 未准备好 | |
特殊类 | PRE | 1100B | 前导(这是一个令牌包) |
ERR | 1100B | 错误(这是一个握手包) | |
SPLIT | 1000B | 分裂事物(这是一个令牌包) | |
PING | 0100B | PING测试(这是一个令牌包) | |
…… | 0000B | 保留,未使用 |
4.2.2 Packet包的内容--地址域
地址由7位的设备地址和4位的端点地址组成。
addr0 (LSB) | addr1 | addr2 | addr3 | addr4 | addr5 | addr6 |
addr0 (LSB) | addr1 | addr2 | addr3 |
4.2.3 Packet包的内容--帧号域
帧号域由以下特性:
- 11位
- 主机每发出一个帧,帧号都会自动加1(全速和低速设备1ms发出一帧, 高速设备0.125ms发出一帧)
- 当帧号达到0x7FFF的时候,将清零帧号重新计数
- 仅在每个帧的帧首才传输一次SOF包
4.2.4 Packet包的内容--数据域
根据传输类型的不同,数据域的数据长度从0-1024字节不等。
传输类型 | 控制传输 | 批量传输 | 中断传输 | 同步传输 | ||||||||
设备速度 | HS | FS | LS | HS | FS | LS | HS | FS | LS | HS | FS | LS |
数据包长度 | 64 | 64 | 8 | 512 | 64 | N.A | 1024 | 64 | 8 | 1024 | 1023 | N.A |
4.2.5 Packet包的内容--CRC域
4.3 Packet的类型
4.3.1 Packet包的类型--令牌包
令牌包的组成为:PID+地址+CRC
- PID:IN、OUT、SETUP令牌
- 地址:7位的设备地址和4位的端点号组成
- CRC:这里是对地址域计算
4.3.2 Packet包的类型--SOF包
SOF包的组成为:PID+帧号+CRC
- PID:SOF令牌
- 帧号:LS/FS每1ms一个帧,HS每0.125ms一个帧
- CRC:这里是对帧号域计算
4.3.3 Packet包的类型--数据包
数据包的组成为:PID+数据+CRC
- PID:DATA0、DATA1、DATA2、MDATA令牌
- 数据:传输类型不同,数据包的最大长度有所不同
- CRC:这里是对数据域计算
4.3.4 Packet包的类型--握手包
握手包的组成为:PID
- PID:ACK、NAK、STALL、NYET令牌
- ACK:表示正确接收数据,并且有足够的空间来容纳数据。主机和设备都可以用ACK来确认,而NAK、STALLA、NYET只能设备返回,主机不能使用这些握手包。
- NAK:表示没有数据需要返回,或者数据正确接收但是没有足够的空间来容忍它们。 当主机收到NAK时,知道设备还未准备好,主机会在以后的合适的时机进行重新传输。
- STALL:表示设备无法执行这个请求,或者端点已经被挂起,它表示一种错误的状态。 设备返回STALL后,需要主机进行干预才能解除这种STALL状态。
- NYET:只在USB2.0的高速设备输出事物中使用,表示设备本次数据成功接收,但是没有 足够的空间来接收下一次数据。主机在下一次输出数据时,将先使用PING令牌包来试探 设备是否有空间接收数据,以避免不必要的带宽浪费。
注意:
1. 当收到SETUP包的时候,设备只能回复ACK;
2. 当同步传输的时候,没有握手包。
5 传输类型
USB的传输类型分为控制传输、中断传输、批量传输和同步传输,每种传输类型用在特定的场合。
5.1 控制传输
非周期性传输,用于命令和状态的传输。每个USB设备都必须有控制端点,支持控制传输来进行命令和状态的传输。USB主机驱动将通过控制传输与USB设备的控制端点通讯,完成USB设备的枚举和配置。
控制传输是双向的传输,必须有IN和OUT两个方向上的特定端点号的控制端点来完成两个方向上的控住传输。
5.2 中断传输
周期性,低频率传输,允许有限延迟的通信,中断传输用于那些频率不高,但对周期有一定要求的数据传输。具有保证的带宽,并能在下个周期对先前错误的传输进行重传;对于全速端点,中断传输的时间间隔在1ms到255ms之间,对于低速端点,时间间隔限制在10ms到255ms之间,对于高速端点, 时间间隔为2bInterval-1*125us,bInterval的值在1到16之间。
中断传输总算单向的,可以用单向的中断端点来实现某个方向上的中断传输。
5.3 批量传输
非周期性,大容量数据的通信,数据可以占用任意带宽。大容量数据传输适用于那些需要大数据量传输,但是对实时性,对延迟性和带宽没有严格要求的应用。大容量传输可以占用任意可用的数据带宽。
大容量传输是单向的,可以用单向的大容量传输端点来实现某个方向的大容量传输。
5.4 同步传输
周期性,持续的传输,用于传输与时效相关的信息,并且在数据中保存时间戳的信息。同步传输用于传输那些需要保证带宽,并且不能忍受延迟的信息。整个带宽都将用于保证同步传输的数据完整,并且不支持出错重传。
同步传输总是单向的,可以使用单向的同步端点来实现某个方向上的同步传输。
6 复位挂起和唤醒机制
USB使用的差分传输模式,两个数据线D+和D-(VOH:2.8V VOL:0.3V)
- 差分信号1:D+ > VOH and D- < VOL
- 差分信号0:D- > VOH and D+ < VOL
- IDLE状态:J状态
- 复位信号:D+ and D- < VOL for >= 10ms
- 挂起信号:USB主机3m内不发送任何信号(3ms以上的IDLE状态)
- 唤醒信号:K状态持续20ms以上,并以低速EOP信号结尾。
状态 | 速度 | 差分值 |
J状态 | LS | 差分0 |
FS | 差分1 | |
K状态 | LS | 差分1 |
FS | 差分0 |
接下来讲解USB的各类应用及代码,敬请期待。。。