理解Linux设备树(DTS)

news2024/11/18 11:17:40

DTS

Dts:DTS即Device Tree Source,是一个文本形式的文件,用于描述硬件信息。一般都是固定信息,无法变更,无法overlay。

Dtsi:可以理解为dts的公共部分,添加、变更非常灵活。Dtsi包含在dts中。

Dtb:Dtb编译出来的二进制

Dtbo:Overlay编译出来的二进制

dtbo-base:指定overlay是以哪个dtb为base来覆盖的。

Node:树的节点

Property:属性

设备树(Device Tree)简介

设备树由来
linux内核源码中,之前充斥着大量的平台相关(platform Device)配置,而这些代码大多是杂乱且重复的,这使得ARM体系结构的代码维护者和内核维护者在发布一个新的版本的时候有大量的工作要做,以至于LinusTorvalds 在2011年3月17日的ARM Linux邮件列表中宣称“Gaah.Guys,this whole ARM thing is a f*cking pain in the ass”这使得整个ARM社区不得不重新慎重考虑平台配置,于是设备树(Device Tree,DT)被ARM社区采用。需要说明的是,设备树最初是由开发固件(Open Firmware)使用的用来向客户程序(通常是一个操作系统)传递数据的通信方法中的一部分内容。在运行时,客户程序通过设备树发现设备的拓扑结构,这样就不需要把硬件信息硬编码到程序中。

设备树的作用

设备树是一个描述硬件的数据结构,甚至你可以将其看成一个大结构体(这个结构体就是平台,成员就是具体的设备),需要注意的是设备树并不能解决所有的硬件配置问题(例如:机器识别),它只是提供一种语言,将硬件的配置从linux内核的源码中提取出来。

Linux使用设备树的主要原因如下

A:平台识别

B:实时配置

C:设备植入

设备树解耦目标

目标一 vendor相关修改,完全独立出来,禁止在soc原生的dtsi中修改,只允许以dtbo的方式存在;

目标二 同基线项目dtbo要共二进制

设备树解耦框架设计

在这里插入图片描述

设备树识别原理及设备树共二进制原理

项目号(Project No)与 PCB ID两个变量同时与dtbo中的两个属性“dtsi_No”“pcb_No”完全匹配,就可以找到对应的dtbo文件。而dtbo可以通过Makefile的控制打包到dtbo.img中,这样就实现了共二进制。

设备树代码架构

在这里插入图片描述

设备树overlay规则

该节内容为overlay机制原生规则,罗列出来帮助驱动工程师解决各种异常问题。

规则1:对于同一个节点的设置情况,dts中的配置会覆盖dtsi中的配置;

规则2:对于节点的修改,先引用后修改;例如原生节点定义如下:
在这里插入图片描述
需要在reserved-memory节点中添加一个新的节点或者直接修改reserved-memory节点的属性,都需要先引用reserved_memory节点(注意节点的引用名与节点名可以不一致)
在这里插入图片描述
如上案例中,引用 reserved-memory 节点,并删除了 ranges 属性,删除了hyp_mem节点,新增了kboot_uboot_logmem节点;

规则3:只有引用申明的节点,在dtsi中“&节点名”才会生效,否则引用点将不生效;例如:firmware节点下fstab 节点的定义如下
在这里插入图片描述
firmware:firmware中“:”之前的内容为引用申明。只有申明后才可以在其他地方引用。Firmware下的fstab 节点没有引用声明,在其他位置就不可以引用。如果要修改fstab节点里的属性,引用firmware节点然后修改其中属性,案例如下:
设备树overlay规则
对于同一个节点的设置情况,dts文件中的内容会覆盖dtsi中.

设备树调试手段

反编译工具代码中自带,只需要初始化一下环境变量就可以使用。初始化指令如下:
在这里插入图片描述
反编译dtb.img
dtc-I dtb -O dts dtb.img -o dtsi.txt
反编译dtbo.img
mkdtimgdump dtbo.img -b dtbo
dtc -I dtb -O dts dtbo.00 -o dtsi.txt

