1.USB 概述

USB 设备现在是用的非常普遍的一种接口了,它即插即用的特性给人们带来了很大的方便。在嵌入式的应用中, USB 经常被用来作为与上位机通信的接口,还用来通过 U 盘存储数据等。USB 按通讯速度可分为低速,全速和高速设备。在我们的应用中,低速和全速是最为普遍的,在此我们对 USB 从物理层到协议层做一个简要的介绍。高速 USB 的原理是一样的,在理解了低速和全速设备的工作原理后再去理解高速设备就比较简单了,在此我们暂不讨论。

 

低速(Low Speed, 1.5Mbps):键盘,鼠标,手写笔

全速(Full Speed, 12Mbps):音频

高速(High Speed, 480Mbps):视频

USB 协议是开放的,可以从官方网站 usb.org 下载。

 

2.主机,设备(Host, Device)

 

 

上图是一个典型的 USB 全速主机和设备的连接示意图。主机要有对外的供电能力,图中可以看到作为主机的单片机,一个引脚用来控制三极管或 MOSFET,提供 5V 的电源至 USB 口。设备供电有两种方法:一种是通过 USB 总线,从主机提供的 5V 获得,如我们常用的 U 盘;一种是自己从另外的电源获得,此时主机至设备的电源线可以不连。如果设备的 1.5k 上拉电阻是加在 D-上,那么此设备将被主机识别为低速设备。高速设备的上拉与全速设备一样是加到 D+,需要靠软件协议进一步区分。

 

通过 USB 总线获得供电的设备,分为两种配置:

低功率设备(Low-power devices): 最大电流不超过 100mA

高功率设备(High-power devices): 刚连接后设备后的枚举阶段不超过 100mA,配置完成后最大不超过 500mA。

 

USB 所有的通讯都是由主机发起。当主机检测到有设备连接时,首先会询问设备,让设备自报家门,看看设备都具备哪些能力,其中就包括最大电流,然后主机根据上报的描述进行相应的操作。这个过程叫自举(Enumeration)。设备通过描述符(Descriptor)来声明自己的能力,包括:

设备描述符(Device Descriptor)

配置描述符(Configuration Descriptor)

接口描述符(Interface Descriptor)

端点描述符(Endpoint Descriptor)

字符串描述符(String Descriptor)

 

端点(Endpiont)是 USB 通信的基本单元,每个 USB 设备都会包含若干个端点。主机下发的数据最终会根据设备地址和端点地址到达某一个端点,主机获取数据也是给某个端点发出读数据命令,此端点随后把存储在自己缓冲区的数据发给主机。

 

在端点之上是逻辑组织,多个端点可以归到一个接口,多个接口可以归为一个配置。而一个设备可以有多个配置。

 

3.USB 物理层

 

(USB Specification 2.0)

 

 1 红色 Vbus(5V)

 2 白色  D-

 3 绿色  D+

 4 黑色  GND

 

有的 USB 接口会多出一根 ID 线,以支持 OTG(On The Go)。支持 OTG 的线两端是不一样的,其中一端插到 OTG 设备时会把设备接口的识别引脚 ID 拉低,此设备识别到自己的 ID 拉低后会进入主机状态(Host),连线另一端的设备 ID 没有拉低,默认进入设备状态(Device)。之后通过软协议可以主从切换。但是集中这种应用不是太多,一台设备要么作主机,要么作设备的情况比较多。

 

USB 使用的是差分传输模式,有两根数据线 D+和 D-。
Differential 1:D+ > VOH(min) (2.8V) 且 D- < VOL(max)(0.3V)
Differential 0:D- > VOH and D+ < VOL

J 状态:对于低速 USB 是 Differential 0,对于全速 USB 是 Differential 1
K 状态:对于低速 USB 是 Differential 1,对于全速 USB 是 Differential 0

除此之外,通过把 D+,D-当作单端信号拉低,拉高,可以表示一些特殊的状态。

SE0 状态(Single Ended 0):D+ 低,D- 低
SE1 状态(Single Ended 1):D+ 高,D- 高

Reset 信号:D+ and D- < VOL for >= 10ms
主机在要和设备通信之前会发送 Reset 信号来把设备设置到默认的未配置状态。即主机拉低两根信号线(SE0 状态)并保持 10ms。

 

