2. USB协议基础与emUSB架构总览
USB 2.0 设备通信的核心并不在于“插上线就能用”,而在于主机与设备之间一套严格分层的逻辑结构。理解这套结构,是读懂 emUSB Device 配置宏与回调机制的前提。本节先梳理端点、管道、传输类型、描述符与枚举这几个基础概念,再剖析 emUSB Device 的分层架构与核心组件。
端点、管道与传输类型
端点(Endpoint)是设备侧可被主机寻址的最小通信单元,它由“端点号 + 方向”唯一确定。方向以主机为参照:IN 表示设备到主机,OUT 表示主机到设备。端点 0 是默认控制端点,必须双向存在,用于枚举和标准请求。除端点 0 外,其余端点都需要在配置描述符中声明,并由主机在配置阶段分配带宽。
管道(Pipe)是主机侧对“端点 + 传输类型 + 服务间隔”的抽象。设备开发者关心端点,主机驱动关心管道,两者一一对应。USB 2.0 定义了四种传输类型,它们的取舍直接决定端点参数:
- 控制传输:用于枚举、标准请求和类请求,保证送达但不保证带宽,固定使用端点 0。
- 批量传输:用于大数据量、可容忍延迟的场景,如大容量存储、CDC 数据口,具备错误重传,不预留带宽。
- 中断传输:用于小数据量、有周期上限的场景,如 HID 键盘、鼠标,主机保证在指定间隔内轮询。
- 等时传输:用于音视频等实时流,预留带宽、保证时序,但不重传,出错即丢包。
以全速设备为例,批量端点最大包长为 8/16/32/64 字节,中断端点为 1~64 字节,等时端点可达 1023 字节。这些数值不是随意填写,而是描述符中 wMaxPacketSize 字段的合法取值,写错会导致主机拒绝配置。
描述符与枚举过程
描述符是设备向主机“自我介绍”的结构化数据,按层级组织:设备描述符描述整体身份(VID、PID、设备类、端点 0 包长);配置描述符描述一种供电与接口组合;接口描述符描述功能单元(如 CDC 控制接口、数据接口);端点描述符描述每个端点的地址、类型、包长与轮询间隔。字符串描述符则提供厂商、产品等可读信息。
枚举是主机读取这些描述符并分配地址、加载驱动的过程。典型顺序为:主机复位设备 → 通过端点 0 读取设备描述符前 8 字节获取端点 0 包长 → 再次读取完整设备描述符 → 设置地址 → 读取配置描述符(含接口与端点)→ 选择配置 → 若设备类为 0 则加载对应类驱动。整个过程全部走控制传输,任何一步描述符长度或校验出错,枚举都会失败。
emUSB Device 分层架构
emUSB Device 把上述协议细节封装成四层结构,自下而上依次是:硬件/驱动层、核心层、类驱动层和应用层。
硬件/驱动层负责与具体 USB 控制器交互,包括端点 FIFO 读写、中断处理、DMA 搬运。SEGGER 为不同 MCU 提供对应的 USB 驱动,开发者通常只需在配置中选择目标器件,无需改动这一层。
核心层是 emUSB Device 的中枢,承担枚举响应、标准请求处理、端点管理与传输调度。它维护设备状态机(Attached、Powered、Default、Address、Configured),并根据描述符表自动应答主机请求。核心层还提供 USBD_Init()、USBD_Start() 等入口,以及端点读写 API,如 USBD_Write()、USBD_Read()。
类驱动层实现具体 USB 类协议,如 CDC、HID、MSC、Audio。每个类驱动向核心层注册自己的接口与端点,并处理类请求。例如 CDC 类驱动会注册一个控制接口和一个数据接口,数据接口使用两个批量端点。
应用层调用类驱动暴露的 API 完成业务逻辑,例如通过 CDC 发送串口数据、通过 MSC 读写存储扇区。应用层不直接操作端点,而是通过类驱动间接使用管道。
核心组件与配置宏
emUSB Device 的配置集中在 USBD_Config.c 与 USBD_Config.h 中。关键配置宏包括:
- USBD_MAX_NUM_ENDPOINTS:设备支持的最大端点数,需与硬件能力匹配。
- USBD_MAX_NUM_INTERFACES:最大接口数,决定可同时启用的类驱动数量。
- USBD_MAX_NUM_CONFIGURATIONS:配置数量,多数设备为 1。
- USBD_DEBUG_LEVEL:调试输出等级,排障时可调高。
- USBD_USE_HIGH_SPEED:是否启用高速模式,需硬件支持。
类驱动通过 USBD_AddDriver() 注册,核心层在枚举时按注册顺序匹配接口。以 CDC 为例,注册后核心层会自动把 CDC 的接口描述符、端点描述符拼入配置描述符,主机读取时即可看到完整层级。
一个最小配置示例
假设使用某 Cortex-M4 器件,硬件支持 6 个端点、全速模式,仅启用 CDC 类。配置可写为:
#define USBD_MAX_NUM_ENDPOINTS 6
#define USBD_MAX_NUM_INTERFACES 2
#define USBD_MAX_NUM_CONFIGURATIONS 1
#define USBD_USE_HIGH_SPEED 0
#define USBD_DEBUG_LEVEL 1
CDC 需要 1 个控制接口 + 1 个数据接口,共 2 个接口;数据接口使用 1 个 IN 批量端点和 1 个 OUT 批量端点,加上端点 0,共 3 个端点,6 个端点的上限留有扩展余地。编译后通过 USBD_Init() 初始化,USBD_Start() 启动,主机枚举成功后可在设备管理器中看到 CDC 串口。若枚举失败,优先检查描述符总长度是否与 USBD_MAX_NUM_INTERFACES 一致,以及端点地址是否与硬件 FIFO 分配冲突。