1. 课程导论:嵌入式设备树与ACPI的起源、设计目标、适用场景对比

在嵌入式Linux系统中,硬件描述是操作系统与硬件平台之间的“通信契约”。设备树(Device Tree)与高级配置与电源管理接口(ACPI)是当前两大主流硬件描述规范。本章从历史起源、设计哲学与适用场景三个维度,对两者进行系统性对比,为后续兼容设计奠定认知基础。

1.1 起源:从“硬编码”到“可描述”的演进

早期嵌入式Linux内核通过大量board-*.c文件硬编码硬件信息,导致内核源码与特定板卡高度耦合,维护成本急剧上升。2005年前后,PowerPC架构率先引入设备树(Flattened Device Tree, FDT),随后被ARM架构采纳,成为嵌入式领域的事实标准。

ACPI则起源于1990年代PC/服务器生态,由Intel、Microsoft、Toshiba等公司联合制定,旨在统一x86平台的电源管理与设备枚举。ACPI最初以DSDT(Differentiated System Description Table)为核心,逐步演变为涵盖硬件描述、热管理、性能调优的完整规范。

关键转折点: 2012年,Linux内核主线强制要求ARM架构使用设备树,标志着嵌入式硬件描述进入标准化时代。同期,ACPI在ARM服务器领域(如Ampere、华为鲲鹏)开始扩展,形成两大规范的交汇。
硬件描述规范演进时间线 硬编码 board-*.c 2000~2005 设备树 FDT 2005~2012 ARM 强制设备树 2012 ACPI on ARM 2016~至今 趋势:从平台耦合 → 标准化描述 → 跨架构兼容

1.2 设计目标:静态描述 vs. 动态配置

设备树与ACPI虽然都用于描述硬件,但其设计目标存在本质差异:

对比维度 设备树 (Device Tree) ACPI
核心目标 提供静态的硬件拓扑描述,减少内核与板级代码耦合 提供动态的硬件配置与电源管理接口,支持操作系统运行时控制
数据格式 文本化 .dts 源文件,编译为二进制 .dtb AML (ACPI Machine Language) 字节码,由解释器执行
运行时行为 只读,内核启动时一次性解析,后续不修改 可读写,支持动态方法调用(如 _PS0 唤醒设备)
电源管理 依赖驱动自身实现,设备树仅提供寄存器地址 内置 _PSx、_PRx 等标准电源对象,统一管理
热插拔支持 有限,需额外驱动逻辑 原生支持 PCIe/USB 热插拔事件
固件依赖 Bootloader 加载 dtb 传递给内核 UEFI 固件提供 ACPI 表,内核解析
设计哲学总结: 设备树是“硬件描述语言”,ACPI是“硬件虚拟机”。设备树告诉内核“有什么”,ACPI告诉内核“怎么用”。
设备树 vs ACPI 设计目标对比 设备树 (Device Tree) 静态硬件拓扑描述 一次性解析,只读 驱动自行管理电源 Bootloader 传递 dtb 适合固定硬件平台 ACPI 动态硬件配置接口 AML 字节码解释执行 标准电源对象 _PSx UEFI 固件提供表 适合复杂动态平台 设计哲学差异

1.3 适用场景:嵌入式 vs. 通用计算

选择设备树还是ACPI,本质上取决于目标平台的硬件复杂度、电源管理需求以及生态兼容性要求。

设备树主导的场景

  • ARM Cortex-M/R/A 嵌入式系统: 资源受限,无需复杂电源管理,设备树轻量级优势明显。
  • FPGA SoC 平台: 如 Xilinx Zynq、Intel SoC FPGA,设备树可灵活描述可编程逻辑侧硬件。
  • 物联网与边缘设备: 固定硬件拓扑,无热插拔需求,设备树编译后体积小(通常 < 50KB)。
  • 实时操作系统(RTOS)混合系统: 设备树可被多种操作系统解析,便于裸机与Linux共享硬件描述。

ACPI主导的场景

  • x86/ARM 服务器: 需要标准化的电源管理(如 P-state、C-state)、热管理、PCIe 热插拔。
  • PC/笔记本/平板: 需要支持 S3/S4 休眠、电池管理、屏幕亮度调节等高级功能。
  • 多操作系统共存环境: ACPI 由固件提供,Windows/Linux/BSD 均可直接使用,无需修改内核。
  • 虚拟化平台: ACPI 提供虚拟电源按钮、虚拟 PCIe 设备枚举等 Hypervisor 友好接口。
常见误区: 并非所有ARM平台都只能用设备树。ARM服务器(如Ampere Altra、华为鲲鹏920)已全面采用ACPI,以兼容企业级Linux发行版和虚拟化栈。同样,x86嵌入式系统(如Intel Atom、AMD Ryzen Embedded)也可使用设备树,但需额外适配。
设备树与ACPI适用场景分布 硬件复杂度 → 低 高 电源管理需求 → 设备树 嵌入式/物联网/FPGA ACPI 服务器/PC/笔记本 虚拟化/多OS共存 兼容 设计区域 本课程重点:在兼容设计区域(绿色)实现设备树与ACPI的统一驱动框架

1.4 兼容设计的必要性

随着ARM服务器、边缘计算网关、混合关键系统等场景的兴起,同一款SoC或驱动IP可能同时面对设备树和ACPI两种环境。兼容设计不再是“二选一”,而是要求驱动开发者:

  1. 抽象硬件访问层: 将寄存器读写、中断映射、时钟控制等操作封装为通用接口,屏蔽描述格式差异。
  2. 统一电源管理回调: 设备树驱动的.suspend/.resume与ACPI驱动的_PS0/_PS3方法需映射到同一套PM逻辑。
  3. 资源获取抽象: 设备树通过of_property_read_*获取资源,ACPI通过acpi_dev_get_resources获取,两者需在驱动入口处统一。
  4. 编译时/运行时选择: 通过IS_ENABLED(CONFIG_OF)和IS_ENABLED(CONFIG_ACPI)宏实现条件编译,或通过device_match运行时判断。
课程目标: 学完本课程后,你将能够编写一份驱动代码,同时支持设备树和ACPI两种硬件描述方式,无需为每个平台维护独立驱动版本。

1.5 本章小结

要点 核心结论
起源差异 设备树源于嵌入式解耦需求,ACPI源于PC/服务器标准化需求
设计目标 设备树是静态描述,ACPI是动态配置接口
适用场景 设备树主导嵌入式固定平台,ACPI主导通用计算动态平台
兼容趋势 ARM服务器与边缘计算推动两者融合,驱动需统一抽象