设备树简介

1.概念

设备树(Device Tree)是描述计算机的特定硬件设备信息的数据结构,以便于操作系统的内核可以管理和使用这些硬件,包括CPU或CPU,内存,总线和其他一些外设。

1.1 dts

硬件的相应信息都会写在.dts为后缀的文件中,每一款硬件可以单独写一份xxxx.dts,一般在Linux源码中存在大量的dts文件,对于arm架构可以在arch/arm/boot/dts找到相应的dts,另外mips则在arch/mips/boot/dtspowerpcarch/powerpc/boot/dts

1.2 dtsi

值得一提的是,对于一些相同的dts配置可以抽象到dtsi文件中,然后类似于C语言的方式可以includedts文件中,对于同一个节点的设置情况,dts中的配置会覆盖dtsi中的配置。具体如下图所示; 在这里插入图片描述

1.3 dtc

dtc是编译dts的工具,可以在Ubuntu系统上通过指令apt-get install device-tree-compiler安装dtc工具,不过在内核源码scripts/dtc路径下已经包含了dtc工具;

1.4 dtb

dtb(Device Tree Blob)dts经过dtc编译之后会得到dtb文件,dtb通过Bootloader引导程序加载到内核。所以Bootloader需要支持设备树才行;Kernel也需要加入设备树的支持; 在这里插入图片描述

2.DTS结构

https://i-blog.csdnimg.cn/blog_migrate/133ace21c895edb21b47800a22dc3b2d.jpeg

2.1 compatible 属性

compatible 属性也叫做 “兼容性” 属性,这是非常重要的一个属性! compatible 属性的值是一个字符串列表, compatible 属性用于将设备和驱动绑定起来。字符串列表用于选择设备所要使用的驱动程序。compatible 属性值的推荐格式:

"manufacturer,model"

① manufacturer : 表示厂商;② model : 一般是模块对应的驱动名字。

compatible = "arm,cortex-a53";

设备首先会使用第一个属性值在 Linux 内核里面查找,看看能不能找到与之匹配的驱动文件;如果没找到,就使用第二个属性值查找,以此类推,直到查到到对应的驱动程序 或者 查找完整个 Linux 内核也没有对应的驱动程序为止。 注:一般驱动程序文件都会有一个 OF 匹配表,此 OF 匹配表保存着一些 compatible 值,如果设备节点的 compatible 属性值和 OF 匹配表中的任何一个值相等,那么就表示设备可以使用这个驱动。

2.2 model 属性

model 属性值也是一个字符串,一般 model 属性描述设备模块信息,比如名字什么的,例如:

model = "Samsung S3C2416 SoC";

2.3 status 属性

status 属性看名字就知道是和设备状态有关的, status 属性值也是字符串,字符串是设备的状态信息,可选的状态如下表所示:

2.4 #address-cells 和 #size-cells

#address-cells 和 #size-cells的值都是无符号 32 位整型,可以用在任何拥有子节点的设备中,用于描述子节点的地址信息。

#address-cells 属性值决定了子节点 reg 属性中地址信息所占用的字长(32 位)

#size-cells 属性值决定了子节点 reg 属性中长度信息所占的字长(32 位)。

#address-cells 和 #size-cells 表明了子节点应该如何编写 reg 属性值,一般 reg 属性都是和地址有关的内容,和地址相关的信息有两种:起始地址和地址长度,reg 属性的格式一为:

reg = <address1 length1 address2 length2 address3 length3……>

reg = <0x0 0x40000000 0x0 0x08800000>;

