Lazy loaded image
🥳嵌入式Linux开发
🌳Linux Device Tree Overlay 机制详解
Words 1505Read Time 4 min
2026-9-2
2026-9-2
Device Tree Overlay(DT Overlay)是 Linux 内核提供的一种运行时动态修改设备树的机制。它允许在不重新编译整个 DTB 的情况下,增量式地添加、修改或覆盖设备树节点和属性,极大地提升了硬件描述的灵活性。

一、基本概念

1.1 Device Tree 回顾

Device Tree(设备树)是一种描述硬件拓扑的数据结构,内核启动时解析 DTB(Device Tree Blob)来识别和配置硬件。
术语
说明
DTS
Device Tree Source,文本格式的设备树源文件
DTC
Device Tree Compiler,将 DTS 编译为 DTB
DTB
Device Tree Blob,二进制格式,内核直接加载
DTBO
Device Tree Blob Overlay,Overlay 的二进制格式
FDT
Flattened Device Tree,DTB 在内存中的表示

1.2 为什么需要 Overlay

传统方式下,修改硬件配置需要重新编译整个 DTB 并重启。Overlay 解决了以下痛点:
  • 动态外设管理 — 运行时加载/卸载扩展板(如 BeagleBone Cape、Raspberry Pi HAT)的硬件描述
  • 减少 DTB 碎片化 — 基础 DTB 保持简洁,功能差异通过 Overlay 叠加
  • 开发调试效率 — 修改单个外设绑定无需重编译完整设备树
  • 产品线复用 — 同一基础 DTB + 不同 Overlay 组合覆盖多个 SKU

1.3 Overlay 与 Base DT 的关系

Overlay 通过 fragmenttarget 指定要修改的 Base DT 节点,然后将 __overlay__ 中的内容合并到目标节点。

二、机制流程

2.1 Overlay DTS 结构

Overlay 源文件使用 /plugin/; 声明,核心由 fragment 构成:
关键字段:
  • target — 通过 phandle(<&label>)定位 Base DT 中的目标节点
  • target-path — 通过绝对路径定位目标节点(二选一)
  • __overlay__ — 要合并到目标节点的内容

2.2 编译流程

-@ 参数是关键:它让 DTC 生成 __symbols____fixups__ 节点,使得 Overlay 能在加载时解析 phandle 引用。

2.3 内核加载机制

内核侧 Overlay 的核心 API 位于 drivers/of/overlay.c
API
功能
of_overlay_fdt_apply()
将 DTBO 应用到 Live DT,返回 overlay_id
of_overlay_remove()
通过 overlay_id 移除已应用的 Overlay
__symbols__
Base DTB 中的符号表,提供 label → path 映射
__fixups__
DTBO 中待修正的 phandle 引用列表
__local_fixups__
DTBO 内部 phandle 的偏移修正表
加载时序:
  1. 用户空间将 DTBO 写入 ConfigFS 或通过内核模块调用 API
  1. 内核解析 DTBO,根据 __fixups__ 修正 phandle
  1. __overlay__ 内容合并到 Live DT 对应节点
  1. 触发 OF_RECONFIG_* 通知链,驱动 probe 自动执行
  1. 返回 overlay_id 供后续移除使用

2.4 Overlay 移除

Overlay 遵循 LIFO(后进先出) 栈模型:
  • 只能按加载的逆序移除
  • 移除时触发对应驱动的 remove 回调
  • 恢复被覆盖的原始属性值

三、操作指南

3.1 编译 DTBO

⚠️
Base DTB 必须带 -@ 编译,否则不会生成 __symbols__ 节点,Overlay 中的 phandle 引用将无法解析。

3.2 通过 ConfigFS 加载(推荐)

3.3 通过 U-Boot 加载(启动阶段)

3.4 QEMU 环境验证

针对 QEMU sabrelite(i.MX6)开发环境的验证步骤:

3.5 调试与排错

现象
排查方向
status 显示 unapplied
检查 dmesgof_overlay 相关错误;确认 Base DTB 有 __symbols__
phandle 解析失败
确认 DTBO 用 -@ 编译;检查 target label 在 Base DT 中存在
驱动未 probe
检查 compatible 字符串匹配;确认总线控制器 status = "okay"
移除失败
确认按 LIFO 顺序移除;检查是否有用户空间进程持有设备文件
属性值未生效
Overlay 只能追加或覆盖,不能删除已有属性

四、最佳实践

  1. Base DTB 保持最小化 — 只包含 SoC 核心和共用外设,差异化通过 Overlay 叠加
  1. 使用 label 而非路径target = <&i2c1>target-path 更健壮,不受节点路径重构影响
  1. 每个外设独立一个 DTBO — 便于组合和独立调试
  1. 版本化管理 Overlay — 将 DTS 源文件纳入 Git,与驱动代码同仓管理
  1. CI 中加入 DT 校验 — 使用 dt-validatedtc -W 检查绑定合规性
上一篇
Linux 内核原子操作详解:CAS 与 Test-and-Set
下一篇
DMA溢出破坏场景的物理内存视图

Comments
Loading...