返回首页

USB 设备驱动模型学习笔记

概述

Zephyr USB 设备栈提供了一个完整的 USB 设备端实现,支持多种 USB 类(HID、CDC、MSC、MIDI 等)。

当前 Zephyr 主线样例多数已经切到新的 USB device stack(CONFIG_USB_DEVICE_STACK_NEXT=y,运行时调用 usbd_enable());本文中涉及的 usb_enable() / usb_disable() 仍适合用来理解 legacy 栈模型,但属于旧接口。

USB 设备栈架构

┌─────────────────────────────────────────┐
│            应用程序层                     │
│  - USB HID 应用 / USB CDC 应用           │
├─────────────────────────────────────────┤
│            USB 类驱动                     │
│  - HID / CDC / MSC / MIDI / Audio       │
├─────────────────────────────────────────┤
│            USB 设备层                     │
│  - 枚举处理 / 标准请求 / 端点管理         │
├─────────────────────────────────────────┤
│            USB 控制器驱动                 │
│  - nRF52 / nRF53 / nRF54 USB 控制器      │
├─────────────────────────────────────────┤
│            硬件层                         │
│  - USB PHY / 端点硬件                     │
└─────────────────────────────────────────┘

核心组件

1. USB 设备控制器 (UDC)

#include <zephyr/drivers/usb/udc.h>

/* 获取 USB 控制器设备 */
const struct device *udc_dev = DEVICE_DT_GET(DT_NODELABEL(usbd));

/* 初始化 USB 控制器 */
int ret = udc_init(udc_dev, NULL);
if (ret != 0) {
    LOG_ERR("UDC init failed: %d", ret);
}

2. USB 设备栈

#include <zephyr/usb/usb_device.h>  // legacy
#include <zephyr/usb/usbd.h>        // current stack

/* 启用 USB 设备栈 */
int usb_enable(usb_dc_status_callback status_cb);

/* 禁用 USB 设备栈 */
int usb_disable(void);

/* 获取 USB 状态 */
enum usb_dc_status_code usb_get_status(void);

3. 状态回调

/* USB 状态变化回调 */
void usb_status_callback(enum usb_dc_status_code status, const uint8_t *param)
{
    switch (status) {
    case USB_DC_CONNECTED:
        LOG_INF("USB connected");
        break;
    case USB_DC_CONFIGURED:
        LOG_INF("USB configured - ready for communication");
        break;
    case USB_DC_DISCONNECTED:
        LOG_INF("USB disconnected");
        break;
    case USB_DC_SUSPEND:
        LOG_INF("USB suspended (low power mode)");
        break;
    case USB_DC_RESUME:
        LOG_INF("USB resumed from suspend");
        break;
    case USB_DC_RESET:
        LOG_INF("USB bus reset");
        break;
    case USB_DC_ERROR:
        LOG_ERR("USB error occurred");
        break;
    }
}

USB 枚举过程

枚举流程

主机                    设备
  │                      │
  ├──── 总线复位 ────────>│
  │                      │
  ├──── 获取设备描述符 ──>│
  │<──── 设备描述符 ─────┤
  │                      │
  ├──── 设置地址 ────────>│
  │                      │ (分配新地址)
  │                      │
  ├──── 获取配置描述符 ──>│
  │<──── 配置描述符 ─────┤
  │                      │
  ├──── 设置配置 ────────>│
  │                      │ (激活配置)
  │<──── ACK ────────────┤
  │                      │
  [设备枚举完成,可以传输数据]

标准请求处理

/* USB 标准请求 */
enum usb_request_type {
    USB_REQ_GET_STATUS = 0,
    USB_REQ_CLEAR_FEATURE = 1,
    USB_REQ_SET_FEATURE = 3,
    USB_REQ_SET_ADDRESS = 5,
    USB_REQ_GET_DESCRIPTOR = 6,
    USB_REQ_SET_DESCRIPTOR = 7,
    USB_REQ_GET_CONFIGURATION = 8,
    USB_REQ_SET_CONFIGURATION = 9,
    USB_REQ_GET_INTERFACE = 10,
    USB_REQ_SET_INTERFACE = 11,
    USB_REQ_SYNCH_FRAME = 12,
};

