深入浅出理解USB协议

深入浅出理解USB协议

深入浅出理解USB协议

zzg

机器人爱好者 , 嵌入式

​关注他

70 人赞同了该文章

USB 基础概念

协议版本与带宽

如下图所示 ,低速设备与全速设备通过硬件上拉电阻区分 。高速设备与全速设备均是 D+上拉 ,高速设备在枚举过程中host 通过高速设备总线特有的电平序列得知设备类型。

主机(host)与设备(device)

下图中,是USB常见的连接方式,PC端通过USB-Hub连接各种类型的设备 ,对于Hub而言 intf0 是作为设备与主机PC通信 , intf1-intf4做为主机与外接设备通信,从图中可以看出 , intf1-intf4 数据最终都是通过 intf0 与PC交互 , 可以说是intf1-intf4 共用 intf0的带宽 。USB主机会为连接的设备分配一个7位的设备地址,后续通信均用此地址区分不同的设备,因此一个USB主机最多连接 127个设备。

USB热插拔

背景

热插拔即带电拔插 ,是指设备能够带电接入或者移出正在工作的系统 ,而不影响系统工作的技术。这句话由两个使用需求提炼出:

  • 对连接到总线上的设备,对单个设备的插入或者拔出时,不能对总线产生较大干扰,引起总线其他设备误码或停机
  • 在军事,电信,金融领域,设备投入运行后,必须不断电进行工作,对这类设备进行维修,维护,扩展时,系统也不能停机

在没有热插拔技术之前 , 若设备带电插入或拔插会造成什么问题呢?这里我们使用 MCU读取I2C的传感器设备为例 ,来分析传感器带电断开和接入会造成怎样的问题。

如上图所示 , 一个I2c总线示例,需求如下:

  • 支持3类设备接入 ,温度类 , 内存类 和 ROM类 (类比USB的各种类型的设备)
  • 每类设备支持最大支持接入16个设备 (类比USB同类设备可同时存在多个)
  • 同类别设备存在的设备数量不固定 , 可随时增加或删减

以MCU的实现思维 ,会形成以下逻辑

  • MCU的I2C主机初始化
  • 初始化阶段,判断当前所有接入的传感器 : 按类查询所有地址是否存在设备应答
  • 将收到应答的设备加入到在线列表
  • 在主循环里分别去读取在线列表的设备数据

系统处于工作状态后,此时新设备的插入与在线设备拔出会造成什么后果?

新设备接入:

  • 新设备不在在线列表中 ,无法识别(为什么不在主循环中定时检测设备是否有新增?类与同类设备支持的个数可扩展,检索低效)
  • 新设备在接入时,供电存在一段稳定期 ,若其他设备正在通信 , 新设备电源的不确定性可能影响 SCL 与SDA的电平, 导致通信出错

老设备移除:

  • 若设备正在通信 , 强制将其拔出,由于不能通知到主机设备已经断开连接,主机在尝试继续通信的过程中会发现无法通信 , 进而判断设备断开连接,并将设备从在线列表中删除。
  • 若设备能够自供电,在通信时被拔出,设备SDA会被锁住,需要SCL继续给信号才能恢复 , 若锁住的设备再次接入总线,会影响SDA电平,导致通信出错。

由此可看出,热插拔需要面临的问题主要有以下:

  • 设备插入拔出造成的硬件信号干扰问题(如闩锁效应,静电等)- 硬件解决
  • 设备插入与拔出及时通知到主机与设备 , 主机与设备及时处理状态

原理

硬件上, USB主机的数据线 D+ D- 上存在下拉电阻 Rpd , 设备未插入前 , D+,D-均为低电平;设备端全速与高速设备的 D+ 上存在一个可控上拉电阻 Rpu , 在设备插入后 , D+ 将由低电平逐渐变为高电平(内部存在电容) , 此时主机与设备均能检测到此信号。

下图是 USB hub上电,到设备插入的时序图。其中几个时间含义如下:

  • t1 : USB hub开始供电到 hub电源稳定 (对hub的设计要求)
  • t2 : 设备插入,到检测到连接完成的时间参数<100ms
  • t3 : 设备检测到连接,到总线电平稳定的时间 > 100ms
  • t4 : 总线保持信号稳定持续的时间达到t4 , 设备将进入挂起模式
  • t5 : 复位设备时间
  • t6 : 复位稳定时间

USB端点

