前言:
USB 本身是一个很庞大、复杂的体系,本课程的重点在于工业互联,USB 是其中的一个小小知识点。本章课程的目的 在于:能理解 USB 的一些概念,能使用 USB 传输数据,本节主要介绍 USB 概念,最后移植 USBX 实现 USB 串口功能。
在学习之前,先记住几个术语,这在后面的代码会经常看到
① HCD(Host Controller Driver)主机控制器驱动程序
② DCD(Device Controller Driver)设备控制器驱动程序
③ PCD(Low layer USB Peripheral Control Driver)底层USB外设控制驱动程序
④ CDC(Communication Device Class)通信设备类
USB 系统硬件框架和软件框架:
1.实验现象
现象:把 USB 设备比如 Android 手机接到 PC
① 右下角弹出"发现 android phone"
② 跳出一个对话框,提示你安装驱动程序
问 1:USB 设备插到电脑上去,接触到的对方设备是什么?
答 1:是 USB 控制器,是 USB 控制器内嵌的 root hub
问 2. 既然还没有"驱动程序",为何能知道是"android phone"?
答 2. windows 里已经有了 USB 的总线驱动程序,接入 USB 设备后,是"总线驱动程序"知道你是"android phone"、提示你安装的是"设备驱动程序"。USB 总线驱动程序负责:识别 USB 设备, 给 USB 设备找到对应的驱动程序。
问 3. 为什么一接入 USB 设备,PC 机就能发现它?
答 3. PC 的 USB 口内部,D- 和 D+ 接有 15K 的下拉电阻,未接 USB 设备时为低电平 。USB设备的 USB 口内部,D- 或 D+ 接有 1.5K 的上拉电阻;它一接入 PC,就会把 PC USB 口的 D- 或D+ 拉高 ,从硬件的角度通知 PC 有新设备接入。(不过这只限于低速和全速 类型的USB端口和USB设备,后面会介绍识别高速类型的方法)
问 4. USB 设备种类非常多,为什么一接入电脑,就能识别出来它的种类?
答 4. PC 和 USB 设备都得遵守一些规范。比如:USB 设备接入电脑后,PC 机会发出"你是什么"?USB 设备就必须回答"我是 xxx", 并且回答的格式是固定的。USB 总线驱动程序会发出某些命令想获取设备信息(描述符),USB 设备必须返回"描述符"给 PC。
问 5. PC 机上接有非常多的 USB 设备,怎么分辨它们?
答 5. 每一个 USB 设备接入 PC 时,USB 总线驱动程序都会给它分配一个编号。PC 机想访问某个 USB 设备时,发出的命令都含有对应的编号(地址)。
问 6. USB 设备刚接入 PC 时,还没有编号;那么 PC 怎么把"分配的编号"告诉它?
答 6. 新接入的 USB 设备的默认编号是 0,在未分配新编号前,PC 使用 0 编号和它通信。(也就是说,如果同时有多个 USB 设备接入PC,那么PC只能先给一个设备编号,因为默认只能使用编号0)
2.硬件框架
在 USB 系统中,有 2 个硬件概念 :
① USB Host(USB控制器 ):它跟处理器相连,处理器通过 USB Host 跟各类 USB 设备通信。USB Host 中集成有一个 root hub
② USB Device:这分为两类设备
a. Hub:用来扩展 USB 接口
b. Function:就是普通的 USB 设备,比如 U 盘、声卡等

从这个图可以知道,CPU通过USB控制器连接Hub(USB扩展口 )或Func(USB设备),而且最多只能有6级Hub,第7级必定为USB设备
3.软件框架

APP可以通过USB设备驱动程序访问USB设备,也可以绕过USB设备驱动,直接通过USB控制器驱动访问USB设备。
软件工程师眼里的 USB 电气信号
1.USB 设备状态切换图
USB 2.0 协议支持 3 种速率:低速(Low Speed,1.5Mbps)、全速(Full Speed, 12Mbps)、高速(High Speed, 480Mbps)。
USB Hub、USB 设备,也分为低速、全速、高速 三种类型。一个 USB 设备,可能兼容低速、全速,可能兼容全速、高速,但是不会同时兼容低速、高速。

2.硬件线路
下图是兼容高速模式的 USB 收发器电路图:

