RK3566 LubanCat 开发板 USB Gadget 配置完整复盘

> **作者**: 郑智乾
> **职位**: LINUX驱动开发
> **日期**: 2026-02-01
> **平台**: RK3566 LubanCat 开发板
> **系统**: Ubuntu 20.04 (Focal) Lite
> **内核**: Linux 6.1


## 前言

这是一篇完整的技术复盘文章,记录了我在 RK3566 LubanCat 开发板上配置 USB Gadget 功能(NCM 网卡 + ADB 调试)的全过程。从最初的需求分析,到中途踩过的各种坑,再到最终成功解决问题,整个过程充满了曲折。希望这篇文章能帮助到同样在嵌入式 Linux USB 功能配置上遇到困难的开发者。


## 第一章:需求分析与背景

### 1.1 我的需求是什么?

我有一块 RK3566 LubanCat 开发板,希望实现以下功能:

| 功能 | 描述 | 用途 |

|------|------|------|

| **USB NCM 网卡** | 通过 USB OTG Type-C 连接电脑后,在电脑上创建一个虚拟网卡 | 方便调试,不依赖网线 |

| **ADB 调试** | 支持 Android Debug Bridge | 文件传输、命令行调试 |

| **USB ACM 串口** | USB 虚拟串口 | 日志输出、串口调试 |

| **以太网 DHCP** | 插网线后自动获取 IP | 正常上网 |

| **SSH 远程登录** | 允许 root 用户通过 SSH 登录 | 远程管理 |

### 1.2 网络架构设计

```

┌─────────────────┐

│ 路由器 │

│ (DHCP 服务器) │

└────────┬────────┘

│ eth0 (DHCP: 如 192.168.1.100)

│ ← 上网用,默认网关

┌──────────────────┐ │

│ Windows/Mac │ ┌────┴────┐

│ 192.168.100.2 │ │ RK3566 │

└────────┬─────────┘ │ 开发板 │

│ └──────────┘

└──────────────┤

usb0 (NCM)

192.168.100.1 (无网关,本地通信)

```

设计要点:

  • **以太网 eth0**:通过 DHCP 自动获取 IP,用于上网,有默认网关

  • **USB NCM usb0**:静态 IP 192.168.100.1,仅用于开发板与电脑的本地通信,**无网关**(避免路由冲突)

### 1.3 技术背景知识

什么是 USB Gadget?

USB Gadget 是 Linux 内核提供的一种机制,允许设备作为 USB 从设备(Device)与主机(Host)通信。常见的 USB Gadget 功能包括:

| 功能 | 缩写 | 说明 |

|------|------|------|

| Android Debug Bridge | ADB | 安卓调试桥,支持文件传输和命令行 |

| Network Control Model | NCM | USB 网卡,macOS/Linux 原生支持 |

| Remote NDIS | RNDIS | USB 网卡,Windows 原生支持 |

| USB Video Class | UVC | USB 摄像头 |

| Abstract Control Model | ACM | USB 虚拟串口 |

| Mass Storage | MSC | USB 大容量存储 |

LubanCat SDK 构建系统

LubanCat SDK 是野火针对 RK3566/RK3568 芯片定制的开发套件,基于 Rockchip 官方 SDK。其构建流程大致如下:

```

./build.sh defconfig → 加载板卡配置

./build.sh kernel → 编译内核

./build.sh rootfs → 编译根文件系统

./build.sh all → 编译全部

./rkflash.sh → 烧录到开发板

```


## 第二章:第一次尝试------修改错误的配置文件

### 2.1 最初的错误思路

一开始,我直接去修改 `output/.config` 文件,以为这样就能改变编译配置:

错误的做法!

vim output/.config

添加 RK_USB_NCM=y 等配置

然后重新编译... 结果发现配置没有生效。

### 2.2 问题分析

`output/.config` 是编译时**自动生成**的临时配置文件,每次执行 `./build.sh defconfig` 都会被覆盖。真正的永久配置文件在:

```

device/rockchip/.chips/rk3566_rk3568/LubanCat_rk3566_ubuntu_lite_defconfig

```