如上图所示 , USB host 与 device在硬件层面的通信其实是 各个端点之间的通信。端点特点如下:

  • 所有的端点均能发送和接收数据 , 对于 D+与D-,他们属于并联 ,且同一时刻,只能一个端点发送或接收
  • 端点0固定为控制端点 , 主机在检测到设备插入后 ,会通过端点0获取设备信息(枚举),其余端点可作为数据端点
  • 端点存在最大包长限制,即端点一次最多能传输多少字节,常见全速 64字节 ,高速1024字节(还和传输模式相关)
  • 端点所有的数据传输都由主机发起 , device需要发数据时,数据会放到对应的端点缓存 , 等待host来取走数据
  • 端点的IN 和 OUT均针对主机而言 ,如 device 的 ep0_out 端点 ,对应device而言 ,其实是接收主机控制命令的端点,而 ep0_in则表示发送应答端点

主机发送数据过程:

  • host应用层产生数据 并调用USB发送接口 , 根据设计,可知道应用数据所关联的 数据端点
  • host通过端点0 发送控制命令 : 告诉device,主机准备发送数据 ,以及使用的端点,device切换对应的端点去接收
  • host通过端点1 的OUT发送应用数据 ,device通端点1的 OUT接收数据
  • device通过端点1的IN发送数据包握手信息 , 一次数据通信完成

主机接收数据过程:

  • device应用层产生数据 并调用USB发送接口 , 根据设计,可知道应用数据所关联的数据端点 , 此时数据并未发送出去,在端点1缓存
  • host通过端点0 发送控制命令 : 告诉device ,主机准备读取数据,以及读取的端点号 ,device切换对应的端点准备发送数据
  • device通过端点1 的IN发送应用数据 ,host通过端点1的 IN接收数据
  • host通过端点1的IN发送数据包握手信息 , 一次数据通信完成

USB协议

在USB端点章节,我们对USB数据传输过程有了一个大概的了解,这一节,深入了解一下协议构成的细节,以 USB2.0为例。

如上图所示 , USB由三部分组成 , 分别是应用 ,协议和硬件(为了便于理解才如此分,实际USB2.0协议不一定这样分) 。 USB硬件部分在上一节有介绍端点,关于NRZI编码,这里不做深入介绍,只需要理解:NRZI编码是将我们要发送数字信号 ,通过NRZI编码方式产生 D+ 与 D-的电平变化信号即可。USB协议类似套娃,最小单位为包 ,不同包的组合形成事务 , 不同的事务组合形成传输 , USB不同的类会指定某种传输模式。

包的构成

  • SOP : (start of packet) 包的起始信号 ,是一种特殊的电平信号 ,类似I2c的start信号
  • SYNC: 同步信号 ,用于消除通信过程中的相位误差
  • EOP:包的结束信号,类似 I2C的 stop信号
  • packet content
    • PID :包的标识符 ,通过此字段标识包的类型 : 令牌包 , 数据包 ,握手包 ,特殊包
    • ADDRRESS : 7bits 的设备地址 (一个host最多连接127个device) , 4bits的端点地址 (最多支持16个端点)
    • Frame number: 帧号 ,只在特定的包里面存在
    • data : 数据域 , 最大1024字节 ,可为0字节。
    • CRC : 包内容CRC校验

关于包的组成,以及SOP等电平细节,可参考:https://blog.csdn.net/weiaipan1314/article/details/112911453

包的分类

事务的构成

SETUP事务

IN事务

OUT事务

传输的构成

控制传输

控制传输固定使用端点0 ,枚举过程使用大量的控制传输,可参考后文中枚举过程的实际报文。控制传输为了保证配置数据的传输的有效性,使用了指令再确认机制 (通信双方初始通信参数相同,能正确通信 , 某时刻host 希望更改通信参数 , host发送修改参数请求 ,devices收到请求并校验配置有效 ,应答host ,但配置此时不更新 ,主机在收到应答后,判断为正响应,主机给device发送确认信息,device回应答,双方同步更新配置 ,保证后续使用新的配置继续通信)

BULK传输

BULK传输多用于大容量存储(U盘) , 传输速率受系统占用率影响,可以粗略理解为,当系统占用率为70%时,剩余30%的 性能用于BULK传输,相对于PC的CPU主频,可能只需要很小的的性能就能跑满 BULK传输的带宽。一个生活中的实例:当电脑非常卡或者某个应用程序完全卡死时,U盘的拷贝速率会受极大影响。BULK传输的速率取决于主机IN 或OUT事务的间隔,系统占用率高,IN或OUT事务间隔可能就变大,系统占用率小,IN或OUT事务间隔可能减小。

中断传输

中断传输在格式上与BULK传输没有任何区别,BULK传输速率不确定是因为IN或OUT事务是在其他任务空闲时发出,而中断传输的IN或OUT事务则是定时发出,定时周期取决于设备端点的配置,全速设备最小间隔1ms , 高速设备最小间隔125us 。因此相对于BULK的传输,中断传输的实时性得到了提高,但整体的速率被限制(全速64KB/s), 中断传输多用于数据量小,实时性高的设备,如HID设备。

同步传输

