从Host到Device:解锁RK3399 Linux板卡的USB OTG U盘模拟实战
2026/6/30 11:55:17 网站建设 项目流程

1. RK3399 USB OTG功能基础解析

第一次接触RK3399开发板时,我发现这个六核处理器不仅性能强悍,它的USB OTG功能更是隐藏着不少实用玩法。USB OTG全称USB On-The-Go,简单理解就是让设备既能当主机(Host)也能当设备(Device)。就像手机既能连接U盘(Host模式),又能作为存储设备连接电脑(Device模式)一样。

RK3399的Type-C接口默认是Host模式,用来连接鼠标、键盘或U盘。但通过内核配置,我们可以让它摇身一变成为被电脑识别的"U盘"。这种模式在嵌入式开发中特别实用,比如:

  • 快速传输日志文件
  • 作为系统恢复盘
  • 实现无网络环境下的数据交换

我实测过,用这种方式传文件比SCP/SFTP方便多了,特别是当网络驱动还没调试好时。不过要注意,RK3399的OTG接口有USB2.0和USB3.0两种模式,实际传输速度差异很大。在USB3.0模式下,传输大文件能快10倍不止。

2. 内核配置与驱动编译实战

2.1 内核菜单配置详解

要让RK3399变身U盘,首先得在内核中开启几个关键选项。我建议用make menuconfig命令进入配置界面,按以下路径设置:

Device Drivers → [*] USB support → <*> DesignWare USB2 DRD Core Support → DWC2 Mode Selection (Dual Role mode)

这里有个坑我踩过:必须选Dual Role模式,单纯选Peripheral模式在某些板子上会不识别。接着配置Gadget相关选项:

<*> USB Gadget Support → (500) Maximum VBUS Power usage → (2) Number of storage pipeline buffers → <M> USB functions configurable through configfs → [*] Mass storage → <M> Gadget Filesystem → <M> Mass Storage Gadget

特别注意configfs要编译为模块,这是现代Linux推荐的方式。存储管道缓冲区数量建议保持默认,改大了反而可能降低性能。

2.2 模块编译与验证

配置保存后,执行make modules编译。成功后会生成四个关键模块:

  • libcomposite.ko:复合设备框架
  • gadgetfs.ko:旧版Gadget API
  • g_mass_storage.ko:Mass Storage主驱动
  • usb_f_mass_storage.ko:存储功能实现

我习惯用modinfo检查模块信息:

modinfo drivers/usb/gadget/legacy/g_mass_storage.ko

输出中应该能看到parm: file:...参数,后面配置会用到这个。

3. 虚拟U盘创建全流程

3.1 磁盘镜像制作技巧

创建镜像文件时,dd命令的参数选择直接影响性能:

dd if=/dev/zero of=/mnt/udisk.img bs=4M count=400 status=progress

这里有几个经验值:

  • bs=4M:块大小建议4M,太小会导致写入慢
  • count=400:得到约1.6GB镜像(调整count值改变大小)
  • status=progress:显示实时进度

格式化建议用VFAT,兼容性最好:

mkfs.vfat -F 32 -n "RK3399_DISK" /mnt/udisk.img

-F 32强制使用FAT32,-n设置卷标名。如果镜像大于4GB,可以考虑exFAT格式。

3.2 内存盘加速方案

把镜像放在内存里能极大提升速度,实测USB3.0下能达到35MB/s:

mount -t tmpfs -o size=2G tmpfs /mnt/tmp dd if=/dev/zero of=/mnt/tmp/udisk.img bs=4M count=500

注意内存大小限制,我的经验是预留至少512MB给系统。

4. 设备挂载与性能优化

4.1 动态挂载实战

先用losetup关联镜像文件:

losetup -fP /mnt/udisk.img # 自动分配loop设备 losetup -l # 查看分配的设备号

然后加载驱动模块:

modprobe libcomposite insmod /path/to/g_mass_storage.ko file=/dev/loop0 stall=0 removable=1

关键参数说明:

  • stall=0:禁用STALL协议,提升兼容性
  • removable=1:模拟可移动磁盘

如果听到电脑"叮咚"声但看不到盘符,可能是没有正确格式化。这时需要检查内核日志:

dmesg | tail -20

4.2 速度优化技巧

我测试过不同配置下的传输速度:

配置方案写入速度读取速度
eMMC+USB2.03.2MB/s5.1MB/s
内存盘+USB2.018MB/s22MB/s
内存盘+USB3.032MB/s38MB/s

提升性能的几个建议:

  1. 使用sync命令手动刷新缓存
  2. 避免同时读写操作
  3. PC端使用好的USB线材
  4. 在RK3399上设置CPU性能模式:
echo performance > /sys/devices/system/cpu/cpufreq/policy0/scaling_governor

5. 高级应用与故障排查

5.1 多功能复合设备

RK3399其实可以同时模拟多种设备,比如U盘+键盘:

mkdir /sys/kernel/config/usb_gadget/g1 cd /sys/kernel/config/usb_gadget/g1 # 设置USB属性 echo "0x1d6b" > idVendor echo "0x0104" > idProduct mkdir strings/0x409 echo "123456789" > strings/0x409/serialnumber # 创建配置 mkdir configs/c.1 mkdir configs/c.1/strings/0x409 echo "My Composite Device" > configs/c.1/strings/0x409/configuration # 添加Mass Storage功能 mkdir functions/mass_storage.usb0 echo "/dev/loop0" > functions/mass_storage.usb0/lun.0/file ln -s functions/mass_storage.usb0 configs/c.1/ # 启用设备 echo "dwc2" > UDC

5.2 常见问题解决方案

问题1:PC提示"需要格式化"

  • 检查镜像文件是否已用mkfs格式化
  • 确认内核配置开启了VFAT支持

问题2:传输速度突然下降

  • 检查CPU温度:cat /sys/class/thermal/thermal_zone*/temp
  • 查看USB模式:lsusb -t(应该显示3.0或2.0)

问题3:设备无法识别

  • 确认Type-C线支持数据传输
  • 检查内核配置是否开启DRD模式
  • 尝试不同的USB端口

我在实际项目中遇到过最棘手的问题是热插拔不稳定,后来发现是电源管理导致的,解决方法:

echo "on" > /sys/bus/usb/devices/usb1/power/control

6. 实际应用场景扩展

除了基本的数据传输,这种技术还可以实现:

  • 系统恢复工具:把镜像文件预装系统镜像,插上就能恢复
  • 安全审计:模拟U盘自动运行安全检测脚本
  • 数据采集:直接将传感器数据写入虚拟U盘

有个有趣的玩法是创建只读U盘:

mount -o ro /dev/loop0 /opt/udisk insmod g_mass_storage.ko file=/dev/loop0 ro=1

这样PC端就无法修改内容,适合分发固件或文档。

对于需要频繁切换模式的开发者,可以写个切换脚本:

#!/bin/bash case "$1" in host) echo "host" > /sys/devices/platform/fe8a0000.usb2-phy/otg_mode ;; device) echo "device" > /sys/devices/platform/fe8a0000.usb2-phy/otg_mode ;; esac

最后提醒下,长时间使用内存盘时,记得定时备份数据到eMMC,避免断电丢失。我通常会用cronjob每小时同步一次:

* * * * * cp /mnt/tmp/udisk.img /userdata/backup.img

需要专业的网站建设服务?

联系我们获取免费的网站建设咨询和方案报价,让我们帮助您实现业务目标

立即咨询