首页
/ 一文搞定Zephyr RTOS USB复合设备:CDC+MSC实战指南

一文搞定Zephyr RTOS USB复合设备:CDC+MSC实战指南

2026-02-05 05:10:08作者:魏侃纯Zoe

引言:为什么需要USB复合设备?

你是否曾遇到过嵌入式开发中"接口不够用"的困境?一个设备既要实现串口通信又要充当U盘,传统方案需要两个独立USB接口,而Zephyr RTOS的USB复合设备功能可以让单个USB端口同时提供CDC(虚拟串口)和MSC(大容量存储)两种功能,完美解决嵌入式设备接口资源紧张的痛点。本文将带你从零开始实现这一功能,只需简单配置即可让你的嵌入式设备秒变多功能USB设备。

USB复合设备原理

USB复合设备(Composite Device)允许一个USB设备同时实现多个独立功能,这些功能通过不同的接口(Interface)呈现给主机。在Zephyr RTOS中,这一功能通过USB设备控制器(UDC)驱动和复合设备框架实现,主要涉及以下核心组件:

准备工作

硬件要求

  • 支持USB设备模式的Zephyr开发板(如nRF52840 DK、STM32F4 Discovery等)
  • USB数据线
  • 电脑(Windows/macOS/Linux均可)

软件要求

实现步骤

1. 创建项目结构

在Zephyr项目中创建一个新的应用目录,结构如下:

usb_composite/
├── src/
│   └── main.c
├── boards/
│   └── <your_board>.overlay
├── prj.conf
└── CMakeLists.txt

2. 配置Kconfig选项

prj.conf中添加以下配置,启用USB复合设备、CDC ACM和MSC功能:

# 启用USB设备支持
CONFIG_USB_DEVICE=y
CONFIG_USB_DEVICE_STACK=y

# 启用CDC ACM功能
CONFIG_USB_CDC_ACM=y
CONFIG_USB_CDC_ACM_RINGBUF_SIZE=1024

# 启用MSC功能
CONFIG_USB_MASS_STORAGE=y
CONFIG_USB_MASS_STORAGE_DISK_NAME="RAM"

# 启用复合设备支持
CONFIG_USB_COMPOSITE_DEVICE=y

# 配置RAM磁盘(用于MSC存储)
CONFIG_DISK_DRIVER_RAM=y
CONFIG_DISK_RAM_SIZE=1048576  # 1MB RAM磁盘

3. 设备树配置

创建boards/<your_board>.overlay文件,配置USB节点和RAM磁盘:

/ {
    chosen {
        zephyr,console = &cdc_acm_uart0;
        zephyr,shell-uart = &cdc_acm_uart0;
    };

    cdc_acm_uart0: cdc_acm_uart {
        compatible = "zephyr,cdc-acm-uart";
        label = "CDC_ACM_0";
    };

    ramdisk0: ramdisk {
        compatible = "zephyr,ram-disk";
        label = "RAM_DISK";
        size = <1048576>;  /* 1MB */
    };
};

&usb0 {
    status = "okay";
    compatible = "zephyr,usb-device";
};

4. 编写应用代码

src/main.c中实现CDC数据回显和MSC存储初始化:

#include <zephyr/kernel.h>
#include <zephyr/device.h>
#include <zephyr/drivers/uart.h>
#include <zephyr/drivers/usb/usb_device.h>
#include <zephyr/drivers/usb/cdc_acm.h>
#include <zephyr/fs/fs.h>

/* CDC ACM设备 */
static const struct device *cdc_acm_dev = DEVICE_DT_GET(DT_CHOSEN(zephyr_cdc_acm_uart));

/* MSC存储设备 */
static const struct device *ramdisk = DEVICE_DT_GET(DT_NODELABEL(ramdisk0));

/* 接收缓冲区 */
static uint8_t rx_buf[1024];
static volatile bool data_received;

/* CDC ACM接收回调 */
static void cdc_acm_cb(const struct device *dev, struct cdc_acm_msg *msg, void *user_data)
{
    if (msg->type == CDC_ACM_MSG_RX_DONE) {
        data_received = true;
    }
}

