当前位置: 首页 > news >正文

USB基础 -- USB2.0设备插入的过程

“USB2.0 设备插入后,主机侧从硬件信号令牌(Token)层的完整过程”按时间线拆开讲清楚。为了便于实现/调试,把每一步的电气线状态(D+/D-)、主机/Hub 的动作、以及紧接着发生的令牌级事务都写在一起,并给出典型时序与数据包结构。

一、物理层:插入→检测→复位→速度判定

1) 线缆插入与上电(Attach/Powered)

  • VBUS:主机/Hub 端口向下游供电(约 5V),设备上电。

  • 下拉/上拉电阻

    • 主机/Hub 端口:D+、D- 各有 15 kΩ 下拉到 GND。

    • 设备:

      • 全速(FS, 12 Mb/s)/高速(HS, 480 Mb/s)设备初始表现为 FS:在 D+ 上拉 1.5 kΩ 到 3.3V
      • 低速(LS, 1.5 Mb/s)设备:在 D- 上拉 1.5 kΩ 到 3.3V
  • 连接去抖(Debounce):Hub 监测到某条线持续为“J 状态”达到去抖时间后,判断有设备接入。

    • FS/HS 设备接入 → D+ 为高、D- 为低(J 状态(FS 视角))。
    • LS 设备接入 → D- 为高、D+ 为低(J 状态(LS 视角))。

线状态速查

  • J/K 状态:差分逻辑电平,FS/LS 的定义相反:

    • FS 视角:J= D+高/D-低;K= D+低/D-高
    • LS 视角:J= D-高/D+低;K= D-低/D+高
  • SE0:D+、D- 同时为低

  • SE1:D+、D- 同时为高(非法)

2) 端口复位(Reset → Default)

  • Hub 报告“连接”后,主机对该端口发起复位:把总线驱到 SE0(D+、D- 都低)持续 ≥10 ms(常见实现 10–20 ms)。
  • 设备看到 SE0 复位,进入 Default 状态,地址=0,**端点0(EP0)**处于就绪(控制传输)。

3) 高速协商(HS Chirp,若设备支持 HS)

只有 HS 设备才会进行。不支持 HS 的设备保持 FS/LS。

  1. 复位末尾,主机仍保持 SE0;HS 设备开始向主机发送“Chirp K”(在 FS 视角下的 K:D-高、D+低)。
  2. 主机检测到设备 Chirp K 后,回送交替的 K/J 脉冲序列(至少 3 对 KJ)
  3. 设备检测到足够的 KJ 对,切换到 HS 终端与驱动(差分 45 Ω 终端、电流模驱动),链路进入 High-Speed(480 Mb/s)
  4. 若主机未回 Chirp KJ,设备保持 FS

结果:

  • HS 成功 → 之后主机以 125 μs 微帧调度(SOF/微帧 SOF)。
  • FS/LS → 之后主机以 1 ms 帧调度(SOF)。

4) 空闲(Idle)/SOF 启动

  • 复位结束后,主机开始发 SOF(Start Of Frame)记时:

    • FS:每 1 ms 一个 SOF Token(帧号递增)。
    • HS:每 125 μs 一个微帧 SOF Token(微帧号 0–7)。

二、枚举起点:从“地址 0、端点 0”的控制传输开始

控制传输(EP0)三阶段:SETUP → DATA(可选,读/写方向)→ STATUS(0 字节、反向)
令牌层(Token/Data/Handshake)上,每个**事务(Transaction)**都由“Token 包 +(可选)Data 包 +(可选)Handshake 包”组成。

包结构速查

  • SYNC(位同步,NRZI 编码+位填充)
  • PID(8 bit,低 4 位为类型,高 4 位为其反码)
  • Token 包(IN/OUT/SETUP/SOF):PID(8) + ADDR(7) + ENDP(4) + CRC5(5)(SOF 用 FrameNum(11)+CRC5)
  • Data 包(DATA0/DATA1/DATA2/MDATA):PID(8) + Payload(0..N) + CRC16(16)
  • Handshake 包(ACK/NAK/STALL/NYET):PID(8)
  • EOP(包结束,SE0 ~2 bit time + J)

