2. 开发环境搭建
Platform 驱动开发与普通应用开发最大的区别在于:驱动代码运行在内核空间,编译目标不是本机 x86 环境,而是目标开发板或 QEMU 模拟的 ARM/ARM64 平台。因此,开发环境搭建的核心是建立一条“宿主机编译 → 目标机运行”的完整链路。这条链路包含四个关键环节:交叉编译工具链、内核源码与配置、目标运行环境、驱动编译与加载。只有这四个环节全部打通,后续的字符设备、platform_driver、设备树匹配等实验才能顺利开展。
一、交叉编译工具链:从 x86 到 ARM 的桥梁
交叉编译工具链是一组运行在宿主机(通常是 x86_64 Linux)上、但生成目标平台(如 ARM32 或 ARM64)可执行代码的工具集合。它至少包含 gcc、ld、objcopy、strip 等组件。对于 Linux 内核和驱动开发,最常用的是 Linaro 或 ARM 官方提供的 GNU 工具链,命名通常形如 arm-linux-gnueabihf- 或 aarch64-linux-gnu-。
安装方式有两种:一是通过发行版包管理器安装,例如 Ubuntu 下执行 sudo apt install gcc-arm-linux-gnueabihf;二是下载官方预编译工具链并解压到 /opt 目录,再将其 bin 路径加入 PATH。安装完成后必须验证版本与目标架构是否匹配。
# 查看交叉编译器版本
arm-linux-gnueabihf-gcc -v
# 验证能否生成 ARM 目标文件
echo 'int main(){return 0;}' > test.c
arm-linux-gnueabihf-gcc test.c -o test
file test
# 输出应包含: ELF 32-bit LSB executable, ARM, EABI5
二、内核源码获取与配置
驱动必须针对某一具体内核版本编译,因为内核模块与内核之间的符号、结构体布局、配置选项强相关。获取内核源码有三种常见途径:从 kernel.org 下载主线源码、从 SoC 厂商获取 BSP 内核、或使用开发板厂商提供的 SDK。对于 QEMU 实验,推荐使用与 QEMU 机器类型匹配的主线内核,例如 linux-6.6。
获取后先解压,再进入源码目录进行配置。配置的目标是生成 .config 文件,它决定了哪些功能被编译进内核、哪些编译为模块。常用命令如下:
tar -xvf linux-6.6.tar.xz
cd linux-6.6
# 指定交叉编译器和目标架构
export ARCH=arm
export CROSS_COMPILE=arm-linux-gnueabihf-
# 使用默认配置或开发板 defconfig
make vexpress_defconfig
# 打开菜单配置,按需开启模块支持
make menuconfig
在 menuconfig 中,必须确认 Enable loadable module support 已开启,否则无法生成 .ko 文件。同时要确保 Module unloading 和 Module versioning support 按实验需求选择。配置完成后执行 make -j$(nproc) 编译内核,生成 arch/arm/boot/zImage 和 vmlinux。
三、QEMU 或开发板环境准备
目标运行环境有两种选择:QEMU 模拟器和真实开发板。QEMU 的优势是无需硬件、启动快、便于反复实验;开发板的优势是能验证真实外设和时序。对于 Platform 驱动入门,建议先用 QEMU 的 vexpress-a9 或 virt 机器跑通流程,再迁移到开发板。
QEMU 环境需要准备三样东西:内核镜像 zImage、设备树文件 vexpress-v2p-ca9.dtb、根文件系统 rootfs。根文件系统可以用 BusyBox 制作,也可以直接使用发行版提供的 initramfs。启动命令示例如下:
qemu-system-arm \
-M vexpress-a9 \
-m 512M \
-kernel arch/arm/boot/zImage \
-dtb arch/arm/boot/dts/vexpress-v2p-ca9.dtb \
-append "root=/dev/mmcblk0 rw console=ttyAMA0" \
-sd rootfs.ext4 \
-nographic
启动后若能看到内核日志并进入 shell,说明目标环境已就绪。此时可以通过 uname -a 确认内核版本,通过 ls /lib/modules 确认模块目录是否存在。
四、驱动编译与加载流程
驱动编译有两种方式:独立编译(out-of-tree)和内核树内编译。项目实战中通常采用独立编译,便于快速迭代。一个最小的驱动 Makefile 如下:
obj-m += hello_platform.o
KDIR := /home/user/linux-6.6
PWD := $(shell pwd)
all:
make -C $(KDIR) M=$(PWD) modules
clean:
make -C $(KDIR) M=$(PWD) clean
执行 make 后生成 hello_platform.ko。将该文件拷贝到目标机,使用 insmod 加载、lsmod 查看、rmmod 卸载。加载时内核会进行版本校验和符号解析,若失败可通过 dmesg 查看具体原因。
# 在目标机上操作
insmod hello_platform.ko
lsmod | grep hello
dmesg | tail -20
rmmod hello_platform
insmod 报错,排查时应优先看 dmesg 的最后几行。五、环境搭建检查清单
| 环节 | 关键检查项 | 验证命令 |
|---|---|---|
| 交叉工具链 | 版本、ABI、PATH 生效 | arm-linux-gnueabihf-gcc -v |
| 内核源码 | ARCH、CROSS_COMPILE、.config | make vexpress_defconfig |
| 内核编译 | zImage、dtb、模块支持 | make -j$(nproc) |
| QEMU/开发板 | 启动日志、shell、/lib/modules | uname -a |
| 驱动加载 | insmod、lsmod、dmesg | insmod hello_platform.ko |
下面用一张信号链式的环境拓扑图,把宿主机、工具链、内核源码、目标机与驱动模块之间的关系串联起来,帮助建立整体认知。