void main(void)
{
    int ret;

    printk("USB复合设备(CDC+MSC)示例\n");

    /* 初始化RAM磁盘 */
    if (!device_is_ready(ramdisk)) {
        printk("RAM磁盘未就绪\n");
        return;
    }

    /* 初始化CDC ACM */
    if (!device_is_ready(cdc_acm_dev)) {
        printk("CDC ACM设备未就绪\n");
        return;
    }

    ret = cdc_acm_register_callback(cdc_acm_dev, cdc_acm_cb, NULL);
    if (ret < 0) {
        printk("注册CDC ACM回调失败: %d\n", ret);
        return;
    }

    ret = cdc_acm_set_receive(cdc_acm_dev, rx_buf, sizeof(rx_buf));
    if (ret < 0) {
        printk("设置CDC接收缓冲区失败: %d\n", ret);
        return;
    }

    /* 启动USB设备 */
    ret = usb_enable(NULL);
    if (ret < 0) {
        printk("USB初始化失败: %d\n", ret);
        return;
    }

    printk("USB复合设备启动成功\n");

    /* 主循环:处理CDC数据 */
    while (1) {
        if (data_received) {
            /* 回显接收到的数据 */
            cdc_acm_write(cdc_acm_dev, rx_buf, strlen(rx_buf));
            data_received = false;
            /* 重新开始接收 */
            cdc_acm_set_receive(cdc_acm_dev, rx_buf, sizeof(rx_buf));
        }
        k_sleep(K_MSEC(10));
    }
}

5. 构建与烧录

使用以下命令构建并烧录到目标开发板:

west build -b <your_board> usb_composite
west flash

测试验证

1. 连接设备

将开发板通过USB连接到电脑,系统应自动识别为复合设备,在Linux系统中可通过dmesg命令查看:

usb 2-1: new full-speed USB device number X using xhci_hcd
usb 2-1: New USB device found, idVendor=2fe3, idProduct=0100
usb 2-1: New USB device strings: Mfr=1, Product=2, SerialNumber=3
usb 2-1: Product: Zephyr CDC+MSC Composite
usb 2-1: Manufacturer: ZEPHYR
usb 2-1: SerialNumber: 0001
cdc_acm 2-1:1.0: ttyACM0: USB ACM device
scsi hostY: usb-storage 2-1:1.1
scsi Y:0:0:0: Direct-Access     ZEPHYR   RAM Disk        1.0  PQ: 0 ANSI: 0 CCS
sd Z: Z:0:0:0: [sdb] 2048 512-byte logical blocks: (1.05 MB/1.00 MiB)
sd Z: Z:0:0:0: [sdb] Write Protect is off
sd Z: Z:0:0:0: [sdb] Mode Sense: 03 00 00 00
sd Z: Z:0:0:0: [sdb] No Caching mode page found
sd Z: Z:0:0:0: [sdb] Assuming drive cache: write through
sd Z: Z:0:0:0: [sdb] Attached SCSI removable disk

2. 测试CDC功能

使用串口工具(如minicom、Putty)连接到虚拟串口(Linux通常为/dev/ttyACM0,Windows为COMx),设置波特率115200,发送任意字符,设备应回显相同内容。

3. 测试MSC功能

电脑应自动挂载1MB的RAM磁盘,你可以像使用普通U盘一样在其中创建、编辑和删除文件,所有操作会保存在设备的RAM中。

常见问题解决

问题1:设备无法枚举

解决方法

  • 检查USB硬件连接是否正常
  • 确认设备树中USB节点状态设置为"okay"
  • 验证Kconfig配置是否正确包含CONFIG_USB_DEVICE=y

问题2:MSC存储无法挂载

解决方法

  • 检查RAM磁盘大小配置是否正确
  • 确认CONFIG_DISK_DRIVER_RAM已启用
  • 查看设备启动日志,确认是否有磁盘初始化错误

问题3:CDC数据传输不稳定

解决方法

  • 增大接收缓冲区大小CONFIG_USB_CDC_ACM_RINGBUF_SIZE
  • 确保回调函数中正确处理接收完成事件
  • 检查串口工具配置是否与设备匹配

总结与扩展

通过本文的步骤,你已经成功实现了Zephyr RTOS下的USB复合设备,同时提供CDC虚拟串口和MSC存储功能。这一方案可广泛应用于需要同时进行数据通信和文件传输的嵌入式设备,如工业控制器、物联网网关等。

后续你可以进一步扩展这一功能:

  • 添加更多USB功能,如HID(人机接口设备)
  • 改用外部Flash或SD卡作为MSC存储介质
  • 实现文件系统加密保护敏感数据

完整项目代码可参考官方示例的组合应用:samples/subsys/usb/cdc_acmsamples/subsys/usb/mass

希望本文能帮助你充分利用Zephyr RTOS的USB功能,为你的嵌入式项目添加更多可能性!如果你有任何问题或改进建议,欢迎参与Zephyr社区讨论。

登录后查看全文
热门项目推荐
相关项目推荐