Linux设备树语法详解

Linux内核从3.x开始引入设备树的概念,用于实现驱动代码与设备信息相分离。在设备树出现以前,所有关于设备的具体信息都要写在驱动里,一旦外围设备变化,驱动代码就要重写。引入了设备树之后,驱动代码只负责处理驱动的逻辑,而关于设备的具体信息存放到设备树文件中,这样,如果只是硬件接口信息的变化而没有驱动逻辑的变化,驱动开发者只需要修改设备树文件信息,不需要改写驱动代码。比如在ARM Linux内,一个.dts(device tree source)文件对应一个ARM的machine,一般放置在内核的"arch/arm/boot/dts/“目录内,比如exynos4412参考板的板级设备树文件就是"arch/arm/boot/dts/exynos4412-origen.dts”。这个文件可以通过$make dtbs命令编译成二进制的.dtb文件供内核驱动使用。

基于同样的软件分层设计的思想,由于一个SoC可能对应多个machine,如果每个machine的设备树都写成一个完全独立的.dts文件,那么势必相当一些.dts文件有重复的部分,为了解决这个问题,Linux设备树目录把一个SoC公用的部分或者多个machine共同的部分提炼为相应的.dtsi文件。这样每个.dts就只有自己差异的部分,公有的部分只需要"include"相应的.dtsi文件, 这样就是整个设备树的管理更加有序。我这里用`Linux4.8.5源码自带的dm9000网卡为例来分析设备树的使用和移植。这个网卡的设备树节点信息在"Documentation/devicetree/bindings/net/davicom-dm9000.txt"有详细说明,其网卡驱动源码是"drivers/net/ethernet/davicom/dm9000.c"。
在这里插入图片描述

设备树框架

设备树用树状结构描述设备信息,它有以下几种特性

每个设备树文件都有一个根节点,每个设备都是一个节点。
节点间可以嵌套,形成父子关系,这样就可以方便的描述设备间的关系。
每个设备的属性都用一组key-value对(键值对)来描述。
每个属性的描述用;结束
所以,一个设备树的基本框架可以写成下面这个样子,一般来说,/表示板子,它的子节点node1表示SoC上的某个控制器,控制器中的子节点node2表示挂接在这个控制器上的设备(们)。

/{                                  //根节点
    node1{                          //node1是节点名,是/的子节点
        key=value;                  //node1的属性
        ...
        node2{                      //node2是node1的子节点
            key=value;              //node2的属性
            ...
        }
    }                               //node1的描述到此为止
    node3{
        key=value;
        ...
    }
}

节点名
理论个节点名只要是长度不超过31个字符的ASCII字符串即可,此外
Linux内核还约定设备名应写成形如[@<unit_address>]的形式,其中name就是设备名,最长可以是31个字符长度。unit_address一般是设备地址,用来唯一标识一个节点,下面就是典型节点名的写法
在这里插入图片描述
上面的节点名是firmware,节点路径是/firmware@0203f000,这点要注意,因为根据节点名查找节点的API的参数是不能有"@xxx"这部分的。

Linux中的设备树还包括几个特殊的节点,比如chosen,chosen节点不描述一个真实设备,而是用于firmware传递一些数据给OS,比如bootloader传递内核启动参数给内核

Key

在设备树中,键值对是描述属性的方式,比如,Linux驱动中可以通过设备节点中的"compatible"这个属性查找设备节点。
Linux设备树语法中定义了一些具有规范意义的属性,包括:compatible, address, interrupt等,这些信息能够在内核初始化找到节点的时候,自动解析生成相应的设备信息。此外,还有一些Linux内核定义好的,一类设备通用的有默认意义的属性,这些属性一般不能被内核自动解析生成相应的设备信息,但是内核已经编写的相应的解析提取函数,常见的有 “mac_addr”,“gpio”,“clock”,“power”。“regulator” 等等。

compatible
设备节点中对应的节点信息已经被内核构造成struct platform_device。驱动可以通过相应的函数从中提取信息。compatible属性是用来查找节点的方法之一,另外还可以通过节点名或节点路径查找指定节点。dm9000驱动中就是使用下面这个函数通过设备节点中的"compatible"属性提取相应的信息,所以二者的字符串需要严格匹配。
在下面的这个dm9000的例子中,我们在相应的板级dts中找到了这样的代码块:
在这里插入图片描述
然后我们取内核源码中找到dm9000的网卡驱动,从中可以发现这个驱动是使用的设备树描述的设备信息(这不废话么,显然用设备树好处多多)。我们可以找到它用来描述设备信息的结构体,可以看出,驱动中用于匹配的结构使用的compatible和设备树中一模一样,否则就可能无法匹配,这里另外的一点是struct of_device_id数组的最后一个成员一定是空,因为相关的操作API会读取这个数组直到遇到一个空。
在这里插入图片描述
address
(几乎)所有的设备都需要与CPU的IO口相连,所以其IO端口信息就需要在设备节点节点中说明。常用的属性有

#address-cells,用来描述子节点"reg"属性的地址表中用来描述首地址的cell的数量,
#size-cells,用来描述子节点"reg"属性的地址表中用来描述地址长度的cell的数量。
有了这两个属性,子节点中的"reg"就可以描述一块连续的地址区域。下例中,父节点中指定了#address-cells = <2>;#size-cells = <1>,则子节点dev-bootscs0中的reg中的前两个数表示一个地址,即MBUS_ID(0xf0, 0x01)和0x1045C,最后一个数的表示地址跨度,即是0x4

interrupts
一个计算机系统中大量设备都是通过中断请求CPU服务的,所以设备节点中就需要在指定中断号。常用的属性有

interrupt-controller 一个空属性用来声明这个node接收中断信号,即这个node是一个中断控制器。
#interrupt-cells,是中断控制器节点的属性,用来标识这个控制器需要几个单位做中断描述符,用来描述子节点中"interrupts"属性使用了父节点中的interrupts属性的具体的哪个值。一般,如果父节点的该属性的值是3,则子节点的interrupts一个cell的三个32bits整数值分别为:<中断域 中断 触发方式>,如果父节点的该属性是2,则是<中断 触发方式>
interrupt-parent,标识此设备节点属于哪一个中断控制器,如果没有设置这个属性,会自动依附父节点的
interrupts,一个中断标识符列表,表示每一个中断输出信号
设备树中中断的部分涉及的部分比较多,interrupt-controller表示这个节点是一个中断控制器,需要注意的是,一个SoC中可能有不止一个中断控制器,这就会涉及到设备树中断组织的很多概念,下面是在文件"arch/arm/boot/dts/exynos4.dtsi"中对exynos4412的中断控制器(GIC)节点描述:
在这里插入图片描述
要说interrupt-parent,就得首先讲讲Linux设备管理中对中断的设计思路演变。随着linux kernel的发展,在内核中将interrupt controller抽象成irqchip这个概念越来越流行,甚至GPIO controller也可以被看出一个interrupt controller chip,这样,系统中至少有两个中断控制器了,另外,在硬件上,随着系统复杂度加大,外设中断数据增加,实际上系统可以需要多个中断控制器进行级联,形成事实上的硬件中断处理结构:
在这里插入图片描述
在这种趋势下,内核中原本的中断源直接到中断号的方式已经很难继续发展了,为了解决这些问题,linux kernel的大牛们就创造了irq domain(中断域)这个概念。domain在内核中有很多,除了irqdomain,还有power domain,clock domain等等,所谓domain,就是领域,范围的意思,也就是说,任何的定义出了这个范围就没有意义了。如上所述,系统中所有的interrupt controller会形成树状结构,对于每个interrupt controller都可以连接若干个外设的中断请求(interrupt source,中断源),interrupt controller会对连接其上的interrupt source(根据其在Interrupt controller中物理特性)进行编号(也就是HW interrupt ID了)。有了irq domain这个概念之后,这个编号仅仅限制在本interrupt controller范围内,有了这样的设计,CPU(Linux 内核)就可以根据级联的规则一级一级的找到想要访问的中断。当然,通常我们关心的只是内核中的中断号,具体这个中断号是怎么找到相应的中断源的,我们作为程序员往往不需要关心,除了在写设备树的时候,设备树就是要描述嵌入式软件开发中涉及的所有硬件信息,所以,设备树就需要准确的描述硬件上处理中断的这种树状结构,如此,就有了我们的interrupt-parant这样的概念:用来连接这样的树状结构的上下级,用于表示这个中断归属于哪个interrupt controller,比如,一个接在GPIO上的按键,它的组织形式就是:

中断源–interrupt parent–>GPIO–interrupt parent–>GIC1–interrupt parent–>GIC2–…–>CPU

有了parant,我们就可以使用一级一级的偏移量来最终获得当前中断的绝对编号,这里,可以看出,在我板子上的dm9000的的设备节点中,它的"interrupt-parent"引用了"exynos4x12-pinctrl.dtsi"(被板级设备树的exynos4412.dtsi包含)中的gpx0节点:
在这里插入图片描述
而在gpx0节点中,指定了"#interrupt-cells = <2>;“,所以在dm9000中的属性"interrupts = <6 4>;“表示dm9000的的中断在作为irq parant的gpx0中的中断偏移量,即gpx0中的属性"interrupts"中的”<0 22 0>”,通过查阅exynos4412的手册知道,对应的中断号是EINT[6]。
在这里插入图片描述
gpio
gpio也是最常见的IO口,常用的属性有
“gpio-controller”,用来说明该节点描述的是一个gpio控制器
“#gpio-cells”,用来描述gpio使用节点的属性一个cell的内容,即 `属性 = <&引用GPIO节点别名 GPIO标号 工作模式>
GPIO的设置同样采用了上述偏移量的思想,比如下面的这个led的设备书,表示使用GPX2组的第7个引脚:
在这里插入图片描述

