USB通信协议

电子说

1.3w人已加入

描述

 USB,是英文Universal Serial Bus(通用串行总线)、支持设备的即插即用和热插拔功能。在1994年底由英特尔、IBM、Microsoft等公司联合提出的,在此之前PC的接口杂乱,扩展能力差,热拔插不支持等。USB正是为了解决速度,扩展能力,易用性等而出现的,本文阐述了usb 协议的特点及其四种传输模式。
1. usb的特点
 

usb

USB 接口有4根线,两根电源及两根信号,Standard A类型的接口定义 如下
一般的排列方式是:红白绿黑从左到右
红色-USB电源:标有-VCC、Power、5V、5VSB字样
绿色-USB数据线:(正)-DATA+、USBD+、PD+、USBDT+
白色-USB数据线:(负)-DATA-、USBD-、PD-、USBDT+
黑色-地线:GND、Ground
1.1 Usb的四层描述符
  USB协议采取主从模式,从设备端没有主动通知USB主机端的能力,从机插入后,主机控制器根据协议,获取设备描述符及驱动匹配。 每个usb设备可以有一个或多个配置(config),不同的配置的体现即不同的组合接口。 接口(interface)是一个逻辑概念,接口之间通常是隔离的,互相不干扰。 端点(endpoint)是usb设备的唯一可识别部分,也是host和device之间的通信流的终点。它是一个host或device上的一个数据缓冲区,用来存放和发送usb的各种数据。每个端点都是一个单一连接,支持一个方向的数据流(in: device→host)(out: host→device)。 端点0:所有的usb设备都要拥有端点0,该端点用于对一个逻辑设备进行配置。端点0支持控制传输,且总是在设备接入和上电时就进行配置。
一个设备通常有一个或多个配置;
一个配置通常有一个或多个接口;
一个接口通常有一个或多个端点。

usb

》设备描述符
/* USB_DT_DEVICE: Device descriptor /
struct usb_device_descriptor {
__u8 bLength; //本结构体大小
__u8 bDescriptorType; //描述符类型
__le16 bcdUSB; //usb版本号 200->USB2.0
__u8 bDeviceClass; //设备类
__u8 bDeviceSubClass; //设备类子类
__u8 bDeviceProtocol; //设备协议,以上三点都是USB官方定义
__u8 bMaxPacketSize0; //端点0最大包大小
__le16 idVendor; //厂家id
__le16 idProduct; //产品id
__le16 bcdDevice; //设备出厂编号
__u8 iManufacturer; //设备厂商字符串索引
__u8 iProduct; //产品描述
__u8 iSerialNumber; //设备序列号字符串索引
__u8 bNumConfigurations; //配置的个数
} attribute ((packed));
》配置描述符
/ USB_DT_CONFIG: Config descriptor /
struct usb_config_descriptor {
__u8 bLength; //自身长度
__u8 bDescriptorType;//描述符类型(0x02)
__le16 wTotalLength; //该配置下,信息的总长度
__u8 bNumInterfaces; //接口的个数
__u8 bConfigurationValue; //Set_Configuration命令所需要的参数值
__u8 iConfiguration; //描述该配置的字符串的索引值
__u8 bmAttributes;//供电模式的选择
__u8 bMaxPower;//设备从总线提取的最大电流
} attribute ((packed));
》接口描述符
/ USB_DT_INTERFACE: Interface descriptor */
struct usb_interface_descriptor {
__u8 bLength;
__u8 bDescriptorType;//接口描述符的类型编号(0x04)
__u8 bInterfaceNumber; //该接口的编号
__u8 bAlternateSetting; //备用的接口描述符编号
__u8 bNumEndpoints; //该接口使用的端点数,不包括端点0
__u8 bInterfaceClass; //接口类
__u8 bInterfaceSubClass; //子类
__u8 bInterfaceProtocol; //协议
__u8 iInterface;//描述该接口的字符串索引值
} attribute ((packed));