USB 连接涉及 Hub Port 和 USB 设备,硬件连接如下:

可以看到在Hub端口没有上拉电阻,在USB设备没有下拉电阻,怎么理解这个图呢?往下看:


Hub 端口引出四根线,其中 D- 和 D+ 是一对差分信号线 。当 Hub 端口未连接 USB 设备时,D- 和 D+ 通过 15kΩ 下拉电阻接地,保持低电平;而 USB 设备端的 D- 或 D+ 则通过 1.5kΩ 上拉电阻接高电平。一旦 USB 设备接入 Hub 端口,设备端的上拉电阻就会将 Hub 端对应的 D- 或 D+ 从低电平拉高为高电平。正是通过这两根线的电平组合,系统可以区分出 4 种状态(00、01、10、11) ,从而识别设备的接入与类型。
3.电子信号
USB 连接线有 4 条:5V、D+、D-、GND。数据线 D+、D-,只能表示 4 种状态。USB 协议中,很巧妙地使用这两条线路**实现了空闲(Idle)、始(SOP)、传输数据(Data)、结束(EOP)**等功能。
4.低速/全速信号电平

注意:看上图虚线部分,对于不同速率的设备,J状态和K状态的差分信号不同。J/K状态只是差分信号的别名而已。
5.高速信号电平


6.设备连接与断开
(1)连接
Hub端口的D+、D-都有15K的下拉电阻,平时为低电平。全速设备内部的D+有1.5K的上拉电阻,低速设备内部的D-有1.5K的上拉电阻 ,连接到Hub后会导致Hub的D+或D-电平变化,Hub根据变化的引脚分辨接进来的是全速设备还是低速设备 。高速设备一开始也是作为全速设备被识别的 。全速设备、高速设备连接时,D+引脚的电平由低变高:


可以看到全速设备、高速设备连接时,D+引脚的电平由低变高:


低速设备连接时,D-引脚的电平由低变高:
(2)断开
对于低速、全速设备,接到Hub时导致D-或D+引脚变为高电平,那断开设备后,D-或D+引脚自然会变为低电平:

对于高速设备 ,它先作为全速设备被识别出来,然后再被识别为高速设备。工作于高速模式时,D+的上拉电阻是断开的 ,所以对于工作于高速模式的USB设备,无法通过D+的引脚电平变化监测到它已经断开。
但工作于高速模式的设备,D+、D-两边有45欧姆的下拉电阻 ,用来消除反射信号 :

原理:当 Hub 与高速设备连接时,Hub 向高速设备发出信号,由于高速设备端接有 45Ω 下拉电阻,该电阻会吸收(消除)反射信号,因此反射回来的信号幅度基本不变 ;而当高速设备断开后,Hub 再发出信号时,反射信号无法被衰减,发出的信号与反射回来的信号发生叠加,导致信号幅度显著增大 。Hub 正是通过监测到这种异常增大的信号幅度,来判断高速设备已经断开 。内部电路图如下:

7.复位
从状态切换图上看,一个 USB 设备连接后,它将会被供电,然后被复位。当软件出错时,我们也可以发出复位信号重新驱动设备。
那么,USB Hub 端口或 USB 控制器端口如何发出复位信号?发出 SE0 信号,并维持至少10ms。
USB 设备看到 Reset 信号后,需要准备接收"SetAddress()"请求;如果它不能回应这个请求,就是"不能识别的设备"。
8.设备速率识别
(1)低速/全速
Hub 端口的 D+、D-都有 15K 的下拉电阻,平时为低电平。**全速设备内部的 D+有 1.5K 的上拉电阻,低速设备内部的 D-有 1.5K 的上拉电阻,连接到 Hub 后会导致 Hub 的 D+或 D-电平变化,Hub 根据变化的引脚分辨接进来的是全速设备还是低速设备**。

