驱动移植与I2C驱动适配:设备驱动工程实践环境配置实战 - 第2节

2.1 内核源码树布局:从顶层到驱动目录

嵌入式 Linux 内核源码采用树形结构组织,顶层目录按功能模块划分。理解源码树布局是驱动移植的第一步,它决定了驱动代码应该放在哪个位置、依赖哪些核心子系统。

核心原则:驱动代码遵循“设备类型 + 总线”分类法。字符设备、块设备、网络设备、I2C 设备、SPI 设备等各有专属目录,驱动开发者只需关注对应子目录下的 Kconfig 和 Makefile。

2.1.1 顶层目录功能速查

目录名 功能描述 驱动开发者关注度
arch/ 体系结构相关代码(ARM、x86、RISC-V 等) ⭐⭐⭐⭐⭐(移植必需)
drivers/ 所有设备驱动代码 ⭐⭐⭐⭐⭐(核心工作区)
include/ 内核头文件,包含 linux/、uapi/、asm/ ⭐⭐⭐⭐(API 定义)
kernel/ 核心调度、进程管理、中断 ⭐⭐(调试时参考)
fs/ 文件系统实现 ⭐⭐(块驱动相关)
net/ 网络协议栈 ⭐⭐(网络驱动相关)
Documentation/ 内核文档、设备树绑定说明 ⭐⭐⭐(查阅规范)
scripts/ 编译脚本、Kconfig 解析工具 ⭐(自动化构建)

2.1.2 drivers/ 子目录:驱动代码的“家”

drivers/ 是驱动开发的主战场,其内部按设备类型和总线协议进一步细分:

  • i2c/ — I2C 总线控制器驱动 + I2C 设备驱动(本课程核心)
  • spi/ — SPI 总线驱动
  • gpio/ — GPIO 控制器驱动
  • input/ — 输入设备(触摸、按键、传感器)
  • char/ — 字符设备(杂项、mem、random)
  • misc/ — 杂项设备
  • pinctrl/ — 引脚控制子系统
  • clk/ — 时钟框架
  • regulator/ — 电压调节器
实战提示:在移植 I2C 触摸屏驱动时,驱动文件应放入 drivers/input/touchscreen/,而非 drivers/i2c/。I2C 总线控制器驱动才放入 drivers/i2c/busses/。设备类型优先于总线类型。
嵌入式 Linux 内核源码树核心结构 Linux 内核根 arch/ drivers/ include/ kernel/ fs/ i2c/ spi/ gpio/ input/ char/ pinctrl/ touchscreen/ keyboard/ mouse/ 📌 驱动放置规则 I2C 触摸屏驱动 → drivers/input/touchscreen/ I2C 总线控制器驱动 → drivers/i2c/busses/

2.2 Kconfig 与 Makefile 机制:驱动编译的“开关”与“配方”

Kconfig 定义驱动的配置选项,Makefile 根据配置决定是否编译以及如何编译。两者配合实现内核的模块化构建。

2.2.1 Kconfig 语法核心

Kconfig 文件位于每个驱动目录下,使用 menuconfig 工具解析。一个典型的 I2C 驱动 Kconfig 条目如下:

config TOUCHSCREEN_GT911
    tristate "Goodix GT911 I2C touchscreen"
    depends on I2C
    help
      Say Y here to support Goodix GT911 I2C touchscreen controller.
      If unsure, say N.

      To compile this driver as a module, choose M here.
关键字 含义 可选值
tristate 三态选项:不编译 / 编译进内核(Y) / 编译为模块(M) Y / M / N
bool 布尔选项:只能 Y 或 N,不能编译为模块 Y / N
depends on 依赖条件,只有条件满足时该选项才可见 I2C、SPI、OF(设备树) 等
select 反向选择,选中本选项时自动选中另一选项 如 select REGMAP_I2C
help 帮助文本,描述驱动功能 自由文本
常见错误:忘记添加 depends on I2C 会导致在非 I2C 平台上也能看到该驱动选项,编译时因缺少 I2C 核心头文件而报错。移植驱动时务必检查依赖链。

2.2.2 Makefile 编译规则

Makefile 使用 obj-$(CONFIG_xxx) 模式控制编译:

# drivers/input/touchscreen/Makefile
obj-$(CONFIG_TOUCHSCREEN_GT911)    += gt911.o
obj-$(CONFIG_TOUCHSCREEN_EDT_FT5X06) += edt-ft5x06.o
obj-$(CONFIG_TOUCHSCREEN_GOODIX)  += goodix.o

