找回密码
立即注册
搜索
热搜: Java Python Linux Go
发回帖 发新帖

2275

积分

0

好友

304

主题
发表于 2 小时前 | 查看: 2| 回复: 0

设备树作为描述芯片以及单板架构、组成的一种 ABI 形式载体,其自身的构成、传输、展开与应用都遵循一套固定规则,才能做到独立于 kernel 代码、并具备更强的适配能力。作为一种独立于 kernel 镜像的 ABI 载体,它需要单独编写并生成二进制文件,再传递给 kernel;kernel 按既定规则解析所需数据,供驱动代码使用。

摘抄 kernel: usage-model.rst 的描述如下:

The "Open Firmware Device Tree", or simply Device Tree (DT), is a datastructure and language for describing hardware. More specifically, it is a description of hardware that is readable by an operating system so that the operating system doesn't need to hard code details of the machine.

设备树生命周期

Linux设备树生命周期解析:DTS/DTB到内核驱动实现 - 图片 - 1

设备树文件经历源码阶段、编译阶段、复制传输阶段、解析增添阶段,最终变成可用的 Expanded Device Tree(EDT)供驱动代码使用。

源码阶段

设备树源文件有两种尾缀:.dts.dtsi。通常意义上:

  • dtsi:定义 SoC 级别的硬件信息
  • dts:定义 board 级别的硬件信息
  • dts 通过 #include 的方式包含 dtsi 文件

设备树的代码实现遵循 device tree 协议以及各厂商规定的兼容 binding 规则,device tree 协议官网(纯 URL 前后加空格提升可读性):
https://www.devicetree.org/

Linux设备树生命周期解析:DTS/DTB到内核驱动实现 - 图片 - 2

各厂商规定的兼容 binding 规则需要在社区提交审核,最终出现在 release kernel 的 documents 中。

Linux设备树生命周期解析:DTS/DTB到内核驱动实现 - 图片 - 3

编译阶段

kernel 编译时使用 scripts 下的 dtc 工具(宿主机同样也有 dtc 工具),根据 arch/arm/boot/dts/Makefile 中的规则,将设备树源码编译成 dtb 格式的 ABI 文件。

Linux设备树生命周期解析:DTS/DTB到内核驱动实现 - 图片 - 4

复制传输阶段

dtb 文件可独立于 kernel 镜像,也可以追加到 zImage 镜像之后,再由 U-Boot 将其复制加载到 memory。

当使用前者进行复制加载时,通过 U-Boot 提供的 fdt 命令可对设备树文件进行局部修改,修改后再传递给 kernel。

Linux设备树生命周期解析:DTS/DTB到内核驱动实现 - 图片 - 5

当使用后者将 dtb 追加到 zImage 文件之后时,kernel 未提供相关的工具链。需要 kernel 打开 CONFIG_ARM_APPENDED_DTB,将 dtb 文件 cat 到 zImage 文件之后即可。

Linux设备树生命周期解析:DTS/DTB到内核驱动实现 - 图片 - 6

Linux设备树生命周期解析:DTS/DTB到内核驱动实现 - 图片 - 7

解析阶段

当 U-Boot 通过 ARM 通用寄存器 r2 将设备树 dtb 文件 memory 地址传递给 kernel 之后,kernel 会将“平铺”的 FDT 文件解析成 EDT 文件,提取 root、chosen、aliases、nodes 等信息供驱动代码使用。

相关的系统与内核启动话题,也可以在 网络/系统 里找到更多实战讨论与案例分析。

设备树的源码实现

设备树基本组成元素

vexpress-v2p-ca9.dts 为例,设备树文件的基本组成元素包括:根节点、设备类型、chosen 结点、aliases 结点、某 bus 类型的各种 node。

Linux设备树生命周期解析:DTS/DTB到内核驱动实现 - 图片 - 8

model

在设备树应用于 ARM 平台前,U-Boot 通过给 ARM 通用寄存器 r1 赋值来给 kernel 传递 machine type;在设备树文件应用于 ARM 平台后,kernel 通过解析设备树文件的 model 来识别并匹配对应设备,以进行适配与初始化硬件。

chosen

这个结点不描述具体硬件信息,主要用于设备树与 kernel 之间传递信息,通常传递的是 bootargs。

在设备树中可以将该节点置空,也可以预先定义一些 bootargs,然后在 kernel 的 boot 阶段填充。比如当前设备树文件中 chosen 结点是空的,但 kernel 启动后再去查看 chosen 结点,就会发现其中已经被填充了 bootargs。

Linux设备树生命周期解析:DTS/DTB到内核驱动实现 - 图片 - 9

aliases

kernel 通常按照绝对路径查询一个设备结点,而 aliases 会给普通设备结点的 label 取一个别名,方便后续定位与查看设备。

例如 vexpress-v2p-ca9.dts 文件中将串口和 i2c 做了别名处理,那么在查看 dtb 的反汇编文件时,别名会按绝对路径展开。

Linux设备树生命周期解析:DTS/DTB到内核驱动实现 - 图片 - 10

使用了别名的串口、i2c 与未使用别名的 watchdog 对比很明显,也更容易看清串口设备的编号关系。

Linux设备树生命周期解析:DTS/DTB到内核驱动实现 - 图片 - 11

nodes

普通设备结点是设备树文件中占比最多的内容。这些结点必须从属于某一种总线类型,例如 simple-bus 或 amba-bus。普通设备结点下包含硬件描述信息,常见字段包括:

  • 设备的适配名(compatible 等)
  • 寄存器(reg)
  • 中断(interrupts)
  • 时钟(clocks)
  • DMA 通道
  • 引脚复用(pinctrl)等

不同设备需要按其实际特性描述。对于 USB、PCI、Graph 等总线结构的设备,还需要在设备树中体现拓扑结构、中断映射 map 等特性。你是否也遇到过“设备节点写了但驱动就是 probe 不到”的情况?很多时候问题就藏在这些属性与绑定规则里。

设备树的头文件

设备树头文件包含是一种“覆盖/插入”的实现方式:xxx.dts 包含 xxx.dtsi 文件,当 dts 与 dtsi 都包含同一个结点 node_A 但结点信息不同时,编译器会将 dtsi 中 node_A 的硬件信息条目插入到 dts 的 node_A 结点。

设备树编译

前文已经提到 dtc。这里再补充一点:dtc 具有反汇编功能。当手头只有一个 dtb 文件,希望查看其 dts 内容时,反汇编会非常实用。

如果 kernel 启动后文件系统中具备 dtc 工具,通过反汇编还可以验证 U-Boot 是否对 dtb 文件做过修改。下面是一个反汇编实例:

Linux设备树生命周期解析:DTS/DTB到内核驱动实现 - 图片 - 12

设备树编写参考文档

如需获取更多 kernel 文档解读、源码解析与实践踩坑记录,可在 云栈社区 的知识库与讨论区继续延伸阅读。




上一篇:神经网络入门:隐藏层、ReLU与反向传播计算图
下一篇:JS逆向渗透靶场搭建:encrypt-labs与BP解密插件实战
您需要登录后才可以回帖 登录 | 立即注册

手机版|小黑屋|网站地图|云栈社区 ( 苏ICP备2022046150号-2 )

GMT+8, 2026-1-18 21:32 , Processed in 0.434134 second(s), 40 queries , Gzip On.

Powered by Discuz! X3.5

© 2025-2026 云栈社区.

快速回复 返回顶部 返回列表