2023.2.13

整理解析设备树的相关of函数

一、设备树节点结构体:
struct device_node {
 const char *name;      //节点名  mynode
 const char *full_name; //节点全名 mynode@0x12345678
 struct property *properties; //节点中键值对的结构体(属性结构体)
 struct device_node *parent; //父节点
 struct device_node *child;  //子节点
 struct device_node *sibling; //兄弟节点
}

二、节点属性结构体:
struct property { 
 char *name; //键的名字
 int length;    //值的长度(单位是字节)
 void *value; //值
 struct property *next; //指向下一个成员
};

三、获取设备树节点的of函数:
函数所需的头文件:#include <linux/of.h>
struct device_node *of_find_node_by_path(const char *path)
功能:通过路径获取设备节点
参数:
    @path:节点的路径 ("/mynode@0x12345678")
返回值:成功返回节点的首地址,失败返回NULL
        
struct device_node *of_find_node_by_name(struct device_node *from,const char *name);
功能:通过节点名获取设备节点
参数:
    @from:已知结构体首地址,(NULL,默认从根开始解析)
    @name:节点名 "mynode"
返回值:成功返回节点的首地址,失败返回NULL
        

struct device_node *of_find_compatible_node(struct device_node *from,
                                   const char *type, const char *compat);
功能:通过compatible来解析节点
参数:
    @from :填写NULL,从根开始解析
    @type :类型填写为NULL
    @compat:compatible的值
返回值:成功返回节点的首地址,失败返回NULL

四、节点属性解析相关的of函数:
struct property *of_find_property(const struct device_node *np,
      const char *name,
      int *lenp)
功能:根据属性名获取属性结构体
参数:
    @np:节点的首地址
    @name:键
    @lenp:获取到的值的字节个数
返回值:成功返回属性结构体地址,失败返回NULL

int of_property_read_u32_index(const struct device_node *np,
           const char *propname,
           u32 index, u32 *out_value)
功能:获取u32类型的值
参数:
    @np:节点指针
    @propname:键的名字
    @index:值中32位数的索引号
    @out_value:获取到的值
返回值:成功返回0,失败返回错误码
        
int of_property_read_variable_u32_array(const struct device_node *np,
          const char *propname, u32 *out_values,
          size_t sz_min, size_t sz_max) 
功能:获取u32类型的数组
参数:
    @np:节点指针
    @propname:键的名字
    @out_value:获取到的值的首地址
    @sz_min:数组的下标最小值
    @sz_max:数组的下标最大值
返回值:成功返回0,失败返回错误码
        
int of_property_read_string(const struct device_node *np, const char *propname,
    const char **out_string)
功能:获取字符串类型的值
参数:
    @np:节点指针
    @propname:键的名字
    @out_value:获取到字符串首地址
返回值:成功返回0,失败返回错误码
    
 int of_property_read_variable_u8_array(const struct device_node *np,
     const char *propname, u8 *out_values,
     size_t sz_min, size_t sz_max)
功能:获取u8类型的数组
参数:
    @np:节点指针
    @propname:键的名字
    @out_value:获取到的值的首地址
    @sz_min:数组的下标最小值
    @sz_max:数组的下标最大值
返回值:成功返回0,失败返回错误码
        
static inline int of_property_read_u8_array(const struct device_node *np,
         const char *propname,
         u8 *out_values, size_t sz)
功能:获取u8类型的数组
参数:
    @np:节点指针
    @propname:键的名字
    @out_value:获取到的值的首地址
    @sz:数组成员的个数
返回值:成功返回0,失败返回错误码

实例:

#include <linux/init.h>
#include <linux/device.h>
#include <linux/cdev.h>
#include <linux/fs.h>
#include <linux/uaccess.h>
#include <linux/of.h>
#include <linux/of_gpio.h>
#include <linux/gpio.h>
#include <linux/module.h>

/*
mynode@0x12345678{
    compatible = "hqyj,mynode";
    a-string = "mynode string";
    a-uint   = <0x12345678 0xaabbccdd>;
    a-binhex = [00 0c 29 7b f9 be];
    a-mixed  = "fish",<0x11223344>,[11 22 33];
};
*/

struct device_node *node;
struct property *pr;

static int __init mycdev_init(void)
{
    int len;
    int i;
    node = of_find_node_by_path("/mynode@0x12345678");
    if(node==NULL){
        printk("of_find_name_by_path error");
        return -EINVAL;
    }
    printk("name=%s value=%s\n",node->properties->name,(char *)node->properties->value);
    printk("name=%s value=%s\n",node->properties->next->name,\
                        (char *)node->properties->next->value);
    printk("name=%s value1=%#x value2=%#x\n",node->properties->next->next->name,\
                        __be32_to_cpup((uint32_t *)node->properties->next->next->value),\
                        __be32_to_cpup((uint32_t *)(node->properties->next->next->value+4)));

    pr=of_find_property(node,"a-binhex",&len);
    if(pr==NULL){
        printk("of_find_property error");
        return -EINVAL;
    }
    for (i = 0; i < len;i++){
        printk("name=%s value%d=%#x\n", pr->name, i, *(char *)(pr->value + i));
    }

    return 0;
}

static void __exit mycdev_exit(void)
{
    
}

module_init(mycdev_init);
module_exit(mycdev_exit);
MODULE_LICENSE("GPL");
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值