Linux 设备树: 设备树节点与属性在 dtb 文件中的存储

前言

  • 当前新版本的 Linux 内核 设备驱动框架,与设备树(Device Tree)结合密切,整体 设备树的设备驱动框架,比较的庞大,但又非常的经典。

  • 一个个的 设备树解析函数,都是前人【智慧】的结晶,了解 设备树的实现,了解设备树的解析,对Linux 设备驱动开发非常有利,并且可以大大提高开发编码能力

  • 虽然Linux 内核庞大、开源,但是Linux 内核各个模块的实现都是经典,非常适合学习深造

设备树 dtb 文件的由来

  • Linux 内核启动后,载入的设备树文件是 dtb,而不是 dts,也就是 设备树 dts 源文件经过类似编译(二进制化)的方式生成 设备树 dtb 文件

  • 那么问题就是: 设备树 dts 或者 dtsi 中文本描述的设备树节点 node 与属性 property,如何呈现在设备树 dtb 文件中?直接改为二进制,还是有一定的转换规则?

  • 经过对比设备树源文件 dts 与 设备树生成的 dtb 二进制文件,并查看对应的代码,找到了转换的规则,并不是简单的二进制化。

二进制化规则

  • 设备树源文件,大概有三类文件组成:

    • (1)设备树源文件 dts,一个 dts 文件生成一个 dtb 文件
    • (2)设备树源文件的头文件 dtsi,类似于 C 语言的 include 头文件,可以有多个,dtsi 中也可以包含 更多的 dtsi
    • (3)设备树 dt-bindings C 语言的头文件,这些头文件中,大部分都是【宏定义】,并不包含 C 语言的结构体,用于代替设备树中的【宏】
  • 其实 设备树 源文件生成 设备树 dtb 的过程,有点类似于 C 语言的编译过程,大概有两个过程:【预处理】部分,把 设备树 dts 文件 当成 C 源文件,把 设备树 dtsi 与 设备树 C 语言的 .h 头文件当成 C 语言 头文件,预处理后就生成一个设备树文件(中间文件),然后再使用 dtc 工具 进行转换(类似于 C 语言的编译)。

设备树 dtb 构成

  • 设备树 dtb 文件构成可以参考 设备树的规范文件:设备树规范可以通过 https://github.com/devicetree-org/devicetree-specification 获取到,当前版本是 devicetree-specification-v0.4.pdf

  • 设备树很复杂?其实就是由 节点 (node) 与 属性 (property)构成的

  • 可以有多个节点,一个节点下面,可以包含多个节点。以实际树做个比喻,树干、树枝、树叶,树枝可以包含多级树枝,最后是树叶。

  • 设备树中 树根、树干、树枝、树叶,都用 【节点】或者【容器】来表示。而属性 property,一个设备树节点的描述细节,可以有多个,附属于某个设备树节点。

  • 如果设备树 节点 是个树叶,那么 这个设备树 节点的属性可以有大小、颜色等描述用的属性

设备树 dtb 中 C 语言的描述与实现

  • 设备树 dtc 工具如何转换 设备树源文件到目标 dtb 文件?设备树 dtc 工具也是由 C 语言编写的,位置在 Linux 内核 scripts\dtc\dtc.c

  • dtc 的 设备树源文件只能输入一个,如果一个设备树包含 dts、多个 dtsi、多个 .h dt-bindings C 语言的头文件,需要借助 gcc 工具进行预处理,这样转换为一个中间的 设备树 源文件,也就是 包含的dtsi 文件被真实文件内容填充,【宏定义】被真实的数据代替。为了管理(解析)方便,再经过 dtc 工具,转换为 最终的 dtb 格式的文件。

  • 设备树 dtb 的 C 语言描述, scripts\dtc\libfdt\fdt.h ,节点 fdt_node_header 与 属性 fdt_property

