Skip to content

LV001-USB简介

USB,即通用串行总线(Universal Serial Bus),包括 USB 协议和 USB 硬件两个方面,支持热插拔功能。现在日常生活的很多方面都离不开 USB 的应用,如充电和数据传输等场景。

USB 经过多次修改, 1996 年确定了初始规范版本 USB1.0,目前由非盈利组织 USBIF(Front Page | USB-IF)管理。 STM32 自带的 USB 符合USB2.0 规范,故 2.0 版本仍是学习的重点。

一、USB简介

USB 本身的知识体系非常复杂,这里就简单介绍一下,想更系统地学习 USB 的知识可以参考《圈圈教你玩 USB》、塞普拉斯提供的《USB101:通用串行总线 2.0 简介》等文献 。

1. USB 的硬件接口

USB 协议有漫长的发展历程,为的不同的场合和硬件功能而发展出不同的接口: Type-A、Type-B、 Type-C, Type-C 规范碰巧是跟着 USB3.1 的规范一起发布的。常见的接口类型列出如下图:

image-20240115220202759

USB 发展到现在已经有 USB1.0/1.1/2.0/3.x/4 等多个版本。目前用的最多的就是版本USB1.1 和 USB2.0, USB3.x/USB4 目前也在加速推广。从图中可以发现不同的版本的 USB 接口内的引脚数量是有差异的。 USB3.0 以后为了提高速度,采用了更多数量的通讯线,比如同样的是 Type A 接口, USB2.0 版本内部只有四根线,采用半双工式广播式通讯, USB3.0 版本则将通讯线提高到了 9 根,并可以支持全双工非广播式的总线,允许两个单向数据管道分别处理一个单向通信。

USB2.0 常使用四根线: VCC(5V)、 GND、 D+(3.3V)和 D-(3.3V) (注:五线模式多了一个DI 脚用于支持 OTG 模式, OTG 为 USB 主机+USB 设备双重角色),其中数据线采用差分电压的方式进行数据传输。在 USB 主机上, D-和 D+都是接了 15K 的电阻到地的,所以在没有设备接入的时候, D+、 D-均是低电平。而在 USB 设备中,如果是高速设备,则会在 D+上接一个 1.5K的电阻到 3.3V,而如果是低速设备,则会在 D-上接一个 1.5K 的电阻到 3.3V。这样当设备接入主机的时候,主机就可以判断是否有设备接入,并能判断设备是高速设备还是低速设备。

关于 USB 硬件还有更多具体的细节规定,硬件设计时需要严格按照 USB 的器件的使用描述和 USB 标准所规定的参数来设计。

2. USB 速度

USB 规范已经为 USB 系统定义了以下四种速度模式:低速(Low-Speed)、全速(Full-Speed)、高速(Hi-Speed)和 超高速(SuperSpeedUSB)。接口的速度上限与设备支持的 USB 协议标准和导线长度、阻抗有关,不同协议版本对硬件的传输线数量、阻抗等要求各不相同,各个版本的能达到的理论速度上限对应如图:

image-20240115220336229

USB 端口和连接器有时会标上颜色,以指示 USB 规格及其支持的功能。这些颜色不是 USB规范所要求的,并且在设备制造商之间不一致。例如,常见的支持 USB3.0 的 U 盘和电脑等设备使用蓝色指示,英特尔使用橙色指示充电端口等。

3. USB 系统

USB 系统主要包括三个部分:控制器(Host Controller)、集线器 (Hub) 和 USB 设备。

控制器(Host Controller),主机一般可以有一个或多个控制器,主要负责执行由控制器驱动程序发出的命令。控制器驱动程序(Host Controller Driver)在控制器与 USB 设备之间建立通信信道。

集线器(Hub)连接到 USB 主机的根集线器,可用于拓展主机可访问的 USB 设备的数量。

USB 设备(USB Device)则是我们常用的如 U 盘, USB 鼠标这类受主机控制的设备。

4. USB 通讯

USB 针对主机、集线器和设备制定了严格的协议。概括来讲,通过检测、令牌、传输控制、数据传输等多种方式,定义了主机和从机在系统中的不同职能。USB 系统通过“管道”进行通讯,有“控制管道”和“数据管道”两种, “控制管道”是双向的,而每个“数据管道”则是单向的,这种关系如图:

image-20240115220503230

