文章目录

  • 前言
  • 一、在设备树中添加自定义节点
  • 二、用到的of函数简介
    • 1.用到的结构体
    • 2.各of函数介绍
      • 1>.of_find_node_by_path
      • 2>.of_find_property
      • 3>.of_property_read_u32_array
      • 4>.of_property_read_string
  • 三、相关文件编写
    • 1.ofdriver.c文件
    • 2.Makefile文件
  • 四、运行结果查看
  • 总结

前言

本文的主要内容是Linux下设备树中常用的of操作函数举例,通过一个具体的例子来了解几个常用of函数的功能。


一、在设备树中添加自定义节点

打开与我们板子型号相匹配的设备树文件imx6dl-c-sabresd.dts,在其中添加test节点,代码如下。

test1:test{#address-cells = <1>;#size-cells = <1>;compatible = "test";reg = <0x20ac000 0x0000004>;status = "okay";};&test1{compatible = "test123"; //编译后,"test123"会替换上面定义中的"test"
};

添加的位置如下图所示,其他的代码不做改动。

根节点下的compatible属性是和开发板型号匹配的,若能匹配成功,则该设备树能成功烧写进开发板并启动,否则不可以。
添加完成后保存,打开WSL编译该设备树文件,并将其复制到tftp文件夹下。具体的操作步骤可以参见:Linux下通过tftp烧写设备树文件并启动开发板。


二、用到的of函数简介

1.用到的结构体

Linux下的设备都是以节点的形式“挂”到设备树上的,因此要想获取某个设备的属性信息,就必须先获取到这个设备的节点。
Linux内核使用device_node结构体来描述一个节点,此结构体定义在文件/linux-4.1.15/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 properties */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
};

节点的属性信息里面保存了驱动所需要的内容,因此对于属性值的提取非常重要,Linux内核中使用结构体property表示属性,其定义也在文件of.h 中。

struct property {char    *name; //属性名字int length;  //属性长度void    *value; //属性值struct property *next;  //下一个属性unsigned long _flags;unsigned int unique_id;struct bin_attribute attr;
};

2.各of函数介绍

1>.of_find_node_by_path

of_find_node_by_path的功能是查找节点,其在of.h文件中的定义如下。

static inline struct device_node *of_find_node_by_path(const char *path)
{return of_find_node_opts_by_path(path, NULL);
}

参数介绍:
path:带有全路径的节点名。
返回值:
查找成功时返回找到的节点,失败时返回NULL

2>.of_find_property

of_find_property的功能是查找节点的属性,其在of.h文件中的定义如下。

extern struct property *of_find_property(const struct device_node *np, const char *name, int *lenp);

参数介绍:
np:设备节点名。
name:要读取的属性名。
lenp:属性值的字节数。
返回值:
查找成功时返回对应的属性,失败时返回NULL

3>.of_property_read_u32_array

of_property_read_u32_array的功能是读取属性中u32类型的数组数据,一般情况下,reg属性都是数组类型,使用该函数可以一次读出reg属性中的所有数据,其在of.h文件中的定义如下。

extern int of_property_read_u32_array(const struct device_node *np, const char *propname, u32 *out_values, size_t sz);

参数介绍:
np:设备节点名。
propname:要读取的属性名。
out_values:读取到的数组值,类型为u32。
sz:要读取的数组元素数量。
返回值:
读取成功时返回0,读取失败时返回负值。

4>.of_property_read_string

of_property_read_string的功能是读取属性中的字符串,其在of.h文件中的定义如下。

extern int of_property_read_string(struct device_node *np, const char *propname, const char **out_string);

参数介绍:
np:设备节点名。
propname:要读取的属性名。
out_string:读取到的字符串。
返回值:
读取成功时返回0,读取失败时返回负值。


三、相关文件编写

1.ofdriver.c文件

#include <linux/init.h>
#include <linux/module.h>
#include <linux/of.h> int size;
u32 out_values[2] = {0};
const char *str;
struct device_node *test_device_node;
struct property *test_node_property;static int hello_init(void)
{int ret = 0;/*查找节点*/test_device_node = of_find_node_by_path("/test");  //在设备树节点中查找test这个节点if(test_device_node == NULL){printk("of_find_node_by_path is error!\n");return -1;}printk("test_device_node name is %s.\n", test_device_node->name); //获取节点的名字/*获取compatible属性   使用of_find_property函数读取*/test_node_property = of_find_property(test_device_node, "compatible", &size); if(test_node_property == NULL){printk("of_find_property is error!\n");return -1;}printk("test_node_property name is %s.\n", test_node_property->name);  //获取name属性,即compatibleprintk("test_node_property value is %s.\n", (char *)test_node_property->value); //获取compatible属性值/*获取reg属性   使用of_property_read_u32_array函数读取*/ret = of_property_read_u32_array(test_device_node, "reg", out_values, 2);if(ret < 0){printk("of_property_read_u32_array is error!\n");return -1;}printk("out_values[0] is 0x%08x.\n",out_values[0]); //打印读取到的数组值printk("out_values[1] is 0x%08x.\n",out_values[1]);/*获取status属性   使用of_property_read_string函数读取*/ret = of_property_read_string(test_device_node, "status", &str);if(ret < 0){printk("of_property_read_string is error!\n");return -1;}printk("status is %s.\n",str); //打印读取到的字符串/* 用of_find_property函数也可以访问,下面的代码和of_property_read_string的功能是相同的test_node_property = of_find_property(test_device_node, "status", &size); //参数依次为节点名、要查找的属性名、长度if(test_node_property == NULL){printk("of_find_property is error!\n");return -1;}printk("test_node_property name is %s.\n", test_node_property->name); printk("test_node_property value is %s.\n", (char *)test_node_property->value); //获取compatible属性值*/return 0;
}
static void hello_exit(void)
{printk("exit!\n");
}module_init(hello_init);
module_exit(hello_exit);
MODULE_LICENSE("GPL");