struct fdt_node_header {fdt32_t tag;char name[];
};struct fdt_property {fdt32_t tag;fdt32_t len;fdt32_t nameoff;char data[];
};
  • 可以看到,节点就是一个【容器】的概念,每个节点包含一个或者多个 属性 struct fdt_property

  • 节点用于归类或者分组,类似于定义一个【结构体】,属性 struct fdt_property 是其中的成员。

  • 注意这里 的 struct fdt_property 与Linux 内核 of 中 解析使用的 struct property 不太一样,因为这里的 struct fdt_property 关注的是 属性的物理存放规则, struct property 是设备树【树化】展开使用的属性描述节点(包含链表等层次结构化成员)。

  • struct fdt_property 的设备树节点,就是【并排】的堆叠操作,可以认为是 flat 扁平化的,【属性1】【属性2】。。。【属性N】。

如何区分 设备树节点与设备树 属性

  • 设备树节点使用 FDT_BEGIN_NODE,也就是 32位值 00 00 00 01 四个字节表示一个设备树节点的开始, 使用 FDT_END_NODE,也就是 32位值 00 00 00 02 四个字节表示一个设备树节点的结束
#define FDT_BEGIN_NODE	0x1		/* Start node: full name */
#define FDT_END_NODE	0x2		/* End node */
  • 设备树节点的属性,使用 FDT_PROP,32位值, 00 00 00 03 作为 tag 的方式,用于设备树属性的开始
#define FDT_PROP	0x3		/* Property: name off,size, content */
  • 设备树 结构部分:设备树节点、设备树属性,结束使用 FDT_END 表示,也就是 32位值 00 00 00 09 表示 设备树结构部分的 【结束】
#define FDT_END		0x9
  • 设备树 dt 并不是 设备树源文件的 直接二进制化,而是有个转换(翻译)规则,比如 设备树节点或者属性都有 name 属性,而 name 属性本身也是个字符串,而这些 name 属性都聚集到了一起,形成了 string 区域,所以类似于 compatible = "rockchip,rk3368-i2c", "rockchip,rk3288-i2c"; 属性, 存储到 dtb 时, compatible 字符串 放在了 string 字符串区域struct fdt_property 中使用 字符串区域的偏移 fdt32_t nameoff来表示,而 "rockchip,rk3368-i2c", "rockchip,rk3288-i2c" 属性值,是以实际字符串的方式存储(4字节对齐)。

  • 如此看来, 设备树 dtb 文件有三个区域组成:

    • (1)设备树 头部,结构体是 struct fdt_header
    • (2)设备树节点与属性存放区域 dt_struct,包括 struct fdt_node_headerstruct fdt_property
    • (3)设备树 字符串区域,主要是 设备树节点与属性的 name 字符串,用于索引,好处就是【公用】,比如很多设备树节点中都有 compatible 属性,这里公用一个 compatible name 字符串,也就是 属性中的 name 字符串也要存储,只是为了【公用】,并且索引管理方便,集中存放在一个区域。

在这里插入图片描述

小结

  • 本篇简单描述 dtb 文件的存储构成,了解了 dtb 文件的构成(内容),才能更好的管理与解析设备树,或者更好的利用好设备树。

  • 设备树不只是用于Linux 这个系统,一些嵌入式系统,理论上也可以使用设备树,当然可能占用一些额外的资源,比如 u-boot 中已经普及使用设备树了

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.hqwc.cn/news/588842.html

如若内容造成侵权/违法违规/事实不符,请联系编程知识网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

go: go.mod file not found in current directory or any parent directory.如何解决?

这个错误表明你正在执行 go get 命令&#xff0c;但是当前目录或任何父目录中都找不到 go.mod 文件。这可能是因为你的项目还没有使用 Go Modules 进行管理。 要解决这个问题&#xff0c;有几种方法&#xff1a; go mod init <module-name> 其中 <module-name>…

华为OD机试 - 最大社交距离(Java 2024 C卷 100分)

华为OD机试 2024C卷题库疯狂收录中&#xff0c;刷题点这里 专栏导读 本专栏收录于《华为OD机试&#xff08;JAVA&#xff09;真题&#xff08;A卷B卷C卷&#xff09;》。 刷的越多&#xff0c;抽中的概率越大&#xff0c;每一题都有详细的答题思路、详细的代码注释、样例测试…

基于 java + Springboot + vue +mysql 大学生实习管理系统(含源码)

