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 框架使用。三个层次分别是:

  1. 描述层:DTS/DTSI 语法、节点与属性、地址与中断映射、pinctrl 与 clock 引用。
  2. 内核层:设备树展开、platform_device 生成、driver 匹配、probe 顺序与依赖。
  3. Android 层:boot.img 与 dtb/dtbo 分区、vendor 分区中的内核模块、HAL 对内核节点的访问。

两类适配则是:SoC 平台适配(如高通、瑞芯微、全志等平台的启动链差异)与板级外设适配(屏幕、触摸、摄像头、传感器、Wi-Fi 等)。下图展示了从 DTS 源码到 Android 系统启动的完整数据流与关键检查点:

Android 内核与设备树平台适配主线 描述层 DTS / DTSI 源码 节点、属性、引用 编译层 dtc 编译 DTB / DTBO 镜像 内核层 展开 device_node driver 匹配 probe Android HAL / 框架 访问内核节点 关键检查点 compatible 字符串是否与驱动 of_match_table 一致 reg / interrupts / clocks / pinctrl 引用是否完整且无冲突 内核 config 是否开启对应驱动,模块是否随镜像加载 SoC 平台适配 启动链、时钟树、电源域 中断控制器、DMA 通道 厂商 BSP 与主线差异 板级外设适配 屏幕、触摸、摄像头 Wi-Fi、传感器、音频 GPIO 与 regulator 配置 验证与排障 串口日志、dmesg /proc/device-tree 检查 dtc 反编译对比

四、实战路线图:按阶段推进,避免“一上来就改 DTS”

很多初学者拿到新板卡后直接修改 DTS,结果编译通过但系统无法启动,排查成本极高。建议按以下路线推进:

  1. 环境与工具准备:搭建交叉编译环境,确认 dtc、mkdtimg、adb、串口工具可用,并获取厂商 BSP 与原理图。
  2. 读懂现有设备树:从 SoC .dtsi 入手,理清 CPU、内存、中断、时钟等基础节点,再对照板级 .dts 看差异。
  3. 最小系统启动:先保证串口有输出、内核能挂载 rootfs,再逐步添加外设节点。
  4. 单外设适配:以 I2C 触摸屏或 SPI 传感器为例,完成 pinctrl、regulator、中断、compatible 的完整配置。
  5. Android 集成:将 DTB/DTBO 打包进 boot 或 dtbo 分区,验证 HAL 层能否正常访问设备节点。
  6. 复盘与固化:记录每次修改的节点、属性与验证结果,形成板级适配文档。
建议在修改设备树前,先用 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 启动链与典型外设适配。你在学习过程中应始终围绕一个核心问题:硬件信息是如何被正确描述、正确传递、正确匹配并最终被系统使用的。只要这条链路清晰,平台适配就不再是“碰运气”,而是可分析、可验证、可复现的工程过程。