4. USB 设备状态机:连接、上电、默认、地址、配置、挂起状态转换图

USB 设备的生命周期由一套严格定义的状态机管理。从物理连接到功能可用,设备必须依次经历 连接 (Attached)、上电 (Powered)、默认 (Default)、地址 (Address)、配置 (Configured) 五个核心状态,并可在任意时刻因总线空闲进入 挂起 (Suspended) 状态。理解这套状态机是掌握 USB 枚举流程的基石。

核心要点: 状态转换由主机发起的总线事件(复位、SETUP 事务、帧起始包)驱动,设备端被动响应。任何一步失败都会导致枚举终止或设备不被识别。

4.1 状态定义与转换条件

下表列出了 USB 2.0 规范定义的 6 个设备状态及其触发条件:

状态 触发条件 设备行为 主机视角
连接 (Attached) 设备插入 USB 端口 D+/D- 线上拉电阻生效,产生电平变化 检测到端口电平变化,准备供电
上电 (Powered) 主机为端口提供 VBus (5V) 内部电路上电,等待复位信号 端口已供电,等待设备稳定
默认 (Default) 主机发送复位信号 (SE0 ≥ 10ms) 复位结束后响应默认地址 0,等待主机请求 复位结束,开始枚举流程
地址 (Address) 主机发送 SET_ADDRESS 请求 分配唯一地址,后续通信使用新地址 设备有了唯一标识,可进行配置
配置 (Configured) 主机发送 SET_CONFIGURATION 请求 加载配置描述符,功能可用 设备功能就绪,可进行数据传输
挂起 (Suspended) 总线空闲 ≥ 3ms 进入低功耗模式,保留地址和配置 总线进入暂停状态,可唤醒

4.2 状态转换流程图

下图展示了 USB 设备状态机的完整转换路径,箭头上的标注为触发事件:

USB 设备状态机转换图 USB 设备状态机转换图 连接 (Attached) 上电 (Powered) 默认 (Default) 地址 (Address) 配置 (Configured) 挂起 (Suspended) VBus 供电 复位 (SE0 ≥ 10ms) SET_ADDRESS SET_CONFIGURATION 总线空闲 ≥ 3ms 总线空闲 ≥ 3ms 总线空闲 ≥ 3ms 唤醒信号 唤醒信号 唤醒信号 状态转换说明 • 状态转换严格单向(除挂起) • 挂起可返回原状态(保留地址/配置) • 复位信号使设备回到默认状态 • 拔除设备回到连接状态

4.3 关键状态详解

4.3.1 默认状态与复位

设备上电后处于 上电状态,等待主机发送复位信号。主机通过将 D+ 和 D- 同时拉低至少 10ms(SE0 状态)来复位设备。复位结束后,设备进入 默认状态,此时:

  • 设备地址为 0(默认地址),所有设备共享此地址进行初始通信。
  • 设备响应主机在端点 0 上的控制传输请求。
  • 设备的最大包长度(MaxPacketSize0)已确定(通过读取设备描述符的前 8 字节)。
常见陷阱: 复位信号持续时间不足 10ms 可能导致设备无法正确识别。部分低速设备对复位时序要求更严格,主机必须保证 SE0 信号连续且稳定。

4.3.2 地址状态与 SET_ADDRESS

主机在获取设备描述符后,通过控制传输发送 SET_ADDRESS 请求,为设备分配一个唯一的 1~127 之间的地址。设备在收到请求后:

  1. 在状态阶段完成后立即切换到新地址。
  2. 后续所有通信(包括获取配置描述符)都使用新地址。
  3. 地址分配后,设备进入 地址状态,但此时尚未加载功能配置。
// SET_ADDRESS 请求格式(主机到设备)
// bmRequestType: 0x00 (主机到设备,标准请求,设备接收)
// bRequest:      0x05 (SET_ADDRESS)
// wValue:        新地址 (0x01 ~ 0x7F)
// wIndex:        0x0000
// wLength:       0x0000

// 示例:分配地址 0x12
// 令牌包: 0x00 0x05 0x0012 0x0000 0x0000
// 设备在状态阶段后切换到地址 0x12

4.3.3 配置状态与 SET_CONFIGURATION

主机读取所有配置描述符后,发送 SET_CONFIGURATION 请求,选择设备的某个配置(通常为配置 1)。设备进入 配置状态 后:

  • 加载所选配置下的所有接口和端点。
  • 功能接口(如 HID、Mass Storage、CDC)开始工作。
  • 设备可以开始进行批量、中断或同步传输。
调试技巧: 在逻辑分析仪上捕获 SET_CONFIGURATION 请求后,观察设备是否返回 ACK。如果设备返回 STALL,说明配置描述符解析失败或设备不支持该配置。

4.4 挂起与唤醒机制

当总线空闲超过 3ms 时,设备必须进入 挂起状态,以降低功耗。挂起状态下:

  • 设备保留当前地址和配置信息。
  • 设备电流消耗降至 500µA 以下(未配置时为 2.5mA)。
  • 设备可通过远程唤醒信号(Resume)或主机发起的复位信号退出挂起。

挂起状态是 USB 电源管理的关键,尤其在电池供电设备中。主机通过周期性发送 SOF(帧起始包) 来防止总线空闲超过 3ms,从而避免设备意外挂起。

4.5 状态机与枚举流程的对应关系

下表将状态机转换与枚举流程中的具体步骤对应起来,方便实战调试时定位问题:

枚举步骤 设备状态 主机操作 常见失败原因
1. 检测设备插入 连接 → 上电 检测 D+/D- 电平变化,提供 VBus 上拉电阻损坏、VBus 短路
2. 复位设备 上电 → 默认 发送 SE0 信号 ≥ 10ms 复位时序不足、设备未响应
3. 获取设备描述符 默认 发送 GET_DESCRIPTOR 请求 端点 0 未配置、MaxPacketSize0 错误
4. 分配地址 默认 → 地址 发送 SET_ADDRESS 请求 地址冲突、设备未 ACK
5. 获取配置描述符 地址 发送 GET_DESCRIPTOR (配置) 描述符长度错误、接口描述符缺失
6. 选择配置 地址 → 配置 发送 SET_CONFIGURATION 请求 配置值无效、设备 STALL
实战建议: 在调试枚举问题时,使用逻辑分析仪捕获总线上的复位信号和 SET_ADDRESS 请求。如果设备在复位后没有返回设备描述符,检查复位时序和端点 0 的最大包长度设置。如果 SET_ADDRESS 后设备无响应,检查地址分配是否与总线上的其他设备冲突。