背景

设备树在Linux驱动开发中是一种比较常用的架构。

参考:《设备树DTS使用总结》《linux内核设备树及编译》

Linux设备树 介绍

在Linux 2.6中,arch/arm/plat-xxx和arch/arm/mach-xxx中充斥着大量的垃圾代码,相当多数的代码只是在描述板级细节,而这些板级细节对于内核来讲,不过是垃圾,如板上的platform设备、resource、i2c_board_info、spi_board_info以及各种硬件platform_data。

在Linux3.x版本后,arch/arm/plat-xxx和arch/arm/mach-xxx中,描述板级细节的代码(比如platform_device、i2c_board_info等)被大量取消,取而代之的是设备树,其目录位于arch/${ARCH}/boot/dts。设备树(Dervice tree source) 最早用于PowerPC等其他体系架构,到现在,很多架构都支持设备树。

开放固件设备树---Open Firmware Device Tree

  • Device Tree可以描述的信息包括:CPU的数量和类别内存基地址和大小总线和桥外设连接中断控制器和中断使用情况GPIO控制器和GPIO使用情况Clock控制器和Clock使用情况
  • 设备树信息被保存在一个ASCII 文本文件中,适合人类的阅读习惯,类似于xml文件, 在ARM Linux中,一个.dts文件对应一个ARM的machine放置在内核的arch/${ARCH}/boot/dts/
  • 设备树是一种数据结构,用于描述设备信息的语言,具体而言,是用于操作系统中描述硬件,使得不需要对设备的信息进行硬编码(hard code)
  • Device Tree由一系列被命名的结点(node)和属性(property)组成,而结点本身可包含子结点。所谓属性,其实就是成对出现的key和value
  • 设备树源文件dts被编译成dtb二进制文件,在bootloader运行时传递给操作系统,操作系统对其进行解析展开(Flattened),从而产生一个硬件设备的拓扑图有了这个拓扑图,在编程的过程中可以直接通过系统提供的接口获取到设备树中的节点和属性信息

设备树有关名词解释:

DT : Device Tree

FDT : Flattened Device Tree

OF : Open Firmware

DTS : Device Tree Source

DTSI : Device Tree Source Include

DTB : Device Tree Blob

DTC : Device Tree Compiler

设备树的编译、加载过程图:

graph LR
DTS,DTSI--> |DTC| DTB
DTB--> |Bootloader| kernel

linux内核对硬件的描述方式

  • 在以前的内核版本中:

1)内核包含了对硬件的全部描述;

2)bootloader会加载一个二进制的内核镜像,并执行它,比如uImage或者zImage;

3)bootloader会提供一些额外的信息,成为ATAGS,它的地址会通过r2寄存器传给内核;

ATAGS包含了内存大小和地址,kernel command line等等;

4)bootloader会告诉内核加载哪一款board,通过r1寄存器存放的machine type integer;

5)U-Boot的内核启动命令:bootm

  • 现今的内核版本使用了Device Tree:

1)内核不再包含对硬件的描述,它以二进制的形式单独存储在另外的位置:the device tree blob

2)bootloader需要加载两个二进制文件:内核镜像和DTB

内核镜像仍然是uImage或者zImage;

DTB文件在arch/arm/boot/dts中,每一个board对应一个dts文件;

3)bootloader通过r2寄存器来传递DTB地址,通过修改DTB可以修改内存信息,kernel command line,以及潜在的其它信息;

4)不再有machine type;

5)U-Boot的内核启动命令:bootm <kernel img addr> - <dtb addr>

有些bootloader不支持Device Tree,或者有些专门给特定设备写的bootloader版本太老了,也不包含。

为了解决这个问题,CONFIG_ARM_APPENDED_DTB被引进,会告诉内核,在紧跟着内核的地址里查找DTB文件;

由于没有built-in Makefile rule来产生这样的内核,因此需要手动操作:

  1. cat arch/arm/boot/zImage arch/arm/boot/dts/myboard.dtb > my-zImage
  2. mkimage ... -d my-zImage my-uImage

另外,CONFIG_ARM_ATAG_DTB_COMPAT选项告诉内核去bootloader里面读取ATAGS,并使用它们升级DT。

设备树原理

  1. 首先用户要了解硬件配置和系统运行参数,并把这些信息组织成Device Tree source file。
  2. 通过DTC(Device Tree Compiler),可以将这些适合人类阅读的Device Tree source file变成适合机器处理的Device Tree binary file(也叫DTB,device tree blob)。
  3. 在系统启动的时候,boot program(例如:firmware、bootloader)可以将保存在flash中的DTB copy到内存(或通过bootloader的交互式命令加载DTB,或者firmware可以探测到device的信息,组织成DTB保存在内存中),并把DTB的起始地址传递给client program(例如OS kernel,bootloader或者其他特殊功能的程序)。对于计算机系统(computer system),一般是firmware->bootloader->OS,对于嵌入式系统,一般是bootloader->OS。
  4. 本质上,Device Tree改变了原来用hardcode方式将HW 配置信息嵌入到内核代码的方法,改用bootloader传递一个DB的形式。

设备树有关文件介绍

