Linux内核模块解析设备树内容

嵌入式技术

1368人已加入

描述

1. 前言

设备树中添加设备节点后,驱动可以根据节点中的属性进行一些设置。那么,驱动如何获取设备节点的属性信息呢?

答案是通过 of_xxx() 函数。

这些函数在 /include/linux/of.h 中声明,/drivers/of/property.c 中定义。

设备树

简单说明:

of_property_read_bool()查询某个属性是否存在;

of_property_read_xx() 读取单个值;

of_property_read_xx_array() 读取一个数组;

of_property_read_xx_index() 按照索引读取数组中的某一个;

of_property_read_variable_xx_array()读取数组中的几个;

下面的例子会展示上面函数的用法。

2. 操练一把

2.1 新建 module

我基于这里的步骤在 petalinux 工程中创建 hkm-devtree 模块。

设备树中的节点:

/{
    hkm-devtree {
            compatible = "sdc,hkm";
            hkm,name = "hkm-device-tree";
            uint-value = < 100 >;
            uint-array = < 0x11 0x22 0x33 0x44 >;
            dev-enable;
    };
};

hkm-devtree.c:

#include < linux/module.h >
#include < linux/string.h >
#include < linux/of_device.h >
#include < linux/of_platform.h >

#define DRIVER_NAME     ("hkm-device-tree")

static int hkm_devtree_probe(struct platform_device *pdev)
{
    struct device_node *node = pdev- >dev.of_node;
    u32 i = 0;
    s32 ret = 0;
    u32 value = 0;
    u32 arr[4] = {0};
    const char *name = NULL;

    printk(KERN_DEBUG "call hkm device tree driver probe functionn");

    if(NULL != node)
    {
        ret = of_property_read_string(node, "hkm,name", &name);
        if(0 == ret)
        {
            printk(KERN_DEBUG "hkm name is '%s' in device treen", name);
        }

        ret = of_property_read_u32(node, "uint-value", &value);
        if(0 == ret)
        {
            printk(KERN_DEBUG "value is %u in device treen", value);
        }

        ret = of_property_read_bool(node, "dev-enable");
        if(true == ret)
        {
            printk(KERN_DEBUG "device is enablen");
        }

        ret = of_property_read_u32_array(node, "uint-array", arr, 4);
        if(0 == ret)
        {
            printk(KERN_DEBUG "value array, 0x%x, 0x%x, 0x%x, 0x%xn", arr[0], arr[1], arr[2], arr[3]);
        }

        ret = of_property_read_u32_index(node, "uint-array", 3, &value);
        if(0 == ret)
        {
            printk(KERN_DEBUG "index 3 item of array:0x%xn", value);
        }

        memset(arr, 0, sizeof(arr));

        ret = of_property_read_variable_u32_array(node, "uint-array", arr, 2, 0);
        if(2 == ret)
        {
            printk(KERN_DEBUG "read 2 item of array:0x%x, 0x%xn", arr[0], arr[1]);
        }
   }

    return 0;
}

static int hkm_devtree_remove(struct platform_device *pdev)
{
    printk(KERN_DEBUG "call hkm device tree driver remove functionn");

    return 0;
}

#ifdef CONFIG_OF
static struct of_device_id hkm_devtree_of_match_table[] = {
    {.compatible = "sdc,hkm"},
    {/*end of list*/},
};

MODULE_DEVICE_TABLE(of, hkm_devtree_of_match_table);
#else
#define hkm_devtree_of_match_table
#endif


static struct platform_driver hkm_devtree_driver = {
    .driver = {
        .name = DRIVER_NAME,
        .owner = THIS_MODULE,
        .of_match_table = hkm_devtree_of_match_table,
    },

    .probe = hkm_devtree_probe,
    .remove = hkm_devtree_remove,
};

static int __init hkm_init(void)
{
    printk(KERN_DEBUG "hello, sdcn");

    return platform_driver_register(&hkm_devtree_driver);
}

static void __exit hkm_exit(void)
{
    printk(KERN_DEBUG "bye, sdcn");

}

module_init(hkm_init);
module_exit(hkm_exit);

MODULE_DESCRIPTION("KM in kernel source");
MODULE_AUTHOR("sdc");
MODULE_LICENSE("GPL");

工程仓库:https://gitee.com/sdc-coding/device-tree-parse

运行结果:

设备树

3. 设备树、内核、驱动之间的关系

驱动和设备树之间通过“设备树协议”进行通信。设备树语法就是协议规则,设备树就是符合协议的内容,内核提供解析协议的能力,驱动使用上述能力解析设备树,获取设备信息。

打开APP阅读更多精彩内容
声明:本文内容及配图由入驻作者撰写或者入驻合作网站授权转载。文章观点仅代表作者本人,不代表电子发烧友网立场。文章及其配图仅供工程师学习之用,如有内容侵权或者其他违规问题,请联系本站处理。 举报投诉

全部0条评论

快来发表一下你的评论吧 !

×
20
完善资料,
赚取积分