概述

USB DRD (Dual-Role Data) 是一种允许 USB 接口在主机与设备角色之间进行动态切换的功能。它打破了传统 USB 连接中角色固定的限制,使设备能够根据连接对象或应用需求灵活改变自身属性。

Ameba 能够软件控制切换角色,从而通过单一物理接口满足系统对扩展性与兼容性的双重需求。

DRD(设备)

../../_images/usb_drd_device_overview.svg

DRD(主机)

../../_images/usb_drd_host_overview.svg

应用场景

DRD 提升了设备灵活性,Ameba 可调整工作模式,通过单一物理接口适应适应多样化的的交互与扩展需求,例如:

  • 智能行车记录仪/运动相机:在主机模式下,Ameba 主动将 GPS 模块轨迹写入外接 U 盘;当插入 PC 时切换为设备模式,模拟成大容量存储设备(MSC),供用户直接拷贝导出文件。

  • 工业手持数据终端:在主机模式下,Ameba 连接扫码枪或红外传感器(HID/CDC)采集现场数据;当回到办公室连接 PC 时切换为设备模式,模拟成串口或 U 盘,将采集的日志与报表批量上传至管理系统。

  • 车载 CarPlay 互联终端:Ameba 刚上电时处于设备模式,完成必要的初始验证流程;验证通过后切换为主机模式,主动连接车机设备,建立 NCM 和 iAP2 双协议通信以实现 CarPlay 全功能。

协议简介

在 USB 应用中,实现主机与设备角色的切换通常采用以下两种方法:

  • 基于 USB OTG (On-The-Go) 协议的硬件切换

    依赖物理线缆的 ID 引脚状态来判定角色。该机制包含以下具体协议:

    • SRP (Session Request Protocol): 允许从设备请求主机开启 VBUS 电源。

    • HNP (Host Negotiation Protocol): 允许连接双方通过协商临时交换 Host/Device 角色。

  • 软件控制的 USB DRD 切换

    不依赖物理连接状态,而是由软件直接修改控制器寄存器来进行角色变更。此方式虽不属于标准 USB 传输协议,但具有极高的实用价值。

DRD 软件切换对比 OTG 的核心优势

尽管硬件自动检测具备基础易用性,但在实现复杂、高可靠性的系统时, DRD 软件切换 展现出不可替代的优势:

  • 摆脱硬件依赖与适配 Type-C

    • 不依赖 ID 引脚,规避了因硬件设计缺陷或物理损坏导致的失效。

    • 特别是在 Type-C 规范中,OTG 定义的 HNP 协议已被弃用,且无传统 ID 引脚,软件切换成为更符合现代接口规范的方案。

  • 灵活的软件切换

    • 支持在不更换物理线缆的情况下动态改变角色,可选择应用主动切换,或外部按键、事件或消息请求等多种方式触发切换。

    • 极大提高了系统的容错率、可维护性以及自动化测试效率。

类驱动

USB DRD 软件控制角色切换本质上属于应用层的功能,主要涉及控制器工作模式的变更,本身并不需要特定的“DRD 类驱动”, 其实质是根据当前的 USB 角色,动态加载相应的标准类驱动。关于 DRD 不同角色下使用的类驱动,请参阅对应设备/主机方案的类驱动章节。

应用示例

应用设计

本节介绍 DRD 应用进行角色切换的开发设计流程,其中设备模式切换为主机模式过程可概括为(反之亦然):

  • 加载设备驱动

  • 主动切换或事件/消息等触发切换角色

  • 卸载设备驱动

  • 加载主机驱动

  • 卸载主机驱动

MSC 设备和 MSC 主机 的 DRD 应用实例中,Ameba 先作为设备模式,20s 后通过软件强制切换为主机模式,下面介绍具体实现:

加载 MSC 设备驱动

定义配置结构体和回调函数,随后调用初始化接口,对底层存储初始化并加载 USB 设备核心驱动及 MSC 类驱动。

static usbd_config_t usbd_msc_cfg = {
    .speed = CONFIG_USBD_MSC_SPEED,
    .isr_priority = INT_PRI_MIDDLE,
};

