3、USB协议核心概念(上):USB主机与设备、端点、管道、传输类型
各位同学,今天我们来啃一啃USB协议里最基础、也最绕不开的几个概念。说实话,我刚接触USB时,被“端点”、“管道”这些词搞得一头雾水。后来在项目里调了几个月驱动,才慢慢摸清楚它们到底是怎么回事。
这一节我们先讲上半部分:主机与设备的关系、端点是什么、管道怎么连通、以及四种传输类型各自用在什么场景。嗯,内容有点干,但都是后面实战的根基。
3.1 USB主机与设备——谁说了算?
USB总线是典型的主从结构。主机(Host)是老大,设备(Device)是小弟。所有通信都由主机发起,设备只能被动响应。你想想看,U盘插到电脑上,U盘不会主动说“我准备好了”,而是电脑先问“你是谁?”,U盘再回答。
我在项目中遇到过一个问题:用STM32做USB Host去读一个自定义设备,结果设备没响应。查了半天,发现是设备的上拉电阻没配置对,导致主机根本检测不到设备连接。说白了,主机连设备的存在都不知道,后面的事全白搭。
核心要点:
- 主机控制所有事务(Token包、数据包、握手包)
- 设备不能主动发数据,只能等主机来要
- 一个USB总线上只能有一个主机,但可以挂多个设备(通过Hub扩展)
主机内部有Host Controller硬件,负责处理底层的包传输。我们写驱动时,其实是在跟Host Controller的寄存器或DMA缓冲区打交道。CubeMX生成的代码里,这部分已经被HAL库封装好了,但理解底层逻辑对调试很有帮助。
3.2 端点(Endpoint)——设备内部的数据出入口
端点这个概念,我刚开始总觉得抽象。后来我把它想象成设备内部的一个“邮箱”。每个邮箱有一个编号(端点号),还有一个方向(IN还是OUT)。
- IN端点:设备发给主机的数据,从这个邮箱出去
- OUT端点:主机发给设备的数据,投到这个邮箱里
每个USB设备至少有一个端点——端点0。它是控制端点,双向的,用于设备枚举和基本控制。其他端点(端点1、2、3...)根据设备功能来定。比如一个USB鼠标,通常只有一个IN端点用来发鼠标数据;而一个USB音频设备,可能有多个端点分别处理麦克风输入和扬声器输出。
| 端点特性 | 说明 |
|---|---|
| 端点号 | 0~15,0为控制端点(双向),1~15为功能端点 |
| 方向 | IN(设备→主机)或 OUT(主机→设备) |
| 传输类型 | 控制、批量、中断、同步 |
| 最大包大小 | 由端点描述符定义,低速8字节,全速64字节,高速可达1024字节 |
个人经验:调试时,我经常用Bus Hound抓包看端点通信。如果设备不响应,先检查端点描述符里的最大包大小对不对。有一次我写了个批量端点,最大包设成128字节,但全速模式下最大只能64字节,结果主机一直发NAK。改回来就好了。
3.3 管道(Pipe)——端点和主机之间的逻辑通道
管道是主机上的一个软件概念。每个端点对应一条管道。主机通过管道向端点发送或接收数据。你可以把管道理解成“主机和端点之间的一条虚拟数据线”。
管道有两种:
- 消息管道:用于控制传输,数据有结构(比如Setup包+数据+状态)
- 流管道:用于批量、中断、同步传输,数据没有固定结构,就是纯数据流
我记得第一次看USB协议栈源码时,看到“pipe”这个变量名,以为是水管的意思。后来才明白,它就是端点在主机侧的“代理”。你往管道里写数据,数据就通过USB总线到达对应的端点。
注意:管道是单向的。一个IN端点对应一条IN管道,一个OUT端点对应一条OUT管道。端点0虽然是双向的,但在主机侧它对应两条管道(控制IN管道和控制OUT管道)。
3.4 四种传输类型——各司其职
USB协议定义了四种传输类型,每种都有特定的应用场景。我按自己的理解给你捋一遍。
3.4.1 控制传输(Control Transfer)
这是USB的“官方语言”。所有设备都必须支持。用于枚举、配置、获取描述符等。控制传输分三个阶段:Setup阶段(发请求)、Data阶段(可选,传数据)、Status阶段(确认结果)。
我在项目中遇到过:设备枚举时,主机发Get Descriptor请求,设备返回的描述符长度不对,导致枚举失败。后来发现是描述符里的bLength字段写错了。控制传输对数据格式要求非常严格,一个字节都不能错。
3.4.2 批量传输(Bulk Transfer)
用于大数据量传输,比如U盘读写、打印机。批量传输没有带宽保证,但保证数据正确(有CRC校验和重传)。USB协议会利用空闲带宽来传批量数据,所以总线忙时批量传输会变慢。
我曾经调一个U盘驱动,写数据时速度忽快忽慢。后来发现是批量传输的缓冲区没对齐,导致HAL库底层做了额外的内存拷贝。改成4字节对齐后,速度就稳定了。
3.4.3 中断传输(Interrupt Transfer)
别被名字骗了,它不是硬件中断。中断传输是主机定期轮询设备,看有没有数据要传。用于鼠标、键盘、游戏手柄等需要低延迟的设备。全速模式下,中断传输的轮询间隔可以设为1ms~255ms。
嗯,这里要注意:中断传输保证延迟(主机保证在指定间隔内轮询),但不保证带宽。如果总线忙,轮询可能被推迟。
3.4.4 同步传输(Isochronous Transfer)
用于音视频等实时数据流。同步传输没有重传机制,丢包就丢了,但保证带宽和固定延迟。比如USB麦克风,数据必须实时传输,偶尔丢一帧人耳听不出来,但如果重传导致延迟,声音就卡顿了。
| 传输类型 | 应用场景 | 错误重传 | 带宽保证 | 延迟保证 |
|---|---|---|---|---|
| 控制 | 枚举、配置、命令 | 是 | 10%(保留) | 无 |
| 批量 | U盘、打印机 | 是 | 无(用空闲带宽) | 无 |
| 中断 | 鼠标、键盘 | 是 | 无 | 有(轮询间隔) |
| 同步 | 音频、视频 | 否 | 有 | 有 |
选型建议:做USB设备时,先想清楚你的数据是什么类型。如果是命令/状态,用控制传输;如果是大块数据,用批量传输;如果是周期性小数据,用中断传输;如果是实时流,用同步传输。选错了,轻则性能差,重则设备无法正常工作。
3.5 知识结构图
下面这张图把USB主机、设备、端点、管道和传输类型的关系串起来了。我建议你多看几遍,把这张图印在脑子里。
这张图从左到右看:主机通过管道与设备的端点通信。管道是逻辑通道,端点是物理出入口。每种传输类型对应不同的应用场景,选型时一定要匹配好。
3.6 小结
这一节我们讲了USB协议最核心的几个概念。主机是老大,设备是小弟。端点是设备内部的数据出入口,管道是主机到端点的逻辑通道。四种传输类型各有各的脾气,选错了会出大问题。