》端点描述符
/* USB_DT_ENDPOINT: Endpoint descriptor */
struct usb_endpoint_descriptor {
__u8 bLength;//端点描述符字节数大小(7个字节)
__u8 bDescriptorType;//端点描述符类型编号(0x05)
__u8 bEndpointAddress; //端点地址及输入输出属性
__u8 bmAttributes; //属性,包含端点的传输类型,控制,中断…
__le16 wMaxPacketSize; //端点收、发的最大包大小
__u8 bInterval; //主机查询端点的时间间隔
__u8 bRefresh;
__u8 bSynchAddress;
} attribute ((packed));
1.2 USB 结构及通信形式
 

USB总线是一个单主方式的实现,是一种轮询方式的总线,为树形拓扑结构。协议规定所有的数据传输都必须由主机发起,host controller初始化所有的数据传输,各种设备紧紧围绕在主机周围。

usb

USB通信最基本的形式是通过USB设备里一个叫endpoint的端点(可以理解为硬件寄存器或者buff),而主机和endpoint之间的数据传输是通过pipe,pipe通信有两种,一种是stream,另一种是message,协议中规定:message管道要求从它那儿过的数据必须具有一定的格式,message管道必须对应两个相同号码的端点,一个用来in,一个用来out,咱们的缺省管道就是message管道,当然,与缺省管道对应的端点0就必须是两个具有同样端点号0的端点。

usb

一个USB逻辑设备就是一系列端点(endpoint)的集合,它与主机之间的通信发生在主机上的一个缓冲区和设备上的一个端点之间,通过管道来传输数据。管道的一端是主机上的一个缓冲区,另一端是设备上的端点 ,构成一个通信信道。
2. USB 四种通信方式
  USB endpoint有四种类型,分别对应了四种不同的数据传输方式。它们是控制传输(Control Transfers),中断传输(Interrupt Data Transfers),批量传输(Bulk Data Transfers),等时传输(Isochronous Data Transfers)。其中批量传输、等时传输和中断传输每传输一次数据都是一个事务;控制传输包括三个过程,建立过程和状态过程分别是一个事务,数据过程则可能包含多个事务。从usb设备端来看,也可以把端点分为四种类型为控制端点、中断端点、批量端点、等时端点。USB传输数据先发数据低位(LSB),再发高位数据(MSB)
2.1 控制传输
  控制传输用来控制对USB设备不同部分的访问,通常用于配置设备,获取设备信息,发送命令到设备,或者获取设备的状态报告。总之就是用来传送控制信息的,每个USB设备都会有一个endpoint 0的控制端点,内核里的USB core使用它在设备插入时进行设备的配置,它会一种等待着USB core发送控制命令。
控制传输分为三个过程:
  建立过程使用一个建立事务。建立事务是一个输出数据包的过程,需要注意的点有:
• 首先是令牌包,建立过程使用SETUP令牌包;
• 其次是数据包类型,SETUP只能使用DATA0包;
• 最后是握手,设备只能采用ACK来应答(错了的情况不应答),不能使用NAK或者STALL来应答,即设备必须要接受建立事务的数据。

usb

数据过程是可选的,即一个控制传输可能没有数据过程。如果有,一个数据过程可以包含一个或多个数据事务,需要注意的是:
• 首先所有的数据事务必须是同一个方向的(在控制读传输中,数据过程中的所有数据事务都必须是输入的;在控制写传输中,数据过程中的所有数据都必须是输出的);
• 其次,一旦数据传输方向改变,就会认为进入到状态过程,状态过程的第一个数据包必须是DATA1包;
• 最后,每次争取传输一个数据包后就在DATA0和DATA1之间交换。
在这里插入图片描述
 

控制传输的Status阶段是序列中的最后一个事务,状态阶段由前一阶段的数据流方向改变描绘,并始终使用DATA1 PID。

获取设备描述符为控制传输,由5个事务组成,分别是SETUP、IN、IN、IN、OUT,具体过程如下:

