设备树的官方文档:

https://www.devicetree.org/specifications/

一、理论部分

如何看下面这张图:

1)从根节点开始看起,即 /

2)在根节点中有属性以及设备节点名称

3)属性的格式有两种形式:property-name = value;property-name ;(一个有值,一个没值)

   当property-name = value时,value的取值有三种形式

4)设备节点(child nodes)的格式

总结:

(1) 语法:
Devicetree node格式:
[label:] node-name[@unit-address] {
  [properties definitions]
  [child nodes]
};

Property格式1:
[label:] property-name = value;

Property格式2(没有值):
[label:] property-name;

Property取值只有3种:
arrays of cells         (1个或多个32位数据, 64位数据使用2个32位数据表示),
string                     (字符串),
bytestring              (1个或多个字节)

示例:
a. Arrays of cells : cell就是一个32位的数据
interrupts = <17 0xc>;

b. 64bit数据使用2个cell来表示:
clock-frequency = <0x00000001 0x00000000>;

c. A null-terminated string (有结束符的字符串):
compatible = "simple-bus";

d. A bytestring(字节序列) :
local-mac-address = [00 00 12 34 56 78]; // 每个byte使用2个16进制数来表示
local-mac-address = [000012345678]; // 每个byte使用2个16进制数来表示

e. 可以是各种值的组合, 用逗号隔开:
compatible = "ns16550", "ns8250";
example = <0xf00f0000 19>, "a strange property format";

(2) DTS文件布局(layout):

/dts-v1/;
[memory reservations]         // 格式为: /memreserve/ <address> <length>;
/ {
  [property definitions]
  [child nodes]
};

(3) 特殊的、默认的属性:
a. 根节点:
#address-cells    // 在它的子节点的reg属性中, 使用多少个u32整数来描述地址(address)
#size-cells      // 在它的子节点的reg属性中, 使用多少个u32整数来描述大小(size)

例子:

#address-cells = <1>;
#size-cells = <1>;

memory@30000000 {
  device_type = "memory";
  reg = <0x30000000 0x4000000>;  
};

在子节点的reg属性中,0x30000000表示地址,0x4000000来表示大小。我凭什么知道在reg中用一个32位整数来描述地址,一个32位整数来描述大小。就是通过

#address-cells = <1>;
#size-cells = <1>;

进行指定的。

compatible     // 定义一系列的字符串, 用来指定内核中哪个machine_desc可以支持本设备
           // 即这个板子兼容哪些平台
           // uImage : smdk2410 smdk2440 mini2440 ==> machine_desc 。一个uImage可以支持多种单板,比如说    smdk2410、smdk2440、mini2440。每种单板在内核中都有一个对应的machine_desc结构体,里面会有不同的初始化函数。因此利用compatible这个属性可以选择单板,让内核去执行对应的初始化函数。

举例:

compatible = "samsung,smdk2440";  通过这样指定,内核就会去执行smdk2440中的初始化函数

compatible可以是一个或多个字符串。比如说compatible = "samsung,smdk2440"  "samsung,smdk24xx"

smdk2440就更加具体,s3c24xx就比较广泛些,可以适配更多的单板。使用设备树时,优先去内核中寻找支持smdk2440的machine_desc,如果找不到的话,再去寻找支持smdk24xx的machine_desc。优先选择第一项,如果没有,再往后选择。

model    // 咱这个板子是什么
         // 比如有2款板子配置基本一致, 它们的compatible是一样的
        // 那么就通过model来分辨这2款板子

b. /memory
device_type = "memory";    //这是约定俗称的,必须写这个。
reg // 用来指定内存的地址、大小

c. /chosen
bootargs // 内核command line参数, 跟u-boot中设置的bootargs作用一样

例子:

chosen {
  bootargs = "noinitrd root=/dev/mtdblock4 rw init=/linuxrc console=ttySAC0,115200";   //内核启动时的命令行参数
};

d. /cpus
/cpus节点下有1个或多个cpu子节点, cpu子节点中用reg属性来标明自己是哪一个cpu
既然谈到了reg属性,那么必定少不了两个东西:#address-cells和#size-cells

所以 /cpus 中有以下2个属性:
#address-cells // 在它的子节点的reg属性中, 使用多少个u32整数来描述地址(address)

