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 图形化配置工具进行操作:
- 进入内核源码目录并启动配置界面
cd /path/to/linux-kernel make ARCH=arm menuconfig # 根据目标架构调整 ARCH 参数 - 使能 USB Gadget 支持
依次进入菜单:
Device Drivers → USB support → USB Gadget Support,将<*> USB Gadget Support选中为编译进内核。 - 使能 USB Gadget Configfs
在同一菜单下,找到
<M> USB Gadget Configfs并设置为模块。 - 选择目标板 UDC 驱动
在
USB Gadget Support → USB Peripheral Controller中,选择与硬件匹配的 UDC 驱动(如DWC2、DWC3、Fotg210等)。 - 使能所需功能驱动
在
USB Gadget Support → USB Gadget precomposed configurations下,将以下功能设置为模块:Serial Gadget (with CDC ACM support)Ethernet Gadget (with CDC ECM support)Mass Storage GadgetHID Gadget
- 保存配置并退出
选择
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 各配置项之间的依赖关系与数据流路径:
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 内核配置与编译部署工作已完成,可以进入下一阶段的复合设备功能配置。