STM32-USB学习笔记(一) USB基础

USB基础知识扫盲

前言

本文将从USB的 插入检测身份识别数据传输三个方面对USB通信整个过程扫盲,其中有些知识点的详细信息会放在文章最下面的附录中供查看,从而保证文章的总体简洁。在进入主题以前,首先了解一下USB的一些基础知识

USB的分类 学习

  • 按接口类型分spa

    • 控制器/主机(controller/host)
    • 设备(peripheral)
    • OTG(on-the-go),经过id线肯定做为主机仍是做为设备
  • 按照USB速度分3d

    • 低速(low speed)
    • 全速(full speed)
    • 高速(high speed)

1、USB插入检测

USB接口通常是4根线,VCC GND DM(D-) DP(D+)
  • A:USB是如何检测到设备插入的
  • Q:主机端将DM DP接入下拉电阻;设备端根据不一样速度,将DM DP的某一根接上拉电阻,插入时经过压差便可断定是否插入code

    • 低速设备:在DM线上接入上拉
    • 全速设备:在DP线上接入上拉
    • 高速设备:在DP线上接入上拉,在主机对设备进行复位后进一步的确认,详情

2、USB身份识别

对于插入的USB设备,主机须要发送比较短的请求来确认设备的身份、类型、速度等信息,这个过程称之为 枚举

2.1 描述符

设备的“身份”信息存储在描述符中。每一个USB设备中都有以下描述符。须要注意的是blog

  • 一个USB设备只能有一个设备描述符
  • 其余描述符均可以有多个,对应复合设备,例如USB键鼠
  • 设备描述符(device description)索引

    • 配置描述符(config description)接口

      • 接口描述符 (interface description)图片

        • 端点描述符 (endpoint description)
        • 端点描述符
      • 接口描述符事务

        • 端点描述符
    • 配置描述符ip

      • 接口描述符

        • 端点描述符

2.2 枚举过程

  1. 等待稳定:主机经过电平差检测到设备,等待100ms让设备电平趋于稳定
  2. 首次复位:HUB发起复位,让设备进入初始的地址0模式
  3. 首次查询设备描述符:GET_DESCRIPTOR 主机查询设备描述符,只要前8字节 ==> 80 06 01 00 00 00 12 00
  4. 二次复位:在接收到设备描述符前8个字节后,再次重启设备
  5. 设置地址:SET_ADDRESS 主机下发设置地址命令,设备获取新地址 ==> 00 05 01 00 00 00 00 00
  6. 二次查询设备描述符:GET_DEVICE_DESCRPTOR获取整个18字节的设备描述符 ==> 80 06 01 00 00 00 12 00
  7. 获取配置描述符:GET_CONFIGURATION 获取9字节配置描述符 ==> 80 06 02 00 00 00 09 00
  8. 完成配置:SET_CONFIGURATION,

2.3 描述符详解

搞懂了描述符,调好了枚举,就完成了USB通信的一大半,下面就对描述符进行详细的探索
设备描述符 18 配置描述符 9 接口描述符 9 终点描述符 7
bLength 1 bLength 1 bLength 1 bLength 1
bDescriptorType 1 bDescriptorType 1 bDescriptorType 1 bDescriptorType 1
bcdUSB 2 wTotalLength 2 bNumInterfaces 1 bEndpointAddress 1
bDeviceClass 1 bNumInterfaces 1 bAlterateSetting 1 bmAttributes 1
bDeviceSubClass 1 bConfigurationValue 1 bNumEndpoints 1 wMaxPacketSize 2
bDeviceProtocol 1 iConfiguration 1 bInterfaceClass 1 bInterval 1
bMaxPackeerSize0 1 bmAttributes 1 bInterSubfaceClass 1
idVendor 2 bMaxPower 1 bInterfaceProtocol 1
idProduct 2 iInterface 1
bcdDevice 2
iManufacturer 1
iProduct 1
iSerialNumber 1
iNumConfigurations 1

附录

F一、USB通信协议详解

学习协议我我的以为应该仍是从总体流程向下详细到具体协议,上来就看最基本单元/协议会让人一头雾水,这段附录的大致流程也是如此。传输概念->传输流程->基础传输单元->传输流程控制->

F1.1 USB通信概念

  1. 在USB的通信中,有传输(transfer),事务(Transaction),包(packet)三级。包是最基础的传输单元,与TCP/IP协议中的MAC层协议做用相同。
  2. 在一次传输中,由屡次事务组成,每次的事务又由多个包组成
  3. 与众多协议相同,较高级别的协议的报文是基于/内嵌在低级协议的报文当中的,在USB中也不例外,例如,包中预留了DATA位,其目的就是填写报文
  • 传输(transfer): 控制(control)、中断(interrupt)、批量(bulk),同步(Isochronous)

    • 事务(transaction):传输方向、流程控制

      • 包(packet):

        1. 令牌(Token):IN、OUT、SETUP、SOF,前导包,用于确认本次事务的方向、目的等,是每次事务必需要有的包。
        2. 数据(data):DATA0、DATA一、DATA二、MDATA,夹带数据
        3. 握手(handshake):ACK、NAK、STALL、NYSET,做为应答、状态回复

F1.2 一次完整传输过程

