设备树.dts文件

发布时间 2023-04-11 15:11:47作者: Haowen_Zhao

一,概念

设备树(Device Tree)是描述计算机的特定硬件设备信息的数据结构,以便于操作系统的内核可以管理和使用这些硬件,包括CPU或CPU,内存,总线和其他一些外设。它起源于OpenFirmware。采用设备树后,许多硬件的细节可以直接传递给linux,不需要在内核中充斥着大量的冗余代码。

Linux内核从3.x版本之后开始支持使用设备树,这样做的意义重大,可以实现驱动代码与设备的硬件信息相互的隔离,减少了代码中的耦合性,在此之前,一些与硬件设备相关的具体信息都要写在驱动代码中,如果外设发生相应的变化,那么驱动代码就需要改动。但是在引入了设备树之后,这种尴尬的情况找到了解决的办法,通过设备树对硬件信息的抽象,驱动代码只要负责处理逻辑,而关于设备的具体信息存放到设备树文件中,这样,如果只是硬件接口信息的变化而没有驱动逻辑的变化,开发者只需要修改设备树文件信息,不需要改写驱动代码。

二,框架理解

设备树由一系列的节点和属性组成,节点可包含子节点。在设备树中,可描述的信息包括:

  • CPU数量和类型
  • 内存基地址和大小
  • 总线和桥
  • 外设连接
  • 中断控制器和中断使用情况
  • GPIO控制器和GPIO使用情况
  • 时钟控制器和时钟使用情况

bootload会将这些信息传递给内核,内核开始识别这些树,并解析成linux内核中platform_device,i2c_client,spi_device等设备,而这些设备使用的内存资源,中断等信息也传递给内核。内核会将这些资源绑定给相应的设备。

dtb(Device Tree Blob)dts经过dtc编译之后会得到dtb文件,dtb通过Bootloader引导程序加载到内核。所以Bootloader需要支持设备树才行;Kernel也需要加入设备树的支持;

 

 三,语法

一个dts文件主要包含以下几个部分:

  • 根节点:\
  • 设备节点:nodex
    • 节点名称:图中node
    • 节点地址:node@0就是节点的地址;
    • 子节点:childnode
  • 属性:属性名称(Property name)和属性值(Property value)
  • 标签

比如下面这个:

 

 对该dts文件做一些解释:

  • /dts-v1/;:这是DTS文件的版本指令,表示该文件使用版本1的DTS语法。
  • /:该节点是根节点,表示整个系统。
  • #address-cells#size-cells:这些属性用于指定节点的地址和大小长度,这里设置为1,即32。
  • compatible:该属性用于描述系统和其组件的兼容性,compatible 属性的值是一个字符串列表, compatible 属性用于将设备和驱动绑定起来,用于选择设备所要
    使用的驱动程序。
  • model:该属性用于描述该系统的型号信息,描述设备模块信息。
  • L xx :在Device Tree文件中,L是一个label(标签)的前缀,用于标识不同的节点。Label是一个唯一的字符串标识符,可以用于在设备树中引用节点。在这个文件中,L被用于标识不同的节点,如serial0、cpus、soc等等。
  • aliases:该节点是别名节点,允许为设备定义别名,以便在系统中引用。这里定义了一个串口设备别名“serial0”。

CPU部分:

  • cpus:该节点是CPU节点,用于描述系统中的CPU资源。这里定义了一个名为“cpu@0”的CPU,使用了“sifive,rocket0”和“riscv”兼容属性。
  • hardware-exec-breakpoint-count = <1>; 表示硬件执行断点计数器的数量为1。
  • i-cache-block-size = <64>; 表示I缓存块的大小为64字节。
  • i-cache-sets = <64>; 表示I缓存的组数为64。
  • i-cache-size = <4096>; 表示I缓存总大小为4096字节。
  • reg = <0x0>; 表示该处理器的寄存器起始地址为0。
  • riscv,isa = "rv32imac"; 表示该处理器的指令集为RV32IMAC。
  • riscv,pmpgranularity = <4>; 表示处理器的物理内存保护(PMP)粒度为4字节。
  • riscv,pmpregions = <8>; 表示该处理器支持8个PMP区域。
  • sifive,dtim = <&L4>; 表示该处理器的数据总线RAM接口使用标签为L4的节点。
  • status = "okay"; 表示该处理器节点已启用。
  • timebase-frequency = <1000000>; 表示该处理器的时间基准频率。
  • L2: 标签“interrupt-controller”表示该节点是一个中断控制器。
  • #interrupt-cells = <1>; 表示中断编号单元数为1。
  • compatible = "riscv,cpu-intc"; 表示该中断控制器与RISC-V CPU中断控制器兼容。
  • interrupt-controller; 表示该节点是一个中断控制器。
  • htif:这个DTS片段定义了一个名为"htif"的节点,它具有属性"compatible",其值为"ucb,htif0"。这意味着此节点是兼容于"ucb,htif0"的硬件。 "htif"是"Host-Target Interface"的缩写,用于在主机和目标之间建立通信通道。在此情况下,这个节点可能表示与主机之间的通信接口。

  • soc 节点中,#address-cells#size-cells 属性指定了地址和大小的编码方式。 compatible 属性指定了 SoC 的类型和所使用的总线类型。ranges 属性可以指定子节点寻址的偏移量和大小的转换。
  • boot-address-reg 子节点描述了启动地址寄存器,用于指定系统启动时的执行位置。
  • clint 子节点是 RISC-V 处理器的计时器和中断控制器,可处理外部中断并在内部生成软件中断,"interrupts-extended"属性列出了与此节点相关联的中断线,指定了中断控制器的编号和每个控制器中断的编号。"reg"属性指定了此节点的物理地址和大小,"reg-names"属性指定了此地址范围的名称。。
  • clock-gater 子节点是 SoC 的时钟门控制器,用于控制时钟的开关和频率。
  • debug-controller 子节点是处理器的调试控制器,用于支持外部调试工具的连接。
  • dtim 子节点是 SoC 的数据存储器,用于存储指令和数据。
  • error-device 子节点是错误信息设备,用于报告硬件错误和异常。

  • interrupt-controller 子节点是 SoC 的中断控制器,用于处理外部中断并将其分发到适当的处理器或设备。它的地址范围是从 0x0 到 0x1000。该控制器是支持 jtag 连接的,因此 debug-attach 属性设置为 "jtag"。此外,它的中断号设置为 65535,即不使用中断。其 compatible 属性表示它符合 sifive,debug-013riscv,debug-013 规范。
  • lbwif-ramlbwif-rom 子节点是 SoC 上的 RAM 和 ROM 存储器。lbwif-rom 是一个只读存储器(ROM),用于存储启动代码和固件等固定数据
  • rom@10000: 这是 SoC 中的另一个 ROM 存储器,其物理地址范围为 0x10000 到 0x20000。
  • serial 子节点是 SoC 的串行通信设备,用于与外部设备进行通信。
  • subsystem_pbus_clock 子节点是 SoC 的时钟设备,用于控制总线时钟频率。这里定义了一个名为subsystem_pbus_clock的时钟节点,其频率为100MHz。它使用了fixed-clock的驱动程序,并且没有#clock-cells属性,表明它是一个固定频率的时钟。此时钟节点没有父时钟,它是根时钟。
  • tile-reset-setter 子节点是重置控制器,用于重置 SoC 中的各个模块。