IT数码 购物 网址 头条 软件 日历 阅读 图书馆
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
图片批量下载器
↓批量下载图片,美女图库↓
图片自动播放器
↓图片自动播放器↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁
 
   -> 系统运维 -> 2021-09-29 -> 正文阅读

[系统运维]2021-09-29

什么是设备树
设备树全称叫开发固件设备树——Open Firmware Device Tree

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

设备树文件在 arch/arm/boot/dts 目录下(2.6版本以及之前版本的内核没有设备树)

Linux设备树的由来——为什么会有设备树

  1. 在Linux2.6中,arch/arm/plat-xxx和arch/arm/mach-xxx中充斥着大量描述板级细节的垃圾代码,如板上的platform设备,resource、i2c_board_info、spi_board_info以及各种硬件platform_data。常见的s3c2410、s3c6410等板级目录,代码量在数万行。
  2. Linus Torvalds对此种情况大发雷霆,在2011年的ARM Linux邮件列表宣称”this whole ARM thing is a f*ucking pain in the ass"。
  3. 随后Linux开发社区就开始整改,设备树最早用于PowerPC等其他体系架构,ARM架构开发社区就开始采用设备树来描述设备的信息。

2.6中在 arch/arm/目录下描述板级信息,例如

static struct clk s3c2440_clk_cam_upll = {
	.name		= "camif-upll",
	.id		= -1,
	.set_rate	= s3c2440_camif_upll_setrate,
	.round_rate	= s3c2440_camif_upll_round,
};

快速编译设备树——DTC(device tree compiler)

  1. .dts文本文件会被DTC编译为.dtb二进制文件,二进制文件会被内核使用。
  2. DTC的源码为于内核的scripts/dtc目录,在Linux内核使能了Device Tree的情况下,编译内核的时候主机工具DTC会被编译出来。
  3. 在Linux内核的arch/arm/boot/dts/Makefile中,描述了当某种SoC被选中后,哪些.dtb文件会被编译出来,如与EXYNOS对应的.dtb包括
#如果在ARM架构下并且时EXYNOS平台下,那么就会编译出以下这么多目标文件,dtb文件对应同名dts
dtb-$(CONFIG_ARCH_EXYNOS) += exynos4210-origen.dtb \	
	exynos4210-smdkv310.dtb \
	exynos4210-trats.dtb \
	exynos4210-universal_c210.dtb \
	exynos4412-odroidx.dtb \
	exynos4412-origen.dtb \
	exynos4412-smdk4412.dtb \
	exynos4412-tiny4412.dtb \
	exynos4412-trats2.dtb \
	exynos5250-arndale.dtb \
	exynos5250-smdk5250.dtb \
	exynos5250-snow.dtb \
	exynos5420-arndale-octa.dtb \
	exynos5420-smdk5420.dtb \
	exynos5440-sd5v1.dtb \
	exynos5440-ssdk5440.dtb

.dtsi相当于.dts文件中的头文件,包含通用的设备信息描述,如要编译自己创建的dts文件,则在Makefile文件中相关平台下添加对应文件名就行。

如何创建自己的dts文件并编译

  • 参考版origen的设备树文件作为参考
cp arch/arm/boot/dts/exynos4412-origen.dts arch/arm/boot/dts/exynos4412-fs4412.dts
  • 添加新文件需修改Makefile才能编译
vim arch/arm/boot/dts/Makefile

dtb-$(CONFIG_ARCH_EXYNOS) += exynos4210-origen.dtb \下添加exynos4412-fs4412.dts\

-编译设备树文件,在内核文件最上层编译

make dtbs

执行后

DTC arch/arm/boot/dts/exynos4412-fs4412.dtb
  • 拷贝内核和设备树文件到/tftpboot目录下
cp arch/arm/boot/dts/exynos4412-fs4412.dtb /tftpboot/
  • 设置启动参数
set bootcmd tftp 0x41000000 uImage\; tftp 0x42000000 exynos4412-fs4412.dtb\; bootm 0x41000000-0x42000000

设备树文件是如何被内核使用的

set bootcmd tftp 0x41000000 uImage\; tftp 0x42000000 exynos4412-fs4412.dtb\; bootm 0x41000000-0x42000000

bootm后,启动内核,内核会自动去0x42000000读取dtb文件,读取后会展开成二叉树
根节点
|_
| | |
子节点 子节点 子节点

节点中有自己定义的信息,时钟、中断……
启动过程中内核可以看到信息,
驱动中如果想读取某个特定的节点,只要遍历整个节点,找到某个节点的标识符,内核会提供API接口of_api

相关的缩写名词解释

DT:Device Tree //设备树
FDT:Flattened DeviceTree //展开设备树,做成树状结构
OF:Open Firmware //开放式固件
DTS:device tree source
DTSI:device tree source include
DTB:device tree blob
DTC:device tree compiler

设备树的语法

  • 节点
  • 属性
  • 根节点
  • compatible属性
  • reg属性
  • #address-cells和#address-siz属性
  • 中断信息属性–interrupts和interrupts

设备树基本语法

设备树模板

/{	//根节点
	node1 {	//子节点
		/* 属性 */
		a-string-property = "A string";
		a-string-list-property = "first string", "second string";
		a-byte-data-property = [0x01 0x23 0x34 0x56];
		child-node1 {	//子子节点
			first-child-property;	/* 属性可以为空,表示标志位  */
			second-child-property = <1>;
			a-string-property = "Hello,world";
		}; 
		child-node2{	//子子节点
		};
	};

	node2{	//子节点
		an-empty-property;
		a-cell-property = <1 2 3 4>;	/* each number(cell) is a uint32 */
		child-node1{	//子子节点
		};
	};
}

节点