数据切换位(Data Toggle):控制读写的 DATA0/DATA1 翻转规则在枚举时尤为重要(见下文示例)。


三、主机侧令牌层:典型的两笔枚举起始事务

以下按令牌级展开两个最关键的控制读事务(以 FS 为例;HS 相同只是速率/微帧不同):

事务 A:读取前 8 字节设备描述符(Get Descriptor, first 8B)

目的:探测 bMaxPacketSize0(EP0 的最大包长),决定后续控制传输的分段。

  1. SETUP 阶段(Host → Dev)
  • TokenSETUPADDR=0, ENDP=0
  • DataDATA0,8 字节 Setup 请求体:
    bmRequestType=80h (IN, Standard, Device)
    bRequest=GET_DESCRIPTOR (0x06)
    wValue=(DEVICE<<8) | 0
    wIndex=0
    wLength=64(主机想读最多 64 字节,但先读 8 字节以确定 MPS0)
  • Handshake:设备 ACK
  1. DATA 阶段(Dev → Host,控制读)
  • TokenIN,ADDR=0, EP0
  • Data:设备回 DATA1仅 8 字节(前 8 Byte 的 Device Descriptor,含 bMaxPacketSize0
  • Handshake:主机 ACK
  1. STATUS 阶段(Host → Dev,反向 0B)
  • TokenOUT,ADDR=0, EP0
  • DataDATA1零长度包(ZLP)
  • Handshake:设备 ACK

要点

  • 控制读里,数据阶段方向为 IN状态阶段为 OUT ZLP
  • SETUP 数据包固定使用 DATA0,随后的数据阶段从 DATA1 起始
  • 此时主机已经知道 EP0 的 bMaxPacketSize0(常见 8/16/32/64)

事务 B:设置地址(SET_ADDRESS)

目的:把设备从默认地址 0 切到 新地址 N(1…127)

  1. SETUP 阶段(Host → Dev)
  • TokenSETUP,ADDR=0, EP0
  • DataDATA0,8 字节 Setup:
    bmRequestType=00h (OUT, Standard, Device)
    bRequest=SET_ADDRESS (0x05)
    wValue=N
    wIndex=0
    wLength=0
  • Handshake:设备 ACK
  1. STATUS 阶段(Dev → Host,反向 0B)
  • TokenIN,ADDR=0, EP0
  • Data:设备发 ZLP(DATA1)
  • Handshake:主机 ACK

要点

  • 地址切换状态阶段的 ACK 后生效。之后主机对该设备一律用 ADDR=N 访问。
  • 随后主机会用新地址继续 Get_Descriptor(Device)(本次可按 MPS0 分段读取完整 18 字节),再 Get_Descriptor(Configuration) 等,直至 Set_Configuration

四、更多主机侧“令牌级”细节(你实现/抓包时会用到)

  1. SOF/SOF 微帧
  • FS:每 1 ms 发一次 SOF TokenPID=SOF + FrameNumber(11) + CRC5),用于全总线时间基准与带宽预算
  • HS:每 125 μs 发一次 微帧 SOF(帧号与微帧索引)。等时/中断端点在主机调度里按(微)帧精确分配时隙。
  1. 控制传输的数据切换位
  • SETUP 数据包总用 DATA0
  • 随后的 数据阶段第一个数据包用 DATA1,之后在同一个控制传输内按规则交替;
  • 状态阶段:始终用 对端方向的 0 字节包(常见实现中对端一般用 DATA1 作为状态 ZLP)。
  1. 握手(Handshake)
  • ACK:正确接收且 CRC 正确;
  • NAK:暂时无数据或未就绪(主机可重试,常见在中断/批量端点);
  • STALL:功能不支持或需要清错(主机可能发 ClearFeature(Halt) 恢复);
  • NYET/PING:高速优化用语义(大多与 Bulk OUT 的缓冲/分组交互相关)。
  1. 编码与位填充
  • NRZI:数据“0”触发电平翻转,“1”保持;
  • 位填充:连续 6 个“1” 后插入一个“0”避免丢失时钟;
  • EOP:包末尾强制 SE0 ~2 bit time 再回到 J(空闲)。
  1. 端口复位与清空数据切换
  • 每次 总线复位 会把控制端点的 Data Toggle 复位(EP0 回到初始),这点在你实现栈重连或错误恢复时要注意。
  1. 速度对应的帧与带宽感知
  • LS:受 Hub 事务转换(Split/TT)限制,主机通过上游 Hub 进行低速分时通道调度;
  • FS/HS:主机直接调度;HS 里等时传输可在每微帧获得更高吞吐与更低抖动。