/* 描述符类型 */
enum usb_descriptor_type {
    USB_DESC_DEVICE = 1,
    USB_DESC_CONFIGURATION = 2,
    USB_DESC_STRING = 3,
    USB_DESC_INTERFACE = 4,
    USB_DESC_ENDPOINT = 5,
    USB_DESC_DEVICE_QUALIFIER = 6,
    USB_DESC_OTHER_SPEED = 7,
    USB_DESC_INTERFACE_POWER = 8,
    USB_DESC_OTG = 9,
};

USB 传输

传输类型

类型用途特点
控制 (Control)枚举、配置可靠、双向
中断 (Interrupt)HID、小数据量定期轮询、低延迟
批量 (Bulk)大容量存储可靠、带宽保证
等时 (Isochronous)音频、视频实时、无重传

端点操作

/* 写入端点 (IN 传输到主机) */
int usb_write(uint8_t ep, const uint8_t *data, uint32_t data_len, uint32_t *bytes_ret);

/* 读取端点 (OUT 传输从主机) */
int usb_read(uint8_t ep, uint8_t *data, uint32_t max_data_len, uint32_t *ret_bytes);

/* 设置端点回调 */
void usb_set_endpoint_callback(uint8_t ep, usb_ep_callback cb);

端点配置

/* 端点配置结构 */
struct usb_ep_cfg_data {
    uint8_t ep_addr;           /* 端点地址 */
    uint16_t ep_mps;           /* 最大包大小 */
    usb_ep_callback ep_cb;     /* 回调函数 */
};

/* 端点地址格式 */
#define USB_EP_DIR_MASK     0x80
#define USB_EP_DIR_IN       0x80
#define USB_EP_DIR_OUT      0x00

#define USB_EP_NUM_MASK     0x0F

/* 示例:端点地址 */
#define EP_IN_ADDR  0x81   /* 端点 1 IN */
#define EP_OUT_ADDR 0x01   /* 端点 1 OUT */

配置 USB 设备栈

基础配置

# 当前样例主线
CONFIG_USB_DEVICE_STACK_NEXT=y

# legacy 栈
# CONFIG_USB_DEVICE_STACK=y

# USB 设备信息
CONFIG_USB_DEVICE_VID=0x2FE3
CONFIG_USB_DEVICE_PID=0x0100
CONFIG_USB_DEVICE_MANUFACTURER="MyCompany"
CONFIG_USB_DEVICE_PRODUCT="MyDevice"
CONFIG_USB_DEVICE_SN="1234567890"

# USB 日志
CONFIG_USB_DRIVER_LOG_LEVEL_INF=y
CONFIG_USB_DEVICE_LOG_LEVEL_INF=y

多配置支持

# 支持多个配置
CONFIG_USB_DEVICE_CONFIGURATION_COUNT=2

# 支持远程唤醒
CONFIG_USB_DEVICE_REMOTE_WAKEUP=y

# 支持自供电
CONFIG_USB_DEVICE_SELF_POWERED=y

完整示例

简单 USB 设备

#include <zephyr/kernel.h>
#include <zephyr/usb/usb_device.h>
#include <zephyr/logging/log.h>

LOG_MODULE_REGISTER(usb_demo, LOG_LEVEL_INF);

/* USB 状态回调 */
static void usb_status_cb(enum usb_dc_status_code status, const uint8_t *param)
{
    ARG_UNUSED(param);
    
    switch (status) {
    case USB_DC_CONFIGURED:
        LOG_INF("USB configured");
        break;
    case USB_DC_DISCONNECTED:
        LOG_INF("USB disconnected");
        break;
    default:
        break;
    }
}

void main(void)
{
    int ret;
    
    LOG_INF("USB Device Demo");
    
    /* 启用 USB */
    ret = usb_enable(usb_status_cb);
    if (ret != 0) {
        LOG_ERR("USB enable failed: %d", ret);
        return;
    }
    
    LOG_INF("USB device ready");
    
    while (1) {
        k_sleep(K_SECONDS(1));
    }
}

调试技巧

USB 日志

CONFIG_USB_DRIVER_LOG_LEVEL_DBG=y
CONFIG_USB_DEVICE_LOG_LEVEL_DBG=y

Linux 调试

# 查看 USB 设备
lsusb
lsusb -v -d <VID>:<PID>

# 查看 USB 日志
dmesg | grep usb

# USB 抓包
sudo modprobe usbmon
sudo cat /sys/kernel/debug/usb/usbmon/0u

Windows 调试

常见问题

1. 设备不被识别

2. 枚举失败

3. 数据传输失败

参考链接


*学习笔记创建时间: 2026-03-19*