Linux设备树


系统总线为树干,主线连接的 设备控制器为分支, 设备为分支上的树枝,设备树相当于stm32的数据手册。

设备树结构
图源:正点原子.

/ {
//根节点——树干
	compatible = "fsl,imx6ull-alientek-evk", "fsl,imx6ull";
	
	//分支
	cpus {
		#address-cells = <1>;
		#size-cells = <0>;
		
		//树枝
		//CPU0 节点
		cpu0: cpu@0 {
			compatible = "arm,cortex-a7";
			device_type = "cpu";
			reg = <0>;
		};
	};
	
	//soc 节点
	soc {
		#address-cells = <1>;
		#size-cells = <1>;
		compatible = "simple-bus";
		ranges;
		
		//ocram 节点
		ocram: sram@00900000 {
			compatible = "fsl,lpm-sram";
			reg = <0x00900000 0x20000>;
		};
	} 
}

DTS文件

设备树源码文件

语法

头文件

.h.dtsi.dts 文件
.dtsi文件:SOC 的内部外设信息

设备节点

根节点/
子节点aliasescpusintc
命名

  1. 节点名称@设备地址(寄存器首地址)
interrupt-controller@00a01000
cpu@0
  1. 节点标签:节点名称@地址
cpu0:cpu@0

可以用&cpu0访问节点

节点属性
  1. compatible——兼容性,匹配内核中的驱动程序
compatible = "fsl,imx6ull-14x14-evk", "fsl,imx6ull";
//设备名称,soc名称
  1. model——模块信息(名称等)
  2. status——设备状态
  3. reg——外设的寄存器起始地址和地址长度
reg = <0x02020000 0x4000>;			//起始地址 长度
  1. #address-cells——reg属性中起始地址的字长
  2. #size-cells——reg属性中地址长度的字长
#address-cells = <1>;
#size-cells = <0>;
在reg的父节点处设置
aips3: aips-bus@02200000 {
	compatible = "fsl,aips-bus", "simple-bus";
	#address-cells = <1>;
	#size-cells = <1>;
	
	dcp: dcp@02280000 {
		compatible = "fsl,imx6sl-dcp";
		reg = <0x02280000 0x4000>;
	};
};
  1. range——地址映射/转换表
ranges;			//空:子地址空间和父地址空间完全相同,不需要进行地址转换
或
ranges = <0x0 0xe0000000 0x00100000>;		
//三个数值分别为child-bus-address(子总线地址空间的物理地址),parent-bus-address(父总线地址空间的物理地址),length
  1. name——节点名字
节点属性的数据形式
  1. 字符串
compatible = "arm,cortex-a7";
  1. 32位unsigned int

  2. 字符串列表

compatible = "fsl,imx6ull-gpmi-nand", "fsl, imx6ul-gpmi-nand";

设备匹配

Linux内核用DT_MACHINE_STARTMACHINE_END来定义一个 machine_desc 结构体来描述这个设备

DT_MACHINE_START(IMX6UL, "Freescale i.MX6 Ultralite (Device Tree)")
	.map_io = imx6ul_map_io,
	.init_irq = imx6ul_init_irq,
	.init_machine = imx6ul_init_machine,
	.init_late = imx6ul_init_late,
	.dt_compat = imx6ul_dt_compat,
MACHINE_END

某个设备(板子)根节点“/”的 compatible 属性值=imx6ul_dt_compat 表中的任何一个值,表示 Linux 内核支持此设备。
Linux 内核找到匹配的 machine_desc :用设备树根节点的compatible 属性值和 Linux 内核中 machine_desc.dt_compat 的值比较,如果相等的话就表示找到匹配的 machine_desc
arch_get_next_mach 函数:获取 Linux 内核中下一个machine_desc 结构体。

添加设备——添加子节点

在设备树文件.dst中添加

&i2c1 {
	clock-frequency = <100000>;
	pinctrl-names = "default";
	pinctrl-0 = <&pinctrl_i2c1>;
	status = "okay";
	
	mag3110@0e {
		compatible = "fsl,mag3110";
		reg = <0x0e>;
		position = <2>;
	};
	
	fxls8471@1e {
		compatible = "fsl,fxls8471";
		reg = <0x1e>;
		position = <0>;
		interrupt-parent = <&gpio5>;
		interrupts = <0 8>;
	};
};

查看设备属性值——绑定文档

绑定文档:在Linux 内核源码中,描述如何添加节点.txt 文档,、路径为:Linux 源码目录/Documentation/devicetree/bindings

在系统文件中查看设备树

根节点

cd /
cd /proc/device-tree
ls

可以看到根节点属性和它的子节点

查看属性值

cat model
cat compatible

特殊子节点

  1. aliases——定义节点别名,方便访问
  2. chosen——uboot写入数据

DTB文件

DTS 编译以后得到的二进制文件

DTC工具

.dts 编译为.dtb
进入Linux 源码根目录

make dtbs

arch/arm/boot/dts/Makefile查看对应开发板所要编译的DTS文件

OF函数

用于获取设备树中的节点或者属性信息,前缀为of_,在 include/linux/of.h中定义。
节点结构体

struct device_node {
	const char *name;						 /* 节点名字 */
	const char *type; 						/* 设备类型 */
	phandle phandle;
	const char *full_name; 				/* 节点全名 */
	struct fwnode_handle fwnode;
	
	struct property *properties; 			/* 属性 */
	struct property *deadprops; 		/* removed 属性 */
	struct device_node *parent; 		/* 父节点 */
	struct device_node *child;			 /* 子节点 */
	struct device_node *sibling;
	struct kobject kobj;
	unsigned long _flags;
	void *data;
#if defined(CONFIG_SPARC)
	const char *path_component_name;
	unsigned int unique_id;
	struct of_irq_controller *irq_trans;
#endif
};

of_find_node_by_name 函数通过节点名字查找指定的节点
of_find_node_by_type 函数通过 device_type 属性查找指定的节点
of_find_compatible_node 函数根据 device_type 和 compatible 这两个属性查找指定的节点
of_find_matching_node_and_match 函数通过 of_device_id 匹配表来查找指定的节点
of_find_node_by_path 函数通过路径来查找指定的节点
of_get_parent 函数用于获取指定节点的父节点(如果有父节点的话)
of_get_next_child 函数用迭代的方式查找子节点
of_find_property 函数用于查找指定的属性
of_property_count_elems_of_size 函数用于获取属性中元素的数量
of_property_read_u32_index 函数用于从属性中获取指定标号的 u32 类型数据值(无符号 32位)
of_property_read_u8_array 函数
of_property_read_u16_array 函数
of_property_read_u32_array 函数
of_property_read_u64_array 函数
一次读取出 reg 属性中的所有数据
of_property_read_u8 函数
of_property_read_u16 函数
of_property_read_u32 函数
of_property_read_u64 函数
读取这种只有一个整形值的属性
of_property_read_string 函数用于读取属性中字符串值
of_n_addr_cells 函数用于获取#address-cells 属性值
of_device_is_compatible检查设备兼容性
of_get_address 函数用于获取地址相关属性
of_translate_address 函数负责将从设备树读取到的地址转换为物理地址
of_address_to_resource 函数,获取内存空间结构体
of_iomap 函数用于直接内存映射

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值