(2)高速
高速设备必定兼容全速模式,所以高速设备内部 D+也有 1.5K 的上拉电阻,只不过这个电阻是可以断开的:工作于高速模式时要断开它。
高速设备首先作为全速设备被识别出来,然后 Hub 如何确定它是否支持高速模式?
Hub 端口如何监测一个新插入的 USB 设备能否工作于高速模式?流程如下:
① 对于低速设备,Hub 端口不会监测它能否工作于高速模式。低速设备不能兼容高速模式。(D-)
② Hub 端口发出 SE0 信号,这就是复位信号 (SE0就是D-和D+都是低电平 )
③ USB 设备监测到 SE0 信号后,会发出"a high-speed detection handshake"信号表示自己能支持高速模式,这可以细分为一下 3 种情景:
a. 如果 USB 设备原来处于"suspend"状态,它检测到 SE0 信号后,就发出"a high-speed detection handshake"信号。
b. 如果 USB 设备原来处于"non-suspend"状态,并且处于全速模式,它检测到 SE0 信号后,就发出"a high-speed detection handshake"信号。这个情景,就是一个设备刚插到 Hub 端口时的情况,它一开始工作于全速模式。
c. 如果 USB 设备原来处于"non-suspend"状态,并且处于高速模式,它会切换回到全速模式(重新连接 D+的上拉电阻),然后发出"a high-speed detection handshake"信号。
"a high-speed detection handshake"信号,就是"高速设备监测握手信号",既然是握手信号,自然是有来有回:
① USB 设备维持 D+的上拉电阻,发出"Chirp K "信号,表示自己能支持高速模式
② 如果 Hub 没监测到"Chirp K "信号,它就知道这个设备不支持高速模式
③ 如果 Hub 监测到"Chirp K "信号后,如果 Hub 能支持高速模式,就发出一系列的 "Chirp K " 、 "Chirp J"信号,这是用来通知 USB 设备:Hub 也能支持高速模式。发出一系列的"Chirp K "、 "Chirp J"信号后,Hub 继续维持 SE0 信号直到 10ms。
④ USB 设备发出"Chirp K "信号后,就等待 Hub 回应一系列的"Chirp K"、"Chirp J"信号
a.收到一系列的"Chirp K"、"Chirp J"信号:USB 设备端口 D+就会断开的1.5kv上拉电阻 ,使能高速模式
b. 没有收到一系列的"Chirp K"、"Chirp J"信号:USB 设备转入全速模式

第一个红虚框是Hub发出SE0复位信号
9.数据信号

(1).低速/全速的SOP和EOP
SOP:Start Of Packet,Hub驱动D+、D-这两条线路从Idle状态变为K状态。SOP中的K状态就是SYNC信号(同步信号)的第1位数据,SYNC格式为3对KJ外加2个K。
怎么理解呢?从前面的低速/全速信号电平图来看

以全速设备为例:全速设备平时处于 Idle/J 状态(D+ 为高电平、D- 为低电平)。当它开始发一个数据包时,D+ 由高电平变为低电平、D- 由低电平变为高电平,即进入 K 状态。SOP 正是 D+、D- 高低电平发生转变的瞬间。(注意:这个Idle/J 状态,对于全速设备和低速设备是不一样的)
从前面的图我们可以知道发送一个数据包,你要先发送SOP,然后发送SYNC(同步信号),那什么是同步信号呢?
在了解同步信号前,我们回顾一下之前学习的UART,它是如何靠一根数据线实现数据传输的?答:双方约定好同一个波特率

通过双方约定好的发送速率,A 会向 B 发送一个持续 1T 时间段的电平信号作为起始信号;B 在收到起始信号后,从起始信号开始计时,等到 1.5T 时刻就可以读取这个信号。
那对于 I2C 和 SPI 呢?它们都有两根线:一根是时钟线(SCK/SCL),一根是数据线(SDA/MOSI、MISO)。时钟线由主机产生固定频率的时钟信号,数据在时钟的边沿(上升沿或下降沿)被采样 。以 I2C 为例,发送方 A 在时钟低电平期间改变数据线上的电平,接收方 B 则在时钟高电平期间读取数据线上的电平,从而保证数据在采样时刻是稳定的。(I2C 这种就是同步通信:发送方和接收方共用一根时钟线(SCL),由主机统一产生时钟信号,双方在时钟的边沿上对齐采样时刻,因此不需要像 UART 那样靠约定波特率来同步.)
对于USB系统,它只有一根数据线,那能不能只靠一根数据线也能实现同步信号呢?可以的,怎么实现的?