#size-cells   // 在它的子节点的reg属性中, 使用多少个u32整数来描述大小(size)
         // 必须设置为0

e. /cpus/cpu*
device_type = "cpu";   //在cpus/cpu这个子节点中,必须有一个device_type = "cpu"
reg          // 表明自己是哪一个cpu

(4) 引用其他节点:

a. phandle : // 节点中的phandle属性, 它的取值必须是唯一的(不要跟其他的phandle值一样)

pic@10000000 {
  phandle = <1>;
  interrupt-controller;    //表明pic@10000000是一个中断控制器,
};

another-device-node {         //这个设备产生了中断,要传给中断控制器,就需要在能发出中断的这个节点another-device-node中,指定                                               //它的interrupt-parent。那么在这个地方如何引用中断控制器呢?有两种方法:可以在中断控制器里面使用                                               //phandle=某个值,这个值是唯一的。比如说有其他的节点里面phandle= <1>,那么此处的phandle就不                                                 //能  等于1。
  interrupt-parent = <1>; // 使用phandle值为1来引用上述节点,这种方法有点麻烦。
};

b. label:          //第二种方法

PIC: pic@10000000 {          //该节点为一个中断控制器。如果在其他节点中要引用此节点的话,可以使用它的lable。
  interrupt-controller;
};

another-device-node {
  interrupt-parent = <&PIC>;   // 使用label来引用上述节点,
                // 使用lable时实际上也是使用phandle来引用,
                // 在编译dts文件为dtb文件时, 编译器dtc会在dtb中插入phandle属性
};

注意第二种方法的实现方式其实和第一种是相同的,编译dts文件时,编译器会在中断控制器所在的节点中加入一个phandle= <xxxx>。将interrupt-parent = <&PIC>替换为interrupt-parent = <xxxx>;这都是编译器帮我们做的。

二、代码

设备树文件里面,它把一些公共的部分写为dtsi文件,dts文件可以去包含dtsi文件,两者的语法格式是一样的。

1、override问题

jz2440.dtsi

  1. // SPDX-License-Identifier: GPL-2.0
  2. /*
  3. * SAMSUNG SMDK2440 board device tree source
  4. *
  5. * Copyright (c) 2018 weidongshan@qq.com
  6. * dtc -I dtb -O dts -o jz2440.dts jz2440.dtb
  7. */
  8.  
  9. #define S3C2410_GPA(_nr) ((0<<16) + (_nr))
  10. #define S3C2410_GPB(_nr) ((1<<16) + (_nr))
  11. #define S3C2410_GPC(_nr) ((2<<16) + (_nr))
  12. #define S3C2410_GPD(_nr) ((3<<16) + (_nr))
  13. #define S3C2410_GPE(_nr) ((4<<16) + (_nr))
  14. #define S3C2410_GPF(_nr) ((5<<16) + (_nr))
  15. #define S3C2410_GPG(_nr) ((6<<16) + (_nr))
  16. #define S3C2410_GPH(_nr) ((7<<16) + (_nr))
  17. #define S3C2410_GPJ(_nr) ((8<<16) + (_nr))
  18. #define S3C2410_GPK(_nr) ((9<<16) + (_nr))
  19. #define S3C2410_GPL(_nr) ((10<<16) + (_nr))
  20. #define S3C2410_GPM(_nr) ((11<<16) + (_nr))
  21.  
  22. /dts-v1/;
  23.  
  24. / {
  25. model = "SMDK24440";
  26. compatible = "samsung,smdk2440";
  27.  
  28. #address-cells = <>;
  29. #size-cells = <>;
  30.  
  31. memory { /* /memory */
  32. device_type = "memory";
  33. reg = < >;
  34. };
  35.  
  36. /*
  37. cpus {
  38. cpu {
  39. compatible = "arm,arm926ej-s";
  40. };
  41. };
  42. */
  43. chosen {
  44. bootargs = "noinitrd root=/dev/mtdblock4 rw init=/linuxrc console=ttySAC0,115200";
  45. };
  46.  
  47. led {
  48. compatible = "jz2440_led";
  49. pin = <S3C2410_GPF()>;
  50. };
  51. };

本来led默认的pin = <S3C2410_GPF(5)>;但是我不想使用这个引脚,并且我也不想去修改这个dtsi文件。怎么办?

