3. 开发环境搭建:交叉编译工具链安装、Linux内核源码获取与配置、启用USB Gadget相关内核选项
嵌入式Linux USB Gadget驱动的开发与调试,离不开一套完整、可复现的交叉编译环境。本章将带领你从零搭建这套环境,涵盖工具链安装、内核源码管理以及USB Gadget相关内核选项的配置。这是后续所有驱动实验的基石,请务必按步骤操作并验证每个环节。
3.1 交叉编译工具链安装
交叉编译工具链(Cross-Compilation Toolchain)在宿主机(x86_64)上运行,生成目标板(ARM64/AArch64)的可执行代码。我们选择通用的 aarch64-linux-gnu- 工具链,它适用于大多数基于Cortex-A系列处理器的开发板(如树莓派4B/5、RK3588、Jetson Nano等)。
3.1.1 工具链选择与下载
| 工具链名称 | 目标架构 | 适用场景 | 推荐版本 |
|---|---|---|---|
| gcc-arm-10.3-2021.07-x86_64-aarch64-none-linux-gnu | AArch64 (ARMv8-A) | 通用嵌入式Linux开发 | 10.3 |
| gcc-arm-11.2-2022.02-x86_64-aarch64-none-linux-gnu | AArch64 (ARMv8-A) | 支持新内核(5.15+) | 11.2 |
| gcc-arm-12.3-2023.07-x86_64-aarch64-none-linux-gnu | AArch64 (ARMv8-A) | 最新内核(6.x) | 12.3 |
3.1.2 安装与验证
将下载的 gcc-arm-11.2-2022.02-x86_64-aarch64-none-linux-gnu.tar.xz 解压到 /opt/toolchains/ 目录,并配置环境变量。
# 创建工具链目录
sudo mkdir -p /opt/toolchains
cd /opt/toolchains
# 解压(请根据实际下载文件名调整)
sudo tar -xvf ~/Downloads/gcc-arm-11.2-2022.02-x86_64-aarch64-none-linux-gnu.tar.xz
# 添加至PATH(建议写入 ~/.bashrc 或 ~/.zshrc)
export PATH=/opt/toolchains/gcc-arm-11.2-2022.02-x86_64-aarch64-none-linux-gnu/bin:$PATH
# 验证安装
aarch64-none-linux-gnu-gcc --version
预期输出应包含类似 aarch64-none-linux-gnu-gcc (GCC) 11.2.1 20220111 的信息。如果提示“command not found”,请检查路径是否正确。
lib32z1、lib32ncurses5、lib32stdc++6 等32位兼容库(Ubuntu/Debian下使用 sudo apt install lib32z1-dev)。
3.1.3 工具链组件清单
一个完整的交叉工具链包含以下核心组件,它们共同完成从源码到目标二进制文件的转换:
- gcc:C语言交叉编译器,将C源码编译为目标架构的汇编。
- g++:C++交叉编译器。
- ld:交叉链接器,将目标文件链接为ELF可执行文件或内核模块。
- as:交叉汇编器,将汇编代码转为机器码。
- ar、ranlib:静态库管理工具。
- objcopy、objdump:二进制文件转换与反汇编工具。
- strip:去除调试符号,减小文件体积。
3.2 Linux内核源码获取与配置
USB Gadget驱动以内核模块或内建方式运行,因此必须获取对应的内核源码树,并完成针对目标板的配置。
3.2.1 获取内核源码
推荐使用LTS(长期支持)版本,本课程以 Linux 6.1 LTS 为例。你可以从kernel.org直接下载,或使用git克隆。
# 方法一:直接下载tar包
wget https://cdn.kernel.org/pub/linux/kernel/v6.x/linux-6.1.76.tar.xz
tar -xvf linux-6.1.76.tar.xz
cd linux-6.1.76
# 方法二:git克隆(推荐,便于切换分支和打补丁)
git clone --depth=1 -b v6.1.76 https://git.kernel.org/pub/scm/linux/kernel/git/stable/linux.git
cd linux
--depth=1 参数只拉取最新提交,可大幅减少下载量。后续需要切换版本时,可使用 git fetch --unshallow 获取完整历史。
3.2.2 内核配置基础
内核配置通过 make ARCH=arm64 CROSS_COMPILE=aarch64-none-linux-gnu- menuconfig 命令启动图形化配置界面。在开始配置USB Gadget之前,需要先确定基础配置:
- 选择目标架构:
ARCH=arm64指定目标为AArch64。 - 指定交叉编译器前缀:
CROSS_COMPILE=aarch64-none-linux-gnu-。 - 加载默认配置:对于树莓派4B,可使用
make bcm2711_defconfig;对于QEMU虚拟目标,可使用make defconfig后手动调整。
# 以树莓派4B为例
make ARCH=arm64 CROSS_COMPILE=aarch64-none-linux-gnu- bcm2711_defconfig
# 进入菜单配置
make ARCH=arm64 CROSS_COMPILE=aarch64-none-linux-gnu- menuconfig
3.3 启用USB Gadget相关内核选项
USB Gadget功能在内核中由多个子系统协同实现。下面通过一个结构图展示其层级关系,然后逐一配置每个关键选项。
3.3.1 USB Gadget软件架构
3.3.2 必须启用的内核选项
在 menuconfig 中,按以下路径启用USB Gadget支持。下表列出了核心选项及其功能描述:
| 配置路径 | 选项名称 | 内核符号 | 功能说明 |
|---|---|---|---|
| Device Drivers → USB support → USB Gadget Support | USB Gadget Support | CONFIG_USB_GADGET | USB Gadget框架主开关,必须启用 |
| USB Gadget Support → USB Gadget Drivers | USB Gadget Drivers (选择 <M> 或 <*>) | CONFIG_USB_GADGET_VBUS_DRAW | 配置设备从VBUS获取的电流值(mA) |
| USB Gadget Support → USB Gadget Drivers → UDC Core | UDC (USB Device Controller) 驱动 | CONFIG_USB_GADGET_DWC2 / DWC3 | 根据硬件选择对应的UDC驱动 |
| USB Gadget Support → USB Gadget Drivers → Gadget Functions | Serial Gadget (CDC ACM) | CONFIG_USB_G_SERIAL | USB虚拟串口功能 |
| USB Gadget Support → USB Gadget Drivers → Gadget Functions | Ethernet Gadget (CDC ECM) | CONFIG_USB_G_ECM | USB虚拟网卡功能 |
| USB Gadget Support → USB Gadget Drivers → Gadget Functions | Mass Storage Gadget | CONFIG_USB_G_MASS_STORAGE | USB大容量存储功能 |
| USB Gadget Support → USB Gadget Drivers → Gadget Functions | HID Gadget | CONFIG_USB_G_HID | USB HID人机交互设备功能 |
| USB Gadget Support → USB Gadget Drivers → Gadget Functions | Audio Gadget (UAC1/UAC2) | CONFIG_USB_G_UAC1 / UAC2 | USB音频设备功能 |
| USB Gadget Support → USB Gadget Drivers → Gadget Functions | ConfigFS Gadget Support | CONFIG_USB_CONFIGFS | 通过configfs动态配置Gadget(推荐) |
3.3.3 使用menuconfig配置示例
以下是在 menuconfig 中启用关键选项的按键序列(以DWC2 UDC和ConfigFS为例):
# 进入USB Gadget主菜单
Device Drivers --->
[*] USB support --->
<M> USB Gadget Support --->
# 在USB Gadget Support子菜单中:
# 1. 启用UDC驱动(以DWC2为例)
<M> DesignWare USB2 DRD Core Support (dwc2)
# 2. 启用ConfigFS接口(必须)
<M> USB Gadget Functions --->
<M> USB Gadget ConfigFS Support
# 3. 启用常用Function模块
<M> Serial Gadget (CDC ACM)
<M> Ethernet Gadget (CDC ECM)
<M> Mass Storage Gadget
<M> HID Gadget
DesignWare USB3 DRD Core Support 而非DWC2。DWC2主要用于树莓派4B、Allwinner H3等平台。
3.3.4 验证配置结果
配置完成后,保存并退出menuconfig。使用以下命令检查关键选项是否已正确启用:
# 检查USB_GADGET是否启用
grep CONFIG_USB_GADGET .config
# 检查ConfigFS
grep CONFIG_USB_CONFIGFS .config
# 检查UDC驱动
grep CONFIG_USB_DWC2 .config
# 检查Function模块
grep CONFIG_USB_G_SERIAL .config
grep CONFIG_USB_G_ECM .config
grep CONFIG_USB_G_MASS_STORAGE .config
预期输出应显示 =y(内建)或 =m(模块),例如:
CONFIG_USB_GADGET=y
CONFIG_USB_CONFIGFS=m
CONFIG_USB_DWC2=m
CONFIG_USB_G_SERIAL=m
CONFIG_USB_G_ECM=m
CONFIG_USB_G_MASS_STORAGE=m
3.4 编译与部署验证
配置完成后,执行交叉编译,生成内核镜像和模块:
# 编译内核镜像
make ARCH=arm64 CROSS_COMPILE=aarch64-none-linux-gnu- -j$(nproc) Image
# 编译设备树
make ARCH=arm64 CROSS_COMPILE=aarch64-none-linux-gnu- -j$(nproc) dtbs
# 编译内核模块
make ARCH=arm64 CROSS_COMPILE=aarch64-none-linux-gnu- -j$(nproc) modules
# 安装模块到目标文件系统(假设挂载在 /mnt/rootfs)
make ARCH=arm64 CROSS_COMPILE=aarch64-none-linux-gnu- INSTALL_MOD_PATH=/mnt/rootfs modules_install
arch/arm64/boot/Image 和设备树文件复制到SD卡或TFTP目录,启动目标板后执行 ls /sys/kernel/config/usb_gadget/,如果看到目录存在,说明ConfigFS Gadget已正确启用。
3.5 本章小结
至此,你已经完成了嵌入式Linux USB Gadget开发环境的全部搭建工作:
- 安装了 aarch64-linux-gnu- 交叉编译工具链并验证了版本。
- 获取了 Linux 6.1 LTS 内核源码,并配置了目标板基础选项。
- 在menuconfig中启用了USB Gadget框架、UDC驱动、ConfigFS接口以及常用的Function模块。
- 完成了内核的交叉编译,并验证了关键配置项。