Linux驱动配置:驱动移植与设备树实例工程实践 - 第1节
1.1 交叉编译工具链安装
嵌入式Linux开发与桌面开发最大的区别在于交叉编译。目标板(ARM/RISC-V/MIPS)资源有限,无法直接运行本地编译器,因此需要在性能强大的宿主机(x86_64)上安装交叉编译工具链,生成目标架构的可执行文件。
1.1.1 工具链获取方式
| 方式 | 适用场景 | 典型命令/路径 |
|---|---|---|
| 发行版包管理器 | 快速验证、通用ARM平台 | sudo apt install gcc-arm-linux-gnueabihf |
| 芯片厂商SDK | 量产项目、特定SoC优化 | NXP Yocto / TI Processor SDK |
| Linaro预编译包 | ARMv7/ARMv8标准工具链 | gcc-linaro-7.5.0-2019.12-x86_64_arm-linux-gnueabihf.tar.xz |
| Buildroot/Yocto自编译 | 深度定制、全系统构建 | make toolchain |
1.1.2 安装步骤(以Linaro ARM工具链为例)
- 下载工具链压缩包到
/opt/toolchains/目录。 - 解压并确认路径:
cd /opt/toolchains/
sudo tar -xvf gcc-linaro-7.5.0-2019.12-x86_64_arm-linux-gnueabihf.tar.xz
ls gcc-linaro-7.5.0-2019.12-x86_64_arm-linux-gnueabihf/bin/
# 应看到 arm-linux-gnueabihf-gcc, arm-linux-gnueabihf-ld 等文件
- 将工具链加入
PATH环境变量(建议写入~/.bashrc):
export PATH=/opt/toolchains/gcc-linaro-7.5.0-2019.12-x86_64_arm-linux-gnueabihf/bin:$PATH
- 验证安装:
arm-linux-gnueabihf-gcc --version
# 输出应显示版本号,如 "arm-linux-gnueabihf-gcc (Linaro GCC 7.5-2019.12)"
提示: 交叉编译工具链的命名规则为
arch-vendor-os-abi。例如 arm-linux-gnueabihf 表示 ARM 架构、Linux 系统、使用硬浮点 ABI。选择错误的工具链会导致内核编译失败或运行时崩溃。
1.2 内核源码获取与解压
Linux内核源码可以从 kernel.org 官方仓库或芯片厂商提供的定制内核仓库获取。本课程使用长期支持版本(LTS)进行实践。
1.2.1 源码获取方式对比
| 方式 | 命令/操作 | 优点 | 缺点 |
|---|---|---|---|
| wget 下载压缩包 | wget https://cdn.kernel.org/pub/linux/kernel/v6.x/linux-6.1.38.tar.xz |
稳定、可校验哈希 | 下载大文件较慢 |
| git 克隆主线仓库 | git clone git://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git |
可切换分支、增量更新 | 首次克隆数据量大 |
| 厂商BSP源码包 | 从NXP/TI/ST官网获取 | 包含板级配置和补丁 | 版本可能滞后 |
1.2.2 解压与目录结构
tar -xvf linux-6.1.38.tar.xz -C ~/workspace/
cd ~/workspace/linux-6.1.38/
ls -F
解压后,内核源码顶层目录包含以下关键子目录:
- arch/ — 体系结构相关代码(arm64, x86, riscv 等)
- drivers/ — 设备驱动代码(char, net, i2c, spi 等)
- include/ — 内核头文件
- Documentation/ — 内核文档(设备树绑定、API说明)
- scripts/ — 编译脚本、设备树编译工具
实践要点: 建议在
~/workspace/ 下建立 linux-<version> 目录,并创建软链接 linux 指向当前工作版本,方便多版本切换。
1.3 内核配置(menuconfig)
内核配置是决定哪些功能、驱动被编译进内核的关键步骤。menuconfig 是基于 ncurses 的图形化配置界面,是嵌入式开发中最常用的配置方式。
1.3.1 配置流程
- 加载默认配置(以 ARM64 为例):
make ARCH=arm64 CROSS_COMPILE=aarch64-linux-gnu- defconfig
- 启动图形化配置界面:
make ARCH=arm64 CROSS_COMPILE=aarch64-linux-gnu- menuconfig
- 在界面中导航:
- 方向键 — 上下移动
- Enter — 进入子菜单
- Y — 编译进内核(built-in)
- M — 编译为模块(module)
- N — 不编译
- ? — 查看帮助
- 保存退出,生成
.config文件。
1.3.2 配置项分类
| 配置类型 | 示例 | 说明 |
|---|---|---|
| bool | CONFIG_ARM64 |
Y/N 二选一 |
| tristate | CONFIG_I2C_DESIGNWARE |
Y/M/N 三选一(驱动常用) |
| int | CONFIG_HZ |
输入整数值 |
| string | CONFIG_DEFAULT_HOSTNAME |
输入字符串 |
常见错误: 直接修改
.config 文件而不执行 menuconfig 或 oldconfig,会导致依赖关系不一致,编译时出现 undefined reference 或 implicit declaration 错误。务必使用 make oldconfig 更新依赖。
1.4 内核编译流程
配置完成后,执行编译命令生成内核镜像(Image/zImage)和设备树二进制文件(.dtb)。
1.4.1 编译命令详解
# 编译内核镜像(ARM64 生成 Image)
make ARCH=arm64 CROSS_COMPILE=aarch64-linux-gnu- -j$(nproc) Image
# 编译设备树
make ARCH=arm64 CROSS_COMPILE=aarch64-linux-gnu- -j$(nproc) dtbs
# 编译内核模块
make ARCH=arm64 CROSS_COMPILE=aarch64-linux-gnu- -j$(nproc) modules
# 安装模块到目标目录
make ARCH=arm64 CROSS_COMPILE=aarch64-linux-gnu- INSTALL_MOD_PATH=~/rootfs modules_install
1.4.2 编译产物清单
| 文件 | 路径 | 说明 |
|---|---|---|
Image |
arch/arm64/boot/Image |
未压缩的内核镜像(ARM64) |
zImage |
arch/arm/boot/zImage |
压缩的内核镜像(ARM32) |
*.dtb |
arch/arm64/boot/dts/<vendor>/ |
编译后的设备树二进制文件 |
vmlinux |
源码根目录 | 未压缩的ELF格式内核(调试用) |
System.map |
源码根目录 | 内核符号表 |
1.5 完整编译流程SVG架构图
下图展示了从源码获取到生成最终烧录镜像的完整编译流水线:
1.6 常见编译问题与排查
| 错误现象 | 根本原因 | 解决方案 |
|---|---|---|
arm-linux-gnueabihf-gcc: command not found |
工具链未加入 PATH | 检查 export PATH 是否生效,或使用绝对路径 |
*** Can't find default configuration "arch/arm64/configs/defconfig" |
ARCH 或 CROSS_COMPILE 设置错误 | 确认目标架构,ARM64 使用 ARCH=arm64 |
undefined reference to `__aeabi_uidiv' |
工具链 ABI 不匹配(软浮点 vs 硬浮点) | 使用 gnueabihf 工具链,或配置 CONFIG_AEABI |
Kernel panic - not syncing: VFS: Unable to mount root fs |
根文件系统驱动未编译进内核 | 确保 CONFIG_EXT4_FS 等文件系统驱动为 built-in |
调试技巧: 编译时添加
V=1 参数(如 make V=1)可输出完整编译命令,便于定位头文件路径、链接顺序等问题。首次编译建议使用 make -j1 观察完整输出,确认无误后再启用多核并行编译。
1.7 本章小结
本章完成了嵌入式Linux内核编译环境的完整搭建:
- 安装交叉编译工具链并验证其可用性
- 获取并解压内核源码,熟悉顶层目录结构
- 使用
menuconfig进行内核功能配置 - 执行编译命令生成内核镜像、设备树和模块
- 掌握常见编译错误的排查方法