VALUE
dts描述一个键的值有多种方式,当然,一个键也可以没有值

在这里插入图片描述

设备树/驱动移植实例
设备树就是为驱动服务的,配置好设备树之后还需要配置相应的驱动才能检测配置是否正确。比如dm9000网卡,就需要首先将示例信息挂接到我们的板级设备树上,并根据芯片手册和电路原理图将相应的属性进行配置,再配置相应的驱动。需要注意的是,dm9000的地址线一般是接在片选线上的,所以设备树中就应该归属与相应片选线节点,我这里用的exynos4412,接在了bank1,所以是"<0x50000000 0x2 0x50000004 0x2>"
最终的配置结果是:
在这里插入图片描述
勾选相应的选项将dm9000的驱动编译进内核。
在这里插入图片描述
执行make uImage;make dtbs,tftp下载,成功加载nfs根文件系统并进入系统,表示网卡移植成功
在这里插入图片描述

Linux设备树操作常用API

Linux设备树语法详解一文中介绍了设备树的语法,这里主要介绍内核中提供的操作设备树的API,这些API通常都在 “include/of.h” 中声明。

device_node

内核中用下面的这个结构描述设备树中的一个节点,后面的API都需要一个device_node对象作为参数传入。
在这里插入图片描述

查找节点API

