设备树(DeviceTree)数组使用

简介

Linux驱动内需要设备数组数据,可以在设备树(devicetree)使用"[1 2 3 4]"或则"<1 2 3 4>"的方式定义,这种方式和我们在C语言内定义数组颇为相似。

解析数组的函数在内核文件drivers/of/property.c中实现,内核实现了获取8/16/32/64位数组的方法。

本文以获取8/32位数组的方法举例。

解析函数定义:

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)

功能:从设备树获取数组,每个数组元素大小是8位。

参数:@np,设备树节点。

           @propname,节点内的属性名称,如下面例子的"key-define"。

           @out_values,存储的位置,需要自行申请

           @sz_min/@sz_max,数组最小/最大长度。

 返回:获取数组元素的个数

例子

linux内核版本:4.14

设备树描述:

定义一个节点,8位数组内容以十六进制表示,但不需要在数字前加0x表示十六进制,数组元素用"[]"方括号围起来,例如

        key-define1 = [ 00 01 02 03 04 05 06 07 08 09 0A 0B 0C 0D 0E 0F 10 ];

32位数组,需要在数字前加入0x表示16进制,数组元素用"<>"尖括号围起来,例如

        key-define2 = <0x11 0x22 0x33>

mtest@43A00000{
        compatible = "mtest";
        reg = <0x43A00000 0x4>;
        interrupt-parent = <&gpio0>;
        interrupts = <160 1>;
        keypad,num-rows = <5>;
        keypad,num-columns=<21>;
        key-define1 = [
            00 01 02 03 04 05 06 07 08 09 0A 0B 0C 0D 0E 0F 10
        ];

        key-define2 = <0x11 0x22 0x33>;
        key-define3 = <11 22 33>;

};

驱动文件:

在自定义的驱动文件,probe函数内调用test_get_dt解析数组内容。

static int test_get_dt(struct device * dev, struct icfc_self_node * self)
{
    int ret;
    int key_number = 0;
    unsigned char def1[20];
    unsigned int def23[16];
    int i;
    
    ret = of_property_read_variable_u8_array(dev->of_node,"key-define1", def1, 2, 20);
    if (ret < 0)
    {
        printk("get define 1 fail\n");
        return -1;
    }
    printk( "get defs 1 number:%d\n", ret);

    for (i = 0; i < ret; i++)
    {
        printk( "%d,", def1[i]);
    }
    printk("\n");
    printk( "--------------------------------------------------------\n");
    ret = of_property_read_variable_u32_array(dev->of_node,"key-define2", def23, 2, 10);
    if (ret < 0)
    {
        printk("get define2 fail\n");
        return -1;
    }
    printk( "get defs 2 number:%d\n", ret);

    for (i = 0; i < ret; i++)
    {
        printk( "%d,", def23[i]);
    }
    printk("\n");
    printk( "--------------------------------------------------------\n");
    ret = of_property_read_variable_u32_array(dev->of_node,"key-define3", def23, 2, 10);
    if (ret < 0)
    {
        printk("define3\n");
        return -1;
    }
    printk( "get defs 3 number:%d\n", ret);

    for (i = 0; i < ret; i++)
    {
        printk( "%d,", def23[i]);
    }
    printk("\n");
    printk( "--------------------------------------------------------\n");
    return 0;
}

内核日志

get defs 1 number:17
0,1,2,3,4,5,6,7,8,9,10,11,13,14,15,16,
--------------------------------------------------------
get defs 2 number:3
17,34,51,
--------------------------------------------------------
get defs 3 number:3
11,22,33,
--------------------------------------------------------

内核函数参考

参考drivers/of/property.c的函数of_property_read_variable_u8_array

/**
 * of_property_read_variable_u8_array - Find and read an array of u8 from a
 * property, with bounds on the minimum and maximum array size.
 *
 * @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_min: minimum number of array elements to read
 * @sz_max: maximum number of array elements to read, if zero there is no
 *      upper limit on the number of elements in the dts entry but only
 *      sz_min will be read.
 *
 * Search for a property in a device node and read 8-bit value(s) from
 * it. Returns number of elements read on success, -EINVAL if the property
 * does not exist, -ENODATA if property does not have a value, and -EOVERFLOW
 * if the property data is smaller than sz_min or longer than sz_max.
 *
 * dts entry of array should be like:
 *  property = /bits/ 8 <0x50 0x60 0x70>;
 *
 * The out_values is modified only if a valid u8 value can be decoded.
 */
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)
{
    size_t sz, count;
    const u8 *val = of_find_property_value_of_size(np, propname,
                        (sz_min * sizeof(*out_values)),
                        (sz_max * sizeof(*out_values)),
                        &sz);

    if (IS_ERR(val))
        return PTR_ERR(val);

    if (!sz_max)
        sz = sz_min;
    else
        sz /= sizeof(*out_values);

    count = sz;
    while (count--)
        *out_values++ = *val++;

    return sz;
}

### 设备树数组的详细介绍 设备树(Device Tree)是一种描述硬件资源配置的标准方式,在设备树中,数组是一种常见的数据类型,用于表示一组相关的数据。数组元素可以是整数、字符串等类型,通常使用尖括号 `<>` 来表示整数数组,用方括号 `[]` 表示字符串数组。 例如,在设备树中可以定义如下的整数数组属性: ```dts node { my_array = <1 2 3 4 5>; }; ``` 这里的 `my_array` 就是一个包含 5 个 `u32` 类型元素的数组。 ### 与 `of_property_read_u32_array` 函数的关联 `of_property_read_u32_array` 函数用于从设备树节点中读取 `u32` 类型的数组。该函数的原型如下: ```c static inline int of_property_read_u32_array(const struct device_node *np, const char *propname, u32 *out_values, size_t sz); ``` - `np`:指向要读取属性的设备树节点的指针。 - `propname`:要读取的属性名称,对应设备树中定义的数组属性名,如上述示例中的 `my_array`。 - `out_values`:用于存储读取到的 `u32` 数组元素的缓冲区。 - `sz`:要读取的 `u32` 元素的数量。 函数返回值为 0 表示成功,返回负值表示失败。 以下是一个使用 `of_property_read_u32_array` 函数读取设备树数组的示例代码: ```c #include <linux/of.h> #include <linux/of_device.h> struct device_node *node; u32 values[5]; int rc; // 获取设备树节点 node = of_find_node_by_path("/path/to/your/node"); if (!node) { // 处理节点未找到的情况 return -ENODEV; } // 读取 u32 数组 rc = of_property_read_u32_array(node, "my_array", values, 5); if (rc < 0) { // 处理读取失败的情况 of_node_put(node); return rc; } // 使用读取到的数组 // ... // 释放节点引用 of_node_put(node); ```
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值