以AB为例,A在向B发送数据前,会先B发送同步信号(即A的固定频率),B接收到这段同步信号,就知道A的一个周期时间T是多少
EOP:End Of Packet,由数据的发送方发出EOP,数据发送方驱动D+、D-这两条线路,先设为SE0状态并维持2位时间,再设置为J状态并维持1位时间,最后D+、D-变为高阻状态,这时由线路的上下拉电阻使得总线进入Idle状态。
(2) 高速的SOP
高速的EOP比较复杂,作为软件开发人员无需掌握。
高速模式中,Ide状态为:D+、D-接地。SOP格式为:从Idle状态切换为K状态。SOP中的K状态就是
SYNC信号的第1位数据。
高速模式中的SYNC格式为:KJKJKJKJ KJKJKJKJ KJKJKJKJ KJKJKJKK,即15对KJ,外加2个K。
(3). NRZI与位填充
NRZI:Non Return Zero Inverted Code,反向不归零编码。NRZI的编码方位为:对于数据0,波形翻转;对于数据1,波形不变。


使用NRZI,发送端可以很巧妙地把"时钟频率"告诉接收端:只要传输连续的数据0即可。在下图中,低速/全速协议中"Sync Pattern"的原始数据是"00000001",接收端从前面的7个0波形就可以算出"时钟频率" 。

使用NRZI时,如果传输的数据总是"1",会导致波形维持不变。如果电平长时间维持不变,比如传输100位1时,如果接收方稍有偏差,就可能认为接收到了99位1、101位1。
而USB中采用了Bit-Stuffing位填充处理,即在连续发送6个1后面会插入1个0,强制翻转发送信号,从而让接收方调整频率,同步接收。而接收方在接收时只要接收到连续的6个1后,直接将后面的0删除即可恢复数据的原貌。
NRZI数据格式如上图所示。
USB 协议层数据格式
1.硬件拓扑结构

compound device :多个设备组合起来,通过 HUB 跟 Host 相连(即Host是一主多从,可以和多个设备连接 )
composite device :一个物理设备有多个逻辑设备(multiple interfaces)
物理设备:指的是实际连接到计算机或其他主机设备上的USB硬件设备,比如USB闪存驱动器、打印机、键盘、鼠标等。
逻辑设备:是指在一个物理USB设备内部,可以独立运行和管理的多个功能模块或接口。每个逻辑设备可以执行不同的功能,并在系统中表现为独立的设备。
例如:一个USB打印机可能内部有多个逻辑设备:
**打印功能:**作为打印机的主要功能。
**扫描功能:**如果打印机是多功能设备,还可能包括扫描功能。
**传真功能:**如果打印机还具备传真功能。
在软件开发过程中,我们可以忽略 Hub 的存在,硬件拓扑图简化如下:

一个物理设备里面可能有多个逻辑设备,Host可以外接多个逻辑设备,硬件拓扑图如下:

2.协议层
要理解协议层、理解数据如何传输,带着这几个问题:
① 如何寻址设备?
② 如何表示数据方向(读、还是写)
③ 如何确认结果?
提前罗列出答案:
① USB 系统是一个 Host 对应多个设备,要传输数据首先要通知设备:
发出 IN 令牌包:表示想读数据,里面含有设备地址
发出 OUT 令牌包:表示想写数据,里面含有设备地址
② 数据阶段:
Host 想读数据:前面发出 IN 令牌包后,现在读取数据包
Host 想发出数据:前面发出 OUT 令牌包后,现在发出数据包
③ 结果如何?有握手包
Host 想读数据,设备可能未就绪,就会回应 NAK 包
Host 想写数据,它发出数据后,设备正确接收了,就回复 ACK 包
(2.1) 字节/位传输顺序
先传输最低位(LSB)。在后续文档中,描述数据时按照传输顺序从左到右列出来。
(2.2) SYNC域
Host发出SOP信号后,就会发出SYNC信号:它是一系列的、最大传输频率的脉冲,接收方使用它来同步数据 。对于低速/全速设备,SYNC信号是8位数据(从左到右是00000001);
对于高速设备,SYNC信号是32位数据(从左到右是00000000000000000000000000000001)。使用NRZI编码时,前面每个"0"都对应一个跳变。
在很多文档里,把SOP和SYNC统一称为"SYNC",它的意思是"SYNC"中含有"SOP"。
3.包格式