在这里插入图片描述

提取通用属性API

在这里插入图片描述

提取addr属性API

在这里插入图片描述

提取resource属性API

在这里插入图片描述

提取GPIO属性API

在这里插入图片描述

提取irq属性API

在这里插入图片描述

提取其他属性API

在这里插入图片描述

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

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

相关文章

基于 EasyOCR + HanLp 实现图片文字实体(中文姓名、机构名、地域名)识别

一、EasyOCR HanLp EasyOCR 是一个python版的文字识别工具。目前支持80中语言的识别。并且支持&#xff1a;图像预处理&#xff08;去噪、色彩饱和度、尖锐处理)、CRAFT文字检测、中间处理&#xff08;倾斜处理等&#xff09;、文字识别、后续处理、输出结果。框架如下&#…

RHCE实验--ansible

第四章 1、使用debug模块&#xff0c;显示当前受管主机的dns服务器的ip地址。 2、将createuser.fact文件传输到受管主机上作为自定义事实变量文件&#xff08;/etc/ansible/facts.d/&#xff09;&#xff0c;该文件的内容如下&#xff1a; [general] username wujing mima…

以太网 STP临时环路的产生、STP BPDU的转发过程、根桥故障案例分析。

2.10.2 以太网 传统STP生成树&#xff08;STP临时环路、STP BPDU的转发过程、根桥故障案例&#xff09; 传统STP生成树2.10.2 以太网 传统STP生成树&#xff08;STP临时环路、STP BPDU的转发过程、根桥故障案例&#xff09;STP临时环路&#xff1a;STP BPDU的转发过程&#xff…

