Linux驱动开发—— of_property_read_u8
在使用設備樹的時候, 有時會遇到下面的問題.
在設備樹中配置的屬性如下:
fusb301,init-mode = <0x20>;
但是在驅動中讀出的卻是:
rc = of_property_read_u8(dev_node,
"fusb301,init-mode", &data->init_mode);
加打印發現, 讀出的值是0, 並不是0x20.
使用下面的命令將對應的節點從內存中pull出來:
adb pull "/sys/firmware/devicetree/base/soc/i2c@7af6000/fusb301@25/fusb301,init-mode"
這是一個二進制文件, 使用二進制閱讀工具打開:
可以看到, 0x20存放在高字節, 即設備樹編譯工具是按大端格式組織數據的, 但是使用of_property_read_u8卻是按小端格式.
然後做了如下實驗:
添加屬性:
fusb301,test = <0x12345678>;
在驅動中解析這個字段:
u8 value8; u16 value16; u32 value32; of_property_read_u8(dev_node,"fusb301,test", &value8); of_property_read_u16(dev_node,"fusb301,test", &value16); of_property_read_u32(dev_node,"fusb301,test", &value32); printk("%s: value8: %x, value16: %x, value32: %x\n", __func__, value8, value16, value32);
輸出的log如下:
fusb301_parse_dt: value8: 12, value16: 1234, value32: 12345678
可以驗證我們的猜想.
那麼如何解決這個問題呢?
通過閱讀內核代碼發現, 內核中其實有說明:
1 /** 2 * of_property_read_u8_array - Find and read an array of u8 from a property. 3 * 4 * @np: device node from which the property value is to be read. 5 * @propname: name of the property to be searched. 6 * @out_values: pointer to return value, modified only if return value is 0. 7 * @sz: number of array elements to read 8 * 9 * Search for a property in a device node and read 8-bit value(s) from 10 * it. Returns 0 on success, -EINVAL if the property does not exist, 11 * -ENODATA if property does not have a value, and -EOVERFLOW if the 12 * property data isn't large enough. 13 * 14 * dts entry of array should be like: 15 * property = /bits/ 8 <0x50 0x60 0x70>; 16 * 17 * The out_values is modified only if a valid u8 value can be decoded. 18 */ 19 int of_property_read_u8_array(const struct device_node *np, 20 const char *propname, u8 *out_values, size_t sz) 21 { 22 const u8 *val = of_find_property_value_of_size(np, propname, 23 (sz * sizeof(*out_values))); 24 25 if (IS_ERR(val)) 26 return PTR_ERR(val); 27 28 while (sz--) 29 *out_values++ = *val++; 30 return 0; 31 } 32 EXPORT_SYMBOL_GPL(of_property_read_u8_array);
然後我做了如下實驗:
添加如下幾個屬性:
fusb301,test8 = /bits/ 8 <0x12>; fusb301,test16 = /bits/ 16 <0x1234>; fusb301,test32 = <0x12345678>;
修改驅動, 解析這些字段:
u8 value8; u16 value16; u32 value32; of_property_read_u8(dev_node,"fusb301,test8", &value8); of_property_read_u16(dev_node,"fusb301,test16", &value16); of_property_read_u32(dev_node,"fusb301,test32", &value32); printk("%s: value8: %x, value16: %x, value32: %x\n", __func__, value8, value16, value32);
輸出的log如下:
fusb301_parse_dt: value8: 12, value16: 1234, value32: 12345678
完.
本文来自博客园,作者:摩斯电码,未经同意,禁止转载