usb

2.2 批量传输
批事务量
{In/Out Data Packet
@令牌包(In/Out token)
@数据包 (In/Out data)
@握手包 (Out/In ack)
}

批量传输用来传输大量的数据,确保没有数据丢失,并不保证在特定的时间内完成。U盘使用的就是批量传输,咱们用它备份数据时需要确保数据不能丢,而且也不能指望它能在一个固定的比较快的时间内拷贝完。
• 批量输出(批量写)时, Out Token→Out Data→ACK/NYET/NAK/STALL,其中ACK代表接收正常,且可以接收下次传输;NYET代表本次数据成功接收,但没能力接收下一次传输;NAK表示没有足够的缓冲区来保存数据;STALL表示数据接收,但是端点处于挂起状态。
• 批量输入(批量读)时,In Token→In Data→ACK /NAK/STALL,与批量写不同,主机发送In令牌包后,若设备检测到错误,则不做任何响应,主机等待超时。若设备没有检测到地址端点等错误,但是设备又没有数据需要返回,那么设备就会返回NAK直接响应主机;若改端点处于挂起状态,返回STALL给主机;若主机正确接收到数据后,主机返回ACK应答设备,同样的,主机检测到错误则不做出响应,设备检测超时。USB协议规定,不允许主机使用NAK拒绝接收数据包。
2.3 中断传输

中断事务
{In/Out Data Packet
@令牌包(In/Out token)
@数据包(In/Out data)
@握手包(Out/In ack)
}

中断传输是一种保证查询频率的传输,用来以一个固定的速率传送少量的数据。中断端点在端点描述符中要报告它的查询时间,主机会保证在小于这个事件间隔的范围内安排一次传输,USB键盘和USB鼠标使用的就是这种方式,USB的触摸屏也是,传输的数据包含了坐标信息。

中断传输不是由设备主动的发出一个设备请求,而是由主机保证不大于某个时间间隔内安排一次传输。中断传输通常用在数据量不大,但是对时间要求较严格的设备。中断传输也可以用来不停的检查某个状态,当条件满足后再用批量传输,除了对端点查询的策略上不一样之外,中断传输和批量传输的结构基本上是一样的。
2.4 等时传输

等时事务
{In/Out Data Packet
@令牌包(In/Out token)
@数据包 (In/Out data)
}

等时传输使用等时事务(Isochronous Transactions)来传输数据。同样用来传输大量的数据,但并不保证数据是否到达,以稳定的速率发送和接收实时的信息,对传送延迟非常敏感。用在数据量大、对实时性要求高的场合,例如音频设备、视屏设备等,这些设备对数据延时敏感,期望能够有个比较稳定的数据流。对音频或者视屏设备来说,对数据的100%正确要求不高,少量数据的错误还是能够容忍的,主要是要保证不能停顿;所以等时传输是不保证数据100%正确的。当数据错误时,并不能进行重传操作。因此等时传输也就没有应答包,并不进行重传操作。数据是否正确,可以由数据包的CRC校验来确认。至于出错的数据如何处理,是由软件来决定的。
控制传输
{Setup Packet(建立阶段)
@令牌包(setup token)-(out) @数据包(Setup data) -(out) @握手包(ack) - (in)
}
{In/Out Data Packet(可选数阶段据)
@(令牌包(In/Out token) @数据包(In/Out data) @握手包(Out/In ack)
}
{Out/In Stautus Packet(状态阶段)
@(令牌包(Out/In token) @数据包(Out/In data) @握手包( In/Out ack)
}

审核编辑 黄昊宇

打开APP阅读更多精彩内容
声明:本文内容及配图由入驻作者撰写或者入驻合作网站授权转载。文章观点仅代表作者本人,不代表电子发烧友网立场。文章及其配图仅供工程师学习之用,如有内容侵权或者其他违规问题,请联系本站处理。 举报投诉

全部0条评论

快来发表一下你的评论吧 !

×
20
完善资料,
赚取积分