多维数据分析

【数据挖掘】数据挖掘#商业智能&#xff08;BI&#xff09;数据分析挖掘概念 数据挖掘目前在各类企业和机构中蓬勃发展。因此我们制作了一份此领域常见术语总结。 分析型客户关系管理&#xff08;Analytical CRM/aCRM&#xff09;: 用于支持决策&#xff0c;改善公司跟顾客的…

redis集群详细搭建方式(含原理、操作指令、异常处理)

目录 1.概述 2.配置 2.1.配置文件 2.2.合体 2.3.进入cli 3.集群操作 3.1.查看集群信息 3.2.集群中录入值 3.3.查询集群中的值 4.故障处理 1.概述 概念&#xff1a; redis集群是从3.0版本开始支持的一个功能&#xff0c;是redis的一种水平扩展方式&#xff0c;将全局数据分…

NNDL 作业12:第七章课后题

习题7-1在小批量梯度下降中,试分析为什么学习率要和批量大小成正比. 在小批量梯度下降中&#xff1a; 令&#xff0c;则&#xff1a; 因此我们要使得参数最优&#xff0c;则为最优的时候的常数&#xff0c;故学习率要和批量大小成正比。 习题7-2在Adam算法中,说明指数加权平均…

以太网 传统STP生成树的BPDU介绍、STP端口状态介绍与切换过程,STP详细的工作过程。

2.10.1 以太网 传统STP生成树&#xff08;STP BPDU、STP端口状态、STP工作过程&#xff09; STP生成树协议的之间的交互通过STP BPDU&#xff08;根协议数据单元&#xff0c;Bridge Protocol Data Unit&#xff09;进行。 传统STP生成树2.10.1 以太网 传统STP生成树&#xff0…

《码出高效》五 异常与日志

前言 本章主要是讲异常处理&#xff0c;关于异常主要有三个问题&#xff1a; 哪里发生异常 谁来处理异常 如何处理异常 围绕这三个问题就有了一套异常处理机制 异常分类 通常异常时针对不稳定代码的&#xff0c;并且需要区分类型 throw和throws的区别&#xff1a; 以此段代…

session条件竞争

PHP SESSION 的存储 Session会话存储方式 PHP将session以文件的形式存储服务器的文件中&#xff0c;session.save_path来控制 默认路径 /var/lib/php/sess_PHPSESSID /var/lib/php/sessions/sess_PHPSESSID /tmp/sess_PHPSESSID /tmp/sessions/sess_PHPSESSID session文件默…

PS图层+移动工具(2)复制删除快捷键 图层分组 前景色填充

查看此文前 你需要先读 PS图层移动工具(1)图层概念-拖动操作-移动工具基础 其实显示变换控件 这个配置相对 是容易造成错误操作 不小心就把文件拖动了 当我们想调这些时 可以直接 按住键盘上的 CtrlT 然后点击图层 这个操作框就出来了 然后调好之后 还是 直接用鼠标双击图层 就…

荧光染料Sulfo-Cyanine 7 Tyramide,Tyramide-Sulfo-Cy7,磺酸基-花青素Cy7 酪酰胺