五、把“抓包视角”与“实现视角”对齐

  • 抓包/分析(Wireshark + USBPcap / Beagle):你会看到上面的 Token→Data→Handshake 三段式序列,PID/ADDR/ENDP/CRC 明确可见。

  • 主机栈实现(比如 xHCI/EHCI/OHCI + 类驱动):

    • 复位/速度枚举由 Host Controller 驱动(HCD)与 Hub 驱动协作完成(端口电源、复位、启用、速度寄存器读取);
    • 令牌级调度由 HCD 的传输描述符(TD/TRB)队列下发,遵循 SOF/微帧时隙;
    • 类驱动(HID/CDC/UVC/MSC… 在 EP0 完成 SetAddress/获取描述符/SetConfig 后,按配置的端点类型提交 URB(中断/批量/等时)即可。

六、总结(实现检查清单)

  1. 电气检测:D+/D- 上拉判速(FS/LS)→ 端口去抖。

  2. 端口复位:SE0 ≥10 ms → 设备进入 Default。

  3. HS 协商(可选):设备 Chirp K → 主机 KJ 对 → 切到 HS 或保持 FS。

  4. SOF/微帧启动:提供调度基准。

  5. 控制传输(EP0)

    • Get_Descriptor(前 8B) → 确定 bMaxPacketSize0
    • Set_Address(状态阶段后生效)
    • 完整 Get_Descriptor(Device/Config/String…) + Set_Configuration
  6. 后续端点:根据配置进行中断/批量/等时端点的 Token/Data/Handshake 调度;留意 NAK/STALL/NYET数据切换位

http://www.lryc.cn/news/619790.html

相关文章:

  • 6 .循环-for
  • MySQL 到 ClickHouse 明细分析链路改造:数据校验、补偿与延迟治理
  • 3.9开发前端常用的几个工具(nvm,json-server,nrm)
  • 力扣top100(day02-05)--二叉树 02
  • 职场与生活如何在手机中共存?(二)
  • AI驱动的政策博弈分析:特与鲍威尔的降息争议及市场响应
  • hadoop 前端yarn查看
  • 体制内程序员证书扫盲(中国内地)
  • 30 HTB Soccer 机器 - 容易
  • Qt中实现OpenGL应用的编程框架
  • 简易路径调试工具
  • C++ 面向对象四大特性:面试深度解析
  • 河南萌新联赛2025第五场 - 信息工程大学
  • 从内核数据结构的角度理解socket
  • 9 ABP Framework 中的 MVC 和 Razor Pages
  • SpringMVC 6+源码分析(六)参数处理
  • 基于R语言的现代贝叶斯统计学方法(贝叶斯参数估计、贝叶斯回归、贝叶斯计算实践过程
  • Datawhale AI夏令营第三期多模态RAG方向 Task3
  • 算法详细讲解 - 离散化/区间合并
  • 【慕伏白】Kali 系统下安装 docker
  • 弹性扩展新范式:分布式LLM计算的FastMCP解决方案
  • Python(二):MacBook安装 Python并运行第一个 Python 程序
  • 【QT】QT实现鼠标左右滑动切换图片
  • MySQL中的缓存机制
  • 如何在VS里使用MySQL提供的mysql Connector/C++的debug版本
  • 如何把ubuntu 22.04下安装的mysql 8 的 数据目录迁移到另一个磁盘目录
  • 设计模式笔记_行为型_策略模式
  • OpenJDK 17 源码 安全点轮询的信号处理流程
  • 资源查看-lspci命令
  • 如何准备一场技术演讲