USB 通讯中的检测和断开总是由主机发起。 USB 主机与设备首次进行连接时会交换信息,这一过程叫“USB 枚举”。枚举是设备和主机间进行的信息交换过程,包含用于识别设备的信息。此外,枚举过程主机需要分配设备地址、读取描述符(作为提供有关设备信息的数据结构),并分配和加载设备驱动程序,而从机需要提供相应的描述符使主机知悉如何操作此设备。整个过程需要数秒时间。完成该过程后设备才可以向主机传输数据。数据传输也有规定的三种类型,分别是: IN/读取/上行数据传输、 OUT/写入/下行数据传输、控制数据传输。

USB 通过设备端点寻址,在主机和设备间实现信息交流。枚举发生前有一套专用的端点用于与设备进行通信。这些专用的端点统称为控制端点或端点 0,有端点 0 IN 和端点 0 OUT 两个不同的端点,但对开发者来说,它们的构建和运行方式是一样的。每一个 USB 设备都需要支持端点 0。因此,端点 0 不需要使用独立的描述符。除了端点 0 外,特定设备所支持的端点数量将由各自的设计要求决定。简单的设计(如鼠标)可能仅要一个 IN 端点。复杂的设计可能需要多个数据端点。

USB 规定的数据 4 种数据传输方式也是通过管道进行,分别是控制传输(Control Transfer)、中断传输(Interrupt Transfer)、批量传输或叫块传输(Bulk Transfer)、实时传输或叫同步传输(Isochronous Transfer ),每种模式规定了各自通讯时使用的管道类型。

关于 USB 还有很多更详细的时序和要求,像 USB 描述符、 VID/PID 的规定、 USB 类设备和调试等,因为 USB2.0 和之后的版本有差异,这里就不再详细描述了, ST 对 USB2.0 也有专门的培训资料,可以去官网查一查。

二、STM32F1的USB

1. 特性

STM32F1 系列芯片自带了 USB FS(FS,即全速, 12Mbps),支持从机(Slave/Device),但其 USB 与 CAN 不能同时使用,因为硬件共享同一个 SRAM。STM32F1 的 USB 外设实现了 USB2.0 的接口和 APB1 总线间的接口。它有以下特性:

  • 符合 USB2.0 全速设备的技术规范
  • 可配置 1 到 8 个 USB 端点
  • CRC(循环冗余校验)生成/校验,反向不归零(NRZI)编码/解码和位填充
  • 支持同步传输
  • 支持批量/同步端点的双缓冲区机制
  • 支持 USB 挂起/恢复操作
  • 帧锁定时钟脉冲生成

2. USB设备框图

STM32F1 的 USB 外设使用标准的 48Mhz 时钟,允许每个端点有独立的缓冲区,每个端点最大为 512 字节缓冲,最大 16 个单向或 8 个双向端点。 USB 的传输格式由硬件完成,状态可以由寄存器标记,可以很大程度上简化我们的程序设计。USB模块启动时间tSTARTUP最大为1us,这个需要在编程时注意。下图引用了 STM32F1 的 USB 设备框图,方便我们理解 USB 这个外设。

image-20240115220808558

三、USB协议栈

到这里我们已经对 USB 的硬件有了一定的了解,但由于 USB 协议的庞杂性,便得直接编写 USB 驱动的上手难度很大。故暂时我们可以从移植 ST 官方的 USB例程入手,学会使用 USB 驱动库。

ST 官方 Cube 库中提供的官方 USB 协议栈,主要是包含了 USBD 内核与 USB 各种类。USBD 内核一般是固定的,用户一般不需要修改,但 USBD 类,如果用户需要修改或者扩展,比如复合设备或者用户自定义设备,则需要用户自行修改。

USB 协议栈将所有 USB 类都抽象成一个数据结构: USBD_ClassTypeDef, USBD 内核与USBD 类之间的纽带就是 USBD_ClassType 这个结构体。这个结构体是一个抽象类,定义了一些虚拟函数,比如初始化,反初始化,类请求指令处理函数,端点 0 发送完成,端点 0 接收处理,数据发送完成,数据接收处理, SOF 中断处理,同步传输发送未完成,同步传输接收未完成处理等等;用户在实现自己具体的 USB 类的时候需要将它实例化, USBD_ClassTypeDef 结构体是 USBD 内核提供给外部定义一个 USB 设备类的窗口,而 USB 类文件实际就是实现这个结构体具体实例化的过程。最后将这个具体实例化的对象注册到 USBD 内核的同时, USBD 内核与 USBD 类也进行了关联。