1. 课程导入
在 Android 系统开发中,内核是连接硬件与上层框架的“地基”,而设备树(Device Tree)则是这块地基上描述硬件资源的“施工图”。过去,大量板级硬件信息被硬编码在 arch/arm/mach-* 目录中,导致内核臃肿、移植困难;引入设备树后,硬件描述从内核代码中剥离,同一份内核镜像可以通过不同 DTB 适配多种板卡。本课程围绕“Android 内核 + 设备树 + 平台适配”这条主线,帮助你建立从硬件描述、内核配置、驱动匹配到系统启动验证的完整能力。
一、学习目标:从“能编译”到“能定位、能适配”
本课程不是单纯讲解设备树语法,而是面向真实 Android 设备开发场景,最终要达成四个层次的目标:
- 理解机制:掌握 DTS/DTB/DTBO 的编译关系、内核启动时设备树展开流程,以及
compatible属性驱动的匹配逻辑。 - 读懂硬件描述:能够阅读 SoC 级
.dtsi与板级.dts,识别 CPU、内存、中断控制器、时钟、GPIO、I2C、SPI、电源域等关键节点。 - 完成平台适配:能够为一块新板卡增删节点、修改引脚复用、配置 regulator 与 pinctrl,并让驱动正确 probe。
- 具备排障能力:能够通过串口日志、
/proc/device-tree、dmesg、dtc反编译等手段定位“驱动不加载、资源冲突、启动卡死”等问题。
二、核心概念:五个必须分清的对象
设备树体系中,最容易混淆的是源码、编译产物与运行时结构。下表给出关键对象及其作用:
| 对象 | 形式 | 作用 | 常见位置 |
|---|---|---|---|
| DTS | 文本源码 | 板级硬件描述,可读可改 | arch/arm64/boot/dts/ |
| DTSI | 文本头文件 | SoC 公共描述,被多个 DTS 包含 | 同目录或 soc/ 子目录 |
| DTB | 二进制 | 内核启动时解析的扁平设备树 | 由 DTS 编译生成 |
| DTBO | 二进制 overlay | Android 动态叠加硬件配置 | dtbo.img |
| OF 节点 | 运行时结构 | 内核中 device_node,驱动匹配依据 |
/proc/device-tree |
其中,compatible 是设备树与驱动之间的“握手字符串”。驱动中通过 of_match_table 声明支持的 compatible 列表,内核在启动时遍历设备树节点,匹配成功则调用驱动的 probe()。理解这条链路,是后续所有适配工作的基础。
三、整体知识框架:从硬件描述到 Android 启动
本课程的知识框架可以概括为“一条主线、三个层次、两类适配”。一条主线是:硬件信息如何从设备树传递到内核驱动,并最终被 Android 框架使用。三个层次分别是:
- 描述层:DTS/DTSI 语法、节点与属性、地址与中断映射、pinctrl 与 clock 引用。
- 内核层:设备树展开、platform_device 生成、driver 匹配、probe 顺序与依赖。
- Android 层:boot.img 与 dtb/dtbo 分区、vendor 分区中的内核模块、HAL 对内核节点的访问。
两类适配则是:SoC 平台适配(如高通、瑞芯微、全志等平台的启动链差异)与板级外设适配(屏幕、触摸、摄像头、传感器、Wi-Fi 等)。下图展示了从 DTS 源码到 Android 系统启动的完整数据流与关键检查点:
四、实战路线图:按阶段推进,避免“一上来就改 DTS”
很多初学者拿到新板卡后直接修改 DTS,结果编译通过但系统无法启动,排查成本极高。建议按以下路线推进:
- 环境与工具准备:搭建交叉编译环境,确认
dtc、mkdtimg、adb、串口工具可用,并获取厂商 BSP 与原理图。 - 读懂现有设备树:从 SoC
.dtsi入手,理清 CPU、内存、中断、时钟等基础节点,再对照板级.dts看差异。 - 最小系统启动:先保证串口有输出、内核能挂载 rootfs,再逐步添加外设节点。
- 单外设适配:以 I2C 触摸屏或 SPI 传感器为例,完成 pinctrl、regulator、中断、compatible 的完整配置。
- Android 集成:将 DTB/DTBO 打包进 boot 或 dtbo 分区,验证 HAL 层能否正常访问设备节点。
- 复盘与固化:记录每次修改的节点、属性与验证结果,形成板级适配文档。
dtc -I dtb -O dts 反编译现有 DTB,确认实际生效的节点结构,再决定改哪里。直接改源码而不看运行时结果,容易改错位置。
五、常见误区与复盘要点
根据以往教学与项目经验,初学者最容易踩的坑集中在以下几处:
- 把 DTS 当配置文件随意改:设备树有严格的层级与引用关系,改错父节点会导致整个子树失效。
- 忽略 pinctrl 与 regulator:驱动 probe 成功但外设不工作,往往是引脚复用未配置或电源未使能。
- compatible 拼写不一致:驱动与设备树之间只差一个字符,就会导致匹配失败且日志不明显。
- 不看启动日志:
dmesg | grep -i of_或cat /proc/device-tree/...往往能直接指出问题节点。 - 忽略 Android 分区差异:dtb 放在 boot 还是 dtbo 分区,直接影响 overlay 是否生效。
# 常用排查命令示例
dmesg | grep -i "of_platform\|probe\|failed"
ls /proc/device-tree/
cat /proc/device-tree/soc/i2c@1c2a0000/status
dtc -I dtb -O dts -o dump.dts out.dtb
本课程后续将沿着上述路线,从设备树语法与编译机制讲起,逐步深入到中断、时钟、pinctrl、regulator、Android 启动链与典型外设适配。你在学习过程中应始终围绕一个核心问题:硬件信息是如何被正确描述、正确传递、正确匹配并最终被系统使用的。只要这条链路清晰,平台适配就不再是“碰运气”,而是可分析、可验证、可复现的工程过程。