这是一个关键的认知错误,浪费了不少时间。

### 2.3 正确的做法

修改板卡的 defconfig 文件:

device/rockchip/.chips/rk3566_rk3568/LubanCat_rk3566_ubuntu_lite_defconfig

USB Gadget functions

RK_USB_NCM=y

RK_USB_ACM=y

RK_USB_UVC is not set # 不启用摄像头功能

**教训一**:永远要搞清楚配置文件的层级关系,修改源头配置而非生成的临时文件。


## 第三章:第二次尝试------内核缺少 NCM 支持

### 3.1 新的错误信息

修改 defconfig 后重新编译,启动开发板发现新的错误:

```

Your kernel doesn't support USB gadget: ncm

Please enable: CONFIG_USB_CONFIGFS_NCM

```

### 3.2 问题分析

SDK 的 defconfig 只是告诉编译系统"我需要 NCM 功能",但内核本身也需要支持这个功能。内核配置和 SDK 配置是**两套独立的系统**。

### 3.3 解决方案

需要同时修改内核的 defconfig:

kernel-6.1/arch/arm64/configs/lubancat_linux_rk356x_defconfig

添加以下配置

CONFIG_USB_CONFIGFS_NCM=y

CONFIG_USB_CONFIGFS_ECM=y

然后重新编译内核:

./build.sh kernel

**教训二**:USB Gadget 功能需要**双重配置**------SDK defconfig + 内核 defconfig。


## 第四章:第三次尝试------Ubuntu rootfs 不执行 overlay 脚本

### 4.1 又一个坑

按照 Rockchip 官方文档,USB Gadget 的运行时配置应该放在:

```

device/rockchip/common/overlays/rootfs/usb-gadget/

```

然后通过 `post-hooks` 机制在编译时复制到 rootfs 中。

我按照这个思路创建了配置文件,编译后挂载 rootfs 镜像检查... 配置文件不存在!

### 4.2 深入分析

通过阅读编译脚本,我发现了一个关键事实:

> **Ubuntu rootfs 的构建流程不会执行 `device/rockchip/common/post-hooks/` 中的脚本!**

这个机制只对 Buildroot 和 Debian 系统生效。对于 Ubuntu 系统,overlay 文件必须直接放在:

ubuntu20.04/overlay/

这个目录下的文件会被**直接复制**到 rootfs 根目录。

### 4.3 正确的文件结构

ubuntu20.04/overlay/

├── etc/

│ ├── profile.d/

│ │ └── usbdevice.sh # USB 功能环境变量

│ ├── usbdevice.d/

│ │ └── ncm.sh # NCM 网卡 IP 配置

│ ├── ssh/

│ │ └── sshd_config # SSH 配置

│ ├── netplan/

│ │ └── 01-network-manager-all.yaml # 以太网 DHCP

│ └── systemd/system/

│ └── sysinit.target.wants/

│ └── usbdevice.service # 软链接,启用服务

**教训三**:不同的 rootfs 类型有不同的 overlay 机制,一定要阅读构建脚本确认。

## 第五章:第四次尝试------usbdevice 服务未启用

### 5.1 服务没有自动启动

配置文件都放对位置了,编译烧录后开机... USB 功能还是不工作。

在开发板上检查:

systemctl status usbdevice

结果:inactive (dead)

服务没有启动!

### 5.2 问题根源

虽然 `usbdevice.service` 文件存在于 `/lib/systemd/system/` 目录,但 systemd 不会自动启用它。需要创建一个软链接来告诉 systemd "开机时启动这个服务"。

### 5.3 解决方案

在 overlay 中创建启用软链接:

mkdir -p ubuntu20.04/overlay/etc/systemd/system/sysinit.target.wants

ln -sf /lib/systemd/system/usbdevice.service \

ubuntu20.04/overlay/etc/systemd/system/sysinit.target.wants/usbdevice.service

这个软链接会被复制到 rootfs 中,系统启动时 systemd 就会自动启动 usbdevice 服务。

**教训四**:systemd 服务需要显式启用,即使服务文件存在也不会自动运行。