USB 总线上传输的数据以包为单位。USB 包里含有哪些内容("域":SOP、SYNC等都是一个域)?
① SOP:用来表示包的起始
② SYNC:用来同步时钟
③ PID:表示包的类型(原来确定数据发送的方向或类型 )
④ 地址:在 USB 硬件体系中,一个 Host 对应多个 Logical Device,那么 Host 发出的包,如何确定发给谁?
a. 发给所有设备:包里不含有设备地址
b. 发给某个设备:包里含有设备地址、端点号
⑤ 帧号、数据等跟 PID 相关的内容
⑥ CRC 校验码
发起一次完整的传输,可能涉及多个包。那么,第 1 个包里含有设备地址、端点号,后续的包就没必要包含设备地址、端点号
(3.1) PID域
注意:所有的 USB 文档提到的"输入"、"输出",都是基于 Host 的角度,"输出"表示从Host 输出到设备,"输入"表示 Host 从设备得到数据。而且无论是Host向设备输出数据,还是Host从设备得到数据,都是由Host主动向设备发起的
有哪些 USB 包?
根据包数据里的 PID 的 bit1, bit0 可以分为 4 类:
① 令牌包(Token):01B(表示二进制)
② 数据包(Data):11B
③ 握手包(Handshake):10B
④ 特殊包(Special):00B
PID 有 4 位,使用 bit1,bit0 确定分类,使用 bit3,bit2 进一步细分。

在USB包中,PID域使用8位来表示,格式如下:

前4位表示PID,后4位是对应位的取反。接收方发现后4位不是前4位的取反的话,就认为发生了错误。
(3.2) 令牌包(Token)
令牌类的PID,起"通知作用",通知谁?SOF令牌包被用来通知所有设备,OUT/IN/SETUP令牌包被用来通知某个设备 。
对于OUT(0011)、IN(1001)、SETUP(1101)令牌包 ,它们都是要通知到具体的设备,格式如下:

对于 SOF 包,英文名为"Start-of-Frame marker and frame number"。对于 USB 全速设备,Host 每 1ms 产生一个帧;对于高速设备,每 125us 产生一个微帧,1 帧里有 8 个微帧。Host 会对当前帧号进行累加计数,在每帧或每微帧开始时,通过 SOF 令牌包发送帧号。对于高速设备,每 1 毫秒里有 8 个微帧,这 8 个微帧的帧号是一样的,每 125us 发送一个SOF 令牌包。
SOF 令牌包格式如下:

(3.3) 数据包
Host使用OUT、IN、SETUP来通知设备:我要传输数据了。数据通过"数据包"进行传输。
数据包也有4种类型:DATA0、DATA1、DATA2、MDATA。其中DATA2、MDATA在高速设备中使用。对
软件开发人员来说,我们暂时仅需了解DATA0、DATA1。
为什么要引入DATA0、DATA1这些不同类型的数据包?为了纠错。
Host和设备都会维护自己的数据包切换机制,当数据包成功发送或者接收时,数据包类型切换。当检测
到对方使用的数据包类型不对时,USB系统认为发生了错误。
比如:
1、Host发送DATA0给设备,设备返回ACK表示成功接收,设备期待下一个数据是DATA1
2、但是Host没有接收到ACK,Host认为数据没有发送成功,Host继续使用DATA0发送上一次的数据
3、设备再次接收到DATA0数据包,它就知道:哦,这是重传的数据包
数据包格式如下:


注意:这里的 PID 不再是令牌类型,而是数据类型(DATA0、DATA1、DATA2、MDATA)。
(3.4 )握手包
握手包有4类:ACK(确认)、NAK(无应答)、STALL(挂起)、NYET(未准备好)
① ACK:数据接收方用来回复发送方,表示正确接收到了数据并且有足够的空间保存数据。
② NAK:Host 发送数据给设备时,设备可以回应 NAK 表示"我还没准备好,没办法接收数据"; Host 想读取设备的数据时,设备可以回复 NAK 表示"我没有数据给你"。
③ STALL:表示发生了错误,比如设备无法执行这个请求(不支持该断点等待)、端点已经挂起。设备返回 STALL 后,需要主机进行干预才能接触 STALL 状态。
④ NYET:仅适用于高速设备 。Host 可以发出 PING 包用来确认设备有数据,设备可以回应NYET表示"还没呢"。Hub 也可以回应 NYET 表示低速/全速传输还没完结。

