设备树(属性)简介

news2024/11/22 21:00:23

1 设备树

简单的整理记录;
学习参考内容:

  • Linux 笔记 https://xuesong.blog.csdn.net/article/details/109522945?spm=1001.2014.3001.5502
  • 正点原子-左盟主 驱动开发
  • 网络资料:IT界小生 https://www.zhihu.com/column/itlife

1.1 设备树简介

设备树是一种描述硬件的数据结构,它起源于OpenFirmware(OF)。
在Linux 2.6中, ARM架构的板极硬件细节过多地被硬编码在arch/arm/plat-xxx和arch/arm/mach-xxx中,采用设备树后,许多硬件的细节可以直接通过它传递给Linux,而不再需要在内核中进行大量的冗余编码。

1.2 DTS、DTB、DTC

DTS:
1.dts文件是设备树的源文件。
2 由于一个SoC可能对应多个设备,这些.dst文件可能包含很多共同的部分,共同的部分一般被提炼为一个.dtsi文件,这个文件相当于C语言的头文件。
3 可针对单独设备编写对应dts文件,调用.dtsi;
DTC:
DTC是将.dts编译为.dtb的工具,相当于gcc。
DTB:
.dtb文件是 .dts 被 DTC 编译后的二进制格式的设备树文件,它可以被linux内核解析。

make dtbs

2 DTS语法

2.1 .dts.dtsi

和 C 语言一样,设备树也支持头文件,设备树的头文件扩展名为 .dtsi;同时也可以像C 语言一样包含 .h头文件;
例如:(imx6ull-alientek-emmc.dtsi)

#include <dt-bindings/input/input.h>
#include "imx6ull.dtsi"

注:.dtsi 文件一般用于描述 SOC 的内部外设信息,比如 CPU 架构、主频、外设寄存器地址范围,比如 UART、 IIC 等等。

2.2 设备节点及属性

在这里插入图片描述
在设备树中节点命名格式如下:

node-name@unit-address

node-name:是设备节点的名称,为ASCII字符串,节点名字应该能够清晰的描述出节点的功能,比如“uart1”就表示这个节点是UART1外设;unit-address:一般表示设备的地址或寄存器首地址,如果某个节点没有地址或者寄存器的话 “unit-address” 可以不要;

注:根节点没有node-name 或者 unit-address,它被定义为 /。

2.3节点属性

设备树中的每个节点都有描述节点特征的属性。属性由名称和值组成

2.3.1节点属性

compatible 属性

compatible 属性也叫做 “兼容性” 属性,这是非常重要的一个属性!compatible 属性的值是一个字符串列表, compatible 属性用于将设备和驱动绑定起来。字符串列表用于选择设备所要使用的驱动程序。compatible 属性值的推荐格式:

 "manufacturer,model"

① manufacturer : 表示厂商;
② model : 一般是模块对应的驱动名字。

注:一般驱动程序文件都会有一个 OF 匹配表,此 OF 匹配表保存着一些 compatible 值,如果设备节点的 compatible
属性值和 OF 匹配表中的任何一个值相等,那么就表示设备可以使用这个驱动。可通过了解驱动模型获取该知识点

model 属性

model 属性值也是一个字符串,一般 model 属性描述设备模块信息,比如名字什么的,例如:

model = "Samsung S3C2416 SoC";

phandle 属性

phandle属性为devicetree中唯一的节点指定一个数字标识符,节点中的phandle属性,它的取值必须是唯一的(不要跟其他的phandle值一样),例如:

pic@10000000 {
phandle = <1>;
interrupt-controller;
};
another-device-node {
interrupt-parent = <1>; // 使用phandle值为1来引用上述节点
};

注:DTS中的大多数设备树将不包含显式的phandle属性,当DTS被编译成二进制DTB格式时,DTC工具会自动插入phandle属性。

label属性

label:node-name@unit-address

PIC: pic@10000000 {
interrupt-controller;
};

