Linux 设备树: of_property_read_bool 的用法与工作原理

前言

  • 不得不说,当前新版本的 Linux 内核 设备驱动框架,与设备树(Device Tree)结合密切,整体 设备树的设备驱动框架,比较的庞大,但又非常的经典。

  • 一个个的 设备树解析函数,都是前人【智慧】的结晶,了解 设备树的实现,了解设备树的解析,对Linux 设备驱动开发非常有利,并且可以大大提高开发编码能力

  • 虽然Linux 内核庞大、开源,但是Linux 内核各个模块的实现都是经典,非常适合学习深造

设备树展开

  • 设备树源文件(dts)与 设备树头文件(dtsi),通过 dtc 工具生成了 设备树二进制文件 (dtb)

  • 设备树二进制文件(dtb)经过展开(反扁平化)成设备树结构在内存中。

  • 可以通过 设备树 root 根节点,通过 设备节点的属性(property)、设备树节点的名称(name)或者路径(full_name)找到相应的设备树节点。

  • 设备树节点类似树的【树枝或者树叶】,【树枝】下面还可以有多个子节点,或者只有叶子节点。

  • 设备树整体像个 【家族族谱】,内核实现使用多级的链表,把各个设备树节点连接起来。

设备树节点

  • 对于每个设备树节点,数据结构 struct device_node 表示如下

  • include\linux\of.h

struct device_node {
	const char *name;
	phandle phandle;
	const char *full_name;
	struct fwnode_handle fwnode;

	struct	property *properties;
	struct	property *deadprops;	/* removed properties */
	struct	device_node *parent;
	struct	device_node *child;
	struct	device_node *sibling;
#if defined(CONFIG_OF_KOBJ)
	struct	kobject kobj;
#endif
	unsigned long _flags;
	void	*data;
#if defined(CONFIG_SPARC)
	unsigned int unique_id;
	struct of_irq_controller *irq_trans;
#endif
};
  • 看起来很复杂,其实多看几次(熟悉),发现并没有想象中的复杂,了解过 JSON 的大概看设备树节点也不会太吃力。

在这里插入图片描述

  • 本篇重点关注 dma-coherent; 这样的设备树节点的 属性(property)如何用于解析,也就是判断这个属性是否存在,通过 of_property_read_bool 函数

设备树节点与设备树节点属性 property 的组织方式

  • 单链表的结构组织,如果有了设备树节点的指针,就可以遍历这个设备树节点下的所有属性 property

  • 注意这个设备树与设备树节点属性的组织关系,实在设备树 dtb 载入后,反扁平化 unflatten_device_tree 后形成的,也就是现成的,用于解析与判断匹配,比如 属性的查找,就是一直单链表遍历查找即可

  • drivers\of\base.c__of_find_property 的属性查找

在这里插入图片描述

  • 设备树节点 与 设备树 自身的各个属性,采用 单链表 的结构串起来

在这里插入图片描述

of_property_read_bool 的实现原理

  • 对于一个设备树节点,属性可以有很多,大部分都是 键值对结构,也有的属性只有 属性名,没有 value

  • 设备树节点的属性(这里使用类似单链表结构),挂在对应的设备树节点上,

  • struct device_node 的成员 struct property *properties;

  • struct property 有个成员 struct property *next;

struct property {
	char	*name;
	int	length;
	void	*value;
	struct property *next;
#if defined(CONFIG_OF_DYNAMIC) || defined(CONFIG_SPARC)
	unsigned long _flags;
#endif
#if defined(CONFIG_OF_PROMTREE)
	unsigned int unique_id;
#endif
#if defined(CONFIG_OF_KOBJ)
	struct bin_attribute attr;
#endif
};
  • 设备树节点 有个 属性的 头结点,这个设备树节点下的属性,以单链表的结构链上去。就像是【糖葫芦】,访问设备树节点时,需要依次【遍历】与匹配(比对)

  • 了解了 设备树节点与属性,of_property_read_bool 的工作原理也就清楚了,只需要判断设备树是否有这个属性即可

  • of_property_read_bool 入参:const struct device_node *np 是一个设备树节点指针

  • const char *propname 如此:设备树是否存在的属性 property 的 name,字符串

  • of_find_property 之前了解过,就是单链表的方式遍历,查找是否存在 property

/**
 * of_property_read_bool - Find a property
 * @np:		device node from which the property value is to be read.
 * @propname:	name of the property to be searched.
 *
 * Search for a property in a device node.
 * Returns true if the property exists false otherwise.
 */
static inline bool of_property_read_bool(const struct device_node *np,
					 const char *propname)
{
	struct property *prop = of_find_property(np, propname, NULL);

	return prop ? true : false;
}

of_property_read_bool 的用法

  • 比如 drivers\of\address.c 中 的:
bool of_dma_is_coherent(struct device_node *np)
{
	struct device_node *node;

	if (IS_ENABLED(CONFIG_OF_DMA_DEFAULT_COHERENT))
		return true;

	node = of_node_get(np);

	while (node) {
		if (of_property_read_bool(node, "dma-coherent")) {
			of_node_put(node);
			return true;
		}
		node = of_get_next_dma_parent(node);
	}
	of_node_put(node);
	return false;
}
  • 这里判断是否存在 dma-coherent 属性

  • 这里还说明了设备树节点有父子兄弟这样的关系,比如父节点或者祖父节点有这个属性,依旧可以认为这个属性存在。

  • 有些设备树节点属性【继承】了上级或者上上级的属性。

  • 真实的设备树节点,父子兄弟关系并没有想象中的那样复杂,大多就三到四级。

疑问

  • 设备树节点 property 为何可以直接遍历查找

  • 【答】这得多亏了 设备树 dtc 工具与 设备树 【反扁平化】操作,这个设备树 dtb 不是直接像普通文件读取到内存的,需要通过 unflatten_device_tree,梳理并把各个设备树节点,组织成设备树结构。类似于 dtb 是一箱水果,需要分门别类,比如按价钱等摆到各自的摊位上,方便大家挑选与购买。

小结

  • 设备树解析部分,其实就是解析【现成】的应经 设备树化后的 各个有组织次序的 设备树。所以操作起来类似于链表的节点查找,字符串比较,没有那么的难
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

zhangsz_sh

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值