一块主板可能接不同扩展板,或者同一产品在出厂后才决定启用某个外设。为每种组合维护完整 DTB 很快会重复且难以维护。设备树 Overlay(DTBO)提供增量描述:它通过 fragment 找到基础树中的目标节点,添加子节点、修改属性或启用/禁用节点;内核/Bootloader 在合适阶段将其合并到基础 DTB。它适合硬件组合变化,却不是可以随时热改任意设备状态的魔法补丁。
Overlay 怎样找到要修改的节点
fragment 使用 target(phandle)或 target-path 指向基础树节点,再在 __overlay__ 中描述变化。为让编译器保留可引用的标签和符号,基础 DTB 与 overlay 通常需要以支持符号的方式编译;编译产物会包含 __symbols__、__fixups__、__local_fixups__ 等帮助合并器修正引用。
1 | /dts-v1/; |
示例只展示表达方式。真实节点还必须按 binding 补齐 spi-max-frequency、中断、供电、复位、pinctrl 等依赖,不能因为基础板恰好残留了某种引脚状态就省略。
编译和应用时要确认什么
常见做法是使用 dtc -@ 生成带符号的 DTBO;Bootloader 可以在启动时合并,Linux 也可在配置支持时通过 configfs 动态应用。无论在哪一层应用,排查时都应看最终运行时树,确认目标属性真的已合并、设备被创建并且驱动 probe 成功。
1 | dtc -@ -I dts -O dtb -o board-addon.dtbo board-addon.dts |
路径可用不代表所有 overlay 都适合动态装卸。应用时的错误应保留完整日志,特别是符号缺失、phandle fixup 失败、节点已存在与驱动 probe defer。
卸载比加载更难
Overlay 添加的设备可能已经被其他驱动、用户态 fd、regulator、clock 或另一个 overlay 引用。移除时内核需要撤销设备和依赖,任何一个仍在使用都可能使操作失败或造成风险。对于真正可插拔的模块,应先设计设备撤销、资源关闭、引用释放和用户态通知,再把 Overlay 当作描述层。
Overlay 最适合表达“硬件组合发生变化”,而不是替代运行时的设备状态机。基础 DTB 和 DTBO 都应受版本管理、schema 检查与实机测试约束。