同步传输综合了BULK传输的整体速率,以及中断传输的实时性,但是去掉了事务的应答,不具备错误重发机制,多用于音视频传输允许少量错误失真地方。为了兼顾速度与实时性 , 同步传输的 IN和OUT事务优先机很高 ,因此只要系统占用率每达到100% , 几乎均可发出IN和OUT事务,且间隔都是尽可能的短。(BULK传输类似系统在空闲任务中才开始传输,若系统空闲时间长,BULK传输在此空闲阶段也能跑满带宽,同步传输类似在高优先级任务中运行,系统性能尽可能去满足传输速率)

帧的构成

前面介绍了USB协议封装的4种传输模式和各自的特点,那么USB传输发生在什么时刻呢?主机应用层需要发送或接收数据就直接使用对应的传输模式传输?空闲时总线电平保持不变?USB协议规定 ,在时间线上,USB传输分为1ms间隔的帧,主机在初始化完成后,会以1ms的周期发送SOF包,每发送一包SOF,SOF中的帧计数器加1 ,满后自动翻转。而前面所介绍的4种传输模式,必须发生在上图的允许传输的时间范围。其中,传输可跨越帧 , 事务与包均不能跨越帧

帧的引入有以下用途。

  • 实现总线上的设备休眠功能 , 设备3ms未收到SOF会挂起,挂起的设备可选择进入休眠模式 ,再次收到 SOF会被唤醒
  • 主机和设备都存在 SOF中断 ,能在时间上进行一个同步
  • 中断传输需要定时发起传输事务 , 定时时间为1ms的整数倍,可借助此中断。
  • SOF的帧计数器在高速传输中有作用
  • 其他

USB描述符

前面章节已经说明了USB如何通信 ,如下步骤:

  • 主机和从机USB初始化完成后 , 主机(USB-FS)会以1ms的周期发送帧起始SOF包
  • 主机在允许传输的时间范围内 , 通过设计的传输模式发送应用层的数据到设备
  • 设备产生的应用层数据缓存在设备的数据端点 , 主机会根据设备端点指定的传输模式 ,轮询读取数据。

通过上面的过程可以发现,主机与从机要想正确通信,需要满足以下要求:

  • 主机要知道从机的速度模式,低速与全速高速可通过上拉电阻判断 , 全速与高速在总线复位期间的电平状态可判断
  • 主机需要知道从机的端点信息 ,除了端点0是固定的,其余端点不同的设备可能有不同的功能
  • 主机支持连接多个从机,类似i2c ,需要为每个从机分配地址

以上要求当然可以像 I2c一样,速度模式,通信模式 ,地址主机和从机均约定好,但是问题在于每新增一类设备,主机都要重新去适配,维护起来会相当麻烦。更优的做法是,设备将自身的配置信息保存在本地 ,主机在检测到设备接入时 ,通过端点0获取设备配置信息,然后根据配置信息,使用配置的模式以及配置的数据端点通信 ,这个过程称为USB枚举 ,枚举所获取的配置称为USB描述符

设备描述符:用于描述此设备的配置数量,设备类型(HID ,CDC ,MSC ,自定义等) ,厂商信息

配置描述符一个设备可以有多种配置 ,配置可分时复用 ,配置描述符主要描述了本配置下的接口数量和供电要求

接口描述符:每个配置下可存在多个接口(功能) ,如一个耳机有 麦和听筒功能 ,接口描述符描述了本接口的端点数和协议类型

端点描述符:描述了端点的最大包长 , 传输模式(控制,中断,bulk,同步) ,主机轮询间隔

字符串描述符:枚举成功后,在主机设备管理器显示的设备名


USB枚举

设备端的描述符存储在本地,主机如何读取描述符?这时就需要指定一套读取的描述符的协议与流程,此流程称为枚举过程。枚举过程使用控制传输 ,如下图所示 ,主机的请求均封包在 Setup阶段的数据包中 , 而设备的响应(描述符)均封包在数据阶段数据包中。

枚举请求协议

所有的请求协议均为下面8字节格式 ,封装在Setup阶段的数据包中 。 bRequest 表示了请求的类型 ,wLength 决定了数据阶段 IN或OUT事务的次数。(注:枚举阶段开始只会读取部分设备描述符 (读到端点0的最大包场),wLength 字段能控制读取部分,而不是读取所有 )

上面表格显示了11种命令 ,重点时标 * 的几条命令,命令需要注意以下事项:

  • 所有类型命令均由主机发起 ,在控制传输的Setup阶段的数据包中填充 , bmRequestType中的方向表示的是数据阶段的方向
  • GET_STATUS 命令的 windex字段的含义需要通过 bmRequestType字段的D0-D4确认到底是设备状态,接口状态,还是端点状态
  • GET_DESCRIPTOR命令通过 wValue字段的种类+索引确定到底是哪种描述符,以及多个相同描述符的索引(端点描述符,接口描述符,配置描述符都可能存在多个),此命令可获取所有类型的描述符
  • SET_CONFIGRATION 命令的配置值用于设置存在多种配置描述符设备使用哪种配置 ,在枚举完成后设置,多数设备只存在一种配置

