Linux驱动开发——(一)设备树的基本属性及其应用

目录

一、常见基本属性

[1.1 compatible属性](#1.1 compatible属性)

[1.2 status属性](#1.2 status属性)

[1.3 reg属性](#1.3 reg属性)

1.4 #address-cells属性和#size-cells属性

二、基本属性在设备树的表现

三、基本属性在驱动代码的表现

[3.1 驱动代码](#3.1 驱动代码)

[3.2 驱动代码中的OF函数](#3.2 驱动代码中的OF函数)

[3.2.1 of_find_node_by_path](#3.2.1 of_find_node_by_path)

[3.2.2 of_find_property](#3.2.2 of_find_property)

[3.2.3 of_property_read_string](#3.2.3 of_property_read_string)

[3.2.4 of_property_read_u32_array](#3.2.4 of_property_read_u32_array)

四、平台实验测试


一、常见基本属性

常见的基本属性有compatible、status、reg、#address-cells 和**#size-cells**。

1.1 compatible属性

compatible属性的值是一个字符串列表,将设备和驱动绑定起来。compatible属性的值格式如下所示:

复制代码
"manufacturer,model"

manufacturer:厂商。

model:模块对应的驱动名字。

比如:

复制代码
compatible = "fsl,imx6ul-evk-wm8960","fsl,imx-audio-wm8960";

其中"fsl" 表示厂商是飞思卡尔,"imx6ul-evk-wm8960 "和 "imx-audio-wm8960"表示驱动模块名字。 这个设备首先使用第一个兼容值"imx6ul-evk-wm8960"在Linux内核里面查找,看看能不能找到与之匹配的驱动文件,如果没有找到的话就使用第二个兼容值"imx-audio-wm8960"查。

1.2 status属性

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

描述
"okay" 表明设备是可操作的。
"disabled" 表明设备当前是不可操作的,但是在未来可以变为可操作的。
"fail" 表明设备不可操作,设备检测到了一系列的错误,而且设备也不大可能变得可操作。
"fail-sss" 含义和"fail"相同,后面的 sss部分是检测到的错误内容。
1.3 reg属性

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

1.4 #address-cells属性和#size-cells属性

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

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


二、基本属性在设备树的表现

以I.MU6ULL为例,打开设备树dts文件,在根节点"/"下创建一个名为"alphaled"的子节点。

复制代码
alphaled { 
    #address-cells = <1>; 
    #size-cells = <1>; 
    compatible = "atkalpha-led"; 
    status = "okay"; 
    reg = < 0X020C406C 0X04 /* CCM_CCGR1_BASE */ 
            0X020E0068 0X04 /* SW_MUX_GPIO1_IO03_BASE */ 
            0X020E02F4 0X04 /* SW_PAD_GPIO1_IO03_BASE */ 
            0X0209C000 0X04 /* GPIO1_DR_BASE */ 
            0X0209C004 0X04 >; /* GPIO1_GDIR_BASE */ 
};

第2、3行,属性**#address-cells** 和**#size-cells** 都为1,表示reg属性中起始地址占用一个字长

(cell),地址长度也占用一个字长 (cell)。

第4行,属性compatbile 设置alphaled节点兼容性为"atkalpha-led"。

第5行,属性status 设置状态为"okay"。

第6~10行,属性reg设置了驱动里面所要使用的寄存器物理地址,比如第6行的" 0X020C406C 0X04"表示 I.MX6ULL的 CCM_CCGR1寄存器,其中寄存器首地址为 0X020C406C,长度为4个字节。

然后重新编译设备树,使用新的设备树启动Linux。


三、基本属性在驱动代码的表现

3.1 驱动代码

驱动入口函数加入以下代码:

复制代码
/* 获取设备树中的属性数据 */

	/* 1、获取设备节点:alphaled */

	dtsled.nd = of_find_node_by_path("/alphaled");

	if(dtsled.nd == NULL) {

		printk("alphaled node nost find!\r\n");

		return -EINVAL;

	} else {

		printk("alphaled node find!\r\n");

	}



	/* 2、获取compatible属性内容 */

	proper = of_find_property(dtsled.nd, "compatible", NULL);

	if(proper == NULL) {

		printk("compatible property find failed\r\n");

	} else {

		printk("compatible = %s\r\n", (char*)proper->value);

	}



	/* 3、获取status属性内容 */

	ret = of_property_read_string(dtsled.nd, "status", &str);

	if(ret < 0){

		printk("status read failed!\r\n");

	} else {

		printk("status = %s\r\n",str);

	}



	/* 4、获取reg属性内容 */

	ret = of_property_read_u32_array(dtsled.nd, "reg", regdata, 10);

	if(ret < 0) {

		printk("reg property read failed!\r\n");

	} else {

		u8 i = 0;

		printk("reg data:\r\n");

		for(i = 0; i < 10; i++)

			printk("%#X ", regdata[i]);

		printk("\r\n");

	}
3.2 驱动代码中的OF函数
3.2.1 of_find_node_by_path

通过路径来查找指定的节点,函数原型如下:

复制代码
inline struct device_node *of_find_node_by_path(const char *path)

path :带有全路径的节点名,可使用节点的别名。
返回值: 找到的节点,如果为 NULL表示查找失败。

3.2.2 of_find_property

用于查找指定的属性compatible,函数原型如下:

复制代码
property *of_find_property(const struct device_node *np, const char *name, int *lenp)

np :设备节点。
name :属性名字。
lenp :属性值的字节数
返回值: 找到的属性。

3.2.3 of_property_read_string

用于读取属性中字符串值,函数原型如下:

复制代码
int of_property_read_string(struct device_node *np, const char *propname, const char **out_string)

np :设备节点。
proname: 要读取的属性名字。
out_string :读取到的字符串值。
返回值: 0,读取成功;负值,读取失败。

3.2.4 of_property_read_u32_array

读取属性中u32类型的数组数据,大多数的reg属性都是数组数据,可以使用该函数一次读取出reg属性中的所有数据。这该函数的原型如下:

复制代码
int of_property_read_u32_array(const struct device_node *np, const char *propname, u32 *out_values, size_t sz)

np:设备节点。

proname: 要读取的属性名字。

out_value:读取到的数组值,分别为 u8、 u16、 u32和 u64。

sz:要读取的数组元素数量。

返回值: 0,读取成功;负值,读取失败,-EINVAL表示属性不存在,-ENODATA表示没有要读取的数据,-EOVERFLOW表示属性值列表太小。


四、平台实验测试

如图:

输出正确,实现成功。

相关推荐
阿部多瑞 ABU22 分钟前
`chenmo` —— 可编程元叙事引擎 V2.3+
linux·人工智能·python·ai写作
徐同保1 小时前
nginx转发,指向一个可以正常访问的网站
linux·服务器·nginx
HIT_Weston1 小时前
95、【Ubuntu】【Hugo】搭建私人博客:_default&partials
linux·运维·ubuntu
实心儿儿1 小时前
Linux —— 基础开发工具5
linux·运维·算法
oMcLin1 小时前
如何在SUSE Linux Enterprise Server 15 SP4上通过配置并优化ZFS存储池,提升文件存储与数据备份的效率?
java·linux·运维
王阿巴和王咕噜6 小时前
【WSL】安装并配置适用于Linux的Windows子系统(WSL)
linux·运维·windows
布史6 小时前
Tailscale虚拟私有网络指南
linux·网络
水天需0106 小时前
shift 命令详解
linux
wdfk_prog6 小时前
[Linux]学习笔记系列 -- 内核支持与数据
linux·笔记·学习
Xの哲學7 小时前
深入剖析Linux文件系统数据结构实现机制
linux·运维·网络·数据结构·算法