## 第六章:第五次尝试------UVC 导致整个 USB Gadget 崩溃

### 6.1 最棘手的问题

这是整个调试过程中最难发现的问题。

之前为了"以后可能会用到",我启用了 UVC(USB 摄像头)功能:

export USB_FUNCS="adb acm uvc ncm"

结果开发板连接电脑后,Windows **完全没有任何反应**。以前至少会有"咚"的一声提示音,现在连这个都没有了。

### 6.2 诊断过程

在开发板上查看日志:

cat /tmp/usbdevice.log

发现大量错误:

Starting functions: uvc adb acm ncm

/usr/bin/usbdevice: 369: cd: can't cd to .../uvc.gs6/...

ln: failed to create symbolic link '...': Device or resource busy

mkdir: cannot create directory '480p': Operation not permitted

mkdir: cannot create directory '720p': Operation not permitted

### 6.3 问题分析

UVC 功能需要硬件支持(实际的摄像头传感器)。当开发板上没有连接摄像头时,UVC 驱动初始化失败。

关键问题在于:**UVC 初始化失败会导致整个 USB Gadget 配置过程中断**,后续的 ADB、ACM、NCM 功能也无法正常工作。

### 6.4 解决方案

移除不需要的 UVC 功能:

ubuntu20.04/overlay/etc/profile.d/usbdevice.sh

export USB_FUNCS="adb acm ncm" # 移除 uvc

同时修改 defconfig:

device/rockchip/.chips/rk3566_rk3568/LubanCat_rk3566_ubuntu_lite_defconfig

RK_USB_NCM=y

RK_USB_ACM=y

RK_USB_UVC is not set # 禁用 UVC