当 CONFIG_TOUCHSCREEN_GT911 为 y 时,gt911.o 被编译进内核;为 m 时编译为 gt911.ko 模块;为 n 时不编译。

2.2.3 Kconfig 层级与菜单结构

Kconfig 通过 source 语句形成树状菜单:

# drivers/Kconfig
source "drivers/i2c/Kconfig"
source "drivers/input/Kconfig"
source "drivers/gpio/Kconfig"

# drivers/input/Kconfig
source "drivers/input/touchscreen/Kconfig"

执行 make menuconfig 时,配置界面呈现为:

  • Device Drivers → Input device support → Touchscreens → Goodix GT911 I2C touchscreen
Kconfig + Makefile 驱动编译工作流 Kconfig 定义配置选项 make menuconfig 生成 .config .config CONFIG_xxx=y/m/n Makefile obj-$(CONFIG_xxx) make 编译/链接 vmlinux / .ko 内核 / 模块 读取 .config 变量 🔁 关键流程 1. Kconfig 定义选项 → 2. menuconfig 生成 .config → 3. Makefile 读取 CONFIG_xxx 4. 若 CONFIG_xxx=y → 编译进内核;若 CONFIG_xxx=m → 编译为 .ko 模块;若未定义 → 跳过 5. 驱动移植时需同时修改 Kconfig(添加条目)和 Makefile(添加 obj 规则)

2.3 内核配置与编译基础:从零构建可运行内核

内核配置与编译是驱动移植的“入场券”。本节以 ARM 平台为例,演示完整流程。

2.3.1 配置内核的三种方式

命令 界面类型 适用场景
make menuconfig 文本菜单(ncurses) 最常用,SSH 终端友好
make xconfig 图形界面(Qt) 桌面环境,搜索方便
make defconfig 默认配置 快速生成平台默认配置
make oldconfig 交互式更新 升级内核版本时保留旧配置

2.3.2 编译内核的完整步骤

  1. 清理环境:make distclean(彻底清理)或 make clean(仅清理目标文件)
  2. 加载默认配置:make ARCH=arm CROSS_COMPILE=arm-linux-gnueabihf- defconfig
  3. 自定义配置:make ARCH=arm CROSS_COMPILE=arm-linux-gnueabihf- menuconfig
  4. 编译内核:make ARCH=arm CROSS_COMPILE=arm-linux-gnueabihf- -j4 zImage
  5. 编译设备树:make ARCH=arm CROSS_COMPILE=arm-linux-gnueabihf- dtbs
  6. 编译模块:make ARCH=arm CROSS_COMPILE=arm-linux-gnueabihf- modules
  7. 安装模块:make ARCH=arm CROSS_COMPILE=arm-linux-gnueabihf- modules_install INSTALL_MOD_PATH=/path/to/rootfs
关键参数说明:
  • ARCH=arm — 指定目标体系结构
  • CROSS_COMPILE=arm-linux-gnueabihf- — 交叉编译工具链前缀
  • -j4 — 并行编译线程数,通常设为 CPU 核心数 × 1.5
  • zImage — 压缩后的内核镜像,ARM 平台常用

2.3.3 .config 文件结构解析

.config 是内核配置的最终输出文件,位于源码根目录。每行格式为:

# 注释行
CONFIG_TOUCHSCREEN_GT911=y      # 编译进内核
CONFIG_TOUCHSCREEN_EDT_FT5X06=m # 编译为模块
# CONFIG_TOUCHSCREEN_GOODIX is not set  # 不编译
调试技巧:当驱动未生效时,首先检查 .config 中对应的 CONFIG_xxx 是否被正确设置为 y 或 m。使用 grep CONFIG_TOUCHSCREEN_GT911 .config 快速定位。
内核编译完整流程 步骤1 make distclean 步骤2 make defconfig 步骤3 menuconfig 步骤4 make zImage 步骤5 make dtbs arch/arm/boot/zImage *.dtb 设备树文件 📦 编译产物清单 zImage — 压缩内核镜像,烧录到 boot 分区 *.dtb — 设备树二进制,与内核分开烧录或打包到 FIT 镜像 *.ko — 内核模块,安装到根文件系统 /lib/modules/ 目录

2.4 本章小结:驱动移植的“地图”与“工具”