1. 设备树基础:什么是设备树(DTS/DTB/DTBO)、为什么Android需要设备树、设备树与ACPI的区别
1.1 设备树的核心概念
设备树(Device Tree)是一种描述硬件资源的数据结构,它使用节点(node)和属性(property)的树形层次来表述系统中所有可寻址的设备及其连接关系。在嵌入式Linux和Android系统中,设备树充当了硬件描述语言的角色,将板级细节从内核代码中剥离出来。
关键术语速查表
| 缩写 | 全称 | 说明 |
|---|---|---|
| DTS | Device Tree Source | 文本格式的设备树源文件,扩展名为 .dts 或 .dtsi |
| DTB | Device Tree Blob | 编译后的二进制设备树,由Bootloader加载并传递给内核 |
| DTBO | Device Tree Blob Overlay | 设备树覆盖(overlay)二进制,用于运行时动态修改基础DTB |
| DTC | Device Tree Compiler | 将DTS编译为DTB/DTBO的工具 |
一个典型的DTS文件片段如下,它描述了UART控制器及其引脚配置:
/dts-v1/;
/ {
model = "Qualcomm SA8155P ADP";
compatible = "qcom,sa8155p-adp", "qcom,sa8155p";
soc: soc@0 {
#address-cells = <2>;
#size-cells = <2>;
ranges;
uart7: serial@a84000 {
compatible = "qcom,msm-uartdm-v1.4", "qcom,msm-uartdm";
reg = <0x0 0x00a84000 0x0 0x1000>;
interrupts = <GIC_SPI 355 IRQ_TYPE_LEVEL_HIGH>;
clocks = <&gcc GCC_UART7_APPS_CLK>;
clock-names = "core";
pinctrl-names = "default", "sleep";
pinctrl-0 = <&qup_uart7_default>;
pinctrl-1 = <&qup_uart7_sleep>;
status = "okay";
};
};
};
提示:
.dtsi 文件是设备树的包含头文件,通常存放SoC级通用定义(如CPU核心、中断控制器、时钟控制器),而 .dts 文件则存放板级特有配置(如外设引脚复用、GPIO键值映射)。这种分离设计是设备树覆盖机制的基础。
1.2 设备树在Android系统中的角色
Android系统从早期版本开始就全面采用设备树来管理硬件适配。与传统的板级文件(board-*.c)相比,设备树带来了以下关键优势:
- 内核与硬件解耦:同一份内核镜像可以支持多种硬件平台,只需更换DTB即可。
- 多板型支持:通过DTBO覆盖机制,可以在不修改内核的情况下适配不同型号的硬件变体。
- 启动流程简化:Bootloader(如U-Boot、ABL)负责选择正确的DTB/DTBO,内核无需关心板级差异。
- 驱动开发标准化:驱动通过
of_match_table匹配设备树节点,无需硬编码资源地址。
下图展示了Android系统从Bootloader到内核启动过程中设备树的传递路径:
1.3 设备树与ACPI的对比
ACPI(Advanced Configuration and Power Interface)是x86平台(如PC、服务器)的标准硬件描述规范,而设备树是嵌入式/ARM平台的事实标准。两者在概念上相似,但在设计哲学、使用场景和实现细节上存在显著差异。
注意: 虽然Android主要运行在ARM/ARM64架构上,但部分x86 Android设备(如Android-x86项目)也会使用ACPI。不过,主流Android手机/平板/嵌入式设备均采用设备树。
| 对比维度 | 设备树 (Device Tree) | ACPI |
|---|---|---|
| 起源平台 | PowerPC / ARM / RISC-V | x86 / x86_64 |
| 描述方式 | 纯文本DTS → 二进制DTB | ASL (ACPI Source Language) → AML (ACPI Machine Language) |
| 运行时修改 | 支持DTBO覆盖,动态合并 | 支持DSDT覆盖,但通常需要重新编译BIOS/UEFI |
| 电源管理 | 依赖驱动实现,设备树仅提供描述 | 内置电源管理状态机(C-states, P-states) |
| 热插拔支持 | 有限,通常需要驱动配合 | 原生支持PCIe热插拔、USB等 |
| 内核集成度 | 轻量级,仅描述硬件拓扑 | 重量级,包含方法、控制逻辑、事件处理 |
| 适用场景 | 嵌入式系统、移动设备、IoT | 服务器、桌面PC、笔记本 |
下图从架构层面展示了设备树与ACPI在系统软件栈中的位置差异:
1.4 为什么Android选择设备树
Android系统选择设备树而非ACPI,主要基于以下技术考量:
- 硬件多样性:Android设备涵盖手机、平板、车载、IoT、可穿戴等形态,SoC厂商(Qualcomm、MTK、Exynos、Rockchip)均原生支持设备树。
- 启动速度:设备树解析开销远小于ACPI的AML解释执行,对Android冷启动时间敏感的场景至关重要。
- 覆盖机制:DTBO允许OEM厂商在基础DTB上叠加板级差异(如屏幕分辨率、传感器型号、GPIO映射),无需修改内核。
- 社区生态:Linux内核主线对设备树的支持成熟,Android Common Kernel(ACK)直接继承上游设备树绑定。
实践要点: 在Android BSP开发中,设备树文件通常存放在
kernel/arch/arm64/boot/dts/vendor/ 目录下。OEM厂商会创建自己的 .dts 文件,并通过 #include 引入SoC厂商提供的 .dtsi 基础定义。DTBO覆盖文件则存放在 device/vendor/board/ 目录中,与硬件抽象层(HAL)配置协同工作。