可以在jz2440_dts文件中将其覆盖。如下所示:

  1. // SPDX-License-Identifier: GPL-2.0
  2. /*
  3. * SAMSUNG SMDK2440 board device tree source
  4. *
  5. * Copyright (c) 2018 weidongshan@qq.com
  6. * dtc -I dtb -O dts -o jz2440.dts jz2440.dtb
  7. */
  8.  
  9. /dts-v1/;
  10.  
  11. #include "jz2440.dtsi"
  12.  
  13. / {
  14. led {
  15. pin = <S3C2410_GPF()>;
  16. };
  17. };

2、lable问题

上面的这个例子中,在dts文件中引用在dtsi中定义的led节点,是非常麻烦的。

/  {

  led {

  };

}

此时lable就派上用场了。

  1. // SPDX-License-Identifier: GPL-2.0
  2. /*
  3. * SAMSUNG SMDK2440 board device tree source
  4. *
  5. * Copyright (c) 2018 weidongshan@qq.com
  6. * dtc -I dtb -O dts -o jz2440.dts jz2440.dtb
  7. */
  8.  
  9. #define S3C2410_GPA(_nr) ((0<<16) + (_nr))
  10. #define S3C2410_GPB(_nr) ((1<<16) + (_nr))
  11. #define S3C2410_GPC(_nr) ((2<<16) + (_nr))
  12. #define S3C2410_GPD(_nr) ((3<<16) + (_nr))
  13. #define S3C2410_GPE(_nr) ((4<<16) + (_nr))
  14. #define S3C2410_GPF(_nr) ((5<<16) + (_nr))
  15. #define S3C2410_GPG(_nr) ((6<<16) + (_nr))
  16. #define S3C2410_GPH(_nr) ((7<<16) + (_nr))
  17. #define S3C2410_GPJ(_nr) ((8<<16) + (_nr))
  18. #define S3C2410_GPK(_nr) ((9<<16) + (_nr))
  19. #define S3C2410_GPL(_nr) ((10<<16) + (_nr))
  20. #define S3C2410_GPM(_nr) ((11<<16) + (_nr))
  21.  
  22. /dts-v1/;
  23.  
  24. / {
  25. model = "SMDK24440";
  26. compatible = "samsung,smdk2440";
  27.  
  28. #address-cells = <>;
  29. #size-cells = <>;
  30.  
  31. memory { /* /memory */
  32. device_type = "memory";
  33. reg = < >;
  34. };
  35.  
  36. /*
  37. cpus {
  38. cpu {
  39. compatible = "arm,arm926ej-s";
  40. };
  41. };
  42. */
  43. chosen {
  44. bootargs = "noinitrd root=/dev/mtdblock4 rw init=/linuxrc console=ttySAC0,115200";
  45. };
  46.  
  47. LED: led {
  48. compatible = "jz2440_led";
  49. pin = <S3C2410_GPF()>;
  50. };
  51. };

在dts文件中,

  1. // SPDX-License-Identifier: GPL-2.0
  2. /*
  3. * SAMSUNG SMDK2440 board device tree source
  4. *
  5. * Copyright (c) 2018 weidongshan@qq.com
  6. * dtc -I dtb -O dts -o jz2440.dts jz2440.dtb
  7. */
  8.  
  9. /dts-v1/;
  10.  
  11. #include "jz2440.dtsi"
  12. &LED {
  13. pin = <S3C2410_GPF()>;
  14. };