与设备树有关的文件一共有3种: dts、dtsi与dtc

1) DTS和DTSI(Source,Include 源文件)

.dts文件是一种ASCII文本对Device Tree的描述,放置在内核的/arch/${ARCH}/boot/dts目录。一般而言,一个.dts文件对应一个ARM的machine。

由于一个SOC可能有多个不同的电路板(.dts文件为板级定义, .dtsi文件为SoC级定义),而每个电路板拥有一个 .dts。这些dts势必会存在许多共同部分,为了减少代码的冗余,设备树将这些共同部分提炼保存在.dtsi文件中,供不同的dts共同使用。.dtsi的使用方法,类似于C语言的头文件,在dts文件中需要进行include .dtsi文件。当然,dtsi本身也支持include 另一个dtsi文件。

DTS的语法结构

每个设备树文件都有一个根节点/,每个设备视为一个节点。节点间可以嵌套,形成父子关系,这样就可以方便的描述设备间的关系。

  • 1个root结点"/"
  • root结点下面含一系列子结点
  • 子结点下又含有一系列子结点
  • 各结点都有一系列属性,属性类型有
    • 空属性:empty-property
    • 字符串属性:string-property
    • 字符串列表属性:string-list-property
    • Cells(u32整型)属性:cell-property
    • 二进制数属性:binary-property

2) DTC (Compiler 编译工具)

DTC为编译工具,dtc编译器可以把dts文件编译成为dtb,也可把dtb编译成为dts文件。

在3.x内核版本中,DTC的源码位于内核的scripts/dtc目录,编译以后的工具在scripts/dtc/dtc中,内核选中CONFIG_OF (即Open Firmware),编译内核的时候,主机可执行程序DTC就会被编译出来。 即scripts/dtc/Makefile中

获取DTC的2种方式

  • 在linux下,make dtbs ,这里的s代表复数可单独编译dtb。
  1. hostprogs-y := dtc
  2. always := $(hostprogs-y)

在内核的arch/${ARCH}/boot/dts/Makefile中,若选中某种SOC,则与其对应相关的所有dtb文件都将编译出来。以下截取了Makefile其中一部分。

  1. ifeq ($(CONFIG_OF),y)
  2. dtb-$(CONFIG_ARCH_TEGRA) += tegra20-harmony.dtb \
  3. tegra30-beaver.dtb \
  4. tegra114-dalmore.dtb \
  5. tegra124-ardbeg.dtb
  • 在系统中安装,例如ubuntu: sudo apt-get install device-tree-compiler,此后输入 dtc 使用即可

3) DTB (Blob 二进制文件)

DTC编译.dts生成的二进制文件(.dtb),bootloader在引导内核时,会预先读取.dtb到内存,进而由内核解析。

dtb文件可以由dtc单独进行编译,编译命令格式如下:

  1. dtc [-I input-format] [-O output-format][-o output-filename] [-V output_version] input_filename

参数说明(由 man dtc 得到):

  1. NAME
  2. dtc - Device Tree Compiler
  3. SYNOPSIS
  4. /usr/bin/dtc [options] <input file>
  5. DESCRIPTION
  6. Device Tree Compiler, dtc, takes as input a device-tree in a given format and outputs a device-tree in another for
  7. mat for booting kernels on embedded systems. Typically, the input format is "dts", a human readable source format,
  8. and creates a "dtb", or binary format as output.
  9. OPTIONS
  10. -h Display help text.
  11. -q Quiet:
  12. -q - Suppress warnings.
  13. -qq - Suppress errors.
  14. -qqq - Suppress all.
  15. -I <input format>
  16. Input formats are:
  17. dts - device tree source text
  18. dtb - device tree blob
  19. fs - /proc/device-tree style directory
  20. -o <output file>
  21. Dump the result into a file, instead of stdout.
  22. -O <output format>
  23. Output formats are:
  24. dts - device tree source text
  25. dtb - device tree blob
  26. asm - assembler source
  27. -V <output version>
  28. Blob version to produce. The default is 17 (only relevant for dtb and asm output).
  29. -d <output dependency file>
  30. -R <number>
  31. Make space for <number> reserve map entries (only relevant for dtb and asm output).
  32. -S <bytes>
  33. Make the blob at least <bytes> long (extra space).
  34. -p <bytes>
  35. Add padding to the blob of <bytes> long (extra space)
  36. -b <number>
  37. Set the physical boot CPU.
  38. -f Force - try to produce output even if the input tree has errors.
  39. -s Sort nodes and properties before outputting (only useful for comparing trees)
  40. -v Print DTC version and exit.
  41. -H <phandle format>
  42. phandle formats are:
  43. legacy - "linux,phandle" properties only
  44. epapr - "phandle" properties only
  45. both - Both "linux,phandle" and "phandle" properties

dtc命令的使用范例

(1) dts编译生成dtb

./scripts/dtc/dtc -I dts -O dtb -o B_dtb.dtb A_dts.dts # 把A_dts.dts编译生成B_dtb.dtb

(2) dtb编译生成dts(反汇编dtb)

./scripts/dtc/dtc -I dtb -O dts -o A_dts.dts A_dtb.dtb # 把A_dtb.dtb反编译生成为A_dts.dts

