Device Tree1

A device tree is a tree data structure with nodes that describe the physical devices in a system.

设备树是一种数据结构,用来描述硬件设备,如此一来硬件信息就无需硬编码在代码中,这样就将设备驱动和实际硬件解耦开来,有了良好的可扩展性。操作系统可以在启动运行时读取相应的文件,必要时也可以修改。当然设备树也没有完全解决所有硬件配置的问题。

Flattened Device TreeDevice Tree SourceDevice Tree Binary

Linux uses DT data for three major purposes:

  • platform identification,
  • runtime configuration, and
  • device population.

Linux 中 ARM 的 dts 文件位于 arch/arm/boot/dts/,通过相关的脚本可以在 dts 和 dtb 之间转换。

$ scripts/dtc/dtc -I dts -O dtb -o /path/my_tree.dtb /arch/arm/boot/dts/my_tree.dts
$ scripts/dtc/dtc -I dtb -O dts -o /path/my_tree.dts /path/my_tree.dtb

dts

基本的语法可以表现为节点 node 以及其中的 key-value 键值对。

label: node@xxx {key = value;
}compatible: "<manufacture>, <model>"// 根据习惯,如果一个 node 含有 reg,那么其名称中必须含有unit-address,即reg中的第一个值。
node: <name>[@<unit-address>] // 由 parent-node 指定下面两个 properties 来帮助确定 reg 中的数据格式。
Addressing: reg = <address1 length1 [address2 length2] [address3 length3] ... >
#address-cells: reg 中 base address 由多少个 cell (32bits values) 来表示
#size-cells: reg 中的 length 由多少个 cell (32bits values) 来表示
/{compatible = "nvidia,harmony", "nvidia,tegra20"; // <manufacture>, <model>"#address-cells = <1>; // 在它的子节点的 reg 属性中, 使用多少个 u32 整数 (cell) 来描述地址 (base address)#size-cells = <1>; // 在它的子节点的 reg 属性中, 使用多少个 u32 整数 (cell) 来描述大小 (size / length)[memory reservations]{[property definitions][child node]};
};// [property definitions]
[label:] node-name[@unit-address] { // 根据习惯,Node含有reg,那么其名称中必须含有unit-address,即reg中的第一个值[property definitions][child nodes]
};// for example
memory@30000000 {device_type = "memory";reg =  <0x30000000 0x4000000>;
};
// node reference by phandle
pic@10000000 {phandle = <1>;interrupt-controller;
};
another-device-node {interrupt-parent = <1>;   // 使用phandle值为1来引用上述节点
};// node reference by label
PIC: pic@10000000 {interrupt-controller;
};
another-device-node {interrupt-parent = <&PIC>;   // 使用label来引用上述节点, // 使用lable时实际上也是使用phandle来引用, // 在编译dts文件为dtb文件时, 编译器dtc会在dtb中插入phandle属性
};

Syntax

  1. 每个Module在Device Tree中都是一个Node, 根据driver的实现,可以有父节点或者子节点;
  2. Root是所有module最终的父节点;

常见的 Top-level module:

cpus: its each sub-nodes describing each CPU in the system.
memory : defines location and size of the RAM.
chosen : defines parameters chosen or defined by the system firmware at boot time. In practice, one of its usage is to pass the kernel command line.
aliases : shortcuts to certain nodes.One or more nodes defining the buses in the SoC
One or mode nodes defining on-board devices

/ :root node,device tree 从该节点开始。
property:每个 property 是一个 Key-value 键值对。

Key

model
compatible
reg:node / device 的物理地址,`reg = <address1 size1 [address2 size2] ...>`
aliases
...

value

  • text-string: 双引号, "string-property = "a string";
  • cell: 32-bit无符号整型: < >, cell-property = <0xbeef 123 0xabcd1234>;
  • binary-property: [ ], binary-property = [0x01 0x23 0x45 0x67];
  • mixed-property: 不同类型的可以放一起: mixed-property = "a string", [0x01 0x23 0x45 0x67], <0x12345678>;
  • string-list: 逗号也用来建立字符串列表: string-list = "red fish", "blue fish";

example

下面以 ARMfoundation v8 作为例子。