soc { #address-cells = <2>; #size-cells = <1>; serial { compatible = "xxx"; reg = <0x4600 0x5000 0x100>; /地址信息是:0x00004600 00005000,长度信息是:0x100/ }; };

2.5 reg 属性

reg 属性的值一般是 (address, length) 对,reg 属性一般用于描述设备地址空间资源信息,一般都是某个外设的寄存器地址范围信息。

例如:一个设备有两个寄存器块,一个的地址是0x3000,占据32字节;另一个的地址是0xFE00,占据256字节,表示如下:

reg = <0x3000 0x20 0xFE00 0x100>;

1reg = <0x3000 0x20 0xFE00 0x100>;

注:上述对应#address-cells = <1>; #size-cells = <1>;。

2.6 ranges 属性

ranges属性值可以为空或者按照 (child-bus-address,parent-bus-address,length) 格式编写的数字矩阵, ranges 是一个地址映射/转换表, ranges 属性每个项目由子地址、父地址和地址空间长度这三部分组成:

child-bus-address: 子总线地址空间的物理地址,由父节点的 #address-cells 确定此物理地址所占用的字长。

parent-bus-address: 父总线地址空间的物理地址,同样由父节点的 #address-cells 确定此物理地址所占用的字长。

length: 子地址空间的长度,由父节点的 #size-cells 确定此地址长度所占用的字长。

soc { compatible = "simple-bus"; 
    #address-cells = <1>; 
    #size-cells = <1>; 
    ranges = <0x0 0xe0000000 0x00100000>;           
    serial { device_type = "serial"; 
            compatible = "ns16550"; 
            reg = <0x4600 0x100>; 
            clock-frequency = <0>; 
            interrupts = <0xA 0x8>; 
            interrupt-parent = <&ipic>; 
        }; 
    };

节点 soc 定义的 ranges 属性,值为 <0x0 0xe0000000 0x00100000>,此属性值指定了一个 1024KB(0x00100000) 的地址范围,子地址空间的物理起始地址为 0x0,父地址空间的物理起始地址为 0xe0000000。 serial 是串口设备节点, reg 属性定义了 serial 设备寄存器的起始地址为 0x4600,寄存器长度为 0x100。经过地址转换, serial 设备可以从 0xe0004600 开始进行读写操作,0xe0004600=0x4600+0xe0000000。

2.7 name 属性

name 属性值为字符串, name 属性用于记录节点名字, name 属性已经被弃用,不推荐使用name 属性,一些老的设备树文件可能会使用此属性。

2.8 device_type 属性

device_type 属性值为字符串, IEEE 1275 会用到此属性,用于描述设备的 FCode,但是设备树没有 FCode,所以此属性也被抛弃了。此属性只能用于 cpu 节点或者 memory 节点。

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

2.9 根节点

每个设备树文件只有一个根节点,其他所有的设备节点都是它的子节点,它的路径是 /。根节点有以下属性:

2.10 特殊节点

2.10.1 /aliases 子节点

aliases 节点的主要功能就是定义别名,定义别名的目的就是为了方便访问节点。例如:定义 flexcan1 和 flexcan2 的别名是 can0 和 can1。

aliases { can0 = &flexcan1; can1 = &flexcan2; };
2.10.2 /memory 子节点

所有设备树都需要一个memory设备节点,它描述了系统的物理内存布局。如果系统有多个内存块,可以创建多个memory节点,或者可以在单个memory节点的reg属性中指定这些地址范围和内存空间大小。

例如:一个64位的系统有两块内存空间:

RAM1: 起始地址是0x0,地址空间是 0x80000000;

RAM2: 起始地址是0x10000000,地址空间也是0x80000000;同时根节点下的 #address-cells = <2>和#size-cells = <2>,这个memory节点描述为:

memory@0 { device_type = "memory"; 
    reg = <0x00000000 0x00000000 0x00000000 0x80000000 
            0x00000000 0x10000000 0x00000000 0x80000000>; 
};

或者:

memory@0 { device_type = "memory"; 
            reg = <0x00000000 0x00000000 0x00000000 0x80000000>; 
        }; 
memory@10000000 { device_type = "memory"; 
            reg = <0x00000000 0x10000000 0x00000000 0x80000000>; 
        };

2.10.3 /chosen 子节点

chosen 并不是一个真实的设备, chosen 节点主要是为了 uboot 向 Linux 内核传递数据,重点是 bootargs 参数。例如:

chosen { bootargs = "root=/dev/nfs rw nfsroot=192.168.1.1 console=ttyS0,115200"; };

2.10.4 /cpus 和 /cpus/cpu* 子节点

cpus节点下有1个或多个cpu子节点, cpu子节点中用reg属性用来标明自己是哪一个cpu,所以 /cpus 中有以下2个属性:
 

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

#size-cells // 在它的子节点的reg属性中, 使用多少个u32整数来描述大小(size)
cpus {
	#address-cells = <1>;
	#size-cells = <0>;
	cpu@0 {
		device_type = "cpu";
		reg = <0>;
		cache-unified;
		cache-size = <0x8000>; // L1, 32KB
		cache-block-size = <32>;
		timebase-frequency = <82500000>; // 82.5 MHz
		next-level-cache = <&L2_0>; // phandle to L2
		L2_0:l2-cache {
			compatible = "cache";
			cache-unified;
			cache-size = <0x40000>; // 256 KB
			cache-sets = <1024>;
			cache-block-size = <32>;
			cache-level = <2>;
			next-level-cache = <&L3>; // phandle to L3
			L3:l3-cache {
				compatible = "cache";
				cache-unified;
				cache-size = <0x40000>; // 256 KB
				cache-sets = <0x400>; // 1024
				cache-block-size = <32>;
				cache-level = <3>;
				};
			};
		};
	cpu@1 {
		device_type = "cpu";
		reg = <1>;
		cache-unified;
		cache-block-size = <32>;
		cache-size = <0x8000>; // L1, 32KB
		timebase-frequency = <82500000>; // 82.5 MHzclock-frequency = <825000000>; // 825 MHz
		cache-level = <2>;
		next-level-cache = <&L2_1>; // phandle to L2
		L2_1:l2-cache {
			compatible = "cache";
			cache-unified;
			cache-size = <0x40000>; // 256 KB
			cache-sets = <0x400>; // 1024
			cache-line-size = <32>; // 32 bytes
			next-level-cache = <&L3>; // phandle to L3
			};
		};
};

如何查看DTB文件呢?

1. 使用 “dtc”命令将dtb文件转换为文本格式:

dtc -I dtb -O dts -o output.dts input.dtb


这将把输入的dtb文件(input.dtb)转换为文本格式(output.dts)。转换后的输出文件可用于查看dtb内容。

2. 使用任何文本编辑器打开转换后的输出文件:

vi output.dts


在此文件中,您可以查看设备树的详细信息,包括设备节点、属性和值等。

3.使用linux工具fdtdump查看:

fdtdump input.dtb


这将直接显示dtb文件的内容。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值