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表示属性值列表太小。


四、平台实验测试

如图:

输出正确,实现成功。

相关推荐
Komorebi.py1 小时前
【Linux】-学习笔记05
linux·笔记·学习
Mr_Xuhhh1 小时前
重生之我在学环境变量
linux·运维·服务器·前端·chrome·算法
内核程序员kevin4 小时前
TCP Listen 队列详解与优化指南
linux·网络·tcp/ip
朝九晚五ฺ8 小时前
【Linux探索学习】第十四弹——进程优先级:深入理解操作系统中的进程优先级
linux·运维·学习
自由的dream8 小时前
Linux的桌面
linux
xiaozhiwise9 小时前
Makefile 之 自动化变量
linux
意疏11 小时前
【Linux 篇】Docker 的容器之海与镜像之岛:于 Linux 系统内探索容器化的奇妙航行
linux·docker
BLEACH-heiqiyihu11 小时前
RedHat7—Linux中kickstart自动安装脚本制作
linux·运维·服务器
一只爱撸猫的程序猿11 小时前
一个简单的Linux 服务器性能优化案例
linux·mysql·nginx