USB 大容量存储(UMS)使用
本教程适用于支持 USB Device / OTG 模式的瑞莎设备,例如 E25、E52C、ROCK4D、ROCK5B 等。如果不确定设备是否支持,请参考对应 SBC 型号硬件文档中关于 OTG / Device 模式的说明。
在进行以下步骤前,请使用一条数据线将 SBC 的 USB OTG 端口(通常为 USB Type-C 接口)连接到上位机(PC 或其他主机设备),建议优先使用 USB 3.0 线缆和接口,以获得更好的传输性能。
如果你的设备 OTG 口是 USB Type A 请使用 A to A 数据线连接设备和主机
概述
USB 大容量存储 Gadget(UMS)允许设备通过 USB 向主机暴露存储设备,主机会将其识别为 U 盘或移动硬盘。典型用途包括:
- 与 PC 之间的数据交换
- 工控系统中的文件交互
- 量产使用:利用虚拟 U 盘安装系统或写入镜像
- NAS 数据桥接(镜像文件可存放于 NAS)
UMS 向主机暴露的是块设备镜像(image file),文件系统由主机独占控制。
前置条件
在开始之前,请确认:
- 设备已成功启动 RadxaOS;
- USB 线已正确连接 SBC 的 OTG 端口和上位机;
然后运行以下命令检查系统是否支持 Gadget 模式:
ls /sys/class/udc
示例输出:
fc000000.usb
该名称对应 USB Device Controller(UDC),即 gadget_name。
如果列出了多个设备:
- 选择与 USB Type-C 口绑定的 UDC。
- 插拔 USB-C 并使用
dmesg | grep -i udc辅助判断。
如果看不到 udc 设备,需要使用 rsetup 打开 USB OTG overlay