下图为一次完整的获取设备描述符的过程

  • 传输:获取设备描述符

    • 设置事务:主机向设备下发 -> 80 06 00 01 00 00 40 00

      • 令牌包 --> :SETUP类型
      • 数据包 --> :因为令牌是SETUP类型,因此主机紧接着下发数据包,DATA0类型
      • 握手包 <-- :设备收到数据包,回复应答
    • 输入事务:设备向主机上发 -> 12 01 00 01 DC 00 00 10 71 04 F0 FF 00 01 00 00

      • 令牌包 --> :IN类型,主机准备好,设备能够上发数据
      • 数据包 <-- :DATA1类型:DATA0与DATA1在发送数据时须要交替,DATA中夹带设备描述符
      • 握手包 --> :主机收到回复,向设备应答
    • 输出事务:无

      • 令牌包 --> :OUT类型
      • 数据包 --> :DATA0类型,再一次切换为DATA0,没有须要发送给设备的
      • 握手包 <-- :设备收到数据包,回复应答

F1.3 基础传输单元:传输基本单元 -- 包(packet)

不一样包的组成部分以下表所示,数字为每个字段所表明位数。结合上面的完整流程能够更输入的理解包的概念。
Token 令牌包 SYNC PID ADDR ENDP CRC5
8/32 8 7 4 5
Data 数据包 SYNC PID DATA CRC16
8/32 8 0-1023 16
Handshake 握手包 SYNC PID
8/32 8
SOF 起始包 SYNC Frame Number CRC5
8/32 11 5
  1. SYNC字段:为固定,FS/LS为8位,HS为32位
  2. PID字段:决定了该包的类型,例如Token包的SETUP,IN,OUT,数据包的DATA0,DATA1,握手包的ACK,NAK等
  3. ADDR字段/ENDP字段:前面说过,一个设备只有一个设备描述符和多个终点描述符,这两个字段就能够在多个设备中准确的找到目标设备以及设备中的目标终点,相似TCP/IP中的IP与PORT
  4. SOF包:在Token包以前发送,Frame Number为主机内部自增序列号,不断循环

    • FS/LS:每1ms发送一次
    • HS:每125us发送一次
  5. EOF:EOF不属于字段或者数据,而是在每一个包最后加上2个数据位宽的SE0信号(DM DP都为低),用于表示包的结束

F1.4 传输流程控制 -- 事务(Transaction)

在分析那个设备描述符的流程时会发现,必须在每次事务的开始,要使用Token(令牌包)确认该次事务的传输“基调”。缘由在于,USB是半双工,DM DP并不是独立工做,因此采用"三段式"通信,保证总线不会冲突

  • 令牌包(Token):主机发起
  • 数据包(Data):根据令牌包中的方向,由主机发起(OUT/SETUP)或者设备发起(IN)数据包
  • 握手包(Handshake):数据包接收方发起握手包,返回状态,包含ACK NAK STALL状态等。

图片描述

  1. 不能中断:USB的每次事务是“堵塞”,必须该事务完整后才能作其余事务
  2. 状态判断:以前的举例当中,每次传输都是成功的回复了ACK,能够看到,上图中,事务发起了三次IN的Token包,设备才发送了下一帧数据。不会由于设备忙就退出事务。
  3. 流程控制: 下发/接收数据、控制进出方向、确认回复

F1.5 传输(Transfer)

终于说到顶层部分了,有点耐心立刻就说完了,首先传输分为如下几种方式,对应不一样需求
传输方式 令牌包 数据包 握手包 特色及医用 特殊性
控制 枚举过程当中使用 屡次事务,简单的下发命令+回复须要2次事务6个包
批量 数据量大,要求准确性,经常使用于U盘等设备 屡次事务,DATA0/DATA1交替
中断 数据量小,要求固定频率,经常使用于USB键盘鼠标 与批量类似,主机会按照固定间隔向设备发令牌包
同步 × 数据量大,要求低延迟,经常使用于USB摄像头、声卡 无握手包的批量传输

F1.5.1 控制传输(Control Transfer)

控制传输经常使用于USB枚举阶段,读取设备描述符、设置地址等少许频繁的工做。上面举的获取完整设备描述符就是一个很是典型的控制传输过程,分为如下几个阶段
  1. 创建阶段:SETUP事务,发下指定命令,设备应答
  2. 数据过程:设备等待主机发起IN事务,并将数据上传,主机回复应答
  3. 状态过程:确认完成,这个阶段传输方向必须与数据传输阶段相反,数据传输是IN,确认就应该用OUT。

图片描述

F1.5.2 批量传输(Bulk Transfer)

  • 区分方向,有批量读与批量写,不能同时执行
  • 一次批量传输由屡次事务组成
  • 传输过程当中数据包类型DATA0/DATA1不断切换,若是发生错误,则主机会要求重传

图片描述

F1.5.3 中断传输(Interrupt Transfer)

中断传输在数据传输方面与批量传输相同,重点在于,主机对中断传输设备必须 保持固定扫描间隔,在设备描述符中标注了该扫面间隔。USB总线即便被其余设备批量传输占用,也会在完成中间抽空向中断传输设备下发令牌

F1.5.4 同步传输(Isochronous Transfer)

由于要求实时性,对数据准确性不是很敏感,因此同步传输中的事务是没有握手包的,以下图

图片描述

F2 USB通信请求 Request

命令 bmRequestType bRequest wValue wIndex wLength Data
GET_STATUS 0
CLEAR_FEATURE 1
SET_FEATURE 3
SET_ADDRESS 5 设备地址 0 0
GET_DESCRIPTOR 80H 6 描述符类型+索引 0/languageID 描述符长度 描述符
SET_DESCRIPTOR 7
GET_CONFIGURATION 8
SET_CONFIGURATION 00H 9 00xxH 配置值,高字节固定00 0 0
GET_INTERFACE 10
SET_INTERFACE 11
GET_STATUS 12

bmRequest字段

D7 D6-D5 D4-D0
0:OUT
1:IN
00:标准请求
01:类请求
10:用户自定义
00:设备01:接02:端03:其余