泰山派RNDIS/ADB共存与NFS文件系统
#立创·泰山派RK3566开发板#
TSPI RK3566 RNDIS/ADB 与 Buildroot NFS
本文档记录了解决 NFS 挂载失败及 USB Gadget 冲突,最终实现 ADB 与 RNDIS 复合设备完美共存的核心流程与代码补丁。为提高可读性,按系统层级重构了原理说明与具体补丁的映射关系。
title: TSPI RK3566 USB Gadget (RNDIS/ADB) 与 NFS 修复复盘
tags: [sdk, rk3566, tspi, usb-gadget, rndis, adb, nfs]
desc: 泰山派 RK3566 NFS 挂载与 RNDIS/ADB 复合设备共存修复笔记。
update: 2026-04-26
title: TSPI RK3566 USB Gadget (RNDIS/ADB) 与 NFS 修复复盘
tags: [sdk, rk3566, tspi, usb-gadget, rndis, adb, nfs]
desc: 泰山派 RK3566 NFS 挂载与 RNDIS/ADB 复合设备共存修复笔记。
update: 2026-04-26
TSPI RK3566 RNDIS/ADB 与 Buildroot NFS
本文档记录了解决 NFS 挂载失败及 USB Gadget 冲突,最终实现 ADB 与 RNDIS 复合设备完美共存的核心流程与代码补丁。为提高可读性,按系统层级重构了原理说明与具体补丁的映射关系。
1. Kernel 层:RNDIS 支持与 UDC 硬件释放
1.1 开启 ConfigFS_ETH*,但不使用传统Gadget
痛点:内核传统网卡 Gadget,阻碍了动态 ConfigFS 接管 USB 控制器,这可能导致usb总线上的read event风暴。
方案:在内核配置 (./build.sh kconfig) 中彻底禁用 CONFIG_USB_ETH 及相关旧架构,开启 ConfigFS ECM/RNDIS。
补丁 (sdk/tspi-rk3566-sdk/kernel-6.1/arch/arm64/configs/rockchip_linux_defconfig):
--- a/arch/arm64/configs/rockchip_linux_defconfig
+++ b/arch/arm64/configs/rockchip_linux_defconfig
@@ -502,9 +502,15 @@ CONFIG_USB_GADGET_VBUS_DRAW=500
CONFIG_USB_CONFIGFS=y
CONFIG_USB_CONFIGFS_UEVENT=y
CONFIG_USB_CONFIGFS_ACM=y
+CONFIG_USB_CONFIGFS_ECM=y
+CONFIG_USB_CONFIGFS_ECM_SUBSET=y
+CONFIG_USB_CONFIGFS_RNDIS=y
+CONFIG_USB_CONFIGFS_EEM=y
CONFIG_USB_CONFIGFS_MASS_STORAGE=y
CONFIG_USB_CONFIGFS_F_FS=y
CONFIG_USB_CONFIGFS_F_UVC=y
+#CONFIG_USB_ETHisnotset+# CONFIG_USB_ETH_RNDIS is not set
CONFIG_TYPEC_TCPM=y
CONFIG_TYPEC_TCPCI=y
CONFIG_TYPEC_HUSB311=y
--- a/arch/arm64/configs/rockchip_linux_defconfig
+++ b/arch/arm64/configs/rockchip_linux_defconfig
@@ -502,9 +502,15 @@ CONFIG_USB_GADGET_VBUS_DRAW=500
CONFIG_USB_CONFIGFS=y
CONFIG_USB_CONFIGFS_UEVENT=y
CONFIG_USB_CONFIGFS_ACM=y
+CONFIG_USB_CONFIGFS_ECM=y
+CONFIG_USB_CONFIGFS_ECM_SUBSET=y
+CONFIG_USB_CONFIGFS_RNDIS=y
+CONFIG_USB_CONFIGFS_EEM=y
CONFIG_USB_CONFIGFS_MASS_STORAGE=y
CONFIG_USB_CONFIGFS_F_FS=y
CONFIG_USB_CONFIGFS_F_UVC=y
+#CONFIG_USB_ETHisnotset+# CONFIG_USB_ETH_RNDIS is not set
CONFIG_TYPEC_TCPM=y
CONFIG_TYPEC_TCPCI=y
CONFIG_TYPEC_HUSB311=y
1.2 屏蔽物理引脚干涉
痛点:底层设备树会监听 Type-C 物理状态,易误判为 Host 模式导致外设注册失败。(maybe)
方案:强制删除 extcon 属性,固定为从机 (peripheral) 模式。
补丁 (sdk/tspi-rk3566-sdk/kernel-6.1/arch/arm64/boot/dts/rockchip/tspi-rk3566-user-v10-linux.dts):
--- a/arch/arm64/boot/dts/rockchip/tspi-rk3566-user-v10-linux.dts
+++ b/arch/arm64/boot/dts/rockchip/tspi-rk3566-user-v10-linux.dts
@@ -194,3 +194,10 @@ ir_key1 {
[removed];
};
};
+
+//Force USB Type-C to act as peripheral (Gadget) for RNDIS/ADB
+&usbdrd_dwc3 {
+ dr_mode = "peripheral";
+ /delete-property/ extcon;
+ status = "okay";
+};
--- a/arch/arm64/boot/dts/rockchip/tspi-rk3566-user-v10-linux.dts
+++ b/arch/arm64/boot/dts/rockchip/tspi-rk3566-user-v10-linux.dts
@@ -194,3 +194,10 @@ ir_key1 {
[removed];
};
};
+
+//Force USB Type-C to act as peripheral (Gadget) for RNDIS/ADB
+&usbdrd_dwc3 {
+ dr_mode = "peripheral";
+ /delete-property/ extcon;
+ status = "okay";
+};
2. Buildroot 层:NFS 客户端支持
2.1 添加 NFS 组件解决挂载失败
痛点:RK3566 默认极简文件系统无 NFS 客户端,导致 mount -a 失败。
方案:开启 nfs-utils 和 NFS client(可取消 rpc.nfsd 节省空间),重新编译 rootfs.img。
补丁 (sdk/tspi-rk3566-sdk/buildroot/configs/rockchip_rk3566_defconfig):
--- a/configs/rockchip_rk3566_defconfig
+++ b/configs/rockchip_rk3566_defconfig
@@ -22,6 +22,9 @@
#include "gui/weston.config"
BR2_PACKAGE_IPERF3=y
BR2_PACKAGE_MINICOM=y
+BR2_PACKAGE_NFS_UTILS=y
+BR2_PACKAGE_NFS_UTILS_NFSV4=y
+# BR2_PACKAGE_NFS_UTILS_RPC_NFSD is not set
BR2_PACKAGE_OPENSSH=y
BR2_PACKAGE_QUECTEL_CM=y
BR2_PACKAGE_TINYALSA=y
--- a/configs/rockchip_rk3566_defconfig
+++ b/configs/rockchip_rk3566_defconfig
@@ -22,6 +22,9 @@
#include "gui/weston.config"
BR2_PACKAGE_IPERF3=y
BR2_PACKAGE_MINICOM=y
+BR2_PACKAGE_NFS_UTILS=y
+BR2_PACKAGE_NFS_UTILS_NFSV4=y
+# BR2_PACKAGE_NFS_UTILS_RPC_NFSD is not set
BR2_PACKAGE_OPENSSH=y
BR2_PACKAGE_QUECTEL_CM=y
BR2_PACKAGE_TINYALSA=y
3. Shell层:ADB-RNDIS 兼容与网络自启
3.1 规避 USB 脚本正则解析陷阱
痛点:官方 /usr/bin/usb-gadget 脚本对配置文件解析存在正则缺陷,遇到 =on 等赋值会截断异常。
方案:配置文件中严禁使用 =on,仅保留宏名本身。
写入文件 (/etc/.usb_config):
usb_adb_en
usb_rndis_en
usb_adb_en
usb_rndis_en
3.2 RNDIS 自动分配 IP 与路由配置
痛点:RNDIS 虚拟网卡 usb0 生成后默认无网络配置。
方案:编写 usb-gadget 启动后置钩子脚本,自动配置 IP 并打通 Windows 网络共享 (ICS) 的 192.168.137.x 网段路由及 DNS。
写入文件 (/etc/usb-gadget.d/rndis.sh):
#!/bin/sh
rndis_post_start_hook()
{
while ! ifconfig usb0 >/dev/null 2>&1; do
sleep .1
done
ifconfig usb0 192.168.137.2 netmask 255.255.255.0 up
route add default gw 192.168.137.1
echo "nameserver 8.8.8.8" > /etc/resolv.conf
echo "nameserver 114.114.114.114" >> /etc/resolv.conf
}
#!/bin/sh
rndis_post_start_hook()
{
while ! ifconfig usb0 >/dev/null 2>&1; do
sleep .1
done
ifconfig usb0 192.168.137.2 netmask 255.255.255.0 up
route add default gw 192.168.137.1
echo "nameserver 8.8.8.8" > /etc/resolv.conf
echo "nameserver 114.114.114.114" >> /etc/resolv.conf
}
4. Host (宿主机) 端配置:ADB 识别
4.1 添加 Vendor ID (VID) 白名单
痛点:由于泰山派作为复合设备时的 Vendor ID 为 0x2207 (Rockchip),某些情况下宿主机的 ADB 进程无法自动识别该非标/第三方设备的 USB 接口,导致 adb devices 找不到设备。
方案:在宿主机的用户目录下创建/修改 .android/adb_usb.ini 文件,强制 ADB 进程扫描该 VID。
写入文件 (Windows: C:\Users\[removed]\.android\adb_usb.ini / Linux/WSL: ~/.android/adb_usb.ini):
0x2207
0x2207
生效命令:配置完成后在宿主机终端执行 adb kill-server 与 adb start-server。
4.2 Windows 设备管理器状态验证
在 Windows “设备管理器” -> “设备属性” -> “详细信息” -> “硬件 Id” 中,该复合设备的接口通常显示为:
USB\VID_2207&PID_0013&REV_0310&MI_02
USB\VID_2207&PID_0013&MI_02
USB\VID_2207&PID_0013&REV_0310&MI_02
USB\VID_2207&PID_0013&MI_02
注:PID_0013 是 Rockchip 为 RNDIS+ADB 组合分配的 Product ID,MI_02 代表这是复合设备中的对应接口(通常代表 ADB 接口)。
5. 结果验证
烧录并启动后,通过电脑端连接 Type-C 接口:
多路网络:开发板通过 usb0 顺畅连接外网,本地宿主机可通过局域网 IP (192.168.137.2) 进行 NFS 和 SSH 连接。
复合 Gadget:设备成功变身复合设备,支持 USB 物理底层 adb shell 及网络端 adb connect 192.168.137.2:5555 并行使用。
WSL2 搭建NFS Server + 开发板配置NFS Client 完整流程总结
全程基于****WSL2 Ubuntu/Debian(NFS服务端)+ 嵌入式Linux开发板(NFS客户端),核心解决WSL2专属坑点(insecure参数、IP解析、权限映射),步骤极简可落地,按顺序执行即可实现开发板挂载WSL的NFS共享目录(读写正常)。
一、WSL2 端:NFS Server 配置(核心步骤)
前提准备
确认WSL为****WSL2:wsl -l -v,若为WSL1执行 wsl --set-version 发行版名 2升级;
记录WSL2内网IP(开发板挂载用):ip a show eth0 → 取 inet后IP(如 192.168.31.110);
确保WSL与开发板****同一内网(连同一个路由器,IP段一致如 192.168.31.x)。
步骤1:安装NFS服务端依赖
sudo apt update && sudo apt install -y nfs-kernel-server rpcbind
步骤2:创建NFS共享目录(避坑:仅在WSL自身文件系统创建)
禁止建在**/mnt/c/d**(Windows挂载目录,权限失效),建议在 /home/下创建:
# 示例目录:/home/pi/imx/mount,可自定义
sudo mkdir -p /home/pi/imx/mount
# 赋予全权限(双重校验:NFS配置+Linux本地权限)
sudo chmod -R 777 /home/pi/imx/mount
sudo chown -R $(whoami):$(whoami) /home/pi/imx/mount
步骤3:配置NFS共享规则(/etc/exports,WSL必配 insecure)
直接覆盖写入(避免格式错误,3种客户端规则任选其一,推荐局域网网段):
#格式:共享目录客户端IP/网段(核心参数,无空格!)# 选项1:允许整个局域网(推荐,开发板/虚拟机通用)
sudo echo "/home/pi/imx/mount 192.168.31.0/24(rw,sync,no_root_squash,no_subtree_check,insecure)" > /etc/exports
# 选项2:允许单个开发板IP(最安全,如开发板IP192.168.31.100)
# sudo echo "/home/pi/imx/mount 192.168.31.100(rw,sync,no_root_squash,no_subtree_check,insecure)" > /etc/exports
#选项3:允许所有设备(测试用,简单)# sudo echo "/home/pi/imx/mount *(rw,sync,no_root_squash,no_subtree_check,insecure)" > /etc/exports
核心参数必选原因(WSL+开发板专属)
rw:读写权限;sync:数据同步写入(防丢失);
no_root_squash:开发板root挂载拥有WSL目录root权限(嵌入式必配,避 Permission denied);
no_subtree_check:关闭子目录检查,提升性能;
insecure:WSL2核心坑点,允许非特权端口访问(不加直接挂载失败)。
步骤4:加载配置+启动NFS服务(确保规则生效)
# 清除旧规则→加载新规则→启动服务→设置开机自启
sudo exportfs -au && sudo exportfs -r
sudo service rpcbind start && sudo service nfs-kernel-server start
sudo update-rc.d rpcbind enable && sudo update-rc.d nfs-kernel-server enable
步骤5:开放WSL防火墙端口(NFS必备111/2049)
# 开放TCP+UDP端口,或直接关闭防火墙(测试用)
sudo ufw allow 111/tcp && sudo ufw allow 111/udp
sudo ufw allow 2049/tcp && sudo ufw allow 2049/udp
sudo ufw reload
#测试用快捷方式:临时关闭防火墙# sudo ufw disable
步骤6:验证WSL NFS服务是否正常(3条命令必过)
# 1. 查看生效的共享规则(有输出即正常)
sudo exportfs -v
# 2. 本地查询共享列表(有目录输出即正常)
showmount -e 127.0.0.1
# 3. 检查服务状态(显示active即正常)
sudo service nfs-kernel-server status && sudo service rpcbind status
二、开发板端:NFS Client 挂载配置(极简步骤)
前提准备
开发板联网并与WSL同一内网,记录开发板IP(可选);
确认开发板已安装NFS客户端工具(嵌入式Linux一般自带,无则手动装)。
步骤1:安装NFS客户端依赖(无则执行,如OpenWrt/纯版Linux)
# Debian/Ubuntu系开发板
sudo apt install -y nfs-common
# 嵌入式Linux(如RT-Thread/OpenWrt)
opkg install nfs-utils-client
# 龙芯/IMX等原厂系统(一般自带,无需安装)
步骤2:创建开发板本地挂载点(可自定义,如/mnt/nfs 或 /mnt
)
sudo mkdir -p /mnt/nfs # 推荐单独创建,避免覆盖原有/mnt内容
步骤3:NFS挂载核心命令(指定NFSv3,嵌入式兼容性最好)
# 格式:sudo mount -t nfs -o 客户端参数 WSL2IP:WSL共享目录 开发板挂载点
mount -t nfs -o rw,sync,vers=3,nolock 192.168.31.110:/home/pi/imx/mount /mnt
mount -t nfs -o nolock,vers=3 192.168.31.110:/home/pi/imx/mount /mnt
客户端参数说明
vers=3:指定NFSv3版本(WSL的NFSv4偶尔有兼容问题,v3最稳定);
nolock:嵌入式Linux推荐,关闭文件锁(避免部分开发板锁机制报错);
rw,sync:与服务端保持一致,强化读写/同步。
步骤4:验证挂载是否成功(读写测试+查看挂载状态)
# 1. 查看挂载状态(有WSL IP和共享目录即正常)
df -h
# 2. 开发板写入测试(创建文件,WSL端可同步看到即成功)
sudo touch /mnt/nfs/test_from_board.txt
sudo echo "开发板挂载NFS成功" > /mnt/nfs/test_from_board.txt
# 3. WSL端验证(回到WSL执行,能看到文件内容即读写正常)
cat /home/pi/imx/mount/test_from_board.txt
可选:在 fstab自动挂载
# 编辑fstab,添加挂载规则
sudo vim /etc/fstab
# 写入以下内容(WSL2IP+共享目录+开发板挂载点,按实际修改)
192.168.31.110:/home/pi/imx/mount /mnt/nfs nfs rw,sync,vers=3,nolock 0 0
# 生效配置(无报错即正常)
sudo mount -a
⚠️ 注意:若WSL2重启后IP变化,需更新 /etc/fstab中的WSL IP(WSL2静态IP可自行配置,解决IP变动问题)。
开发板卸载NFS目录(如需)
#正常卸载sudoumount/mnt/nfs# 强制卸载(挂载卡死时用)
sudo umount -lf /mnt/nfs
三、核心避坑点(WSL+开发板NFS挂载高频问题)
WSL版本:必须WSL2,WSL1不支持网络转发和NFS核心功能;
共享目录位置:禁止在 /mnt/c/d创建,仅在WSL /home/下创建(权限生效);
参数格式:/etc/exports中参数无任何空格,中文括号/逗号会导致解析失败;
IP合法性:客户端规则不能写 192.168.31.xxx占位符,用合法格式(网段/具体IP/*);
双重权限校验:不仅要NFS配置 rw,还要给WSL共享目录加 777Linux本地权限;
WSL IP变动:WSL2重启后IP会变,需重新记录并更新开发板挂载命令/fstab。
四、故障快速排查(按顺序查,99%问题可解决)
现象1:开发板 showmount -e WSLIP → 提示 No route to host
排查:WSL与开发板是否同一内网?WSL防火墙是否开放111/2049端口?WSL的rpcbind/nfs-server是否启动?
解决:重启路由器/重新连网;WSL执行 sudo ufw disable(临时关防火墙);重启NFS服务 sudo service nfs-kernel-server restart。
现象2:开发板挂载 → 提示 Permission denied
排查:WSL的 /etc/exports是否加 insecure和 no_root_squash?共享目录是否 777权限?客户端是否用 sudo挂载?
解决:重新配置 /etc/exports并加载;给目录加 chmod 777;开发板挂载命令加 sudo。
现象3:WSL执行 sudo exportfs -v → 无输出/解析失败
排查:/etc/exports格式是否错误?客户端IP/网段是否合法?共享目录是否存在?
解决:重新用 echo覆盖写入合法配置;检查目录是否创建;客户端规则用 192.168.31.0/24或 *。
现象4:开发板挂载成功但能读不能写
排查:WSL共享目录Linux本地权限是否不足?/etc/exports是否误写 ro?
解决:执行 chmod -R 777 共享目录;检查 /etc/exports确保是 rw而非 ro,重新加载配置。