Linux驱动开发——(一)设备树的基本属性及其应用
目录
1.4 #address-cells属性和#size-cells属性
3.2.4 of_property_read_u32_array
一、常见基本属性
常见的基本属性有compatible、status、reg、#address-cells和#size-cells。
1.1 compatible属性
compatible属性的值是一个字符串列表,将设备和驱动绑定起来。compatible属性的值格式如下所示:
"manufacturer,model"
manufacturer:厂商。
model:模块对应的驱动名字。
比如:
compatible = "fsl,imx6ul-evk-wm8960","fsl,imx-audio-wm8960";
其中”fsl“表示厂商是飞思卡尔,“imx6ul-evk-wm8960”和 “imx-audio-wm8960”表示驱动模块名字。 这个设备首先使用第一个兼容值“imx6ul-evk-wm8960”在Linux内核里面查找,看看能不能找到与之匹配的驱动文件,如果没有找到的话就使用第二个兼容值“imx-audio-wm8960”查。
1.2 status属性
status属性值也是字符串,是和设备状态有关的。
值 | 描述 |
---|---|
”okay“ | 表明设备是可操作的。 |
"disabled" | 表明设备当前是不可操作的,但是在未来可以变为可操作的。 |
”fail” | 表明设备不可操作,设备检测到了一系列的错误,而且设备也不大可能变得可操作。 |
”fail-sss“ | 含义和“fail”相同,后面的 sss部分是检测到的错误内容。 |
1.3 reg属性
reg属性的值一般是 (address length)对。 reg属性一般用于描述设备地址空间资源信息,一般都是某个外设的寄存器地址范围信息。
1.4 #address-cells属性和#size-cells属性
这两个属性的值都是无符号32位整形, #address-cells和 #size-cells这两个属性可以用在任何拥有子节点的设备中,用于描述子节点的地址信息。
#address-cells属性值决定了子节点reg属性中地址信息所占用的字长(32位),#size-cells属性值决定了子节点reg属性中长度信息所占的字长(32位)。
二、基本属性在设备树的表现
以I.MU6ULL为例,打开设备树dts文件,在根节点“/”下创建一个名为“alphaled”的子节点。
alphaled {
#address-cells = <1>;
#size-cells = <1>;
compatible = "atkalpha-led";
status = "okay";
reg = < 0X020C406C 0X04 /* CCM_CCGR1_BASE */
0X020E0068 0X04 /* SW_MUX_GPIO1_IO03_BASE */
0X020E02F4 0X04 /* SW_PAD_GPIO1_IO03_BASE */
0X0209C000 0X04 /* GPIO1_DR_BASE */
0X0209C004 0X04 >; /* GPIO1_GDIR_BASE */
};
第2、3行,属性#address-cells和#size-cells都为1,表示reg属性中起始地址占用一个字长
(cell),地址长度也占用一个字长 (cell)。
第4行,属性compatbile设置alphaled节点兼容性为“atkalpha-led”。
第5行,属性status设置状态为“okay”。
第6~10行,属性reg设置了驱动里面所要使用的寄存器物理地址,比如第6行的“ 0X020C406C 0X04”表示 I.MX6ULL的 CCM_CCGR1寄存器,其中寄存器首地址为 0X020C406C,长度为4个字节。
然后重新编译设备树,使用新的设备树启动Linux。
三、基本属性在驱动代码的表现
3.1 驱动代码
在驱动入口函数加入以下代码:
/* 获取设备树中的属性数据 */
/* 1、获取设备节点:alphaled */
dtsled.nd = of_find_node_by_path("/alphaled");
if(dtsled.nd == NULL) {
printk("alphaled node nost find!\r\n");
return -EINVAL;
} else {
printk("alphaled node find!\r\n");
}
/* 2、获取compatible属性内容 */
proper = of_find_property(dtsled.nd, "compatible", NULL);
if(proper == NULL) {
printk("compatible property find failed\r\n");
} else {
printk("compatible = %s\r\n", (char*)proper->value);
}
/* 3、获取status属性内容 */
ret = of_property_read_string(dtsled.nd, "status", &str);
if(ret < 0){
printk("status read failed!\r\n");
} else {
printk("status = %s\r\n",str);
}
/* 4、获取reg属性内容 */
ret = of_property_read_u32_array(dtsled.nd, "reg", regdata, 10);
if(ret < 0) {
printk("reg property read failed!\r\n");
} else {
u8 i = 0;
printk("reg data:\r\n");
for(i = 0; i < 10; i++)
printk("%#X ", regdata[i]);
printk("\r\n");
}
3.2 驱动代码中的OF函数
3.2.1 of_find_node_by_path
通过路径来查找指定的节点,函数原型如下:
inline struct device_node *of_find_node_by_path(const char *path)
path:带有全路径的节点名,可使用节点的别名。
返回值: 找到的节点,如果为 NULL表示查找失败。
3.2.2 of_find_property
用于查找指定的属性compatible,函数原型如下:
property *of_find_property(const struct device_node *np, const char *name, int *lenp)
np:设备节点。
name:属性名字。
lenp:属性值的字节数
返回值: 找到的属性。
3.2.3 of_property_read_string
用于读取属性中字符串值,函数原型如下:
int of_property_read_string(struct device_node *np, const char *propname, const char **out_string)
np:设备节点。
proname:要读取的属性名字。
out_string:读取到的字符串值。
返回值: 0,读取成功;负值,读取失败。
3.2.4 of_property_read_u32_array
读取属性中u32类型的数组数据,大多数的reg属性都是数组数据,可以使用该函数一次读取出reg属性中的所有数据。这该函数的原型如下:
int of_property_read_u32_array(const struct device_node *np, const char *propname, u32 *out_values, size_t sz)
np:设备节点。
proname: 要读取的属性名字。
out_value:读取到的数组值,分别为 u8、 u16、 u32和 u64。
sz:要读取的数组元素数量。
返回值: 0,读取成功;负值,读取失败,-EINVAL表示属性不存在,-ENODATA表示没有要读取的数据,-EOVERFLOW表示属性值列表太小。
四、平台实验测试
如图:
输出正确,实现成功。
原文地址:https://blog.csdn.net/weixin_61979510/article/details/137845314
免责声明:本站文章内容转载自网络资源,如本站内容侵犯了原著者的合法权益,可联系本站删除。更多内容请关注自学内容网(zxcms.com)!