背景

设备树在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来产生这样的内核,因此需要手动操作:

 cat arch/arm/boot/zImage arch/arm/boot/dts/myboard.dtb > my-zImage
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。
    hostprogs-y := dtc
always := $(hostprogs-y)

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

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

3) DTB (Blob 二进制文件)

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

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

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

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

NAME
dtc - Device Tree Compiler SYNOPSIS
/usr/bin/dtc [options] <input file> DESCRIPTION
Device Tree Compiler, dtc, takes as input a device-tree in a given format and outputs a device-tree in another for‐
mat for booting kernels on embedded systems. Typically, the input format is "dts", a human readable source format,
and creates a "dtb", or binary format as output. OPTIONS
-h Display help text. -q Quiet:
-q - Suppress warnings.
-qq - Suppress errors.
-qqq - Suppress all. -I <input format>
Input formats are: dts - device tree source text
dtb - device tree blob
fs - /proc/device-tree style directory -o <output file>
Dump the result into a file, instead of stdout. -O <output format>
Output formats are: dts - device tree source text
dtb - device tree blob
asm - assembler source -V <output version>
Blob version to produce. The default is 17 (only relevant for dtb and asm output). -d <output dependency file> -R <number>
Make space for <number> reserve map entries (only relevant for dtb and asm output). -S <bytes>
Make the blob at least <bytes> long (extra space). -p <bytes>
Add padding to the blob of <bytes> long (extra space) -b <number>
Set the physical boot CPU. -f Force - try to produce output even if the input tree has errors. -s Sort nodes and properties before outputting (only useful for comparing trees) -v Print DTC version and exit. -H <phandle format>
phandle formats are: legacy - "linux,phandle" properties only
epapr - "phandle" properties only
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. 【JQuery 选择器】 案例

    1.查找以id的某个字段开头的元素 setTimeout(function () { $("a[id^='menu_']").each(function () { $(this). ...

  2. Python 之并发编程之线程上

    一.线程概念 进程是资源分配的最小单位 线程是计算机中调度的最小单位 多线程(即多个控制线程)的概念是,在一个进程中存在多个控制线程,多个控制线程共享该进程的地址空间,相当于一个车间内有多条流水线,都 ...

  3. UITextField的快速基本使用代码块

    概述 UITextField在界面中显示可编辑文本区域的对象. 您可以使用文本字段来使用屏幕键盘从用户收集基于文本的输入.键盘可以配置许多不同类型的输入,如纯文本,电子邮件,数字等等.文本字段使用目标 ...

  4. A*算法和K短路(A*)

    堪称最好的A算法 https://blog.csdn.net/b2b160/article/details/4057781 K短路(A) https://www.jianshu.com/p/27019 ...

  5. centso7设置防火墙

    CentOS 7默认使用的是firewall作为防火墙,使用iptables必须重新设置一下 1.直接关闭防火墙 1 2 3 systemctl stop firewalld.service #停止f ...

  6. 【PAT甲级】1021 Deepest Root (25 分)(暴力,DFS)

    题意: 输入一个正整数N(N<=10000),然后输入N-1条边,求使得这棵树深度最大的根节点,递增序输出.如果不是一棵树,输出这张图有几个部分. trick: 时间比较充裕数据可能也不是很极限 ...

  7. Eclipse中java代码注释变成乱码的问题

    今天在查看曾经写过的代码时发生了一件很是让人头疼的事: 我写的所有注释全部都变成了了乱码,曾经刚入门时也是经常遇到类似的问题,解决起来很快,每天可能都会在工作空间里看到,但是随着时间的推移,写代码的规 ...

  8. rem与部分手机 字体偏大问题

    原因是部分手机自己设置了巨无霸字体.

  9. SpringMVC配置没有任何问题根据请求却怎么都找不到映射(tomcat所导致的问题)

    本人在做SpringMVC练习的时候,配置文件反复检查了不下十几遍,没有任何问题,然后就招了个之前的项目的源码复制进去,原来的项目没有任何问题,这个项目却怎么都不能跳转路径,然后有找了一个Spring ...

  10. 5.Nginx

    1.Nginx 安装 (1) 安装gcc (yum install gcc) 备注:可以输入gcc -v 查询版本信息,看系统是否自带安装 (2) 安装pcre (yum install pcre-d ...