节点名称
每个节点必须有一个"<名称>[@<设备地址>]"形式的名字<名称>就是一个不超过31位的简单ascii字符串,中括号中的内容可有可无。

<设备地址>用来访问该设备的主地址,并且该地址也在节点的reg属性中列出,同级节点命名必须是唯一的,但只要地址不同,多个节点也可以使用一样的通用名称,当然设备地址也是可选的。这里的设备地址主要是用来区分的,不做属性使用。

树中每个表示一个设备的节点都需要一个compatible属性,一般是一个字符串
reg属性表示起始地址和地址长度如:reg = <0x0203F000 0x1000>;

属性property

简单的键-值对,它的值可以为空或者包含一个任意字节流。虽然数据类型并没有编码进数据结构,但在设备树源文件中任有几个基本的数据表示形式:

文件字符串(无结束符)可以用双引号表示:

string-property = "a string"

cells是32位无符号整数 用尖括号限定:

cell-property = <0xbeef 123 0xabcd123>	//单独的数据

二进制数据用方括号限定:

binary-property = [01 23 45 67];	//连续的数据

不同表示形式的数据可以使用逗号连在一起:

mixed-property = "a string",[01 23 45 67],<0x12345678>;	//逗号隔开

都好也可用于创建字符串列表:

string-list = "read fish", "blue fish";

常见属性–compatible属性

指定了系统的名称,是一个字符串列表,实际在代码中可以用于匹配,当前你选择的是哪个机器,它包含了一个"<制造商>,<型号>"形式的字符串。重要的是要指定一个确切的设备,并且包括制造商的名字,以避免命名空间冲突
不要使用通配符的compatible值,比如"fsl,mpc93xx-uart"或类似情况

/{
	compatible = "acme,coyotes-revenge";
}

常见属性–#address-cells和#size-cells

#address-cells = <1>表示address字段的长度为1
#size-cell = <1>;表示length字段的长度为1

external-bus{
	#address-cells=<2>//父节点描述的信息限定子节点
	#size-cells=<1>;

	ethernet@0,0{
		compatible = "smc,smc91c111";
		reg = <0 0 0x1000>;	//地址站两个cells,长度占1个cells
		nterrupts = <5 2>;
	}
}

常见属性–reg属性

reg的组织形式为reg = <address1 length1 address2 length2 address3 length3…>其中的每一组address length表明了设备使用的一个地址范围

/{
	compatible = "acme,coyotes-revenge";
	#address-cells = <1>;
	#size-cells = <1>;
		serial@101f2000{
			compatible = "arm,pl011";
			reg = <0x101f2000 0x1000>;
			interrupts = <2 0>;
		};
}

常见属性–中断信息

描述中断连接需要四个属性
interrupt-controller:一个空的属性定义该节点作为一个接收中断信号的设备

#interrupt-cells:这是一个中断控制器节点的属性。它声明了改中断控制器的中断指示符中cell的个数(类似于#address-cells和#size-cells)

interrupt-parent:这是一个设备节点的属性,包含一个指向该设备连接的中断控制器的phandle(指向或者可以引用&)那些没有interrupt-parent的节点则从他们的父节点中继承该属性。

interrupts:一个设备节点属性,包含一个中断指示符的列表,对应于该设备上的每个中断输出信号

常见属性–中断信息

/{
	compatible = "acme,coyotes-revenge";
	#address-cells = <1>;
	#size-cells = <1>;
	interrupt-parent = <&intc>;
	
	serial@101f0000{
		compatible = "arm,pl011";
		reg = <0x101f0000 0x1000>;
		interrupts = <1 0>;	//这个中断依赖于下面节点描述的控制器
	};
	intc:interrupt-controller@10140000{	//冒号:在其他地方可以引用
		compatible = "arm,pl190";
		reg = <0x10140000 0x1000>;
		interrupt-controller;	//表示这个节点描述的是一个控制器
		#interrupt-cells = <2>;
	};
}

对于arm架构,中断标志的具体含义 interrupts = <1st, 2nd, 3rd>

1st: 表示中断的类型
0:表示SPI interrupts 共享中断
1:表示PPI interrupts 个人中断
IPI:inter-processer interrupt 中断号0~15
PPI:per processor interrupts 中断号16~31
SPI:shared processor interrupts 中断号 32 ~32+224
SGI:software generated interrupts (SGI)
2nd: 表示中断是第一个参数里面的第几个
3rd: 中断触发方式
下面是中断类型值
#define IRQ_TYPE_NONE 0
#define IRQ_TYPE_EDGE_RISING 1
#define IRQ_TYPE_EDGE_FALLING 2
#define IRQ_TYPE_EDGE_BOTH (IRQ_TYPE_EDGE_FALLING | IRQ_TYPE_EDGE_RISING)
#define IRQ_TYPE_LEVEL_HIGH 4
#define IRQ_TYPE_LEVEL_LOW 8

  系统运维 最新文章
配置小型公司网络WLAN基本业务(AC通过三层
如何在交付运维过程中建立风险底线意识,提
快速传输大文件,怎么通过网络传大文件给对
从游戏服务端角度分析移动同步(状态同步)
MySQL使用MyCat实现分库分表
如何用DWDM射频光纤技术实现200公里外的站点
国内顺畅下载k8s.gcr.io的镜像
自动化测试appium
ctfshow ssrf
Linux操作系统学习之实用指令(Centos7/8均
上一篇文章           查看所有文章
加:2021-09-30 12:19:58  更:2021-09-30 12:22:57 
 
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁

360图书馆 购物 三丰科技 阅读网 日历 万年历 2024年11日历 -2024/11/15 16:56:12-

图片自动播放器
↓图片自动播放器↓
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
图片批量下载器
↓批量下载图片,美女图库↓
  网站联系: qq:121756557 email:121756557@qq.com  IT数码