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        # 内核配置

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值