/* * ARM Ltd.* ARMv8 Foundation model DTS *//dts-v1/;
/memreserve/ 0x80000000 0x00010000;
/ {model = "Foundation-v8A";compatible = "arm,foundation-aarch64", "arm,vexpress";interrupt-parent = <&gic>;#address-cells = <2>;#size-cells = <2>;chosen { };aliases {serial0 = &v2m_serial0;...};cpus {#address-cells = <2>;#size-cells = <0>;cpu@0 {device_type = "cpu";compatible = "arm,armv8";reg = <0x0 0x0>;enable-method = "spin-table";cpu-release-addr = <0x0 0x8000fff8>;next-level-cache = <&L2_0>;};cpu@1 { ... };cpu@2 { ... };cpu@3 { ... };L2_0: l2-cache0 {compatible = "cache";};};memory@80000000 {device_type = "memory";reg = <0x00000000 0x80000000 0 0x80000000>,<0x00000008 0x80000000 0 0x80000000>;};gic: interrupt-controller@2c001000 {compatible = "arm,cortex-a15-gic", "arm,cortex-a9-gic";#interrupt-cells = <3>; // 所有以它作为中断接受者的设备都要用3个cell来描述中断信息。#address-cells = <2>;interrupt-controller; // 它是一个中断控制器reg = <0x0 0x2c001000 0 0x1000>,<0x0 0x2c002000 0 0x1000>,<0x0 0x2c004000 0 0x2000>,<0x0 0x2c006000 0 0x2000>;interrupts = <1 9 0xf04>;};timer {compatible = "arm,armv8-timer";interrupts = <1 13 0xf08>,<1 14 0xf08>,<1 11 0xf08>,<1 10 0xf08>;clock-frequency = <100000000>;};pmu: { ... };smb: { ... };

以上面的 CPU 节点为例,其拥有四个子节点和一个 l2-cache0 节点,其中 L2_0l2-cache0 的 label。
cpus 节点中指定了 regaddress 为 2 个 cell,构成一个u64,size 为0,因此没有大小。
根据惯例,所以 CPU@00unit-address 取自 reg 的第一个值 0x0 0x0,两个 cell。

interrupt2

...The 1st cell is the interrupt type; 0 for SPI interrupts, 1 for PPIinterrupts.The 2nd cell contains the interrupt number for the interrupt type.SPI interrupts are in the range [0-987].  PPI interrupts are in therange [0-15].The 3rd cell is the flags, encoded as follows:bits[3:0] trigger type and level flags.1 = low-to-high edge triggered2 = high-to-low edge triggered (invalid for SPIs)4 = active high level-sensitive8 = active low level-sensitive (invalid for SPIs).bits[15:8] PPI interrupt cpu mask.  Each bit corresponds to each ofthe 8 possible cpus attached to the GIC.  A bit set to '1' indicatedthe interrupt is wired to that CPU.  Only valid for PPI interrupts.Also note that the configurability of PPI interrupts is IMPLEMENTATIONDEFINED and as such not guaranteed to be present (most SoC availablein 2014 seem to ignore the setting of this flag and use the hardwaredefault value).

第一个域指明中断是 SPI 还是 PPI,0是 SPI,1是PPI
第二个是中断号
第三个是中断触发类型以及中断发往的 cpu_id

以timer为例

 timer {compatible = "arm,armv8-timer";interrupts = <1 13 0xf08>,<1 14 0xf08>,<1 11 0xf08>,<1 10 0xf08>;clock-frequency = <100000000>;};

上面的描述表明 timer 中断类型为PPI, 分别对应中断号10, 11, 13, 14, 并且对 4 个CPU与之相连, 且为 active low level-sentitive(0xf08)。

dtb

设备树源文件通过 dtc 编译得到 dtb。

struct ftd_header
free space
memory reservation block
free space
structure block
free space
strings block
free space

DTB 的数据为大端 存放。
DTB分为四个部分:struct ftd_headermemory reservation blockstructure blockstrings block
struct ftd_header:用来表明各个分部的偏移地址,整个文件的大小,版本号等;
memory reservation block:在设备树中使用 /memreservation/ 定义的保留内存信息;
structure block:保存节点的信息,节点的结构;
strings block:保存属性的名字,单独作为字符串保存;

struct fdt_header {uint32_t magic;uint32_t totalsize;uint32_t off_dt_struct;uint32_t off_dt_strings;uint32_t off_mem_rsvmap;uint32_t version;uint32_t last_comp_version;uint32_t boot_cpuid_phys;uint32_t size_dt_strings;uint32_t size_dt_struct;
};// 节点信息结构体
struct {uint32_t len; // val 的长度uint32_t nameoff; // 在string block的偏移
};

dtc

sudo apt-get install device-tree-compiler
两种文件格式可以互相转换。

dtc -I dts -O dtb -o /path/to/xxx.dtb /path/toxxx.dts
dtc -I dtb -O dts -o /path/to/xxx.dts /path/to/xxx.dtb

  1. linux/Documentation/devicetree/usage-model.txt ↩︎

  2. https://elixir.bootlin.com/linux/v4.3.6/source/Documentation/devicetree/bindings/arm/gic.txt ↩︎

设备树 DTS DTB相关推荐

  1. [ZedBoard移植嵌入式Linux教程(9,10)]编译设备树dts为dtb,制作根文件系统

    九.编译设备树dts为dtb 前面的linux内核源码目录中已经包含了设备树编译器Device Tree Compiler(dtc),在目录arch/arm/boot/dts/目录下. 将前面生成的x ...

  2. dts 编译过程_linux设备树dts移植详解

    [转] 摘 要:设备树的引入减少了内核为支持新硬件而需要的改变,提高代码重用,加速了Linux 支持包的开发,使得单个内核镜像能支持多个系统.作为U-Boot 和Linux 内核之间的动态 接口,本文 ...

  3. 42.设备树---DTS的语法

    Device Tree Usage - 摩斯电码 - 博客园 设备树dts/dtsi格式_孤独行者的专栏-CSDN博客_dts格式 Linux设备树语法详解 - Abnor - 博客园 设备树笔记 - ...

  4. linux 设备树(.dts)实战解析

    文章目录 前言 设备树 DTS语法内容 标准属性 向节点追加或修改内容 设备树在目录中的体现 Linux 内核解析 DTB 文件 帮助文档信息 设备树节点的操作函数 1.查找节点的 of 函数 2.查 ...

  5. dtsi与dts_设备树DTS规范

    原标题:设备树DTS规范 ------ 作者:韦东山 来自(设备树维基教程第二课,一共2节): http://wiki.100ask.org/Linux_devicetree 第01节_DTS格式 d ...

  6. linux dts 语法格式,设备树DTS格式解析

    8种机械键盘轴体对比 本人程序员,要买一个写代码的键盘,请问红轴和茶轴怎么选? 宿主机: ubuntu16.04 开发板: tq-imx6ull 内核版本: linux-4.1.15 用实例讲解下设备 ...

  7. 设备树学习(二、设备树dts/dtsi格式)

    说明:后续的博文参考自韦东山老师的设备树视屏,老师用的是2440的开发板,我用的是s5pv210的开发板.原理一样 一.前言 简单的说,如果要使用Device Tree,首先用户要了解自己的硬件配置和 ...

  8. i.MX6ULL终结者Linux设备树DTS设备树语法结构

    文章目录 1 dtsi头文件 2 设备节点信息 3 设备节点及label的命名 4 标准属性 5 根节点compatible属性 6 在设备节点中添加或修改内容 一般情况下,我们不会从头编写一个完整的 ...

  9. Linux下设备树dts内容(详细)总结及示例解析

    文章目录 一.简介 二.设备树基础内容 2.1 设备树文件存放路径 2.2 DTS.DTB和DTC关系 2.3 传统驱动代码和使用设备树的对比 三.设备树内容属性介绍 3.1 节点名称 3.2 com ...

最新文章

  1. vb和python-vb与python
  2. C# 给word文档添加水印
  3. Tomcat性能调优-JVM监控与调优
  4. 2、SpringBoot整合JDBC
  5. python map、filter、reduce
  6. ​她回顾过去的学习生活,印象最深刻的并非是收获荣耀的高光时刻, 而是在“看文献、做科研、写论文”循环中推进的每一步...
  7. php apk 分包,H5打包出APP,分包
  8. html+表单+下拉框,HTML+CSS:常用表单控件之单选框、多选框、下拉框的介绍
  9. react native 随手记之打包遇到坑
  10. 那些年你错过的房子 1980-2017年记录: 深圳真实房价
  11. python连接S3
  12. 数据分析大数据面试题大杂烩01
  13. 做出正确选择 重设精彩人生
  14. stc32G库函数(二)——定时器
  15. 外贸群发软件不好用,邮件群发很苦恼
  16. 蘑菇街2021财年Q1财报:直播GMV连续18个季度保持增长
  17. Android 常用技术
  18. 群晖docker注册表,移动网络无法获取
  19. 如何通过 nginx 实现远程投屏并控制 android 手机
  20. 短视频微信小程序界面

热门文章

  1. GIS算法--已知一点经纬度,方位角,距离求另一点
  2. 同一个局域网怎么计算机共享打印机,如何共享同一个局域网中的打印机
  3. [求助+提问]如何用Anylogic进行简单的船舶交通流仿真,具体内容如下(如果可以的话,我会支付一定报酬,谢谢):
  4. Hadoop和Spark简单概述
  5. 安科瑞AFK系列低压复合开关
  6. 十七届文博会闭幕,中兴通讯5G助推智慧广电新发展
  7. java学习笔记-第七章:面向对象编程(基础部分)
  8. linux下实现图像金字塔+Qt5
  9. 【ANTLR学习笔记】2:基本工作流程和歧义处理方法
  10. 最新码支付源码官方版+微信、支付宝、qq监控+易支付H5接口-2022/12/6