another-device-node {
interrupt-parent = <&PIC>; // 使用label来引用上述节点,
// 使用lable时实际上也是使用phandle来引用,
// 在编译dts文件为dtb文件时, 编译器dtc会在dtb中插入phandle属性
};

status 属性

status 属性看名字就知道是和设备状态有关的, status 属性值也是字符串,字符串是设备的状态信息,可选的状态如下表所示:

status值描述

#address-cells 和 #size-cells

#address-cells 和 #size-cells的值都是无符号 32 位整型,可以用在任何拥有子节点的设备中,用于描述子节点的地址信息。
#address-cells 属性值决定了子节点 reg 属性中地址信息
#size-cells 属性值决定了子节点 reg 属性中长度信息
#address-cells 和 #size-cells 表明了子节点应该如何编写 reg 属性值,一般 reg 属性都是和地址有关的内容,和地址相关的信息有两种:起始地址和地址长度,reg 属性的格式一为:

reg = <address1 length1 address2 length2 address3 length3……>
soc {
    #address-cells = <2>;
    #size-cells = <1>;
    serial {
        compatible = "xxx";
        reg = <0x4600 0x5000 0x100>;  /*地址信息是:0x00004600 00005000,长度信息是:0x100*/
        };
};

reg 属性

reg 属性的值一般是 (address, length) 对,reg 属性一般用于描述设备地址空间资源信息,一般都是某个外设的寄存器地址范围信息

例如:一个设备有两个寄存器块,一个的地址是0x3000,占据32字节;另一个的地址是0xFE00,占据256字节,表示如下:

reg = <0x3000 0x20 0xFE00 0x100>;

注:上述对应#address-cells = <1>; #size-cells = <1>;。

ranges 属性

ranges属性值可以为空或者按照 (child-bus-address,parent-bus-address,length) 格式编写的数字矩阵, ranges 是一个地址映射/转换表, ranges 属性每个项目由子地址、父地址和地址空间长度这三部分组成:

child-bus-address:子总线地址空间的物理地址,由父节点的 #address-cells 确定此物理地址所占用的字长。
parent-bus-address:父总线地址空间的物理地址,同样由父节点的 #address-cells 确定此物理地址所占用的字长。
length:子地址空间的长度,由父节点的 #size-cells 确定此地址长度所占用的字长。

soc {
    compatible = "simple-bus";
    #address-cells = <1>;
    #size-cells = <1>;
    ranges = <0x0 0xe0000000 0x00100000>;
    serial {
        device_type = "serial";
        compatible = "ns16550";
        reg = <0x4600 0x100>;
        clock-frequency = <0>;
        interrupts = <0xA 0x8>;
        interrupt-parent = <&ipic>;
        };
};

节点 soc 定义的 ranges 属性,值为 <0x0 0xe0000000 0x00100000>,此属性值指定了一个 1024KB(0x00100000) 的地址范围,子地址空间的物理起始地址为 0x0,父地址空间的物理起始地址为 0xe0000000。

serial 是串口设备节点,

reg 属性定义了 serial 设备寄存器的起始地址为 0x4600,寄存器长度为 0x100。

经过地址转换, serial 设备可以从 0xe0004600 开始进行读写操作,0xe0004600=0x4600+0xe0000000。

name 属性

name 属性值为字符串, name 属性用于记录节点名字, name 属性已经被弃用,不推荐使用name 属性,一些老的设备树文件可能会使用此属性。

device_type 属性

device_type 属性值为字符串, IEEE 1275 会用到此属性,用于描述设备的 FCode,但是设备树没有 FCode,所以此属性也被抛弃了。此属性只能用于 cpu 节点或者 memory 节点。

memory@30000000 {
    device_type = "memory";
    reg =  <0x30000000 0x4000000>;
};

2.3.2 节点

根节点