4.传输细节
(4.1) 传输(Transfer)和事务(Transaction)
USB传输的基本单位是包(Packet),包的类型由PID表示。一个单纯的包,是无法传输完整的数据。
为什么?比如想输出数据,可以发出OUT令牌包,OUT令牌包可以指定目的地。但是数据如何传输呢?
还需要发出DATA0或DATA1数据包。设备收到数据后,还要回复一个ACK握手包。
所以,完整的数据传输,需要涉及多个包:令牌包、数据包、握手包。这个完整的数据传输过程,被称为事务(Transaction)。
有些事务需要握手包,有些事务不需要握手包,有些事务可以传输很大的数据,有些事务只能传输小量数据。
有四类事务:
1、批量事务:用来传输大量的数据,数据的正确性有保证,时效没有保证。
2、中断事务:用来传输周期性的、小量的数据,数据的正确性和时效都有保证。
3、实时事务:用来传输实时数据,数据的正确性没有保证,时效有保证。
4、建立事务:跟批量事务类似,只不过令牌包是SETUP令牌包。
有四类传输(Transfer):
1、批量传输:就是使用批量事务实现数据传输,比如U盘。(数据要可靠,不需要实时 )
2、中断传输:就是使用中断事务实现数据传输,比如鼠标。(数据要可靠,也要实时,注意:这里的中断,并没有中断的效果,而是Host周期地向设备发送数据或者读取数据 )
3、实时传输:就是使用实时事务实现数据传输,比如摄像头。(数据可以不可靠,但要实时 )
4、控制传输:由建立事务、批量事务组成,所有的USB设备都必须支持控制传输,用于"识别/枚举"
暂时记住这个关系:
1、Bit组成域(Field)
2、域组成包(Packet)
3、包组成事务(Transaction)
4、事务组成传输(Transfer)

(4.2) 过程(stage)和阶段(phase)
事务由多个包组成,比如 Host 要发送数据给设备,这就会涉及很多个包:
① Host 发出 OUT 令牌包,表示要发数据给哪个设备
② Host 发出 DATA0 数据包
③ 设备收到数据后,回应 ACK 包
这个完整的事务涉及 3 个包(Packet),分为 3 个阶段(Phase):
① 令牌阶段(Token phase):由令牌包实现
② 数据阶段(Data phase):由数据包实现
③ 握手阶段(Handshake phase):由握手包实现
事务由包组成,这些包分别处于 3 个阶段(phase):令牌阶段,数据阶段,握手阶段 。

对于批量传输、中断传输、实时传输,它们分别由一个事务组成,不再细分为若干个过程。
但是控制传输由多个事务组成 ,这些事务分别处于3个过程:建立过程(stage)、数据过程(stage)、状态
过程(stage)。
总结起来就是:
1、控制传输由多个过程(stage)组成,每个过程由一个事务来实现
2、每个事务由多个阶段(phase)组成,每个阶段有一个包来实现
(4.3) 批量传输
批量传输用批量事务来实现,用于传输大量的数据,数据的正确性有保证,时效没有保证。
批量事务由3个阶段(phase)组成:令牌阶段、数据阶段、握手阶段 。每个阶段都是一个完整的包,含有SOP、SYNC、PID、EOP。
下图中各个矩形框就对应一个完整的包。

示例:

(4.4) 中断传输
中断传输用中断事务来实现,用于传输小量的、周期性的数据,数据的正确性和时效都有保证。
中断事务由3个阶段(phase)组成:令牌阶段、数据阶段、握手阶段。每个阶段都是一个完整的包,含有SOP、SYNC、PID、EOP。
下图中各个矩形框就对应一个完整的包。

