原文地址:www.beyondlogic.org/usbnutshell…
原文作者:
发布时间:
USB协议
与RS-232和类似的串行接口不同,在这些接口中,发送数据的格式是没有定义的,USB是由几层协议组成的。虽然这听起来很复杂,但现在不要放弃。一旦你明白了是怎么回事,你真的只需要担心更高层次的层。事实上,大多数USB控制器的I.C.s将照顾到低层,从而使它几乎看不见的终端设计师。
每个USB事务由一个
- 令牌包(头定义了它所期望遵循的内容),一个
- 可选的数据包,(包含有效载荷)和一个可选数据包。
- 状态包(用于确认交易和提供纠错手段
正如我们已经讨论过的,USB是一个以主机为中心的总线。所有的交易都是由主机发起的。第一个数据包,也叫令牌,由主机产生,描述接下来的内容,数据交易是读还是写,设备的地址和指定的端点是什么。下一个数据包一般是携带有效载荷的数据包,后面是一个握手包,报告是否成功接收到数据或令牌,或者端点是否停滞或无法接受数据。
常见的USB数据包字段
USBus上的数据是先传输LSBit。USB数据包由以下字段组成。
-
同步 所有数据包都必须以同步字段开始。同步字段在低速和全速时为8位,高速时为32位,用于同步接收机和发射机的时钟。最后两个位表示PID字段的起始位置。
-
PID PID代表数据包ID。该字段用于标识正在发送的数据包的类型。下表显示了可能的值。
| 组 | PID 值 | 包标识符 |
|---|---|---|
| Token | 0001 | OUT Token |
| \ | 1001 | IN Token |
| \ | 0101 | SOF令牌 |
| \ | 1101 | SETUP Token |
| 数据 | 0011 | DATA0 |
| \ | 1011 | DATA1 |
| \ | 0111 | DATA2 |
| \ | 1111 | MDATA |
| 握手 | 0010 | ACK 握手 |
| \ | 1010 | NAK握手 |
| \ | 1110 | STALL握手 |
| \ | 0110 | NYET(尚未答复) |
| 特别 | 1100 | 序言 |
| \ | 1100 | ERR |
| \ | 1000 | 分体式 |
| \ | 0100 | Ping |
PID有4位,但为了确保正确接收,这4位被补充和重复,使得总共有8位PID。结果格式如下所示。
PID0 PID1 PID2 PID3 nPID0 nPID1 nPID2 nPID3
-
ADDR 地址字段指定了数据包指定给哪个设备,长度为7位,允许支持127个设备。长度为7位,允许支持127个设备。地址0是无效的,因为任何尚未分配地址的设备必须响应发送到地址0的数据包。
-
ENDP 端点字段由4位组成,允许16个可能的端点。然而,低速设备只能在默认管道的基础上增加2个端点。(最多4个端点)
-
CRC 循环冗余检查是在数据包有效载荷内的数据上执行的,所有令牌数据包有5位CRC,而数据包有16位CRC。所有令牌数据包都有5位CRC,而数据包有16位CRC。
-
EOP 包的结束。由一个单端零(SE0)发出信号,约2位,然后是一个J,时间为1位。
USB数据包类型
USB有四种不同的数据包类型。令牌数据包表示要遵循的事务类型,数据数据包包含有效载荷,握手数据包用于确认数据或报告错误,帧的开始数据包表示新帧的开始。
令牌包
令牌包有三种类型。
- In - 通知USB设备,主机希望读取信息。
- Out - 通知USB设备,主机希望发送信息。
- 设置 - 用于开始控制传输。
令牌包必须符合以下格式。
Sync PID ADDR ENDP CRC5 EOP
数据包
有两种类型的数据包,每种数据包最多可以传输1024字节的数据。
- 数据0
- 数据1
高速模式又定义了两个数据PID,DATA2和MDATA。
数据包的格式如下:
Sync PID Data CRC16 EOP
- 低速设备的最大数据有效载荷大小为8字节。
- 全速设备的最大数据有效载荷大小为1023字节。
- 高速设备的最大数据有效载荷大小为1024字节。
- 数据必须以字节的倍数发送。
握手数据包
有三种类型的握手数据包,它们仅仅由PID组成。
- ACK--确认数据包已成功接收。
- NAK - 报告设备暂时不能发送或接收数据。也用于在中断事务中通知主机没有数据可发送。
- STALL - 设备发现自己处于需要主机干预的状态。
握手包的格式如下。
Sync PID EOP
帧数据包的开始
由11位帧号组成的SOF数据包由主机在全速总线上每1ms±500ns或在高速总线上每125μs±0.0625μs发送一次。
Sync PID Frame Number CRC5 EOP
USB功能
当我们想到USB设备时,我们会想到USB外围设备,但USB设备可以指在主机或外围设备上使用的USB收发器设备,USB集线器或主机控制器IC设备,或USB外围设备。因此,标准中提到了USB功能,可以看作是提供一种能力或功能的USB设备,如打印机、Zip Drive、扫描仪、调制解调器或其他外围设备。
所以,现在我们应该知道构成USB数据包的东西有哪些了。不知道吗?你已经忘记了PID字段是由多少位组成的?好吧,不要太惊慌。幸运的是,大多数USB函数都在硅中处理低级USB协议,直到交易层(我们将在下一章介绍)。我们之所以要涵盖这些信息,是因为大多数USB函数控制器会报告PID Encoding Error等错误。如果不简单介绍,有人会问什么是PID Encoding Error?如果你提出PID的最后四位与前四位的倒数不一致,那么你就对了。
大多数函数会有一系列的缓冲区,通常是8个字节长。每个缓冲区将属于一个端点--EP0 IN,EP0 OUT等。比如说,主机发送一个设备描述符请求。功能硬件将读取设置数据包,并从地址字段判断该数据包是否是给自己的,如果是,将把下面数据包的有效载荷复制到由设置令牌的端点字段中的值所决定的相应端点缓冲区。然后,它将发送一个握手包,以确认接收到字节,并在半导体/微控制器内为适当的端点产生一个内部中断,表示它已收到一个数据包。这通常都是在硬件中完成的。
软件现在得到一个中断,应该读取端点缓冲区的内容并解析设备描述符请求。
端点
端点可以描述为数据的源或汇。由于总线以主机为中心,端点发生在USB功能的通信通道末端。在软件层,例如你的设备驱动程序可能会向你的设备EP1发送一个数据包。当数据从主机流出时,它将最终进入EP1 OUT缓冲区。然后,您的固件将在其闲暇时读取这些数据。如果它想返回数据,该函数不能简单地写入总线,因为总线是由主机控制的。因此,它将数据写入EP1 IN,而EP1 IN则在缓冲区中停留,直到主机向该端点发送一个IN包请求数据。端点也可以看作是功能设备的硬件和功能设备上运行的固件之间的接口。
所有设备都必须支持零端点。这是在枚举期间和设备在总线上运行时的整个持续时间内接收所有设备控制和状态请求的端点。
管道
当设备在一系列端点上发送和接收数据时,客户端软件通过管道传输数据。管道是主机和端点之间的逻辑连接。管道还将有一组与之相关的参数,如分配给它的带宽、它使用的传输类型(控制、批量、异或中断)、数据流的方向和最大数据包/缓冲区大小。例如,默认管道是由端点零进和端点零出组成的双向管道,其传输类型为控制传输。
USB定义了两种类型的管道
-
流管道没有定义的USB格式,也就是说,您可以将任何类型的数据发送到流管道,并可以从另一端检索数据。数据是按顺序流动的,并且有一个预先定义的方向,要么进,要么出。流管道将支持批量、等时和中断三种传输类型。流管道可以由主机或设备控制。
-
消息管道有一个定义的USB格式。它们由主机控制,由主机发送的请求启动。然后,数据将按照请求所规定的方向进行传输。因此,消息管道允许数据双向流动,但只支持控制传输。