综述
通用串行总线即插即用(USB OTG)最初由 Linux USB 子系统支持,结合 Realtek 专门设计的 USB PHY 驱动程序以及对 DWC2 USB 控制器驱动程序的一些修改。
架构
USB 软件架构如下图所示。
实现
原始 USB 由 Linux USB 子系统支持。
文件 |
描述 |
|---|---|
<linux>/drivers/usb/dwc2/ |
由Realtek修改的DWC2主机和设备控制器驱动程序 |
<linux>/drivers/usb/core/ |
HCD 核心 |
<linux>/drivers/usb/gadget/ |
Gadget 核心 |
<linux>/drivers/usb/gadget/function/ |
设备类,例如ADB、CDC ACM、HID、MSC等。 |
<linux>/drivers/usb/class/cdc-acm.* |
CDC ACM 主机类 |
<linux>/drivers/usb/storage/* |
MSC 主机类 |
参考 usb system v5.4 或者 usb system v6.6 获取 USB 子系统的更多细节。
Realtek USB PHY 驱动程序实现为以下文件:
文件 |
描述 |
|---|---|
<linux>/drivers/rtkdrivers/usb_phy/Kconfig |
USB PHY 驱动器 Kconfig |
<linux>/drivers/rtkdrivers/usb_phy/Makefile |
USB PHY 驱动器 Makefile |
<linux>/drivers/rtkdrivers/usb_phy/phy-rtk-usb.c |
USB PHY 函数 |
<linux>/drivers/rtkdrivers/usb_phy/phy-rtk-usb.h |
USB PHY 接口声明 |
配置
设备树配置
USB PHY 设备树配置
USB PHY 的设备树节点在 <dts>/rtl8730e-ocp.dtsi 中定义:
usb_phy: usb-phy@41000000 {
compatible = "realtek,otg-phy";
reg = <0x400B0000 0x20>,
<0x41000060 4>,
<0x42000100 0x10>,
<0x4200825C 4>;
#phy-cells = <0>;
clocks = <&rcc RTK_CKE_USB>;
rtk,cal-data = <0x00 0xE0 0x9D>,
<0x00 0xE1 0x19>,
<0x00 0xE2 0xDB>,
<0x00 0xE4 0x68>,
<0x01 0xE5 0x0A>,
<0x01 0xE6 0xD8>,
<0x02 0xE7 0x52>,
<0x01 0xE0 0x04>,
<0x01 0xE0 0x00>,
<0x01 0xE0 0x04>;
rtk,usb-phandle = <&usb>;
rtk,usb-force-role-en = <1>;
status = "okay";
};
USB PHY 的设备树配置如下所列:
属性 |
描述 |
可配置? |
|---|---|---|
compatible |
用于将 Realtek USB PHY 驱动程序与 USB PHY 设备匹配的 ID。 |
否 |
reg |
USB PHY 寄存器资源 |
否 |
#phy-cells |
指示需要多少个单元来专门描述一个 USB PHY,仅一个 USB PHY 时固定为 0。 |
否 |
clocks |
USB PHY 的时钟源 |
否 |
rtk,cal-data |
USB PHY 的校准数据 |
否 |
rtk,usb-phandle |
USB PHY 的 USB 指针句柄 |
否 |
rtk,usb-force-role-en |
启用在 USB 主机模式和设备模式之间强制切换。 |
1/0 |
status |
USB PHY 状态 |
disabled/okay |
默认情况下,USB PHY 节点是启用的。要禁用它,可以在更高级别的设备树文件中通过节点引用将节点状态覆盖为 disabled,例如芯片特定的设备树文件或电路板特定的设备树文件:
&usb_phy{
status = "disabled";
};
USB 设备树配置
USB 的设备树节点在 <dts>/rtl8730e-ocp.dtsi 中定义:
usb: usb@40080000 {
compatible = "realtek,dwc-otg";
reg = <0x40080000 0x20000>;
interrupts = <GIC_SPI 39 IRQ_TYPE_LEVEL_HIGH>;
g-rx-fifo-size = <512>;
g-np-tx-fifo-size = <256>;
g-tx-fifo-size = <128 120>;
status = "okay";
endpoints {
ep1in {
ep_name = "ep1in";
ep_type = <0x0E>; // USB_EP_CAPS_TYPE_ALL
};
ep2out {
ep_name = "ep2out";
ep_type = <0x0E>; // USB_EP_CAPS_TYPE_ALL
};
ep3in {
ep_name = "ep3in";
ep_type = <0x0E>; // USB_EP_CAPS_TYPE_ALL
};
ep4out {
ep_name = "ep4out";
ep_type = <0x0E>; // USB_EP_CAPS_TYPE_ALL
};
ep5in {
ep_name = "ep5in";
ep_type = <0x0E>; // USB_EP_CAPS_TYPE_ALL
};
ep5out {
ep_name = "ep5out";
ep_type = <0x0E>; // USB_EP_CAPS_TYPE_ALL
};
};
};
USB 的设备树配置如下所示:
属性 |
描述 |
可配置? |
|---|---|---|
compatible |
用于将 DWC2 控制器驱动与 USB OTG 设备匹配的 ID。 |
否 |
reg |
USB 寄存器资源 |
否 |
interrupts |
USB 的 GIC 中断 |
否 |
g-rx-fifo-size |
USB 设备的周期性接收 FIFO 大小(单位:DWORDS)。 |
16~512 |
g-np-tx-fifo-size |
USB 设备的非周期性传输 FIFO 大小(单位:DWORDS)。 |
16~256 |
g-tx-fifo-size |
在专用 FIFO 模式下的 TX FIFO 大小数组。每个值对应一个起始端点(单位:DWORDS)。Realtek USB 在共享 FIFO 模式下工作,因此此配置将被忽略。 |
16~256 |
status |
USB 设备状态 |
disabled/okay |
endpoints |
允许 USB 端点地址配置以满足特定客户需求。 |
是 |
备注
总数据 FIFO 深度为 1016,这意味着 \(g-rx-fifo-size + g-np-tx-fifo-size + g-tx-fifo-size\) 的结果不应大于 1016。
除非确有必要,否则不要更改默认配置。
USB 节点默认是启用的。要禁用它,可以在更高级别的设备树文件中,通过节点引用将节点状态覆盖为 disabled,例如芯片特定的设备树文件或板子特定的设备树文件:
&usb{
status = "disabled";
};
编译配置
USB 功能可以配置为内核固件中的内置功能或独立的内核模块。
内置编译配置
将 USB 功能编译到内核固件中:
模块配置
要将 USB 功能编译为内核模块:
在 选择
M。
在 选择
Y。
选择所需的 USB 模式。
对于主机模式,在 选择
M。对于设备模式,在 选择
M。对于即插即用模式,在 和 全都选择
M。
在 选择
M。
检查 DWC2 模式选择。
对 USB 主机模式,在 Host only mode 选择
Y。对 USB 设备模式,在 Gadget only mode 选择
Y。对 USB 即插即用模式,在 Dual Role mode 选择
Y。
选择所需类别的配置,详情请参阅以下部分。
在运行时载入内核模块。
这里的
<kernel_ver>取决于内核版本,例如 5.4.63。对于主机模式,输入以下命令序列以在加载任何 USB 类特定模块之前加载 USB 通用主机驱动程序:
insmod /lib/modules/<kernel_ver>/kernel/drivers/rtkdrivers/usb_phy/phy-rtk-usb.ko insmod /lib/modules/<kernel_ver>/kernel/drivers/usb/common/usb-common.ko insmod /lib/modules/<kernel_ver>/kernel/drivers/usb/core/usbcore.ko insmod /lib/modules/<kernel_ver>/kernel/drivers/usb/dwc2/dwc2.ko
对于设备模式,输入以下命令序列以在加载任何 USB 类特定模块之前加载 USB 通用设备驱动程序:
insmod /lib/modules/<kernel_ver>/kernel/drivers/rtkdrivers/usb_phy/phy-rtk-usb.ko insmod /lib/modules/<kernel_ver>/kernel/drivers/usb/common/usb-common.ko insmod /lib/modules/<kernel_ver>/kernel/drivers/usb/gadget/udc/udc-core.ko insmod /lib/modules/<kernel_ver>/kernel/drivers/usb/gadget/libcomposite.ko insmod /lib/modules/<kernel_ver>/kernel/drivers/usb/dwc2/dwc2.ko
主机解决方案
在 USB 主机模式下,USB OTG 可以枚举已连接的 USB 设备并启动 USB 传输。
本节仅描述了几个主机类的使用,更多信息请参阅 usb v5.4 或者 usb v6.6.
透传主机方案
配置
除了通用的 USB 主机配置之外,还需要额外的配置来支持 USB CDC ACM 类驱动程序,用户可以选择将其配置为内置功能或独立的内核模块。
以下配置提供了支持典型 CDC ACM 设备(如 USB 串口)的示例。
根据需要调整配置。
内置编译配置
进入 USB support 菜单,输入 Y 选择 USB Modem (CDC ACM) support 与 USB Serial Converter support 选项:
模块配置
应用的 APIs
请参考 usb guide x332 。
使用示例
一旦配置为 CDC ACM 主机,SoC 将识别连接的 CDC ACM 设备为 TTY 设备,并能够通过 TTY 接口与 CDC ACM 设备进行通信。
将 CDC ACM 设备通过 USB 电缆连接到 SoC,控制台上将打印以下日志:
dwc2 40080000.usb: Set speed to high-speed usb 1-1: new high-speed USB device number 2 using dwc2 dwc2 40080000.usb: Set speed to high-speed cdc_acm 1-1:1.0: ttyACM0: USB ACM device
通过设备节点
/dev/ttyACM0与 CDC ACM 设备通信,例如:向 CDC ACM 设备发送数据:
echo helloworld > /dev/ttyACM0从 CDC ACM 设备接收数据:
cat /dev/ttyACM0
请参考 <sdk>/tests/usbh_cdc_acm 以获取 CDC ACM 主机演示。
存储主机方案
配置
除了常见的 USB 主机配置外,还需要额外的配置来支持 USB MSC 类驱动程序,用户可以选择将其配置为内置功能或独立的内核模块。
以下配置提供了一个示例来支持典型的 MSC 设备:使用瑞昱读卡器解决方案的 UDISK,并格式化为 FAT32 文件系统。
USB MSC 类驱动程序所需的常见配置:
根据需要调整配置。
内置编译配置
进入 USB support 菜单,输入 Y 选择 USB Mass Storage support 与 Realtek Card Reader support 选项:
模块配置
应用 APIs
请参考 usb guide x498 。
使用示例
以下是使用支持的 UDISK 测试 USB 主机 MSC 驱动程序的示例。
将 UDISK 连接到 SoC,控制台将输出以下日志。
usb 1-1: USB disconnect, device number 2 dwc2 40080000.usb: Set speed to high-speed usb 1-1: new high-speed USB device number 3 using dwc2 dwc2 40080000.usb: Set speed to high-speed usb-storage 1-1:1.0: USB Mass Storage device detected scsi host0: usb-storage 1-1:1.0 scsi 0:0:0:0: Direct-Access TOSHIBA USB FLASH DRIVE PMAP PQ: 0 ANSI: 6 sd 0:0:0:0: [sda] 30253056 512-byte logical blocks: (15.5 GB/14.4 GiB) sd 0:0:0:0: [sda] Write Protect is off sd 0:0:0:0: [sda] Write cache: disabled, read cache: enabled, doesn't support DPO or FUA sda: sda1 sd 0:0:0:0: [sda] Attached SCSI removable disk
挂载 UDISK 设备。
mkdir /mnt/udisk mount -t vfat /dev/sda1 /mnt/udisk
访问 UDISK 设备。创建一个文件并进行读写操作。
cd /mnt/udisk echo hello >> test.txt cat test.txt hello
卸载 UDISK 设备。
umount /mnt/udisk断开 UDISK 设备连接。
usb 1-1: USB disconnect, device number 2
视频主机方案
配置
除了常见的 USB 主机配置,支持 USB UVC 类驱动程序需要额外的配置,并且用户可以选择将其配置为内置功能或独立的内核模块。
以下配置提供了一个支持典型 UVC 设备(如 UVC 摄像头)的示例。
UVC 摄像头所需的常见配置,在 SDK 中默认选中:
内置编译配置
进入 Media USB Adapters 输入 Y 选择 USB Video Class (UVC) :
模块配置
应用 APIs
它将 UVC 设备视为 V4L2 设备。请参阅 linux video 以获取有关 V4L2 API 的更多信息。
使用示例
以下是典型 UVC 设备(如 USB 摄像头)的简单用法示例:
一旦 USB 摄像头插入 USB 电缆,控制台上将打印以下日志。
dwc2 40080000.usb: Set speed to high-speed
usb 1-1: new high-speed USB device number 2 using dwc2
dwc2 40080000.usb: Set speed to high-speed
uvcvideo: Found UVC 1.00 device USB Camera (0bda:5842)
input: USB Camera: USB Camera as /devices/platform/ocp/40080000.usb/usb1/1-1/1-1:1.0/input/input1
用户可以使用带有 V4L2 库 API 的 IOCTL 访问 USB 摄像头。
在 <sdk>/tests/usbh_uvc 目录下找到 UVC 演示,这是一个从 UVC 摄像头捕获图像并将其保存到 SD 卡的示例。
备注
在运行 UVC 演示之前,应先挂载 SD 卡。
自定义主机方案
Vendor 类是为用户设计的,用于开发自定义的 USB 主机类。
配置
除了常见的 USB 主机配置外,还需要额外的配置来支持 USB Vendor 类驱动程序,用户可以选择将其配置为内置功能或独立的内核模块。
内置编译配置
输入 Y 选择 USB 测试驱动:
模块配置
应用 APIs
无。
使用示例
在 <sdk>/tests/usbh_vendor 目录下找到用于用户空间的 USB 主机 Vendor 示例。
设备解决方案
Linux 协议栈中,USB 设备称为 Gadget 。
在 Gadget 模式下,USB OTG 控制器可被 USB 主机枚举,并响应传输请求。
Gadget 驱动支持两种配置方式:
Configfs 模式:通过用户空间的文件系统接口动态配置 Gadget 功能。
传统模式:通过加载特定内核模块使用预设配置。
本节主要介绍 Configfs 模式下的使用。
有关设备类的更多详细信息,请参考内核文档 usb support v5.4 或 usb support v6.6 。
透传设备方案
配置
启用 CDC ACM 类需在基础 USB 配置之上进行额外设置。用户可将其配置为内核内建功能或独立模块。
内置编译配置
在 Gadget 支持中输入 Y 以选择以下选项:
通过 configfs 可配置的 Gadget 功能
Gadget 串口控制台支持
抽象控制模型 (CDC ACM)
模块配置
在 Gadget 支持中选择以下选项:
输入
M选择 USB Gadget functions configurable through configfs输入
Y选择 Serial gadget console support输入
Y选择 Abstract Control Model (CDC ACM)
在加载通用 USB 设备模块后,加载有关 CDC ACM 类的内核模块。
insmod /lib/modules/<kernel_ver>/kernel/drivers/usb/gadget/function/u_serial.ko insmod /lib/modules/<kernel_ver>/kernel/drivers/usb/gadget/function/usb_f_acm.ko
应用 APIs
请参考 usb guide 。
使用示例
本示例展示如何将开发板配置为 CDC ACM 设备。
使用 USB 线缆连接开发板与 PC。
在开发板终端执行以下命令进行 Configfs 配置:
mkdir /mnt/config mount none /mnt/config -t configfs cd /mnt/config/usb_gadget mkdir cdc && cd cdc echo 0x0200 > bcdUSB echo 0x02 > bDeviceClass echo 0x02 > bDeviceSubClass echo 64 > bMaxPacketSize0 echo 0x8730 > idProduct echo 0x0BDA > idVendor mkdir strings/0x409 echo "Realtek" > strings/0x409/manufacturer echo "VCOM" > strings/0x409/product echo "123456789AB" > strings/0x409/serialnumber mkdir configs/c.1 echo 120 > configs/c.1/MaxPower mkdir configs/c.1/strings/0x409 echo "acm" > configs/c.1/strings/0x409/configuration mkdir functions/acm.ttyS1 ln -s functions/acm.ttyS1 configs/c.1/ echo 40080000.usb > UDC
数据发送测试
在 PC 端打开对应的 COM 端口。在开发板终端输入:
echo 12345 > /dev/ttyGS0PC 端串口工具将接收到字符串
12345。数据接收测试
在开发板终端监听端口:
cat /dev/ttyGS0从 PC 端发送字符串
12345,开发板终端将显示接收到的内容。
备注
Win7 不能直接驱动 CDC ACM 设备。需要安装特定驱动程序: <sdk>/tools/image_tool/RtkUsbCdcAcmSetup.INF 。并且此驱动程序中的 PID / VID 应该与 CDC ACM 设备描述符一致。
备注
如果 PC COM 无法打开,请在 <linux>/drivers/usb/gadget/function/f_acm.c 中注释以下代码以临时解决问题:
static int acm_cdc_notify(struct f_acm *acm, u8 type, u16 value,
void *data, unsigned length)
{
/* ep_queue() can complete immediately if it fills the fifo... */
spin_unlock(&acm->lock);
//status = usb_ep_queue(ep, req, GFP_ATOMIC);
spin_lock(&acm->lock);
}
HID 设备方案
配置
除了常见的 USB 设备配置外,启用 HID 类需确保内核已选中 HID bus support 和 Generic HID driver。
实际上,上述配置在 SDK 中默认启用以支持 ADB。
内置编译配置
模块配置
应用 APIs
请参考 usb guide x498 。
使用示例
本示例展示如何将开发板配置为 HID 鼠标设备。
配置 USB 设备:
mkdir /mnt/config mount none /mnt/config -t configfs cd /mnt/config/usb_gadget mkdir hid cd hid echo 0x0200 > bcdUSB echo 0x03 > bDeviceClass echo 0x00 > bDeviceSubClass echo 64 > bMaxPacketSize0 echo 0x8730 > idProduct echo 0x0BDA > idVendor mkdir strings/0x409 echo "Realtek" > strings/0x409/manufacturer echo "HID" > strings/0x409/product echo "123456789AB" > strings/0x409/serialnumber mkdir configs/c.1 echo 120 > configs/c.1/MaxPower mkdir configs/c.1/strings/0x409 echo "Primary configuration" > configs/c.1/strings/0x409/configuration
配置 HID 报告描述符:
mkdir functions/hid.usb0 echo 1 > functions/hid.usb0/subclass echo 2 > functions/hid.usb0/protocol echo 4 > functions/hid.usb0/report_length echo -ne\\x05\\x01\\x09\\x02\\xa1\\x01\\x09\\x01\\xa1\\x00\\x05\\x09\\x19\\x01\\x29\\x03\\x15\\x00\\x25\\x01\\x95\\x03\\x75\\x01\\x81\\x02\\x95\\x01\\x75\\x05\\x81\\x03\\x05\\x01\\x09\\x30\\x09\\x31\\x09\\x38\\x15\\x81\\x25\\x7f\\x75\\x08\\x95\\x03\\x81\\x06\\xc0\\xc0> functions/hid.usb0/report_desc ln -s functions/hid.usb0 configs/c.1/ echo 40080000.usb > UDC
连接主机后,通过设备节点
/dev/hidg0与主机通信。以下命令将控制鼠标向右下方移动 0x40 像素:echo -ne "\0\x40\x40\0" > /dev/hidg0
备注
鼠标数据包协议格式:
BYTE0
|-- bit7~bit3: RSVD
|-- bit2: middle button press
|-- bit1: right button press
|-- bit0: left button press
BYTE1: x-axis value, -128~127
BYTE2: y-axis value, -128~127
BYTE3: wheel value, -128~127
存储设备方案
配置
除了常见的 USB 设备配置外,还需要额外的配置来支持 USB MSC 类,用户可以选择将其配置为内置功能或独立的内核模块。
内置编译配置
模块配置
在 USB Gadget 支持中配置以下选项:
输入
M选择 USB Gadget functions configurable through configfs输入
Y选择 Mass storage
在加载通用 USB 设备模块后,加载关于 MSC 类的内核模块。
insmod /lib/modules/<kernel_ver>/kernel/drivers/usb/gadget/function/udc-core.ko
insmod /lib/modules/<kernel_ver>/kernel/drivers/usb/gadget/function/usb_f_mass_storage.ko
insmod /lib/modules/<kernel_ver>/kernel/drivers/usb/gadget/function/libcomposite.ko
应用 APIs
请参考 usb guide x498 。
使用示例
本示例展示如何将开发板配置为 USB MSC 设备,并使用 SD 卡作为存储介质。
初始化 SD 卡,详情请参考 SDIO 主机章节。
连接开发板至 PC。
在开发板终端执行配置命令:
mkdir /mnt/config mount none /mnt/config -t configfs cd /mnt/config/usb_gadget mkdir msc && cd msc echo 0x0200 > bcdUSB echo 0x8730 > idProduct echo 0x0BDA > idVendor mkdir strings/0x409 echo "Realtek" > strings/0x409/manufacturer echo "MSC" > strings/0x409/product echo "123456789AB" > strings/0x409/serialnumber mkdir configs/c.1 echo 120 > configs/c.1/MaxPower mkdir configs/c.1/strings/0x409 echo "mass_storage" > configs/c.1/strings/0x409/configuration mkdir functions/mass_storage.0 echo /dev/mmcblk0 >functions/mass_storage.0/lun.0/file echo 1 > functions/mass_storage.0/lun.0/removable echo 0 > functions/mass_storage.0/lun.0/nofua ln -s functions/mass_storage.0 configs/c.1/ echo 40080000.usb > UDC
成功配置后,PC 将识别到一个新的可移动磁盘(UDISK)。
自定义设备方案
Vendor 类旨在供用户开发自定义的 USB 设备类。
配置
除了常见的 USB 设备配置外,还需要额外的配置来支持 USB Vendor 类驱动程序。用户可以选择将其配置为内建功能或独立的内核模块。
内置编译配置
模块配置
在 Gadget 支持中配置以下选项:
输入
M选择 USB Gadget functions configurable through configfs输入
Y选择 Loopback and sourcesink function (for testing)
在加载通用 USB 设备模块之后,加载有关 Vendor 类的内核模块。
insmod /lib/modules/<kernel_ver>/kernel/drivers/usb/gadget/function/udc-core.ko insmod /lib/modules/<kernel_ver>/kernel/drivers/usb/gadget/function/usb_f_ss_lb.ko insmod /lib/modules/<kernel_ver>/kernel/drivers/usb/gadget/function/libcomposite.ko
应用 APIs
无。
使用示例
以下步骤演示如何测试 Gadget Vendor 类功能:
在开发板终端执行配置命令:
mkdir /mnt/config mount none /mnt/config -t configfs cd /mnt/config/usb_gadget mkdir vendor && cd vendor echo 0x0200 > bcdUSB echo 0xa4a0 > idProduct echo 0x0525 > idVendor mkdir strings/0x409 echo "Realtek" > strings/0x409/manufacturer echo "Vendor" > strings/0x409/product echo "123456789AB" > strings/0x409/serialnumber mkdir configs/c.1 mkdir configs/c.2 echo 120 > configs/c.1/MaxPower echo 120 > configs/c.2/MaxPower mkdir configs/c.1/strings/0x409 mkdir configs/c.2/strings/0x409 echo "vendor1" > configs/c.1/strings/0x409/configuration echo "vendor2" > configs/c.2/strings/0x409/configuration mkdir functions/SourceSink.0 mkdir functions/Loopback.0 ln -s functions/SourceSink.0 configs/c.1/ ln -s functions/Loopback.0 configs/c.2/ echo 40080000.usb > UDC
备注
本示例配置为复合设备:
ln -s functions/SourceSink.0 configs/c.1/ 表示默认功能是 sourcesink。
ln -s functions/Loopback.0 configs/c.1/ 表示默认功能是 loopback。
将开发板连接至 USB 主机。
执行主机 Vendor 和设备 Vendor 的交互测试(使用
testusb工具):功能
loopback
sourcesink
配置设定
ln -s functions/Loopback.0 configs/c.1/
ln -s functions/SourceSink.0 configs/c.1/
主机控制台命令
testusb -a -c1 -t30 -s256 -g32 -v1
testusb -a -c1 -tx -s256 -g32 -v1
设备控制台命令
无需命令
无需命令
备注
在主机测试命令中:
Case 30 (
-t30) 专用于 Loopback 功能测试。Case 0~29 (
-tx, x=0..29) 用于 SourceSink 功能测试,参数可根据需求调整。