目录 &#x1f4da; 前言 &#x1f4d1;摘要 &#x1f4d1;实习管理系统的特点 &#x1f4d1;使用架构 &#x1f4da; 总体设计 &#x1f4da; 数据库设计 &#x1f4ac; 系统公告实体属性 &#x1f4ac; 单位成绩实体属性 &#x1f4ac; 学生实体属性 &#x1f4da; 系…

超市销售数据-python数据分析项目

Python数据分析项目-基于Python的销售数据分析项目 文章目录 Python数据分析项目-基于Python的销售数据分析项目项目介绍数据分析结果导出数据查阅 数据分析内容哪些类别比较畅销?哪些商品比较畅销?不同门店的销售额占比哪个时间段是超市的客流高封期?查看源数据类型计算本月…

10.图像高斯滤波的原理与FPGA实现思路

1.概念 高斯分布 图像滤波之高斯滤波介绍 图像处理算法|高斯滤波   高斯滤波(Gaussian filter)包含很多种&#xff0c;包括低通、高通、带通等&#xff0c;在图像上说的高斯滤波通常是指的高斯模糊(Gaussian Blur)&#xff0c;是一种高斯低通滤波。通常这个算法也可以用来模…

02 - 全加器和加法器

---- 整理自B站UP主 踌躇月光 的视频 1. 全加器 用门电路实现两个二进制数相加并求出和的组合线路&#xff0c;称为一位全加器。一位全加器可以处理低位进位&#xff0c;并输出本位加法进位。全加器比半加器多了一位进位。 1.1 实验 1&#xff1a;通过两个半加器设计全加器 1.…

【游戏漏洞】逆向基础之进制

本文给大家讲解我们日后逆向学习和实践过程中息息相关的一些重要基础 我们要讲解的是 例如 111在什么时候是正确的&#xff1f; OD&#xff0c;CE&#xff0c;IDA等工具为什么都是16进制&#xff1f; 计算机只认识0和1&#xff0c;也就2进制。 我们现实生活中常用到的是10进…

【LeetCode热题100】79. 单词搜索(回溯)

一.题目要求 给定一个 m x n 二维字符网格 board 和一个字符串单词 word 。如果 word 存在于网格中&#xff0c;返回 true &#xff1b;否则&#xff0c;返回 false 。 单词必须按照字母顺序&#xff0c;通过相邻的单元格内的字母构成&#xff0c;其中“相邻”单元格是那些水平…

Vue3+Vite Nginx部署 跨域

打包项目 webstorm打开项目之后&#xff0c;在Terminal执行打包命令 pnpm run build:prod 复制到Nginx 打包完成之后,生成的包在根目录dist&#xff0c;把dist目录拷贝到Nginx放网站目录下&#xff1a;\nginx-1.25.2\html\divided &#xff0c;dist改名了divided 修改配置…

Runes 生态一周要览 ▣ 2024.3.25-3.31|Runes 协议更新 BTC 减半在即

Runes 生态大事摘要 1、Casey 发布了 Runes 协议文档 RUNES HAVE DOCS&#xff0c;Github 代码库更新到 ord 0.17.0 版本&#xff0c;Casey 表示符文是一个“严肃”的代币协议。 2、Casey 公布了第一个硬编码的创世符文「UNCOMMONGOODS」 3、4月7日香港沙龙&#xff5c;聚焦「…

1,static 关键字.Java

目录 1.概述 2.定义格式和使用 2.1 静态变量及其访问 2.2 实例变量及其访问 2.3 静态方法及其访问 2.4 实例方法及其访问 3.小结 1.概述 static表示静态&#xff0c;是Java中的一个修饰符&#xff0c;可以修饰成员方法&#xff0c;成员变量。被static修饰后的&#xff…

小明的背包-dp_python

用户登录 动态规划的思想是自底向上&#xff0c;先求局部最优解然后求全局最优解。 dp[i][j]代表的是当前状态物品的数量以及背包的容量。 N, V map(int,input().split()) dp [[0 for _ in range(V1)] for _ in range(N1)]for i in range(1,N1):v, w map(int,input().split(…