请确保您的USB OTG 工作在client模式(Device模式),而非host模式。
获取 gadget_name
运行以下命令:
ls /sys/class/udc
如果输出为:
fc000000.usb
则 gadget_name 为:
fc000000.usb
此参数需传递给所有脚本。
创建 Gadget(初始化脚本)
此步骤仅需执行一次。将以下脚本保存为:
/usr/local/sbin/gadget-init.sh
#!/bin/bash
#
# 初始化 USB Gadget,仅需执行一次
#
set -euo pipefail
GADGET_NAME=${1:-}
if [[ -z "${GADGET_NAME}" ]]; then
echo "用法: sudo $0 <gadget_name>"
exit 1
fi
if [[ $EUID -ne 0 ]]; then
echo "请以 root 权限运行"
exit 1
fi
# 确保 configfs 已挂载
if ! mountpoint -q /sys/kernel/config; then
mount -t configfs none /sys/kernel/config
fi
# 尝试加载 configfs gadget 核心
# CONFIG_USB_CONFIGFS=m 时需要这一句
modprobe libcomposite 2>/dev/null || true
# 检查 usb_gadget 子系统是否存在
if [[ ! -d /sys/kernel/config/usb_gadget ]]; then
echo "当前内核已启用 CONFIG_USB_CONFIGFS=m,但未发现 /sys/kernel/config/usb_gadget。"
echo "请确认 libcomposite 模块已正确加载,或检查内核模块安装是否完整。"
exit 1
fi
G="/sys/kernel/config/usb_gadget/${GADGET_NAME}"
if [[ -d "${G}" ]]; then
echo "Gadget 已存在:${GADGET_NAME}"
exit 0
fi
mkdir -p "${G}"
cd "${G}"
echo 0x1d6b > idVendor
echo 0x0104 > idProduct
mkdir -p strings/0x409
echo "1234567890" > strings/0x409/serialnumber
echo "Radxa" > strings/0x409/manufacturer
echo "Radxa USB Gadget" > strings/0x409/product
mkdir -p configs/r.1
mkdir -p configs/r.1/strings/0x409
echo "Radxa Config" > configs/r.1/strings/0x409/configuration
echo "初始化完成:${GADGET_NAME}"
echo "下一步:使用 ums.sh 启用 UMS 功能"
赋予执行权限并运行(以 fc000000.usb 为例):
sudo chmod +x /usr/local/sbin/gadget-init.sh
sudo /usr/local/sbin/gadget-init.sh fc000000.usb
成功执行后,应看到:
ls /sys/kernel/config/usb_gadget
fc000000.usb
创建 UMS 启用/禁用脚本
将以下脚本保存为:
/usr/local/sbin/ums.sh
#!/bin/bash
#
# 控制 USB 大容量存储启用/禁用
#
set -euo pipefail
ACTION=${1:-}
GADGET_NAME=${2:-}
IMG=${3:-}
if [[ $EUID -ne 0 ]]; then
echo "请以 root 权限运行"
exit 1
fi
G="/sys/kernel/config/usb_gadget/${GADGET_NAME}"
detect_udc() {
if [[ -f "${G}/UDC" ]]; then
local cur
cur=$(cat "${G}/UDC" 2>/dev/null || echo "")
if [[ -n "${cur}" ]]; then echo "${cur}"; return; fi
fi
if [[ -e "/sys/class/udc/${GADGET_NAME}" ]]; then
echo "${GADGET_NAME}"; return
fi
local lst
mapfile -t lst < <(ls /sys/class/udc || true)
if [[ ${#lst[@]} -eq 1 ]]; then echo "${lst[0]}"; return; fi
echo ""
}
disable_gadget() {
if [[ ! -d "${G}" ]]; then return 0; fi
local cur
cur=$(cat "${G}/UDC" 2>/dev/null || echo "")
if [[ -n "${cur}" ]]; then echo "" > "${G}/UDC" 2>/dev/null || true; fi
rm -f "${G}/configs/r.1/mass_storage.usb1" 2>/dev/null || true
rmdir "${G}/functions/mass_storage.usb1" 2>/dev/null || true
}
enable_gadget() {
UDC=$(detect_udc)
if [[ -z "${UDC}" ]]; then
echo "无法确定 UDC 名称"
exit 1
fi
disable_gadget
local loopdev
loopdev=$(losetup -j "${IMG}" | cut -d: -f1 || true)
[[ -n "${loopdev}" ]] && losetup -d "${loopdev}" || true
mount | grep -q " ${IMG} " && umount "${IMG}" || true
mkdir -p "${G}/configs/r.1"
mkdir -p "${G}/functions/mass_storage.usb1"
echo 0 > "${G}/functions/mass_storage.usb1/stall"
echo 1 > "${G}/functions/mass_storage.usb1/lun.0/removable"
echo 0 > "${G}/functions/mass_storage.usb1/lun.0/ro"
echo 1 > "${G}/functions/mass_storage.usb1/lun.0/nofua"
echo "${IMG}" > "${G}/functions/mass_storage.usb1/lun.0/file"
ln -sf "${G}/functions/mass_storage.usb1" "${G}/configs/r.1/mass_storage.usb1"
echo "${UDC}" > "${G}/UDC"
echo "UMS 已启用"
}
case "${ACTION}" in
enable)
enable_gadget
;;
disable)
disable_gadget
echo "UMS 已禁用"
;;
*)
echo "用法:"
echo " sudo $0 enable <gadget_name> <镜像文件>"
echo " sudo $0 disable <gadget_name>"
;;
esac
赋予执行权限:
sudo chmod +x /usr/local/sbin/ums.sh
准备镜像文件
示例:从 NAS 挂载共享目录:
sudo mount -t cifs -o username=user,password=pass \
//192.168.1.100/share /mnt/nas
创建 8GB 镜像:
sudo dd if=/dev/zero of=/mnt/nas/pcdisk.img bs=1M count=8192
镜像无需在 Linux 中挂载。文件系统将在主机上创建和操作。
::: tip
当 pcdisk.img 首次通过 UMS 导出给主机时,主机会将其视为一块全新的空白磁盘:
- Windows 通常会弹出“需要格式化磁盘”的提示;
- Linux / macOS 下可以使用
fdisk、parted、mkfs等工具手动分区并创建文件系统。
这是正常现象,因为通过 dd if=/dev/zero 创建的镜像本身不包含分区表和文件系统。请在主机上完成分区和格式化后,再在主机上将其作为普通 U 盘使用。
:::
启用与禁用 UMS
启用:
sudo ums.sh enable fc000000.usb /mnt/nas/pcdisk.img
主机将识别为 U 盘。
禁用前请先在主机弹出 U 盘:
sudo ums.sh disable fc000000.usb
注意事项
- 确保在启用 UMS 前镜像文件未挂载在设备上。
- 禁用 UMS 前,请务必在主机上弹出 USB 设备以避免数据损坏。
- 两个脚本均需要以 root 权限运行,请仅在可信环境下使用,并避免将脚本暴露给不受信任的用户或服务,以防造成系统数据损坏或被误用。
执行顺序总结
首次:
gadget-init.sh → ums.sh enable → ums.sh disable
后续操作:
ums.sh enable / disable