每个节点都有 compatible 属性,根节点“/”也不例外,imx6ull-alientek-emmc.dts 文件中根
节点的 compatible 属性内容如下所示:

/ {
	 model = "Freescale i.MX6 ULL 14x14 EVK Board";
 	compatible = "fsl,imx6ull-14x14-evk", "fsl,imx6ull";
	......
 }

compatible 有两个值:“fsl,imx6ull-14x14-evk”和“fsl,imx6ull”。设备节点的 compatible 属性值是为了匹配 Linux 内核中的驱动程序,那么根节点中的 compatible属性是为了做什么工作的? 通过根节点的 compatible 属性可以知道我们所使用的设备,一般第一个值描述了所使用的硬件设备名字,比如这里使用的是“imx6ull-14x14-evk”这个设备,第二个值描述了设备所使用的 SOC,比如这里使用的是“imx6ull”这颗 SOC。Linux 内核会通过根节点的compoatible 属性查看是否支持此设备,如果支持的话设备就会启动 Linux 内核;

/aliases 子节点

aliases 节点的主要功能就是定义别名,定义别名的目的就是为了方便访问节点。

例如:定义 flexcan1 和 flexcan2 的别名是 can0 和 can1。

aliases {
can0 = &flexcan1;
can1 = &flexcan2;
};

/memory 子节点

所有设备树都需要一个memory设备节点,它描述了系统的物理内存布局。如果系统有多个内存块,可以创建多个memory节点,或者可以在单个memory节点的reg属性中指定这些地址范围和内存空间大小。

例如:一个64位的系统有两块内存空间:RAM1:起始地址是0x0,地址空间是 0x80000000;RAM2:起始地址是0x10000000,地址空间也是0x80000000;同时根节点下的 #address-cells = <2>和#size-cells = <2>,这个memory节点描述为:

memory@0 {
    device_type = "memory";
    reg = <0x00000000 0x00000000 0x00000000 0x80000000
           0x00000000 0x10000000 0x00000000 0x80000000>;
};

或者:

memory@0 {
    device_type = "memory";
    reg = <0x00000000 0x00000000 0x00000000 0x80000000>;
};
memory@10000000 {
    device_type = "memory";
    reg = <0x00000000 0x10000000 0x00000000 0x80000000>;
};

/chosen 子节点

chosen 并不是一个真实的设备, chosen 节点主要是为了 uboot 向 Linux 内核传递数据,重点是 bootargs 参数。例如:

chosen {
    bootargs = "root=/dev/nfs rw nfsroot=192.168.1.1 console=ttyS0,115200";
};

/cpus 和 /cpus/cpu* 子节点

cpus节点下有1个或多个cpu子节点, cpu子节点中用reg属性用来标明自己是哪一个cpu,所以 /cpus 中有以下2个属性:
#address-cells // 在它的子节点的reg属性中, 使用多少个u32整数来描述地址(address)
#size-cells // 在它的子节点的reg属性中, 使用多少个u32整数来描述大小(size) 必须设置为0
例如:

cpus {
    #address-cells = <1>;
    #size-cells = <0>;
    cpu@0 {
        device_type = "cpu";
        reg = <0>;
        cache-unified;
        cache-size = <0x8000>; // L1, 32KB
        cache-block-size = <32>;
        timebase-frequency = <82500000>; // 82.5 MHz
        next-level-cache = <&L2_0>; // phandle to L2
        L2_0:l2-cache {
            compatible = "cache";
            cache-unified;
            cache-size = <0x40000>; // 256 KB
            cache-sets = <1024>;
            cache-block-size = <32>;
            cache-level = <2>;
            next-level-cache = <&L3>; // phandle to L3
            L3:l3-cache {
                compatible = "cache";
                cache-unified;
                cache-size = <0x40000>; // 256 KB
                cache-sets = <0x400>; // 1024
                cache-block-size = <32>;
                cache-level = <3>;
                };
            };
        };
    cpu@1 {
        device_type = "cpu";
        reg = <1>;
        cache-unified;
        cache-block-size = <32>;
        cache-size = <0x8000>; // L1, 32KB
        timebase-frequency = <82500000>; // 82.5 MHzclock-frequency = <825000000>; // 825 MHz
        cache-level = <2>;
        next-level-cache = <&L2_1>; // phandle to L2
        L2_1:l2-cache {
            compatible = "cache";
            cache-unified;
            cache-size = <0x40000>; // 256 KB
            cache-sets = <0x400>; // 1024
            cache-line-size = <32>; // 32 bytes
            next-level-cache = <&L3>; // phandle to L3
            };
        };
};

