4. 内核配置与编译:使能 USB Gadget 相关内核选项

在构建 USB 多功能复合设备之前,必须确保目标 Linux 内核正确配置并编译了 USB Gadget 子系统。本章将指导你完成从内核选项使能、模块编译到目标板部署的完整流程。

4.1 USB Gadget 内核配置树

USB Gadget 功能依赖于内核中的 CONFIG_USB_GADGET 和 CONFIG_USB_CONFIGFS 两大核心选项。下表列出了构建复合设备所需的关键内核配置项及其作用:

配置项 依赖关系 功能描述 推荐设置
CONFIG_USB_GADGET 无 USB Gadget 框架总开关,启用设备侧 USB 支持 y(编译进内核)
CONFIG_USB_CONFIGFS 依赖 CONFIG_USB_GADGET 通过 configfs 文件系统动态配置 USB 复合设备 m(模块)
CONFIG_USB_GADGETFS 依赖 CONFIG_USB_GADGET 用户空间 Gadget 驱动接口(旧式) m
CONFIG_USB_F_FS 依赖 CONFIG_USB_CONFIGFS FunctionFS 支持,允许用户空间实现 USB 功能 m
CONFIG_USB_F_ACM 依赖 CONFIG_USB_CONFIGFS ACM 串口功能(CDC 抽象控制模型) m
CONFIG_USB_F_ECM 依赖 CONFIG_USB_CONFIGFS ECM 以太网控制模型(RNDIS 替代方案) m
CONFIG_USB_F_MASS_STORAGE 依赖 CONFIG_USB_CONFIGFS 大容量存储功能(U 盘模拟) m
CONFIG_USB_F_HID 依赖 CONFIG_USB_CONFIGFS HID 人机交互设备功能(键盘、鼠标) m
配置建议: 对于嵌入式目标板,建议将核心框架 CONFIG_USB_GADGET 编译进内核(y),而将具体功能驱动编译为模块(m)。这样可以在不重新编译内核的情况下,通过加载/卸载模块灵活切换设备功能。

4.2 内核配置操作步骤

以下步骤基于 Linux 内核源码树,使用 menuconfig 图形化配置工具进行操作:

  1. 进入内核源码目录并启动配置界面
    cd /path/to/linux-kernel
    make ARCH=arm menuconfig   # 根据目标架构调整 ARCH 参数
  2. 使能 USB Gadget 支持

    依次进入菜单:Device Drivers → USB support → USB Gadget Support,将 <*> USB Gadget Support 选中为编译进内核。

  3. 使能 USB Gadget Configfs

    在同一菜单下,找到 <M> USB Gadget Configfs 并设置为模块。

  4. 选择目标板 UDC 驱动

    在 USB Gadget Support → USB Peripheral Controller 中,选择与硬件匹配的 UDC 驱动(如 DWC2、DWC3、Fotg210 等)。

  5. 使能所需功能驱动

    在 USB Gadget Support → USB Gadget precomposed configurations 下,将以下功能设置为模块:

    • Serial Gadget (with CDC ACM support)
    • Ethernet Gadget (with CDC ECM support)
    • Mass Storage Gadget
    • HID Gadget
  6. 保存配置并退出

    选择 Save 并退出 menuconfig,配置将写入 .config 文件。

验证配置: 执行 grep CONFIG_USB_GADGET .config 确认配置项已正确写入。输出应包含:
CONFIG_USB_GADGET=y
CONFIG_USB_CONFIGFS=m
CONFIG_USB_F_ACM=m
CONFIG_USB_F_ECM=m
CONFIG_USB_F_MASS_STORAGE=m
CONFIG_USB_F_HID=m

4.3 USB Gadget 内核配置依赖关系

下图展示了 USB Gadget 各配置项之间的依赖关系与数据流路径:

USB Gadget 内核配置依赖关系图 USB 硬件控制器 (UDC) CONFIG_USB_GADGET CONFIG_USB_CONFIGFS F_ACM (串口) F_ECM (以太网) F_MASS_STORAGE F_HID (键盘/鼠标) 用户空间配置工具 说明:CONFIG_USB_GADGET 为总开关,CONFIG_USB_CONFIGFS 提供动态配置接口,各 F_* 模块实现具体 USB 功能

4.4 编译内核与模块

配置完成后,执行编译操作。推荐使用并行编译以加快速度:

# 编译内核镜像
make ARCH=arm CROSS_COMPILE=arm-linux-gnueabihf- zImage -j4

# 编译设备树
make ARCH=arm CROSS_COMPILE=arm-linux-gnueabihf- dtbs -j4

# 编译内核模块
make ARCH=arm CROSS_COMPILE=arm-linux-gnueabihf- modules -j4

# 安装模块到临时目录
make ARCH=arm CROSS_COMPILE=arm-linux-gnueabihf- modules_install INSTALL_MOD_PATH=./modules_install
交叉编译注意事项:
  • 确保交叉编译工具链已正确安装并添加到 PATH 环境变量中。
  • CROSS_COMPILE 前缀需与目标架构匹配(如 arm-linux-gnueabihf-、aarch64-linux-gnu- 等)。
  • 如果目标板使用 U-Boot 引导,可能需要将 zImage 转换为 uImage 格式:make ARCH=arm uImage。

4.5 部署到目标板

编译完成后,将生成的内核镜像、设备树文件和内核模块部署到目标板。以下是典型部署流程:

步骤 操作内容 目标路径(示例)
1 复制内核镜像到启动分区 /boot/zImage 或 /boot/uImage
2 复制设备树文件到启动分区 /boot/<board>.dtb
3 复制内核模块到根文件系统 /lib/modules/<kernel-version>/
4 更新引导加载程序配置 /boot/extlinux/extlinux.conf 或 U-Boot 环境变量
5 重启目标板并验证新内核 uname -a 检查内核版本

使用 scp 或 nfs 将文件传输到目标板:

# 通过 scp 传输内核镜像和设备树
scp arch/arm/boot/zImage root@<target-ip>:/boot/
scp arch/arm/boot/dts/<board>.dtb root@<target-ip>:/boot/

# 传输内核模块
scp -r modules_install/lib/modules/* root@<target-ip>:/lib/modules/

4.6 验证 USB Gadget 模块加载

部署完成后,登录目标板并验证 USB Gadget 相关模块是否可正常加载:

# 检查内核是否支持 USB Gadget
zcat /proc/config.gz | grep CONFIG_USB_GADGET

# 加载 configfs 模块
modprobe libcomposite

# 检查模块加载状态
lsmod | grep -E "gadget|composite|usb_f"

# 检查 configfs 挂载点
mount | grep configfs
预期输出示例:
CONFIG_USB_GADGET=y
CONFIG_USB_CONFIGFS=m

libcomposite           24576  0
usb_f_acm              16384  0
usb_f_ecm              20480  0
usb_f_mass_storage     28672  0
usb_f_hid              16384  0

configfs on /sys/kernel/config type configfs (rw,relatime)

如果 configfs 已挂载且 libcomposite 模块加载成功,说明 USB Gadget 内核配置与编译部署工作已完成,可以进入下一阶段的复合设备功能配置。