第五十三讲 获取设备树属性
第五十三讲 获取设备树属性
文章目录
- 第五十三讲 获取设备树属性
- 一、获取设备树属性信息
- 1、查看属性所在节点
- device_node 结构体
- 2、如何查找结点
- 节点路径
- 节点类型(不推荐使用)
- 节点名字(不推荐使用)
- 节点属性
- 3、查找节点属性值
- property 结构体
- 4、如何查找节点属性值
- of_find_property
- of_property_read_u32
- of_property_read_u32_array
- of_property_read_string
- 二、设备树属性获取实验
- 1、实验代码
- getDTSproperty.c
- Makefile
- 2、实验步骤
- 3、实验结果
- 参考资料
一、获取设备树属性信息
1、查看属性所在节点
前面讲到我们所编写的设备树源码文件是后缀为.dts的文件。dts文件经过编译生成dtb文件,通过复制dtb文件到开发板的指定位置才能被uboot识别然后加载到指定位置。当内核启动的时候会去指定位置来找到dtb文件,然后对dtb文件进行解析。已经知道dtb文件中的节点与属性信息会被解析填充到kernel的device_node和property结构体中;在start_kernel的后续初始化过程中,device_node还会进一步和各种device进行绑定,有虚拟的platform bus下的platform_device,也有spi、i2c等物理bus下的从设备(client)。
kernel会为设备树root节点下所有带’compatible’ 属性的节点都分配并注册一个platform_device;另外,如果某节点的’compatible’ 符合某些matches条件,则会为该节点下所有带’compatible’ 属性的子节点(child)也分配并注册一个platform_device。
device_node 结构体
路径:ebf_linux_kernel-ebf_4.19.35_imx6ul\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;
#if defined(CONFIG_OF_KOBJ)struct kobject kobj;
#endifunsigned long _flags;void *data;
#if defined(CONFIG_SPARC)const char *path_component_name;unsigned int unique_id;struct of_irq_controller *irq_trans;
#endif
};#define MAX_PHANDLE_ARGS 16
struct of_phandle_args {struct device_node *np;int args_count;uint32_t args[MAX_PHANDLE_ARGS];
};
2、如何查找结点
通过上面的介绍,我们就可以知道如何查找设备树节点了-节点路径、节点类型、节点名字、节点属性。
节点路径
函数 | 原型 | 参数 | 返回值 |
---|---|---|---|
of_find_node_by_path | struct device_node *of_find_node_by_path(const char *path) | path:带节点名的路径 |
成功:device_node节点 失败:NULL |
节点类型(不推荐使用)
函数 | 原型 | 参数 | 返回值 |
---|---|---|---|
of_find_node_by_type | struct device_node *of_find_node_by_type(struct device_node *from,const char *type) |
from:开始搜索的节点,NULL 开始搜索整个设备树。 不会搜索你传递的节点,只会搜索下一个节点; 通常,您传递上一个调用返回的内容。 of_node_put() 将为您调用。 type:要匹配的类型字符串 |
返回一个引用计数递增的节点指针,完成后使用 of_node_put() 。 |
节点名字(不推荐使用)
函数 | 原型 | 参数 | 返回值 |
---|---|---|---|
of_find_node_by_name | struct device_node *of_find_node_by_name(struct device_node *from,const char *name) |
from: The node to start searching from or NULL; the node name: The name string to match against |
Returns a node pointer with refcount incremented, use of_node_put() on it when done. |
节点属性
函数 | 原型 | 参数 | 返回值 |
---|---|---|---|
of_find_compatible_node | struct device_node *of_find_compatible_node(struct device_node *from,const char *type, const char *compatible) |
from:The node to start searching from or NULL, the node you pass will not be searched, only the next one will; typically, you pass what the previous call returned. of_node_put() will be called on it type: The type string to match “device_type” or NULL to ignore compatible: The string to match to one of the tokens in the device “compatible” list.of_node_put() on it when done. |
Returns a node pointer with refcount incremented, use |
3、查找节点属性值
property 结构体
这个结构体存放着节点的属性
路径:ebf_linux_kernel-ebf_4.19.35_imx6ul\include\linux\of.h
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
};
4、如何查找节点属性值
of_find_property
函数 | 原型 | 参数 | 返回值 |
---|---|---|---|
of_find_property | struct property *of_find_property(const struct device_node *np,const char *name,int *lenp) |
np:device_node表示的节点 name:查找属性的名字 lenp:属性值的字节数 |
成功:property属性值 失败:NULL |
of_property_read_u32
函数 | 原型 | 参数 | 返回值 |
---|---|---|---|
of_property_read_u32 | int of_property_read_u32(const struct device_node *np,const char *propname,u32 *out_value) |
np:device node from which the property value is to be read. propname:name of the property to be searched. out_values:pointer to return value, modified only if return value is 0. |
0:成功 负值:失败 |
of_property_read_u32_array
函数 | 原型 | 参数 | 返回值 |
---|---|---|---|
of_property_read_u32_array | int of_property_read_u32_array(const struct device_node *np,const char *propname,u32 *out_values, size_t sz) |
np:device node from which the property value is to be read. propname:name of the property to be searched. out_values:pointer to return value, modified only if return value is 0. sz:number of array elements to read |
Returns 0 on success, -EINVAL if the property does not exist, -ENODATA if property does not have a value -EOVERFLOW if the property data isn’t large enough |
of_property_read_string
函数 | 原型 | 参数 | 返回值 |
---|---|---|---|
of_property_read_string | int of_property_read_string(const struct device_node *np,const char *propname,const char **out_string) |
np:device_node表示的节点 proname:查找属性的名字 out_string:读取到的字符串值 |
0:成功 负值:失败 |
二、设备树属性获取实验
写在前面,由于本节仅演示获取设备树属性,所以并没有按照视频内的方法来写程序,前面有介绍过在加载模块的时候,会自动调用init函数。所以本实验是利用这个直接演示获取其他的设备树属性。并没有注册一个设备。
1、实验代码
getDTSproperty.c
/** @LastEditors: 夜雨* @Date: 2022-03-10 21:52:21* @LastEditTime: 2022-03-16 22:11:36* @FilePath: \code\kernel\012getDTSproperty\getDTSproperty.c*/
#include <linux/kernel.h>
#include <linux/module.h>#include <linux/of.h>#define DEVICE_TREE_PATH "/74hc595"struct device_node *dts_device_node;static __init int dtsPropertyInit(void)
{printk("<3> DTS property init!\n");/*通过路径寻找设备树节点*/dts_device_node = of_find_node_by_path(DEVICE_TREE_PATH);if(dts_device_node == NULL){printk("<3> get "DEVICE_TREE_PATH" DTS property failed!\n");return -1;}printk("<3> "DEVICE_TREE_PATH" node name is %s\n", dts_device_node->name);printk("<3> "DEVICE_TREE_PATH" node type is %s\n", dts_device_node->type);
}
static __exit void dtsPropertyExit(void)
{printk("<3> DTS property exit!\n");
}module_init(dtsPropertyInit);
module_exit(dtsPropertyExit);MODULE_LICENSE("GPL");
MODULE_AUTHOR("Yeyu");
MODULE_DESCRIPTION("dts module!");
MODULE_ALIAS("dts_module");
Makefile
KERNEL_DIR=../../ebf_linux_kernel/build_image/build/ARCH=arm
CROSS_COMPILE=arm-linux-gnueabihf-
export ARCH CROSS_COMPILEobj-m := getDTSproperty.oall:$(MAKE) -C $(KERNEL_DIR) M=$(CURDIR) modules.PHONE:clean copyclean:$(MAKE) -C $(KERNEL_DIR) M=$(CURDIR) clean copy:sudo cp *.ko /home/dragon/nfsshare
2、实验步骤
编译代码
make
将代码复制到共享文件夹
‘make copy’
打开登陆开发板
连接共享文件夹
sudo mount -t nfs 192.168.3.41:/home/xxx/nfsshare /mnt
加载模块
sudo insmod /mnt/getDTSproperty.ko
3、实验结果
[ 3483.270178] getDTSproperty: loading out-of-tree module taints kernel.
[ 3483.286299] <3> DTS property init!
[ 3483.289760] <3> /74hc595 node name is 74hc595
[ 3483.294123] <3> /74hc595 node type is <NULL>
[ 3483.306374] do_init_module: 'getDTSproperty'->init suspiciously returned 32, it should follow 0/-E convention
[ 3483.306374] do_init_module: loading module anyway...
[ 3483.323163] CPU: 0 PID: 582 Comm: insmod Tainted: G O 4.19.35-imx6 #1stable
[ 3483.331450] Hardware name: Freescale i.MX6 UltraLite (Device Tree)
[ 3483.337669] [<801106d4>] (unwind_backtrace) from [<8010c5c8>] (show_stack+0x10/0x14)
[ 3483.345434] [<8010c5c8>] (show_stack) from [<80d5e370>] (dump_stack+0x78/0x8c)
[ 3483.352675] [<80d5e370>] (dump_stack) from [<801ae490>] (do_init_module+0x8c/0x200)
[ 3483.360349] [<801ae490>] (do_init_module) from [<801ad38c>] (load_module+0x2174/0x257c)
[ 3483.368367] [<801ad38c>] (load_module) from [<801ada18>] (sys_finit_module+0xc4/0x110)
[ 3483.376298] [<801ada18>] (sys_finit_module) from [<80101000>] (ret_fast_syscall+0x0/0x54)
[ 3483.384481] Exception stack(0x86061fa8 to 0x86061ff0)
[ 3483.389544] 1fa0: baddb300 00000000 00000003 0045f7e0 00000000 7ef15c48
[ 3483.397732] 1fc0: baddb300 00000000 00000000 0000017b 01f26230 00000000 7ef15dc8 00000000
[ 3483.405917] 1fe0: 7ef15bf8 7ef15be8 00457e41 76d61d92
可以看到,获取到了设备树的属性,感兴趣的朋友也试试其他函数呀!!!
[ 3483.286299] <3> DTS property init!
[ 3483.289760] <3> /74hc595 node name is 74hc595
[ 3483.294123] <3> /74hc595 node type is <NULL>
写在最后,细心的小伙伴可能发现了实验结果有报错呀,这个怎么解决呢?很简单,在init函数最后加上 return 0
即可。哈哈哈,我的问题!!!
参考资料
设备树(二):device_node与device绑定
第五十三讲 获取设备树属性相关推荐
- 第五十五讲 插件设备树
第五十五讲 插件设备树 文章目录 第五十五讲 插件设备树 一.概述 1.概述 2.使用前提 3.编译工具 二.插件设备树实验 1.环境准备 2.实验 3.验证实验 附录 驱动代码 led.c led. ...
- 第五十四讲 设备树实现RGB驱动
第五十四讲 设备树实现RGB驱动 文章目录 第五十四讲 设备树实现RGB驱动 一.基础知识 1.GPIO Write Mode 2.硬件连接 3.重要寄存器(参考IMXULL用户手册) RGB_R R ...
- 【正点原子Linux连载】第四十四章 设备树下的LED驱动实验 -摘自【正点原子】I.MX6U嵌入式Linux驱动开发指南V1.0
1)实验平台:正点原子阿尔法Linux开发板 2)平台购买地址:https://item.taobao.com/item.htm?id=603672744434 2)全套实验源码+手册+视频下载地址: ...
- 【正点原子MP157连载】第二十四章 设备树下的LED驱动实验-摘自【正点原子】STM32MP1嵌入式Linux驱动开发指南V1.7
1)实验平台:正点原子STM32MP157开发板 2)购买链接:https://item.taobao.com/item.htm?&id=629270721801 3)全套实验源码+手册+视频 ...
- Linux 获取设备树源文件(DTS)里描述的资源
Linux 获取设备树源文件(DTS)里的资源 韩大卫@吉林师范大学 在linux使用platform_driver_register() 注册 platform_driver 时, 需要在 plat ...
- 韦东山 IMX6ULL和正点原子_「正点原子Linux连载」第四十四章设备树下的LED驱动实验...
1)实验平台:正点原子Linux开发板 2)摘自<正点原子I.MX6U嵌入式Linux驱动开发指南> 关注官方微信号公众号,获取更多资料:正点原子 上一章我们详细的讲解了设备树语法以及在驱 ...
- linux 获取设备树源文件(dts)里描述的资源,Linux 获取设备树源文件(DTS)里描述的资源...
在linux使用platform_driver_register() 注册 platform_driver 时, 需要在 platform_driver 的probe() 里面知道设备的中断号, 内 ...
- 线性代数学习笔记——第五十三讲——齐次方程组求解实例
1. 给定一个齐次线性方程组,求其通解 (写出系数矩阵 -> 行初等变换为行简化矩阵 -> 求基础解系 -> 写出通解) 2. 示例2 (只有零解的情况) 3. 与基础解系等价的线性 ...
- 设备树下字符设备驱动
设备树下字符设备驱动 一.在设备树里添加自己的节点 二.驱动代码 三.makefile 四.应用层代码 运行测试 总结 一.在设备树里添加自己的节点 alphaled { 2 #address-cel ...
最新文章
- 《Beginning Linux Programming》读书笔记(二)
- oracle siplugincol表,ORACLE 经常使用的命令工具-第三章:表
- .bash_profile和.bashrc的区别
- 我的.net程序在linux上运行起啦
- behavior php,behavior.php
- linux将光驱挂载到目录下,Linux操作系统下关于光驱的挂载
- html的音频播放,HTML5 音频播放 audio
- sonar不支持mysql_sonar-iOS的实践
- requests 获取百度推广信息
- 实现子元素在父元素中水平垂直都居中笔记
- 网课答案免费搜题入口
- Jupyter关联规则挖掘-莫名其妙的问题
- Mybase7延长试用期
- Make a mark of Gates
- 前沿分享|数澜科技联合创始人副总裁 江敏:基于云原生数据仓库AnalyticDB PostgreSQL的最佳实践
- 英语会话必须掌握的五种基本结构[转]
- 利用二维数组实现一个矩阵类:Matrix
- 华为麦芒6支持鸿蒙吗,华为麦芒6支持电信吗_华为麦芒6支持电信卡吗-太平洋IT百科...
- JavaScript读书笔记四
- SQL Server 2005的100范例程序及数据库下载
热门文章
- 淘宝运营 影响ROI的因素 优化直通车ROI 的方法
- oracle数据库时钟,oracle11g巡检RAC数据库
- 电动牙刷头品牌新产品上市软文宣传的策略和技巧,助力产品宣传引导消费者关注和购买
- QXmpp源码 GuiClient
- 笔记本装win10和ubuntu双系统
- 1012: 求绝对值
- 招聘工作第一步:和业务部门沟通招聘需求关键谈的内容是什么?
- Nao机器人实现语音识别
- QT5.8.0+VS2015+OpenCV4.1.2 配置Windows 32位和64位平台
- Navicat创建数据库模型