5.24 USB设备
5.24 USB设备
📚 本节导读
学习时长: 约 45 分钟
难度级别: ⭐⭐⭐⭐⭐
前置知识: C 语言基础、USB 协议基础、5.1 设备驱动框架
🎯 学习目标
- 理解 OneOS 中 TinyUSB 协议栈的集成架构
- 理解 OSAL(操作系统抽象层)在 TinyUSB 中的作用
- 掌握 USB 设备模式(Device)的配置与使用
- 掌握 USB 主机模式(Host)的配置与使用
- 了解 CDC、HID、MSC 等 USB 类驱动
一、概述
OneOS 集成了 TinyUSB 开源 USB 协议栈,提供完整的 USB 设备(Device)和主机(Host)功能。驱动源码位于 drivers/tinyusb/ 和 drivers/usb/ 目录下。TinyUSB 是一个轻量级的开源 USB 主机/设备库,专为嵌入式系统设计,通过 OSAL(操作系统抽象层)与 OneOS 内核无缝集成。
TinyUSB 的特点:
- 双模支持:同时支持 USB Device 和 USB Host 模式
- OSAL 集成:通过 osal_task_delay、osal_mutex 等 OSAL 接口与 OneOS 内核对接
- 多类驱动:支持 CDC(虚拟串口)、HID(人机接口)、MSC(大容量存储)、DFU(固件升级)等
- 模块化设计:分离设备、主机、各类驱动的实现,按需编译
- 事件驱动:基于事件处理机制进行通信和数据传输
二、TinyUSB 架构
2.1 整体架构
┌─────────────────────────────────────────────────────┐ │ 应用层 │ │ (CDC读写 / HID报告 / MSC文件操作) │ ├─────────────────────────────────────────────────────┤ │ TinyUSB 协议栈 (tusb) │ │ ┌──────────┬──────────┬──────────┬──────────┐ │ │ │ CDC │ HID │ MSC │ DFU │ │ │ │ 类驱动 │ 类驱动 │ 类驱动 │ 类驱动 │ │ │ ├──────────┴──────────┴──────────┴──────────┤ │ │ │ USB Device / Host 核心 │ │ │ ├───────────────────────────────────────────┤ │ │ │ OSAL 适配层 (OneOS) │ │ │ │ mutex / queue / task_delay / ... │ │ │ └───────────────────────────────────────────┘ │ ├─────────────────────────────────────────────────────┤ │ OneOS 内核 (mutex/queue/sem) │ ├─────────────────────────────────────────────────────┤ │ MCU USB 外设 (DWC2 / FSDEV) │ └─────────────────────────────────────────────────────┘
2.2 OSAL 适配层
TinyUSB 通过 OSAL 层屏蔽不同 RTOS 的差异,OneOS 的适配实现将 TinyUSB 所需的内核服务映射到 OneOS API:
| TinyUSB OSAL 接口 | OneOS 实现 |
|---|---|
| osal_mutex_create() | os_mutex_create() |
| osal_mutex_lock() | os_mutex_lock() |
| osal_mutex_unlock() | os_mutex_unlock() |
| osal_queue_create() | os_mq_create() |
| osal_queue_send() | os_mq_send() |
| osal_queue_receive() | os_mq_recv() |
| osal_task_delay() | os_task_msleep() |
三、关键 API
3.1 TinyUSB 初始化
c bool tusb_init(void);
初始化 TinyUSB 协议栈,包括设备栈和主机栈。
3.2 设备模式任务
c void tud_task(void);
USB 设备模式任务函数,需要在任务中周期性调用。处理设备枚举、控制传输、类请求等。
3.3 主机模式任务
c void tuh_task(void);
USB 主机模式任务函数,需要在任务中周期性调用。处理设备检测、枚举、数据传输等。
3.4 设备模式 API
`c
/* 检查设备是否已配置 */
bool tud_mounted(void);
/* 检查设备是否挂起 */
bool tud_suspended(void);
/* 远程唤醒主机 */
void tud_remote_wakeup(void);
`
3.5 CDC 类 API
`c
/* CDC 已连接 */
bool tud_cdc_connected(void);
/* CDC 可用字节数 */
uint32_t tud_cdc_available(void);
/* CDC 读取数据 */
uint32_t tud_cdc_read(void *buffer, uint32_t bufsize);
/* CDC 读取一个字符 */
char tud_cdc_read_char(void);
/* CDC 写入数据 */
uint32_t tud_cdc_write(const void *buffer, uint32_t bufsize);
/* CDC 写入一个字符 */
uint32_t tud_cdc_write_char(char ch);
/* CDC 刷新发送缓冲区 */
void tud_cdc_write_flush(void);
`
3.6 HID 类 API
`c
/* 检查 HID 是否就绪 */
bool tud_hid_ready(void);
/* 发送 HID 报告 */
bool tud_hid_report(uint8_t report_id, const void *report, uint16_t len);
`
3.7 主机模式 API
`c
/* 检查设备是否已连接 */
bool tuh_mounted(uint8_t dev_addr);
/* 检查设备是否已断开 */
bool tuh_vid_pid_get(uint8_t dev_addr, uint16_t *vid, uint16_t *pid);
`
四、Kconfig 配置
`kconfig
启用 TinyUSB
config OS_USING_TINYUSB
bool "Enable TinyUSB"
default n
设备模式
config OS_USING_TINYUSB_DEVICE
bool "USB Device Mode"
depends on OS_USING_TINYUSB
主机模式
config OS_USING_TINYUSB_HOST
bool "USB Host Mode"
depends on OS_USING_TINYUSB
CDC 类
config OS_USING_TINYUSB_CDC
bool "CDC Class (Virtual COM Port)"
depends on OS_USING_TINYUSB_DEVICE
HID 类
config OS_USING_TINYUSB_HID
bool "HID Class"
depends on OS_USING_TINYUSB_DEVICE
MSC 类
config OS_USING_TINYUSB_MSC
bool "MSC Class (Mass Storage)"
depends on OS_USING_TINYUSB_DEVICE
`
五、使用示例
5.1 USB CDC 虚拟串口(设备模式)
`c
#include <tusb.h>
#include <os_task.h>
/* USB Device 任务 */
void usb_device_task(void arg)
{
/ 初始化 TinyUSB */
tusb_init();
while (1)
{
/* 周期性调用设备任务 */
tud_task();
/* 检查 CDC 连接状态 */
if (tud_cdc_connected())
{
/* 读取上位机发送的数据 */
if (tud_cdc_available())
{
uint8_t buf[64];
uint32_t count = tud_cdc_read(buf, sizeof(buf));
/* 回显数据 */
tud_cdc_write(buf, count);
tud_cdc_write_flush();
}
}
os_task_msleep(1);
}
}
`
5.2 USB HID 键盘示例
`c
#include <tusb.h>
#include <os_task.h>
/* HID 键盘报告描述符 */
static const uint8_t desc_hid_report[] = {
TUD_HID_REPORT_DESC_KEYBOARD(HID_REPORT_ID(HID_REPORT_ID_KEYBOARD))
};
/* 发送按键 */
void hid_send_key(uint8_t modifier, uint8_t keycode)
{
if (!tud_hid_ready())
return;
/* 按键按下 */
uint8_t report[8] = {modifier, 0, keycode, 0, 0, 0, 0, 0};
tud_hid_report(HID_REPORT_ID_KEYBOARD, report, sizeof(report));
os_task_msleep(10);
/* 按键释放 */
memset(report, 0, sizeof(report));
tud_hid_report(HID_REPORT_ID_KEYBOARD, report, sizeof(report));
}
void hid_task(void *arg)
{
tusb_init();
while (1)
{
tud_task();
/* 每秒发送一次 'A' 键 */
hid_send_key(0, HID_KEY_A);
os_task_msleep(1000);
}
}
`
5.3 USB Host 模式检测设备
`c
#include <tusb.h>
#include <os_task.h>
void usb_host_task(void *arg)
{
tusb_init();
while (1)
{
/* 周期性调用主机任务 */
tuh_task();
/* 检测设备连接 */
for (uint8_t addr = 1; addr <= 127; addr++)
{
if (tuh_mounted(addr))
{
uint16_t vid, pid;
tuh_vid_pid_get(addr, &vid, &pid);
os_kprintf("USB device: VID=0x%04x PID=0x%04x\r\n", vid, pid);
}
}
os_task_msleep(10);
}
}
`
📝 本节小结
本节介绍了 OneOS 中 USB/TinyUSB 设备驱动的使用方法,包括:
- TinyUSB 架构:OSAL 适配层 → USB 核心 → 类驱动(CDC/HID/MSC/DFU)→ 应用层
- OSAL 集成:通过 mutex、queue、task_delay 等 OSAL 接口与 OneOS 内核对接
- 双模支持:同时支持 USB Device 和 USB Host 模式
- CDC 虚拟串口: ud_cdc_read/write 实现与上位机的串口通信
- HID 人机接口: ud_hid_report 发送键盘/鼠标/自定义报告
- Kconfig 配置:按需启用设备模式、主机模式、各类驱动
TinyUSB 是 OneOS 推荐的 USB 解决方案,适用于需要 USB 通信的嵌入式 IoT 设备。