static usbd_msc_cb_t usbd_msc_cb = {
    .status_changed = usbd_msc_cb_status_changed  /* USB status change callback. */
};

int ret = 0;
ret = usbd_msc_disk_init();    /* Initializes the underlying storage disk. */
if (ret != HAL_OK) {
    return;
}

ret = usbd_init(&usbd_msc_cfg);     /* Initialize USB device core driver with configuration. */
if (ret != HAL_OK) {
    usbd_msc_disk_deinit();
    return;
}

ret = usbd_msc_init(&usbd_msc_cb);  /* Initializes the MSC device class. */
if (ret != HAL_OK) {
    usbd_msc_disk_deinit();
    usbd_deinit();
    return;
}

卸载 MSC 设备驱动

按加载的反序释放资源。

/* De-initializes the underlying storage disk. */
usbd_msc_disk_deinit();
/* Deinitialize MSC device class driver. */
usbd_msc_deinit();
/* Deinitialize USB device core driver. */
usbd_deinit();

加载 MSC 主机驱动

定义配置结构体和回调函数,随后调用初始化接口,加载 USB 主机核心驱动及 MSC 类驱动。

static usbh_config_t usbh_cfg = {
  .speed = USB_SPEED_HIGH,
  .ext_intr_enable = USBH_SOF_INTR,
  .isr_priority = INT_PRI_MIDDLE,
  .main_task_priority = 3U,
  .tick_source = USBH_SOF_TICK,
  }

static usbh_msc_cb_t usbh_msc_usr_cb = {
  .attach = usbh_msc_cb_attach,                  /* USB device attach callback */
  .setup = usbh_msc_cb_setup,                    /* USB device setup done, indicate that device is ready for bulk transfer */
};

static usbh_user_cb_t usbh_usr_cb = {
  .process = usbh_msc_cb_process
};

int ret = 0;
ret = usbh_init(&usbh_cfg, &usbh_usr_cb);   /* Initialize USB host core driver with configuration and user callback. */
if (ret != HAL_OK) {
    return;
}

ret = usbh_msc_init(&usbh_msc_usr_cb);          /* Initializes the MSC host class with MSC class user callback. */
if (ret != HAL_OK) {
    usbd_msc_disk_deinit();
    return;
}

卸载 MSC 主机驱动

按加载的反序释放资源。

/* Deinitialize MSC host class driver. */
usbh_msc_deinit();
/* Deinitialize USB host core driver. */
usbh_deinit();

备注

运行方式

本节介绍了一个具备运行时角色切换功能的 USB DRD 应用示例。该示例基于标准 MSC 类驱动,集成了大容量存储主机(MSC Host)与大容量存储设备(MSC Device)的双重功能。

在该示例中,Ameba 可在两种角色间切换:

  • MSC 设备模式:作为 MSC 设备连接主机(如 PC)后,可以读写其挂载的存储介质。

  • MSC 主机模式:作为 MSC 主机挂载并读写外部插入的 FAT32 文件系统的 MSC 设备(如 U 盘)。

该示例代码路径: {SDK}/component/example/usb/usb_drd,可为开发者设计自定义 USB DRD 产品提供完整的设计参考。

备注

本示例主要用于演示协议栈的双角色切换逻辑,不支持 SD 卡热插拔及 USB 接口热插拔。

配置与编译

  • Menuconfig 配置

    amebaxxx_gcc_project 目录下,输入 ./menuconfig.py,按下面步骤选择 USB DRD 和设备存储介质,保存退出。

    - Choose `CONFIG USB --->`:
    
            [*] Enable USB
                    USB Mode (DRD)  --->
    
                    *** USB Device Class ***
            [*] MSC
                    Select storage media (SD Card (SD mode))  --->
    
                    *** USB Host Class ***
            [*] MSC
    
  • 编译与烧录

    执行编译命令,并烧录生成的 Image 文件至开发板:

    cd amebaxxx_gcc_project
    ./build.py -a usb_drd
    

结果验证