**教训五**:不要启用不需要的功能!一个功能的失败可能导致整个子系统崩溃。YAGNI(You Aren't Gonna Need It)原则在嵌入式开发中尤为重要。

## 第七章:SSH 连接卡顿问题

### 7.1 意外发现的问题

在调试 USB 问题的过程中,我发现了另一个问题:SSH 连接特别慢,ping 开发板也很卡,好几秒才响应一次。

### 7.2 问题分析

这是一个经典的 SSH 配置问题。SSH 服务端默认会对客户端 IP 进行反向 DNS 查询,用于日志记录和访问控制。

但在局域网环境中,私有 IP(如 192.168.x.x)在 DNS 服务器上没有记录,查询会超时。每次操作都要等待 DNS 超时,导致严重卡顿。

### 7.3 解决方案

禁用 SSH 的 DNS 反向查询:

ubuntu20.04/overlay/etc/ssh/sshd_config

UseDNS no

GSSAPIAuthentication no

  • **UseDNS no**:禁止 SSH 对客户端 IP 做反向 DNS 查询

  • **GSSAPIAuthentication no**:禁用 Kerberos 认证(开发板用不到)

这两个选项对开发板场景没有任何负面影响,却能显著提升 SSH 响应速度。

**教训六**:遇到网络卡顿问题,优先考虑 DNS 相关配置。


## 第八章:最终配置清单

经过多次调试,以下是最终成功的完整配置:

### 8.1 SDK defconfig

**文件**: `device/rockchip/.chips/rk3566_rk3568/LubanCat_rk3566_ubuntu_lite_defconfig`

RK_UBUNTU_FOCAL=y

RK_ROOTFS_SYSTEM_UBUNTU=y

RK_ROOTFS_TARGET_LITE=y

RK_KERNEL_PREFERRED="6.1"

RK_KERNEL_CFG="lubancat_linux_rk356x_defconfig"

... 其他配置 ...

USB Gadget functions

RK_USB_NCM=y

RK_USB_ACM=y

RK_USB_UVC is not set

### 8.2 内核 defconfig

**文件**: `kernel-6.1/arch/arm64/configs/lubancat_linux_rk356x_defconfig`

CONFIG_USB_CONFIGFS_NCM=y

CONFIG_USB_CONFIGFS_ECM=y

CONFIG_USB_CONFIGFS_RNDIS=y # 已有

### 8.3 USB 功能环境变量

**文件**: `ubuntu20.04/overlay/etc/profile.d/usbdevice.sh`

USB Gadget configuration

export USB_FUNCS="adb acm ncm"

export USB_VENDOR_ID="0x2207"

export USB_FW_VERSION="0x0310"

export USB_MANUFACTURER="Rockchip"

export USB_PRODUCT="rk3xxx"

### 8.4 NCM 网卡 IP 配置

**文件**: `ubuntu20.04/overlay/etc/usbdevice.d/ncm.sh`

#!/bin/sh

NCM USB Network Configuration

ncm_post_start_hook()

{

Wait for usb0 interface to appear

for i in $(seq 50); do

if ip link show usb0 >/dev/null 2>&1; then

break

fi

sleep 0.1

done

Configure static IP for the device side

ip addr add 192.168.100.1/24 dev usb0 2>/dev/null || true

ip link set usb0 up

}

### 8.5 ADB 配置

**文件**: `ubuntu20.04/overlay/etc/profile.d/adbd.sh`

-x /bin/bash \] \&\& export ADBD_SHELL=/bin/bash export ADB_TCP_PORT=5555 #### ### 8.6 SSH 配置 \*\*文件\*\*: \`ubuntu20.04/overlay/etc/ssh/sshd_config\` # LubanCat SSH Server Configuration PermitRootLogin yes PasswordAuthentication yes PermitEmptyPasswords no ChallengeResponseAuthentication no UsePAM yes X11Forwarding yes PrintMotd no AcceptEnv LANG LC_\* Subsystem sftp /usr/lib/openssh/sftp-server # Performance optimization - disable DNS reverse lookup UseDNS no GSSAPIAuthentication no #### ### 8.7 以太网 DHCP 配置 \*\*文件\*\*: \`ubuntu20.04/overlay/etc/netplan/01-network-manager-all.yaml\` \`\`\`yaml network: renderer: NetworkManager ethernets: eth0: dhcp4: true optional: true eth1: dhcp4: true optional: true #### ### 8.8 usbdevice 服务启用 \*\*文件\*\*: \`ubuntu20.04/overlay/etc/systemd/system/sysinit.target.wants/usbdevice.service\` 这是一个软链接,指向 \`/lib/systemd/system/usbdevice.service\` --- ### ## 第九章:编译与验证 #### ### 9.1 编译命令 cd /home/zzq/workspace/rk3566/LubanCat_SDK # 清理缓存(重要!确保使用最新配置) rm -f output/ubuntu/.stamp\* rm -f ubuntu20.04/ubuntu-rk356x-lite-rootfs.img # 编译 rootfs ./build.sh rootfs # 烧录 ./rkflash.sh rootfs #### ### 9.2 验证步骤 开发板重启后,进行以下验证: # 1. 检查 USB 功能配置 echo $USB_FUNCS # 预期输出: adb acm ncm # 2. 检查 usbdevice 服务状态 systemctl status usbdevice # 预期: active (running) # 3. 检查 USB 网卡 ifconfig usb0 # 预期: 192.168.100.1 # 4. 在 Windows 电脑上 # - 设备管理器应出现 NCM 网卡 # - 执行 adb devices 应能看到设备 # 5. 测试 SSH 连接速度 # 应该秒连,不再卡顿 ### ## 第十章:经验总结 #### ### 10.1 踩过的坑 \| 序号 \| 问题 \| 原因 \| 解决方案 \| \|------\|------\|------\|----------\| \| 1 \| 修改 output/.config 无效 \| 临时生成文件,会被覆盖 \| 修改 defconfig 源文件 \| \| 2 \| 内核不支持 NCM \| 内核 defconfig 未配置 \| 添加 CONFIG_USB_CONFIGFS_NCM=y \| \| 3 \| overlay 文件未生效 \| Ubuntu 不使用 post-hooks \| 使用 ubuntu20.04/overlay/ 目录 \| \| 4 \| usbdevice 服务未启动 \| 缺少 systemd 启用软链接 \| 创建 sysinit.target.wants 软链接 \| \| 5 \| USB 设备完全无法识别 \| UVC 初始化失败导致全崩 \| 移除不需要的 UVC 功能 \| \| 6 \| SSH 连接卡顿 \| DNS 反向查询超时 \| 添加 UseDNS no \| #### ### 10.2 核心原则 通过这次调试,我深刻体会到几个软件工程原则的重要性: 1. \*\*KISS(Keep It Simple, Stupid)\*\* - 不要过度设计,能用简单方案解决的问题不要复杂化 - USB 功能只启用需要的,不要"以备将来使用" 2. \*\*YAGNI(You Aren't Gonna Need It)\*\* - 不需要的功能就不要启用 - UVC 的教训:一个不需要的功能导致整个系统崩溃 3. \*\*分层调试\*\* - 遇到问题先确定是哪一层的问题 - SDK 配置 → 内核配置 → 运行时配置 → 服务启动 4. \*\*阅读源码\*\* - 不要完全依赖文档,构建脚本才是真相 - Ubuntu 不执行 post-hooks 这个坑,只有读脚本才能发现 #### ### 10.3 调试技巧 1. \*\*检查日志\*\* cat /tmp/usbdevice.log dmesg \| grep -i usb journalctl -u usbdevice 2. \*\*验证配置是否生效\*\* # 挂载 rootfs 镜像检查 sudo mount -o loop,ro xxx.img /tmp/check cat /tmp/check/etc/profile.d/usbdevice.sh sudo umount /tmp/check 3. \*\*清理缓存\*\* rm -f output/ubuntu/.stamp\* rm -f ubuntu20.04/ubuntu-rk356x-lite-rootfs.img ## ## 结语 嵌入式 Linux 开发的魅力和痛苦并存。一个看似简单的"配置 USB 网卡"需求,实际上涉及到: - SDK 构建系统 - Linux 内核配置 - USB Gadget 子系统 - systemd 服务管理 - 网络配置 - SSH 服务优化 每一层都可能出问题,每一个细节都需要正确配置。 但正是这种复杂性,让问题解决后的成就感更加强烈。希望这篇复盘文章能帮助到遇到类似问题的开发者,少走一些弯路。 \*\*记住\*\*:当你觉得"配置应该没问题"的时候,问题往往就藏在那些被忽略的细节里。 --- ## ## 附录:完整文件清单 ubuntu20.04/overlay/ ├── etc/ │ ├── profile.d/ │ │ ├── usbdevice.sh # USB 功能环境变量 │ │ └── adbd.sh # ADB 配置 │ ├── usbdevice.d/ │ │ └── ncm.sh # NCM IP 配置脚本 │ ├── ssh/ │ │ └── sshd_config # SSH 优化配置 │ ├── netplan/ │ │ └── 01-network-manager-all.yaml # 以太网 DHCP │ └── systemd/system/ │ └── sysinit.target.wants/ │ └── usbdevice.service # 服务启用软链接 device/rockchip/.chips/rk3566_rk3568/ └── LubanCat_rk3566_ubuntu_lite_defconfig # SDK 板卡配置 kernel-6.1/arch/arm64/configs/ └── lubancat_linux_rk356x_defconfig # 内核配置

相关推荐
one____dream2 小时前
【网安】Reverse-非常规题目
linux·python·安全·网络安全·ctf
j_xxx404_2 小时前
Linux:进程程序替换
linux·运维·服务器
祁鱼鱼鱼鱼鱼2 小时前
Keepalived实验环境设定
linux·服务器·网络
Genie cloud2 小时前
VPS 网络连接故障诊断与排查实用指南
linux·服务器·ssh
RisunJan3 小时前
Linux命令-lnstat(快速查找文件和目录)
linux·运维·服务器
滴水之功3 小时前
OpenWrt的WAN和LAN的切换
linux·网络·openwrt
历程里程碑3 小时前
Linux 17 程序地址空间
linux·运维·服务器·开发语言·数据结构·笔记·排序算法
CC.GG3 小时前
【Linux】进程控制(二)----进程程序替换、编写自主Shell命令行解释器(简易版)
linux·服务器·数据库
H Journey4 小时前
Linux 下添加用户相关
linux·运维·服务器·添加用户