一&#xff1a;产品描述 1、名称 英文&#xff1a;Sulfo-Cyanine 7 Tyramide&#xff0c;Tyramide-Sulfo-Cy7 中文&#xff1a;磺酸基-花青素Cy7 酪酰胺 2、所属分类&#xff1a;Cyanine 3、分子式&#xff1a;C43H51N3O8S2 4、分子量&#xff1a;802.01 5、质量控制&am…

二叉树的序列化与反序列化

二叉树的序列化与反序列化 通俗的说就是给定一个二叉树的根节点&#xff0c;用某种方法将树结构的信息存到一个字符串中&#xff0c;并且还可以用这一个字符串还原这棵树。 本文介绍两种方法&#xff0c;分别为递归法和迭代法。 剑指 Offer 37. 序列化二叉树 递归法 序列化&a…

final域的内存语义

重排序规则 1. 在构造函数内对一个final域的写入&#xff0c;与随后把这个被构造对象引用赋值给一个引用变量&#xff0c;着两个操作不能重排序 2. 初次读一个包含final域的对象的引用&#xff0c;与随后初次读取这个final域&#xff0c;这两个操作不能重排序 以下面实例作说明…

基于ssm作业管理系统

随着计算机以及网络的普及&#xff0c;教师与学生对辅助教学方式的要求也越来越高&#xff0c;在教学辅助方式上追求质量及效率。作为教学核心组成之一的作业管理也趋向更加便 捷快速的方式。 经过调查&#xff0c;现阶段高校进行作业管理的方式主要有三种&#xff1a; 情况一&…

SSM学生宿舍管理系统(附源码)

本次介绍的是一个基于SSMJSP开发的学生宿舍管理系统的设计与实现&#xff0c;界面简洁、程序逻辑清晰&#xff0c;适合作为毕业设计的模板参考&#xff01; 前些天发现了一个巨牛的人工智能学习网站&#xff0c;通俗易懂&#xff0c;风趣幽默&#xff0c;忍不住分享一下给大家 …

阿里妈妈star论文重点记录

论文地址&#xff1a;https://arxiv.org/pdf/2101.11427.pdf 1&#xff1a;业务实际应用 自 2020 年底以来&#xff0c;STAR 已部署在阿里巴巴展示广告系统&#xff0c;点击率提升8.0%和RPM增加6% 2&#xff1a;特点 星型拓扑促进跨多个domain的有效信息转换&#xff0c;在…

MATLB|抽水蓄能电站系统的最优竞价策略研究

&#x1f4a5;&#x1f4a5;&#x1f4a5;&#x1f49e;&#x1f49e;&#x1f49e;欢迎来到本博客❤️❤️❤️&#x1f4a5;&#x1f4a5;&#x1f4a5;&#x1f3c6;博主优势&#xff1a;&#x1f31e;&#x1f31e;&#x1f31e;博客内容尽量做到思维缜密&#xff0c;逻辑清…

Python自动化测试面试题——接口篇

目录 网络模型 OSI有哪几层,分别包含哪些协议? 协议 TCP,UDP的区别? TCP如何确保可靠传输? 三次握手与四次挥手? HTTP有哪些请求方法? HTTP常见的状态码有哪些? GET和POST的区别? Cookie和Session的区别? Token和Session的区别? HTTP和HTTPS的区别? 接口…

JavaScript(二):变量、数据类型、类型转换

变量一、变量的使用1.声明变量2.赋值3.变量的初始化4.变量的更新5.同时声明多个变量6.声明变量的特殊情况7.变量的命名规则二、数据类型数字型1.数字型Number2.数字型范围3.数字型的特殊值4.isNaA()字符串型String1.字符串型格式2.字符串型引号嵌套3.字符串转义符4.字符串长度5…

R语言相关分析和稳健线性回归分析

介绍 下面以物种多样性为例子展示了如何在R语言中进行相关分析和线性回归分析。 怎么做测试 相关和线性回归示例 Data read.table(textConnection(Input),headerTRUE) 数据简单图 plot(Species ~ Latitude, dataData, pch16,xlab "Latitude", ylab "Specie…