本小节以使用 SD 卡 作为存储介质为例进行演示。

  • 启动设备

    将 SD 卡插入开发板的 SD 卡槽并重启开发板,观察串口日志,应显示如下启动信息:

    [DRD-I] USB DRD demo start
    [DRD-I] Init disk
    [DRD-I] Init disk
    [MSC-I] SD init
    [SDH-I] Card Detect
    [SDH-I] Voltage match
    [SDH-I] This is a SDHC/SDXC card...
    [SDH-I] Keep 3.3V...
    [SDH-I] Manufacturer ID:3
    [SDH-I] OEM/Application ID:SD
    [SDH-I] Manufacturing date:2021/5
    [SDH-I] RCA = AAAA
    [SDH-I] CSD Version:2.0
    [SDH-I] User data area capacity: 14 GB
    [SDH-I] Max. read data block length: 512 Bytes
    [SDH-I] Max. write data block length: 512 Bytes
    [SDH-I] SD specification version: 3.0X
    [SDH-I] Data status after erase: 0
    [SDH-I] SD card changes to the specified speed mode successfully
    [SDH-I] SD card is initialized
    [DRD-I] Init device driver
    [USBD-A] INIT
    [DRD-I] Init MSC device class
    [MSC-I] Init
    [DRD-I] MSC device session start
    
  • MSC 设备模式测试

    用 USB 线缆将开发板连接到 PC(或其他支持 USB MSC 的主机设备)。

    • 识别与挂载:PC 端文件管理器中应自动弹出一个新的可移动磁盘盘符。

    • 读写测试:用户可以在 20 秒内双击打开该盘符,对其中的文件进行读写操作,验证数据传输是否正常。

    • 角色切换:直到打印出以下日志,表示设备模式结束,准备切换至主机模式:

    [DRD-I] Role switch
    [DRD-I] Deinit MSC device class
    [DRD-I] Deinit device driver
    [USBD-A] DEINIT
    [DRD-I] Deinit disk
    [MSC-I] SD deinit
    [DRD-I] Init host driver
    [DRD-I] Init MSC host driver
    [DRD-I] MSC host session start
    [DRD-I] Register USB disk
    [DRD-I] FatFS USB W/R performance test start...
    
  • MSC 主机模式测试

    将开发板的 USB 端口从 PC 断开,使用 USB 线缆将其连接到已格式化为 FATFS 的 U 盘,开发板将识别 MSC 设备并进行读写性能测试。

    [USBH-A] Device attached,speed 0
    [USBH-A] PID: 0x6545
    [USBH-A] VID: 0x0930
    [USBH-A] Address 1 assigned
    [USBH-A] MFG: TOSHIBA
    [USBH-A] PROD: TransMemory
    [USBH-A] SN: C03FD5F7715FE3417000DE76
    [USBH-A] Enum done, total 1 cfg
    [USBH-A] Switch to itf: 0
    [USBH-A] Class: 0x08
    [USBH-A] SubClass: 0x06
    [USBH-A] Protocol: 0x50
    [DRD-I] Host attach
    [MSC-I] Max lun 1
    [MSC-I] Lun 0
    [DRD-I] Host setup
    [DRD-I] Open file: 0:/TEST0.DAT
    [DRD-I] W test: size 512, round 20...
    [DRD-I] W rate 204.0 KB/s for 20 round @ 49 ms
    [DRD-I] R test: size = 512 round = 20...
    [DRD-I] R rate 476.1 KB/s for 20 round @ 21 ms
    [DRD-I] W test: size 1024, round 20...
    [DRD-I] W rate 540.5 KB/s for 20 round @ 37 ms
    [DRD-I] R test: size = 1024 round = 20...
    [DRD-I] R rate 800.0 KB/s for 20 round @ 25 ms
    [DRD-I] W test: size 2048, round 20...
    [DRD-I] W rate 655.7 KB/s for 20 round @ 61 ms
    [DRD-I] R test: size = 2048 round = 20...
    [DRD-I] R rate 1212.1 KB/s for 20 round @ 33 ms
    [DRD-I] W test: size 4096, round 20...
    [DRD-I] W rate 1095.8 KB/s for 20 round @ 73 ms
    [DRD-I] R test: size = 4096 round = 20...
    [DRD-I] R rate 1600.0 KB/s for 20 round @ 50 ms
    [DRD-I] FatFS USB W/R performance test done
    [DRD-I] File close OK