linux随笔记 - 设备树

make xxxx.dts
由DTC工具,编译dts源文件,生成.dtb二进制文件。系统在启动时会根据dtb设备树文件。

(这个问题是面试着玩的时候被面试官问到的,当时没反应过来,看来板子还得多折腾,实在惭愧,板子一大堆,全部都在吃灰)

设备树是怎么体现实现?
在linux启动时,会加载解析.dtb文件。生成设备树文件目录
在根文件系统中体现,系统启动以后,可以在根文件系统里面看到设备树得节点信息,/proc/device_tree/里面体现
node节点都是以文件夹体现,节点下面得子节点、设备节点均是以文件夹存在。最终会包含其中得属性
属性是以文件形式体现(这应该是废话了,linux下一切皆文件)

设备树常用语法

设备树可以包含头文件,来包含一些原厂做的宏定义,设备树基础信息等。通常我们在开发时,通过参考dtsi文件和相关的头文件,来对xxx.dts(自己的设备树)进行响应的修改,内容追加等。

相同得节点由追加、继承的作用。如果由相同的属性名则是会最后的为准,覆盖前面的。

#include "xxx.dtsi" 

#include "input.h"

compatible  属性

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

例如:欧胜(WOLFSON)出品的 WM8960的属性值如下

compatible = "fsl,imx6ul-evk-wm8960","fsl,imx-audio-wm8960";

model  属性

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

status  属性

status 属性是和设备状态有关的,status 属性值也是字符串,字符串是设备的状态信息。

#address-cells 和#size-cells 属性

#address-cells 和#size-cells 表明了子节点应该如何编写 reg 属性值

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

 ranges  属性

该属性的格式如下,可以为空也可以子地址、父地址、长度表示。

ranges = <child-bus-address, parent-bus-address, length>;
ranges ;
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。

OF函数

of函数可以简单理解为获取设备树的相关资源信息。这样就实现了设备资源通过修改设备树,进行通过驱动获取对应的资源的方式。

大部分函数原型可以在"include/linux/of.h"文件中找到对应的API

查找获取节点

此处用的最多的应该是:inline struct device_node *of_find_node_by_path(const char *path),设备树的枝干改变了,此处的路径也需要进行响应的修改。

/* 
path:带有全路径的节点名,可以使用节点的别名,比如“/backlight”就是 backlight 这个
节点的全路径。
返回值:找到的节点,如果为 NULL 表示查找失败 
*/
inline struct device_node *of_find_node_by_path(const char *path)

/* of_device_id 匹配表来查找指定的节点 */
struct device_node *of_find_matching_node_and_match(struct device_node *from,
                                                    const struct of_device_id *matches,
                                                    const struct of_device_id **match)
/* 通过节点名字查找指定的节点*/
struct device_node *of_find_node_by_name(struct device_node *from,
                                         const char *name);

/* 根据 device_type 和 compatible 这两个属性查找指定的节点 */
struct device_node *of_find_compatible_node(struct device_node *from,
                                            const char *type,
                                            const char *compatible)

提取节点属性

函数并未列举完全,只是列出几个常见的。

/* 查找指定的属性 */
property *of_find_property(const struct device_node *np,
                           const char *name,
                           int *lenp)
/* 读取属性中 u8、u16、u32 和 u64 类型的数组数据,比如大多数的 reg 属性都是数组数据,可以使用这 4 个函数一次读取出 reg 属性中的所有数据 */
int of_property_read_u8_array(const struct device_node *np,
                              const char *propname,
                              u8 *out_values,
                              size_t sz)
int of_property_read_u16_array(const struct device_node *np,
                               const char *propname,
                               u16 *out_values,
                               size_t sz)
int of_property_read_u32_array(const struct device_node *np,
                               const char *propname,
                               u32 *out_values,
                               size_t sz)
int of_property_read_u64_array(const struct device_node *np,
                               const char *propname,
                               u64 *out_values,
                               size_t sz)
/* #address-cells 属性值 #size-cells 属性值 */
int of_n_addr_cells(struct device_node *np)
int of_n_size_cells(struct device_node *np)

of_iomap

of_iomap 函数用于直接内存映射

void __iomem *of_iomap(struct device_node *np, int index)

/*
    	my_led {
		#address-cells = <1>;
		#size-cells = <1>;
		compatible = "my-led";
		status = "okay";
		reg = < 0X020C406C 0X04		/* CCM_CCGR1_BAE 			*/
				0X020E0068 0X04		/* SW_MUX_GPIO1_IO03_BASE 	*/
				0X020E02F4 0X04		/* SW_PAD_GPIO1_IO03_BASE	*/
				0X0209C000 0X04		/* GPIO1_DR_BASE 			*/
				0X0209C004 0X04>;	/* GPIO1_GDIR_BASE 			*/
	    };
*/


IMX6U_CCM_CCGR1 = of_iomap(dtsled.nd, 0);
SW_MUX_GPIO1_IO03 = of_iomap(dtsled.nd, 1);
SW_PAD_GPIO1_IO03 = of_iomap(dtsled.nd, 2);
GPIO1_DR = of_iomap(dtsled.nd, 3);
GPIO1_GDIR = of_iomap(dtsled.nd, 4);

  • 26
    点赞
  • 11
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
B站上的韩顺平老师的《Linux学习笔记》系列课程非常值得推荐。通过这个课程,我学到了很多关于Linux操作系统的知识和技能。 首先,韩老师在课程中详细介绍了Linux的基本概念和特点。我清楚地了解到Linux是一个开源的操作系统,具有稳定性、安全性和可定制性强的特点。这让我对Linux有了更深入的理解,也更有信心去学习和使用它。 其次,韩老师从基础开始,逐步讲解了Linux的安装和配置。他用简单明了的语言和实际操作的示范,帮助我了解了如何在虚拟机上安装Linux系统,并设置网络、用户账户、文件系统等。这为我后续的学习和实践打下了坚实的基础。 此外,韩老师还讲解了Linux的常用命令和工具。他详细介绍了常用的文件和目录操作命令,比如cd、ls、mkdir、cp等。同时,他还讲解了grep、sed、awk等强大的文本处理工具的使用方法。这些内容帮助我更加高效地进行文件管理和数据处理。 最后,韩老师还介绍了Linux的网络管理和安全防护。他讲解了如何配置网络连接、使用ssh远程登录以及设置防火墙等内容。这些知识对我了解网络和保护系统安全非常有帮助。 总的来说,韩顺平老师的《Linux学习笔记》课程非常实用,对于初学者来说是入门学习Linux的好选择。他通过深入浅出的讲解和丰富的实操示范,让我可以轻松地学习到Linux的基本知识和操作技巧。我相信通过学习这个课程,我会在Linux领域有更进一步的发展。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值