中断事务跟批量事务非常类似,Host使用它来周期性地读数据、写数据。
以鼠标为例,我们需要及时获得鼠标的数据,不及时的话你会感觉鼠标很迟钝。但是USB 协议中并没有中断功能,它使用"周期性的读、写"来实现及时性 。具体过程如下:
① Host 每隔 n 毫秒发出一个 IN 令牌包
② 鼠标有数据的话,发出 DATA0 或 DATA1 数据包给 Host;鼠标没有数据的话,发出 NAK 给Host。
中断事务的优先级比批量事务更高,它要求实时性,而批量事务不要求实时性。
(4.5) 实时传输
实时传输用实时事务来实现,用于传输实时数据,对数据的正确性没有要求。
实时事务由2个阶段(phase)组成:令牌阶段、数据阶段。每个阶段都是一个完整的包,含有SOP、SYNC、PID、EOP。
实时事务不需要握手阶段,一个示例的场景是:为了传输摄像头的实时数据,偶尔的数据错误是可以忍受的,大不了出现短暂的花屏。如果为了解决花屏而重传数据,那就会导致后续画面被推迟,实时性无法得到保证。
下图中各个矩形框就对应一个完整的包。

实时事务跟中断事务非常类似,Host也会周期性的发起实时事务,主要区别在于:
1、实时事务不要求准确性,没有握手阶段
2、实时事务传输的数据量比较大,中断事务传输的数据量比较小
(4.6) 控制传输
在使用批量传输时,使用IN令牌包或OUT令牌包表示数据传输方向。
控制传输的令牌包永远是SETUP ,怎么分辨是读数据,还是写数据?发出SETUP令牌包后,还要发出DATA0数据包,根据数据的内容来确定后续是读数据,还是写数据。这个过程称为"建立事务"(SETUP Transaction)
但是控制传输由多个事务组成,这些事务分别处于3个过程:建立过程(stage)、数据过程(stage)、状态过程(stage)。
① 建立过程(stage),使用 SETUP 事务:Host 发出 SETUP 令牌包、DATA0 数据包、得到 ACK握手包
② 数据过程(stage),使用批量事务:
a. 对于输出:Host 发出 OUT 令牌包,发出 DATA0、DATA1 数据包、得到 ACK 握手包
b. 对于输入:Host 发出 IN 令牌包,读到 DATA0、DATA1 数据包、发出 ACK 握手包
③ 状态过程(stage),使用批量事务:
a. 对于输出:Host 发出 IN 令牌包,读到 DATA1 数据包,发出 ACK 握手包
b. 对于输入:Host 发出 OUT 令牌包,发出 DATA1 数据包,等待 ACK 握手包

对于建立过程,数据包表示读或者写

对于数据过程:是由一个或多个批量事务组成的。当需要传输的数据量较大时,一个批量事务无法承载全部数据,就需要通过多个批量事务分批次完成传输,每个批量事务都包含令牌阶段、数据阶段和握手阶段 。

对于状态过程:在控制传输过程中,最后一个事务会改变它的方向,那它怎么表示它的状态呢?
在控制写传输:
如果功能执行完成:设备会向Host发送一个数据长度为0的数据包

如果设备还在处理数据:那么设备会发送一个NAK握手包

在控制读传输中:
Host无论是向设备发送数据还是读取设备的数据,状态最后都是由设备通知Host的,例如:如果Host读数据,读完数据后,还得由设备告诉Host,这个读过程已经结束了
那Host是向设备输出数据,那它怎么得到状态呢?这里有一个取巧的过程

具体来说,控制读传输的状态过程是这样的:
- 令牌包:OUT + 设备地址 + 端点号 + CRC5 ------ 由 Host 发出,告诉总线上"我要向 XX 设备的 XX 端点写"
- 数据包:DATA1 + 空载荷 + CRC16 ------ 还是由 Host 发出,零长度(注意这里必须要有零长度 DATA1)
- 握手包:ACK/NAK/STALL ------ 设备回应
这里的巧妙之处在于: 控制读传输的数据过程是 Host 从设备读取数据(方向是设备→Host),但状态过程却反过来了------由 Host 向设备发出 OUT 令牌包,设备则通过回应握手包来告诉 Host 状态过程是否执行完成。如果设备还在处理数据,它会回应 NAK 握手包,Host 就会继续重试,直到设备准备好为止。
上图中的每一个方框,都是一个完整的事务,含有:Token Packet、Data Packet、Handshake Packet。
在上面建立过程 中,我不是说过数据包 表示读或者写,后续我们会了解这个数据包是怎么表示读还是写?