linux驱动:(15)设备树

目录

概念

设备树起源

平台总线起源

平台总线弊端

设备树作用

设备树基本框架

设备树语法

节点

节点名称

节点别名

节点的作用

属性

大致查看设备树文件

头函数

寻找根节点

分析根节点

dtsi文件

查看方法


概念

  • 设备树是一种描述硬件资源的数据结构。它通过 bootloader将硬件资源传给内核使得内核和硬件资源描述相对独立。
  • 简单来说就是将前面的dev.c变成一个设备树文件,都是描述硬件资源的数据结构,但他不需要重新编译内核,只需要将设备树文件编译成二进制文件然后通过bootloader传递给内核,内核再对其进行解析和展开得到一个关于硬件的拓扑图

设备树起源

平台总线起源

  • 前面学了字符和杂项设备,都是有一个框架,按需填空就好,这样很简单容易
  • 但是很不容易扩展,当写了很多驱动之后就会发现前面很多都相同,到了后面初始化硬件部分不一样,其他的都相同
  • 于是我们将通用的代码和有差异的代码分离出来,来增强我们驱动代码的移植性
  • 分离是把一些不相似的东西放到了 dev.c,把相似的东西放在了 dri.c,
  • 如果有很多相似的设备或者平台,我们只要修改 dev.c就可以了,这样重复性的工作就大大的减少了
  • 这个就是平台总线的由来。

平台总线弊端

  • 当底板不换,换了芯片,换了一个平台,都要修改C文件,并且要重新编译
  • 这样子会留下大量关于以前芯片细节的代码
  • 雨水linux就研究出了设备树,用来剔除相对内核来说的“垃圾代码

设备树作用

  • 即用设备树文件来描述这些设备信息,也就是代替dev.c文件,
  • 虽然拿到了内核外面,但 platform 匹配上基本不变,并且相比于之前的方法,
  • 使用设备树不仅可以去掉大量“垃圾代码”,并且采用文本格式,方便阅读和修改,
  • 如果需要修改部分资源,我们也不用在重新编译内核了,只需要把设备树源文件编译成二进制文件,在通过 bootloader 传递给内核就可以了。
  • 内核在对其进行解析和展开得到一个关于硬件的拓扑图。
  • 我们通过内核提供的接口获取设备树的节点和属性就可以了。
  • 即内核对于同- soc的不同主板,只需更换设备树文件dtb 即可实现不同主板的无差异支持,而无需更换内核文件。

设备树基本框架

  • 设备树从根节点开始,每个设备都是一个节点。
  • 节点和节点之间可以互相嵌套,形成父子关系。
  • 设备的属性用 key-value 对(键值对)来描述,每个属性用分号结束

设备树语法

节点

举例,根节点和子节点和子子节点

/{  //根节点
    node1//子节点 node1
    {
        child-node1 //子子节点
        {
        };
    };
    node2//子节点 node2
    {
    };
};

节点名称

格式

  • <名称>[@<设备地址>]
  • 名称要以设备的类型来取,不能简单随便,要看得出什么设备
  • 设备地址是用来区分设备的,不是操作过程中的基地址

注意

  • 同一级的节点只要地址不一样,名字是可以不唯一的。
  • 设备地址是一个可选选项,可以不写。但为了容易区分和理解,一般是都写的。

节点别名

当我们找一个节点的时候,我们必须书写完整的节点路轻,如果我们的节点名很长,那么我们在引用的时候就十分不方便,所以,设备树允许我们用下面的形式为节点标注引用

举例

  • uart8: serial@02288000
  • uart8:别名
  • serial@02288000:节点名称

节点的作用

一般往一个节点里面添加内容的时候,不会直接把添加的内容写到节点里面,而是通过节点的引用来添加。

举例

&uart8 {
    pinctrl-name = "default",
    pinctrl-0 = <&pinctrl_uart8>;
    status = "okay";
};
  • 直接&加别名就表示向别名的节点添加东西
  • 添加三个值,用节点标志圈起来

注意

  • 在dts底下有两个根节点,会合并成一个根节点,表示相同的节点的不同属性信息会合并

属性

  • reg属性
    • 作用:属性用来描述一个设备的地址范围
    • 格式:reg = <add1 length1 [add2 length2] ......>
    • 举例:其中101F2000就是起始地址,0x1000是长度
      serial@02288000{
          reg = <101F2000 0x1000>;
      };
  • #address-cells和#size-cells属性
    • #address-cells:用来设置子节点中reg地址的数量
    • #size-cells:用来设置子节点中reg地址长度的数量
    • 举例:
      cpu{
          #address-cells = <1>;
          #size-cells = <1>;
          serial@101F2000{
              compatible = "serial";
              reg = <101F2000 0x1000>;
          };
      };
      • 其中#address-cells 和#size-cell 均为1,也就是说我们子节点里面的 reg 属性里这个寄存器组的起始地址只有一个,长度也只有一个。所以101F2000 是起始地址,0x1000 是长度。
  • compatible属性
    • compatible 是一个字符串列表,可以在代码中进行匹配driver.c里的name
    • 举例:
      compatible = “led";
  • status属性
    • status 属性的值类型是字符串,这里我们只要记住俩个常用的即可,一
    • 个是 okay,表示设备可以正常使用
    • 一个是 disable,表示设备不能正常使用

大致查看设备树文件

在 源码根目录/arch/arm/boot/dts/中

头函数

和c语言一样,可以#include "xxx.dts"包含其他设备树文件

寻找根节点

如果该设备树文件没有 /{ } 开头的节点,就去包含的头文件去找,先找到根节点

分析根节点

  • 会有一个model 变量字符串,一般作用是告诉我们这个设备树文件对应什么平台
  • compatible:有几个字符串,作用是可以匹配多个驱动,但会按第一个字符串来先匹配
  • chosen:设置uboot环境变量
  • 包含各个的子节点

dtsi文件

如果在根目录中又包含了一个dtsi文件,进去这个dtsi文件后,就又会看到一个根节点,这就是我上面说的,dtsi里面的根节点会于我们第一个找到的根节点合并成一个根节点

查看方法

找到根节点,从左往右,从上往下

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

码农小白

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值