设备树(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;
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值