看到这里也许有点晕,不过没关系,你如果看 USB 协议会更晕。

 

我们千万不要掉进这个坑里出不来,就像我们用串口也从来不会去触发一个起始信号,或者拉出一个结束信号一样,这些物理层信号状态的处理完全由芯片集成的 USB 控制器来处理。而且提供 USB 软件协议栈也是必须的,靠用户自己完全把所有细节搞清楚是不现实的。然而就像开车一样,你如果对汽车的原理有更深入的了解,一定更能充分的发挥出这辆车的性能。

 

继续,除了以上状态,还有:

Idle State, Resume State, Start of Packet, End of Packet, Disconnect, Connnect.

 

4.Packet

Packet 是 USB 通讯最基本的单位。

 

 

SOP:Start Of Packet,标志由空闲状态转入数据包发送。

SYNC:同步段,供 USB 设备进行时钟同步。

PID:Packet Identifier。种类比较多,下面再详细说明。

Address:设备和端点地址。一个主机可以挂接多个设备,主机会给每个设备分配不同地址。

Frame Number:帧号,每发一帧加 1,达到 7FFFH 时变为 0。

Data:数据段。

CRC:校验和。

EOP:End Of Packet。

通过不同的 PID,数据包被分成 4 个大类,每个大类又包含一些小类:

令牌 (Token) OUT,IN,SETUP,SOF

数据 (Data) DATA0,DATA1

握手 (Handshake) ACK,NAK,STALL,NYET

特殊包 (Special) PRE,ERR

 

5.Transaction

一次 Transaction 总是从主机向设备发出一个令牌(Token)开始。再次强调,USB 所有的通信过程都是由主机发起。三种令牌把 Transaction 分为三类:

 

OUT:主机发送数据给设备。

IN:主机从设备获取数据。

SETUP:主机对设备进行设置。

 

USB 协议里的 OUT 和 IN,都要站在主机的角度来看。下面是比较典型的获取,发送数据的例子:

 

 

每一次 Transaction,Token 总是必需的,数据段和握手则视情况而定。比如在上一个例子中,当主机发出 IN 令牌获取数据时,如果设备没准备好数据,则可以返回 NAK 结束此 Transaction。

 

6.Transfer

好了,有了以上这些,似乎万事俱备了。但是如果进一步想一下,那么还是有些问题不好解决。什么呢?比方说 DATA 数据段的长度规定多长好呢?主机多长时间发起一次通信比较好呢?

 

一个 USB 主机上是允许挂载多个设备的,而这些设备千差万别:比如像鼠标,按键后需要快速响应,把位置信息发送到主机,它的数据量很少,而像 U 盘则需要传输大量的数据。如果按鼠标的时候 U 盘正在传输数据怎么办呢?

 

为了解决上述问题,USB 首先规定了四种传输类型:

控制传输(Control Transfers): 主要用来在设备刚连接到主机时对设备进行设置。还有平时对设备状态的管理。它需要双向的数据传输。

批量传输(Bulk Data Transfers): 主要用来进行量大,但对传输时间要求不严格的场景。例如 U 盘。

中断传输(Interrupt Data Transfers): 需要及时准确的传输信息的场景。中断传输总是单向的。比如鼠标。

同步传输(Isochronous Data Transfers): 一般需要占用相对固定的带宽,延时短而且比较确定。传输是单向的,数据出错后不需要重传。比如 USB 摄像头。

 

然后,为了解决设备的及时响应问题,USB 每隔 1ms (高速 USB 是每隔 125us)发出一个 SOF 令牌,紧接令牌进行同步类型的传输,之后依次是中断类型,控制类型和批量数据传输类型。在每一个 Frame 内,Isochronous,Interrupt 和 Control 都会保证一定的带宽。而 Bulk 型的传输优先级最低,不一定每帧都得到带宽进行数据传输。

 

 

一个 Transfer 由一个或多个 Transactions 组成。比如一次控制传输可以由 Setup,IN,OUT 等 Transactions 组成。Packet 和 Transaction 是不允许被中间打断的,而 Transfer 的多个 Transactions 可以分多次传输。

 

7.小结

我们对 USB 的物理层和协议层做了简要的介绍。在接下来的文章里我们将通过实际的例子来看一下 USB 是如何工作的,并对很多工程师经常忽略或者没有意识到的一些问题进行探讨。