枚举过程

USB类

USB设备在枚举完成后 ,主机已经得到设备的所有信息 ,例如 ,存在两个接口 , 一个是耳机接口,使用端点1将主机端的音乐数据传输到设备的扬声器播放 , 另一个是麦克风接口 ,通过端点2,将设备端采集的音频数据传输到主机扬声器播放。这是一个耳机设备,若有10个厂家准备去研发供电脑使用的耳机 ,如果10个厂家均按自己定义的格式来传输音频数据 , 那每个厂家的设备均要在PC端提供一个驱动,用于解析数据。为了解决这个问题 ,USB协议规定了很多标准类 ,同类的设备所有厂商必须按相同的格式传输数据,否则需单独指明驱动程序。下表是常见的USB类,USB类需要在设备描述符中指明。

CDC类

CDC(Communication Device Class)类是USB2.0标准下的一个子类,定义了通信相关设备的抽象集合。一个常见的理解误区是认为 CDC类就是USB虚拟串口 ,并且认为CDC的速率和串口的速率相当。CDC类还存在很多子类 , 电话 ,网络 ,串口都有可能,我们常见的虚拟串口是 PTSN子类和ATM子类 ,只不过实际使用中没有使用电话特性和AT指令特性。

CDC描述符

以USB虚拟串口为例 ,虚拟串口有的功能如下所示:

  • 主机配置选择波特率 ,以及停止位,校验位等串口参数
  • 设备出现异常能够通知主机状态异常
  • 能够串口数据通信

根据虚拟串口功能,能得到以下描述符。需要注意以下几点:

  • PC端的串口工具 ,使用端点0来获取设备的串口配置和设置串口配置 , 通过 GetLineCoding命令 和 SetLineCoding
  • 控制接口的端点使用中断传输 , 这样能保证设备状态更新同步到主机的实时性
  • 数据端点传输模式任意,一般是bulk传输

除了以上标准描述符,CDC类通信子类还有很多特定的描述符,如Header功能描述符 ,ACM功能描述符Call Management功能描述符,这些描述符为子类功能实现提供帮助,如电话功能,AT指令支持版本等,这些描述符指明了设备串口之上的协议支持程度 ,对于仅需要实现USB转串口功能,这些描述符可不用过多关注。

HID类

HID(human interface device)人机接口设备,常见的HID设备有鼠标,键盘,游戏摇杆等。这类设备有以下特点:

  • 要求低延迟的体验感 (使用中断传输)
  • 兼容性,比如鼠标,各个厂商生产的设备,兼容同一个鼠标驱动

为了实现兼容性 ,HID类设备增加了一个特有的描述符 : 报告描述符 。报告描述符描述了应用数据的格式 。下图是一个标准的鼠标数据格式,以及通过此数据格式生成的报告描述符。下图的报告描述符解释了每个字段的含义 , 实际值是 Value部分的内容,在枚举阶段,主机若得到设备类型为HID ,则会获取报告描述符。若设备报告描述符不正确,会导致枚举失败,这也是HID设备初期调试常见的问题。

对于一些数据格式固定的USB设备 , 可按照数据格式自行生成报告描述符 , 报告描述符的复杂程度取决于数据结构,这种非标的HID设备,需要主机拥有特定的驱动程序才能解析应用数据。

复合设备

前面介绍的CDC类设备和HID类设备均只存在单一功能 ,有没有方法实现插上一个USB口到PC , 能产生种功能呢?比如需要开发一个USB转串口调试工具 , 使用的MCU支持 2路硬件串口 和 1路USB ,我们希望的是 USB插上电脑后,能产生2路虚拟串口。

如上图所示 ,与单路虚拟串口不同的是 ,在双路虚拟串口的描述符中 ,增加了IAD接口关联描述符 ,此描述符的作用在于 ,让主机将相关联的接口组合成一个功能实现(串口) ,为什么在单路虚拟串口中不需要?单路串口中使用的Union描述符(老版本用于关联接口) ,新版本的window更推荐使用 IAD替换 Union描述符。实际测试,在Win10系统上 ,复合设备某个功能存在多个接口时,必须使用IAD描述符,而不能使用Union描述符。

其他类

USB协议是一个庞大的协议族,不同的类可扩展各种各样的协议,因此在进行USB开发时,可根据实际情况,先看看需开发的设备是否是标准类,若是标准,再去学习对应的标准类协议。在了解了基础协议后,也可自定义协议,只不过需要自己实现自定义的驱动程序。

https://zhuanlan.zhihu.com/p/683251257

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值