2.3.3 修改节点内容

原则上不要去修改.dtsi上的内容,这个是共用的文件;建议以追加的形式去修改板子对应dts文件
比如.dtsi部分内容如下

i2c1: i2c@021a0000 {
	#address-cells = <1>;
 	#size-cells = <0>;
 	compatible = "fsl,imx6ul-i2c", "fsl,imx21-i2c";
 	reg = <0x021a0000 0x4000>;
 	interrupts = <GIC_SPI 36 IRQ_TYPE_LEVEL_HIGH>;
 	clocks = <&clks IMX6UL_CLK_I2C1>;
 	status = "disabled";
};

比如.dts部分内容如下

&i2c1 {
 	 clock-frequency = <100000>;
 	 pinctrl-names = "default";
 	 pinctrl-0 = <&pinctrl_i2c1>;
 	 status = "okay";
/* 要追加或修改的内容 */
 	 fxls8471@1e {
 	 compatible = "fsl,fxls8471";
 	 reg = <0x1e>;
 	 position = <0>;
 	 interrupt-parent = <&gpio5>;
 	 interrupts = <0 8>;
 };

3 DTB文件分析

.dtb文件是 .dts 被 DTC 编译后的二进制格式的设备树文件;这块不是不重要,是在深度方面和本文不符,Linux源码跟读,写的有一篇比较详细的,可参阅;
https://zhuanlan.zhihu.com/p/141623370

4 设备树binding文档

设备树是用来描述板子上的设备信息的,不同的设备其信息不同,反映到设备树中就是属性不同。那么我们在设备树中添加一个硬件对应的节点的时候从哪里查阅相关的说明呢?在Linux 内核源码中有详细的.txt 文档描述了如何添加节点,这些.txt 文档叫做绑定文档,路径为:
Linux 源码目录/Documentation/devicetree/bindings

比如我们现在要想在 I.MX6ULL 这颗 SOC 的 I2C 下添加一个节点,那么就可以查看Documentation/devicetree/bindings/i2c/i2c-imx.txt,此文档详细的描述了 I.MX 系列的 SOC 如何在设备树中添加 I2C 设备节点

5 其它

设备树在系统中的体现

Linux 内核启动的时候会解析设备树中各个节点的信息,并且在根文件系统的/proc/device-tree 目录下根据节点名字创建不同文件夹
在这里插入图片描述

# 设备树常用 OF 操作函数
设备树描述了设备的详细信息,这些信息包括数字类型的、字符串类型的、数组类型的,
我们在编写驱动的时候需要获取到这些信息。比如设备树使用 reg 属性描述了某个外设的寄存
器地址为 0X02005482,长度为 0X400,我们在编写驱动的时候需要获取到 reg 属性的0X02005482 和 0X400 这两个值,然后初始化外设。Linux 内核给我们提供了一系列的函数来获
取设备树中的节点或者属性信息,这一系列的函数都有一个统一的前缀“of_”,所以在很多资料里面也被叫做 OF 函数。这些 OF 函数原型都定义在 include/linux/of.h 文件中。

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

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

springboot+freemarker+restful

什么是freemarker? FreeMarker是一种模板引擎&#xff0c;它可以用于生成各种类型的文档&#xff0c;比如HTML、XML、PDF、Word等。它可以通过简单的模板语法和数据模型来生成文档内容。与传统的JSP相比&#xff0c;FreeMarker的语法更加简洁和易读&#xff0c;并且可以很好地…

女生学习软件测试怎么样?

在IT技术行业&#xff0c;女生学习还是有很大优势的。女生相较于男生更有耐心&#xff0c;包容性强&#xff0c;心思细腻&#xff0c;对细节把控更好&#xff0c;同时还能帮助团队男女平衡&#xff0c;活跃气氛。 编程是一个只要你肯学习就会有回报的行业&#xff0c;不论男生…

1W字理解Java虚拟机——JVM

目录 一、初识JVM 二、JVM执行流程 三、内存区域划分&#xff08;JVM运行时数据区&#xff09; 3.1 本地方法栈&#xff08;线程私有&#xff09; 3.2 程序计数器&#xff08;线程私有&#xff0c;无并发问题&#xff09; 3.3 JVM虚拟机栈&#xff08;线程私有&#xff0…

【小程序】微信云托管对象存储管理

微信云托管对象存储用于存放数据或文件&#xff0c;一般用于较大数据或较大文件上传时的中转对象&#xff0c;避免直接上传到服务端&#xff0c;影响服务性能。 对象存储 开通了云托管平台后会自动开通对象存储功能。简单理解就是一个文件目录即可。 存储文件 文件名称&…

串口全双工通信与串口中断

1.串口通信编程 STC-ISP串口助手的使用&#xff1a; 文本模式和HEX模式的区别&#xff1a;文本模式就是那些可打印的字符。HEX模式就是这些可打印字符对应的16进制。它们都对应相同的ASCII码&#xff08;用十进制表示&#xff09;。 很多小白在程序编写完成后调试时会搞不清楚…

利用notepad++处理数据,再用excel做则线图

1、利用串口调试XCOM V2.8得到数据 2、利用Notepad编辑数据 利用正则表达式 删除时间戳 移除空行 继续删掉不要的数据 3、用excel生成折线图 复制数据到excel excel自动根据上文公式填充计算 输入0.1和0.2 框选0.1和0.2&#xff0c;下拉

JavaScript-jQuery的使用 + JS的案例

目录 点击更换图片 猜数字 搜索页面展示 表白墙 点击更换图片 我们先看下面这个例子: 使用input里面的button按钮, 并且利用函数, 将一个搜狗logo转换为百度logo: <!DOCTYPE html> <html lang"en"> <head><meta charset&…

Maven下载安装及IDEA配置Maven的超详细教程

Maven下载安装及IDEA配置Maven的超详细教程 1、IntelliJ IDEA 下载、安装及配置过程2、maven下载、安装、配置过程2.1 mavan下载2.2 安装2.3 配置 3、在IDEA中配置Maven3.1 进入设置界面3.2 maven配置 4、IDEAmaven创建工程示例 Maven是一个能使我们的java程序开发节省时间和精…

ssl证书过期

SSL证书验证网站所有者的身份&#xff0c;并为其访问者建立与服务器的安全加密连接。它保护他们的安全和隐私。 但SSL证书并非永远有效。与您的驾驶执照或护照一样&#xff0c;SSL证书也有过期日期。过期日期后&#xff0c;服务器的身份不再受信任。 为什么网站安全证书会过期…

C++ 类与对象中类的深入知识点+完整思维导图+基本练习题+深入细节+通俗易懂建议收藏

绪论 本章我们接着对类和对象进行探索&#xff0c;这是一个在我们c中比较重要的知识点&#xff0c;下面我们才是我们类和对象的更加深入且困难的知识点&#xff0c;希望你能通过这篇文章对类其有更加深入的了解。 话不多说安全带系好&#xff0c;发车啦&#xff08;建议电脑观看…

使用Taskflow完成简历信息提取

构建模型的步骤&#xff1a; 首先要进行数据处理&#xff0c;抽取简历文件中的数据。 首先要准备数据集&#xff0c;大赛提供的数据集中多为word文档&#xff0c;都为.docx格式&#xff0c; docx文件是基于 XML 的&#xff0c;可以包含文本&#xff0c;对象&#xff0c;样式&…

想让你的应用程序更加可靠?来了解Spring事务的回滚机制吧!

嗨&#xff0c;大家好&#xff0c;我是小米&#xff0c;今天要和大家聊一聊关于Spring框架事务的回滚源码实现。 相信对于使用Spring框架的小伙伴来说&#xff0c;事务管理肯定是非常重要的一个环节&#xff0c;事务的管理不好很容易出现各种问题&#xff0c;如数据不一致等。…

二十五:修改交易

1.功能需求 点击交易的复选框&#xff0c;然后点击修改按钮。进行数据的页面填充 1.流程图 1.代码实现 TranMapper /*** 根据id查询交易*/Tran selectTranDetailFortranId(String tranId); <!-- Tran selectTranDetailFortranId(String tranId);--><select id"…

项目集战略一致性

项目集战略一致性是识别项目集输出和成果&#xff0c;以便与组织的目标和目的保持一致的绩效领域。 本章内容包括&#xff1a; 1 项目集商业论证 2 项目集章程 3 项目集路线图 4 环境评估 5 项目集风险管理战略 项目集应与组织战略保持一致&#xff0c;并促进组织效益的实现。为…

【博客系统】页面设计(附完整源码)

&#x1f389;&#x1f389;&#x1f389;点进来你就是我的人了博主主页&#xff1a;&#x1f648;&#x1f648;&#x1f648;戳一戳,欢迎大佬指点! 欢迎志同道合的朋友一起加油喔&#x1f93a;&#x1f93a;&#x1f93a; 目录 一、页面介绍 二、预期效果 1、博客列表页效…

刚面试了一位5年的Android开发,一问三不知,他还反怼我...

最近帮部门主管面试了很多人&#xff0c;从简历上看这些人的工作年限都不短&#xff0c;但做的都是一些传统的项目&#xff0c;想做现在大环境越来越难&#xff0c;大家找工作都不容易&#xff0c;就打算见一见。 在沟通中发现&#xff0c;由于年限不小&#xff0c;他们的定位…

十、Feign客户端

目录 1、在springcloud-order项目中引入Feign客户端的依赖 2、在server-order服务的启动类中添加注解EnableFeignClients 3、使用FeignClient注解声明Feign客户端需要调用的远程接口 3.1、server-pay服务提供远程接口Controller 3.2、server-member服务提供远程接口Contro…

ES基础知识总结含SQL、DSL、GOLANG

一、简介 Elasticsearch是一个基于Lucene的全文搜索和分析引擎&#xff0c;Lucene Core是一个完全用Java编写的高性能、全功能搜索引擎库。 它可以快速地存储、实时搜索和分析大量数据。 它可以扩展到上百台服务器&#xff0c;处理PB级数据。PB 2^50 Byte&#xff0c; 在数…

联通数科面试准备

Spring中Bean的生命周期 Spring Bean的生命周期全过程分为5个阶段&#xff0c;创建前准备阶段、创建实例阶段、依赖注入阶段和容器缓存阶段以及销毁实例阶段。 阶段1&#xff1a;创建前准备阶段这个阶段主要是在开始Bean加载之前&#xff0c;从Spring上下文中去获取相关的配置…

如何使用Alchemy开发NFT智能合约(ERC721)

&#x1f978; 本教程翻译自官网&#xff1a;[https://docs.alchemy.com/docs](https://docs.alchemy.com/docs)。对部分内容进行了修改。教程中所有实例经过本人实践&#xff0c;代码可见&#xff1a;https://github.com/ChuXiaoYi/web3Study 使用Solidity开发智能合约并在区块…