跳到主要内容

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 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 下可以使用 fdiskpartedmkfs 等工具手动分区并创建文件系统。

这是正常现象,因为通过 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

    您需要登录 GitHub 才能发表评论。如果您已登录,请忽略此消息。

    Radxa-docs © 2026 by Radxa Computer (Shenzhen) Co.,Ltd. is licensed under CC BY 4.0