设备树的规范(dts)的更多相关文章

  1. Linux 获取设备树源文件(DTS)里描述的资源

    Linux 获取设备树源文件(DTS)里的资源 韩大卫@吉林师范大学 在linux使用platform_driver_register() 注册 platform_driver 时, 需要在 plat ...

  2. Linux 获取设备树源文件(DTS)里的资源【转】

    本文转载自:http://blog.csdn.net/keleming1/article/details/51036000 http://www.cnblogs.com/dyllove98/archi ...

  3. Linux 获取设备树源文件(DTS)里描述的资源【转】

    转自:http://www.linuxidc.com/Linux/2013-07/86839.htm 转自:http://blog.sina.com.cn/s/blog_636a55070101mce ...

  4. 2、设备树的规范(dts和dtb格式)

    第01节_DTS格式(1) 语法:Devicetree node格式:[label:] node-name[@unit-address] { [properties definitions]      ...

  5. rk3328设备树学习

    一.用到的rk3328好像使用了设备树 设备树我知道的有三种文件类型,dtbs是通过指令make dtbs编译的二进制文件,供内核使用. 基于同样的软件分层设计的思想,由于一个SoC可能对应多个mac ...

  6. 设备树DTS 学习:2-设备树语法

    背景 通过上一讲了解完设备树DTS有关概念,我们这一讲就来基于设备树例程,学习设备树的语法规则. 参考:设备树详解dts.设备树语法详解.设备树使用总结 设备树框架 1个dts文件 + n个dtsi文 ...

  7. linux设备树笔记__dts基本概念及语法【转】

    转自:http://www.360doc.com/content/15/1113/11/15700426_512794532.shtml 设备树手册(Device Tree Usage)原文地址:ht ...

  8. 我眼中的Linux设备树(一 概述)

    一 概述设备树(Device tree)是一套用来描述硬件属相的规则.ARM Linux采用设备树机制源于2011年3月份Linux创始人Linus Torvalds发的一封邮件,在这封邮件中他提倡A ...

  9. Linux设备树(一 概述)

    一 概述 设备树(Device tree)是一套用来描述硬件属相的规则.ARM Linux采用设备树机制源于2011年3月份Linux创始人Linus Torvalds发的一封邮件,在这封邮件中他提倡 ...

随机推荐

  1. 《京东到家订单中心 Elasticsearch 演进历程》----阅读

    上篇通过阅读文章对京东到家的架构分析有了初步了解,这次对文章(https://mp.weixin.qq.com/s?__biz=MzU1MzE2NzIzMg==&mid=2247486889& ...

  2. NOIP模拟赛1(one)

    题目描述 Description 很久以前,有一个序列,序列里填了一些非负整数. \(zzq\) 每次可以选择序列的一个前缀,把这个前缀里的数都-1,如果这个前缀 中有 0 操作就无法进行. \(zz ...

  3. ESP8266 LUA脚本语言开发: 外设篇-串口

    https://nodemcu.readthedocs.io/en/master/modules/uart/ 串口发送数据 发送一个16进制到串口 uart.write(0, 0xaa) 注: 之所以 ...

  4. CSS使用知识点

    1.空白符   2.字符间距   3.省略号样式   4.水平垂直居中用法   5.CSS角标实现   空格符 1.  相当于键盘按下的空格,区别是 是可以累加的空格,键盘敲下的空格不会累加 2.  ...

  5. 数据仓库002 - 复习Linux shell命令 - echo bash_profile bashrc which命令的理解 alias history

    1.echo 打印 . echo 的作用是在屏幕上打印输出内容,与文件和持久化可以理解为没有丝毫关联.如:在屏幕上打印“ echo 的作用是打印文字! ” 实例1:输出系统的环境变量名称 $PATH ...

  6. (十八)golang--defer关键字

    在函数中,程序员经常需要创建资源(比如,数据库连接,文件句柄,锁等),为了在函数执行完毕后,及时释放资源,go设计者提供defer(延时机制) 用defer申明的语句不会立即执行,而是被存入到defe ...

  7. CAS单点登录之支持数据库认证

    本博客介绍一下基于CAS4.2.7的配置,之前博客CAS4.2.7服务端配置已经介绍了怎么部署CAS服务端,不过在登录机制是用固定的账号密码登录,实际项目肯定不可以这样做,所以本博客怎么配置CAS服务 ...

  8. Java-100天知识进阶-GC种类-知识铺(六)

    知识铺: 致力于打造轻知识点,持续更新每次的知识点较少,阅读不累.不占太多时间,不停的来唤醒你记忆深处的知识点. 一.GC回收器的 4个指标: 1.Throughput,非gc时间与总运行时间的比重. ...

  9. win10每次开机都会自检系统盘(非硬件故障)——解决方案2019.07.12

    1.最近反复遇到了这个问题,之前遇到这个问题就把系统重装了,没想到今天又遇到了,目前系统东西太多了,重装太麻烦了,就下决心解决一下. 2.不要使用网络上流传的修改注册表的方案,把注册表的那个键值删除那 ...

  10. LeetCode 1290. Convert Binary Number in a Linked List to Integer

    题目 /** * Definition for singly-linked list. * struct ListNode { * int val; * ListNode *next; * ListN ...