2.Makefile文件

obj-m += ofdriver.o
KDIR:=/linux/linux-4.1.15
PWD?=$(shell pwd)
all:make -C $(KDIR) M=$(PWD) modules
clean:make -C $(KDIR) M=$(PWD) clean

四、运行结果查看

将上面的代码敲好以后编译,然后将驱动文件发送至开发板。
在开发板上加载驱动,其打印信息如下图所示。

图中标注的①②③④正是of_find_node_by_path、of_find_property、of_property_read_u32_array和of_property_read_string函数各自调用时的打印输出。


总结

以上就是Linux下设备树中常用的of操作函数举例的所有内容了,要通过这个例子掌握这几个主要of函数的用途,便于日后在遇到类似的问题时选择最恰当的函数使用。
本文参考视频:https://www.bilibili.com/video/BV1Vy4y1B7ta?p=27。

Linux下设备树中常用的of操作函数举例相关推荐

  1. Linux 下的tar常用命令及操作

    tar命令可以为linux的文件和目录创建档案.利用tar,可以为某一特定文件创建档案(备份文件),也可以在档案中改变文件,或者向档案中加入新的文件.tar最初被用来在磁带上创建档案,现在,用户可以在 ...

  2. linux mysql常用基本操作,Linux下MySQL数据库常用基本操作 一

    Linux下MySQL数据库常用基本操作 一 0.登录数据库 mysql -u root -p 1.显示数据库 show databases; 2.选择数据库 use 数据库名; 3.显示数据库中的表 ...

  3. Linux下提权常用小命令

    有些新手朋友在拿到一个webshell后如果看到服务器是Linux或Unix操作系统的就直接放弃提权,认为Linux或Unix下的提权很难,不是大家能做的,其实Linux下的提权并没有很多人想象的那么 ...

  4. Linux下推荐的常用应用程序列表

    Linux下推荐的常用应用程序列表 一,网页浏览 1,firefox firefox是现在最火的一个浏览器,支持好多扩展和插件,也有很多漂亮的主题.firefox就是mozilla-firefox,他 ...

  5. linux查看用户的操作记录,Linux下查看用户登陆后的操作记录

    Linux下查看用户登陆后的操作记录  在linux系统的环境下,不管是root用户还是其它的用户只有登陆系统后用进入操作我们都可以通过命令history来查看历史记录,可是假如一台 服务器多人登陆, ...

  6. Linux系统常用函数,浅谈linux下的一些常用函数的总结(必看篇)

    1.exit()函数 exit(int n)  其实就是直接退出程序, 因为默认的标准程序入口为int main(int argc, char** argv),返回值是int型的. 一般在shell下 ...

  7. Linux下查看用户登陆后的操作记录

    Linux下查看用户登陆后的操作记录 在linux系统的环境下,不管是root用户还是其它的用户只有登陆系统后用进入操作我们都可以通过命令history来查看历史记录,可是假如一台 服务器多人登陆,一 ...

  8. Linux系统如何PING地址,Linux下指定源ip进行ping操作的方法

    [序言] 目前在做一台电脑上两个虚拟机之间的通信. 对于每个虚拟机都有两个网卡,一个桥接模式和一个NAT模式. 那么问题来了.... 如果使用简单的ping ip形式的命令得到ping通的结果,只能证 ...

  9. linux sd卡测速工具下载,Linux下3种常用的网络测速工具

    原标题:Linux下3种常用的网络测速工具 不管你用的是什么操作系统,网速都是你非常关心的一个性能指标,毕竟,谁都不想看个视频结果网速卡到你怀疑人生.本文介绍三个 Linux 命令行下的网络测速工具, ...

最新文章

  1. ubuntu linux 编译 opencv
  2. linux 解包与打包
  3. 忘记Oracle中System和Sys密码的解决办法
  4. 计算机应用技术自考知识点,自考计算机应用技术知识点:微处理器结构
  5. 推荐:CLR 完全介绍-一篇讲解CLR内存回收机制以及常见的调试技巧的文章
  6. 高性能Web动画和渲染原理系列(4)“Compositor-Pipeline演讲PPT”学习摘要【华为云技术分享】
  7. 【监控】使用 Grafana、collectd 和 InfluxDB 打造现代监控系统
  8. 对于技术焦虑的一点想法
  9. 记在windows上MySQL8.0安装过程中遇到的问题及解决方案
  10. linux7.7 离线安装nfs客户端_Linux提权姿势二:利用NFS提权
  11. android图片根据屏幕适配
  12. 定时器 cron 表达式
  13. 51单片机c语言程序控制,51单片机C语言总结
  14. 学习有法,事半功倍 — 在线学习的10个技巧
  15. VC890D万用表弹片图片
  16. 文件共享锁溢出 请增加MaxLocksperFile注册表项值
  17. python数据可视化之疫情地图爬虫(含完整代码以及具体报告)
  18. C#学习系列之H264解码
  19. ASP.NET 超市管理系统
  20. 每日一练--IT冷知识C/C++--第一天

热门文章

  1. FSM有限状态机学习及Unity3D案例讲解
  2. 12日的汶川地震让半个亚洲震动,让整个世界震惊。
  3. Tcl -- lappend
  4. android 集成环信SDK
  5. html中增删改查怎么写,增删改查crud
  6. STM32CubeMX上手初体验
  7. 黑金开发板zynq7020
  8. 企业大数据的八个典型应用
  9. python稳健性检验_利用Python检验你的策略参数是否过拟合
  10. linux的unbond服务无法启动,unbound和mail服务的部署和简单应用