欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页

Linux设备树

程序员文章站 2024-01-23 14:51:52
...

设备树

组成

DTS有一系列node(节点)和property(属性),节点可以包含更多子节点,DTS主要描述设备信息

  • CPU的数量及类别
  • 内存基地址和size
  • 总线和桥
  • 外设连接
  • 中断
  • GPIO
  • CLOCK

其有以下几种特性:

  • 每个设备树文件都有一个根节点,每个设备都是一个节点。
  • 节点间可以嵌套,形成父子关系,这样就可以方便的描述设备间的关系。
  • 每个设备的属性都用一组key-value对(键值对)来描述。
  • 每个属性的描述用;结束
/{                                  //根节点
    node1{                          //node1是节点名,是/的子节点
        key=value;                  //node1的属性
        ...
        node2{                      //node2是node1的子节点
            key=value;              //node2的属性
            ...
        }
    }                               //node1的描述到此为止
    node3{
        key=value;
        ...
    }
}

节点名

每个节点必须有节点名,格式< name>[@< unit-address>]

  • < name>:为最长31个字符的ascii字符串,一般用其代表的设备类型命名,
  • unit-address: 描述设备的地址,一般情况下,其提供访问设备的基地址,节点的reg property也用此参数,见下文。

引用

和c语言一样支持引用,如果按照树结构书写嵌套比较深,会十分不方便,可以&节点名来省去路径,相同节点不同属性信息会被合并,相同节点相同的属性会被重写

&cpu{
    cpu0-supply = <&buck2_reg>;
};

KEY

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

- compatible

设备树中每个节点都需要有compatible属性,compatible属性决定每一个设备驱动绑定哪一个设备,设备驱动可以利用这个相应函数读取compatible信息,利用该属性来查找节点,此外也可以通过节点名、节点路径查找指定节点。compatible是一个字符串序列,第一个字符串指定精确设备,第二字符串指定兼容设备。eg:compatible = “fsl,mpc8349-uart”, “ns16550”第一个字符串指定精确设备,第二个指定国家半导体16550 uart兼容设备。

需要注意:驱动中用于匹配的结构使用的compatible和设备树中一模一样,否则就可能无法匹配,这里另外的一点是struct of_device_id数组的最后一个成员一定是空,因为相关的操作API会读取这个数组直到遇到一个

static const struct of_device_id fls[] = {
  { .compatible = "fsl,mpc8349-uart", "ns16550"}
  { /*为空*/}
};
- address

(几乎)所有的设备都需要与CPU的IO口相连,所以其IO端口信息就需要在设备节点节点中说明。常用的属性有

  • #address-cells,用来描述子节点“reg”属性的地址表中用来描述首地址的cell的数量,
  • #size-cells,用来描述子节点“reg”属性的地址表中用来描述地址长度的cell的数量。

这两个属性,子节点中的“reg”就可以描述一块连续的地址区域。eg:父节点中指定了

#address-cells = <2>;
#size-cells = <1>;
reg = <0 0x1046C 0x4>  //reg中的前两个数表示一个地址,即0和0x1045C,最后一个数的表示地址跨度,即是0x4
- interrupts

在设备中经常用到中断,设备树中中断常用属性有

  • interrupt-controller 一个空属性用来声明这个node接收中断信号,即这个node是一个中断控制器
  • #interrupt-cells,是中断控制器节点的属性,用来标识这个控制器需要几个单位做中断描述符,用来描述子节点中“interrupts”属性使用了父节点中的interrupts属性的具体的哪个值。一般,如果父节点的该属性的值是3,则子节点的interrupts一个cell的三个32bits整数值分别为:<中断域 中断 触发方式>,如果父节点的该属性是2,则是<中断 触发方式>
  • interrupt-parent,标识此设备节点属于哪一个中断控制器,如果没有设置这个属性,会自动依附父节点的
  • interrupts,一个中断标识符列表,表示每一个中断输出信号

在内核中中断分层概念趋于流行,使内核中原本的中断源直接到中断号的方式已经很难继续发展了,所以引入了irq domain (中断域),其他的power domain,clock domain等等也是类似。系统中所有的interrupt controller会形成树状结构,对于每个interrupt controller都可以连接若干个外设的中断请求(interrupt source,中断源),interrupt controller会对连接其上的interrupt source(根据其在Interrupt controller中物理特性)进行编号(HW interrupt ID)。引入中断域后,其编号就只限定在本域内,有利于编程

中断源--interrupt parent-->GPIO--interrupt parent-->GIC1--interrupt parent-->GIC2--...-->CPU
[email protected]101f3000 {
        compatible = "arm,pl061";
        reg = <0x101f3000 0x1000
               0x101f4000 0x0010>;
        interrupts = < 3 0 >;
    };

    intc: [email protected]10140000 {  // 中断控制器
        compatible = "arm,pl190";
        reg = <0x10140000 0x1000 >;
        interrupt-controller;
        #interrupt-cells = <2>; // 中断说明符有2 cells,此例中cell 1表示中断号,cell 2 表示触发方式
    };
The 3rd cell is the flags, encoded as follows:  
       bits[3:0] trigger type and level flags.  
               1 = low-to-high edge triggered  
               2 = high-to-low edge triggered  
               4 = active high level-sensitive  
               8 = active low level-sensitive  

- ==补充== 中断划分

中断按来源分类:

  • 外部中断
  • 内部中断

按可屏蔽:

  • 可屏蔽中断
  • 不可屏蔽中断

按入口地址:

  • 向量中断(硬件提供入口地址)
  • 非向量中断(软件提供入口地址)

ARM平台支持GIC中断控制器:

  • GIC所支持的中断类型:

    • 1.PPI:私有中断,中断必须绑定一个固定CPU核,当处理该中断时,必须由绑定的CPU核处理
    • 2.SPI:共享中断,中断的处理可被任意的CPU核处理
    • 3.SWI:软中断,用于处理核间通信和调度。

内核 –|- cpu —– GIC———中断控制器 ……..—|—外设
————————————————-
soc内部

- gpio

gpio也是最常见的IO口,常用的属性有

  • “gpio-controller”,用来说明该节点描述的是一个gpio控制器
  • “#gpio-cells”,用来描述gpio使用节点的属性一个cell的内容,即 `属性 = <&引用GPIO节点别名 GPIO标号 工作模式>
[email protected]4{
    compatible = "xj4421, key";
    gpx2_7 = <&gpx2 7 0>;
}
相关标签: 设备树 Linux