明确了设备树的各种基础概念以后,接下来,我们就来了解实际开发中设备树的语法,以及编写设备树)。

设备树DTS 学习:1-有关概念的更多相关文章

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

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

  2. 设备树DTS 学习:4-编写实战

    背景 讲完设备树的有关概念以及语法以后,我们接下来就让 我们的驱动 使用 设备树. ref : <内核学习笔记14:内核设备树学习>.<u-boot对设备树的支持> 测试代码 ...

  3. 设备树DTS 学习:Linux DTS文件加载过程

    背景 了解机制有利于对内核有更深的认识. wget https://mirrors.aliyun.com/linux-kernel/v3.x/linux-3.2.61.tar.xz 内核 在drive ...

  4. 设备树DTS 学习:3-常用的DTS 函数

    Linux内核中目前DTS相关的函数都是以of_前缀开头的,它们的实现位于内核源码的drivers/of下面 void __iomem*of_iomap(struct device_node *nod ...

  5. 设备树DTS 学习: uboot 传递 dtb 给 内核

    背景 得到 dtb 文件以后,我们需要想办法下载到 板子中,并给 Linux 内核使用. (高级版本的 uboot也有了 自己使用设备树支持,我们这里不讨论 uboot 使用的设备树) Linux 内 ...

  6. Linux dts 设备树详解(二) 动手编写设备树dts

    Linux dts 设备树详解(一) 基础知识 Linux dts 设备树详解(二) 动手编写设备树dts 文章目录 前言 硬件结构 设备树dts文件 前言 在简单了解概念之后,我们可以开始尝试写一个 ...

  7. Linux 设备树 dts

    1. dtb反编译成dts文件命令:./kernel-4.4/scripts/dtc/dtc_overlay -I dtb -O dts out/target/product/m863ur100_p0 ...

  8. Linux dts 设备树详解(一) 基础知识

    Linux dts 设备树详解(一) 基础知识 Linux dts 设备树详解(二) 动手编写设备树dts 文章目录 1 前言 2 概念 2.1 什么是设备树 dts(device tree)? 2. ...

  9. Linux设备树语法详解

    概念 Linux内核从3.x开始引入设备树的概念,用于实现驱动代码与设备信息相分离.在设备树出现以前,所有关于设备的具体信息都要写在驱动里,一旦外围设备变化,驱动代码就要重写.引入了设备树之后,驱动代 ...

随机推荐

  1. Mapgis地图颜色配置(专题图配置)----对比Arcgis根据属性配置图斑颜色

    对于大多数arcgis用户来说,根据属性配置图斑颜色对于大家来说应该并不陌生.本文将就arcgis图斑颜色设置与mapgis做出比对,为大家提供更为绚丽的地图配色.    Arcgis颜色配置方案 右 ...

  2. NET站点升级后,新特新无法编译通过

    NET3.5 webconfig中有自动配置如下代码,用于指示编译器. <system.codedom> <compilers> <compiler language=& ...

  3. 操作系统OS,Python - 生产者消费者模型

    1. 缓冲区(此处用阻塞队列充当),解决消费者和生产者强耦合问题.(生产者和消费者不直接通信) 2. 通过平衡生产者线程和消费者线程,来提高程序整体处理数据速度. 3. 在并发编程中该模式能解决大多数 ...

  4. 单元测试及框架简介 --junit、jmock、mockito、powermock的简单使用

    转 单元测试及框架简介 --junit.jmock.mockito.powermock的简单使用 2013年08月28日 14:33:06 luvinahlc 阅读数:6413 标签: 测试工具单元测 ...

  5. Python 爬取 热词并进行分类数据分析-[热词分类+目录生成]

    日期:2020.02.04 博客期:143 星期二   [本博客的代码如若要使用,请在下方评论区留言,之后再用(就是跟我说一声)] 所有相关跳转: a.[简单准备] b.[云图制作+数据导入] c.[ ...

  6. spark-调节executor堆外内存

    什么时候需要调节Executor的堆外内存大小? 当出现一下异常时: shuffle file cannot find,executor lost.task lost,out of memory 出现 ...

  7. springboot中关于datasource的配置

    datasource spring.dao.exceptiontranslation.enabled: 是否开启PersistenceExceptionTranslationPostProcessor ...

  8. DVWA靶机的命令执行漏洞

    之前在打攻防世界的时候出现过类似的题目,这里再重温一下 (靶机一共低中高三个安全等级,这里只演示低中等级) (1)Security:low 根据提示让我们输入地址ping一下,之后返回以下内容,可以判 ...

  9. VIM学习笔记一

    键位图 转自:链接 永久显示行号: vi ~/.vimrc 加入 :set number 命令 简单说明 :w 保存编辑后的文件内容,但不退出vim编辑器.这个命令的作用是把内存缓冲区中的数据写到启动 ...

  10. 用Jackson进行Json序列化时的常用注解

    Jackson时spring boot默认使用的json格式化的包,它的几个常用注解: @JsonIgnore 用在属性上面,在序列化和反序列化时都自动忽略掉该属性 @JsonProperty(&qu ...