1. 课程导入
在嵌入式 Linux 开发中,设备树(Device Tree,简称 DT)已经成为 ARM、RISC-V、PowerPC 等架构描述硬件资源的标准机制。它把“板级硬件信息”从内核源码中剥离出来,用一份可读、可编译、可复用的文本描述硬件拓扑,让同一份内核镜像能够适配不同主板。本课程围绕“设备树驱动适配工程”展开,目标不是停留在会写几个节点,而是建立从硬件描述、内核解析、驱动匹配到调试验证的完整工程能力。
一、核心概念:设备树到底描述了什么
设备树本质上是一棵由节点(node)和属性(property)组成的层次化数据结构。根节点 / 下通常包含 chosen、memory、cpus、soc 等子节点;soc 内部再挂载 i2c、spi、uart、gpio、ethernet 等控制器节点,外设则作为这些控制器的子节点出现。内核启动时,bootloader 把编译后的 DTB 传给内核,内核的 OF(Open Firmware)子系统将其展开为 device_node,再进一步生成 platform_device 等设备对象,最终与驱动中的 of_match_table 完成匹配。
需要特别区分三个层次:DTS 是源码,DTB 是二进制,设备树是运行时内核中的数据结构。很多初学者把“改 dts”等同于“改驱动”,实际上设备树负责“告诉内核有什么硬件、资源在哪里”,驱动负责“怎么操作这个硬件”,二者通过 compatible 字符串和资源接口解耦。
二、整体知识框架与实战路线图
本课程的知识框架可以概括为“一条主线、四个层次、两类调试”。一条主线是“硬件描述 → 内核解析 → 驱动匹配 → 功能验证”;四个层次分别是语法层、资源层、驱动层和板级适配层;两类调试是静态检查(dtc 编译、schema 校验)和动态调试(probe 日志、sysfs、debugfs、示波器/逻辑分析仪)。
从路线图可以看出,学习顺序建议为:先掌握 DTS 语法和编译工具链,再理解内核如何把节点变成设备,然后进入具体总线驱动(platform、i2c、spi)的匹配与资源获取,最后通过真实板级案例完成从原理图到功能验证的闭环。每一层都要配合调试手段,否则很容易陷入“改了不生效、错了不知道”的状态。
三、典型场景:从原理图到驱动 probe 的完整链路
假设我们要在一块基于 i.MX6ULL 的板子上适配一颗挂在 I2C1 上的温湿度传感器 SHT30。工程动作大致如下:
- 查阅原理图,确认 SHT30 的 I2C 地址为
0x44,SCL/SDA 分别复用为I2C1_SCL和I2C1_SDA,供电由3V3提供。 - 在板级 dts 中确认
&i2c1节点已使能,并补充 pinctrl 与时钟。 - 在
&i2c1下新增子节点,填写compatible、reg等属性。 - 确认内核中已有对应驱动,且其
of_match_table包含相同 compatible。 - 编译 DTB、更新启动镜像,观察
dmesg中是否出现 probe 成功日志。 - 通过
/sys/bus/i2c/devices/和传感器字符设备节点验证数据读取。
&i2c1 {
status = "okay";
clock-frequency = <100000>;
pinctrl-names = "default";
pinctrl-0 = <&pinctrl_i2c1>;
sht30: sensor@44 {
compatible = "sensirion,sht30";
reg = <0x44>;
status = "okay";
};
};
这段代码虽短,却覆盖了资源层和驱动层的核心:status 控制节点是否生效,reg 决定 I2C 从地址,compatible 决定匹配哪个驱动。任何一个写错,都会导致 probe 失败或设备不可用。
四、常见误区与复盘要点
| 误区 | 现象 | 正确做法 |
|---|---|---|
| 只改 dts 不看驱动 compatible | 驱动不 probe,无日志 | 核对驱动 of_match_table 与 dts 字符串完全一致 |
| 忽略 pinctrl 与时钟 | 寄存器读写失败、总线无波形 | 先确认引脚复用和时钟使能,再查设备地址 |
| 把 status 写成 disabled | 节点存在但设备不生成 | 确认目标节点 status = "okay" |
| reg 地址与原理图不符 | I2C 通信超时或读回 0xFF | 用 i2cdetect 扫描总线,确认从地址 |
| 只依赖 printk 不看设备树运行时状态 | 排查效率低 | 查看 /sys/firmware/devicetree/base 与 debugfs |
本课程后续将沿着这条路线逐步展开:从 DTS 语法与编译、OF 子系统原理,到 platform/I2C/SPI 驱动匹配,再到中断、时钟、pinctrl、GPIO 等资源获取,最后通过多个真实板级案例完成综合适配训练。掌握这套框架后,你面对一块新板子时,就能有条不紊地完成从原理图到驱动可用的全过程。