首页 > 编程知识 正文

windows目录结构树形,如何构造树

时间:2023-05-04 13:19:18 阅读:27511 作者:6

前言:我们给出了添加平台的设备信息,但引入设备树结构后,有关设备的信息全部以设备树的方式显示。 内核或驱动程序通过of系列函数获取这些信息。 然后在内核中以链表的形式组织。

相关结构属性:

结构属性{ char * name; int length; void *value; //重点结构属性*下一步; unsigned long _flags; unsigned int unique_id; struct wgdyd_attribute attr; (; 设备节点:

结构设备_ node { const char * name; 常数字符类型; phandle phandle; 常数char * full _ name; 结构fw node _ handle fw node; 结构属性*属性; 结构属性*深度属性;/*移除的属性*/struct device _ node * parent; 结构设备_ node * child; struct device_node *sibling; 结构关键点关键点; unsigned long _flags; Void *数据; # if定义(config _ SPARC ) const char *path_component_name; unsigned int unique_id; sructof _ IRQ _ controller * IRQ _ trans; #endif }; 平台设备:

结构平台_设备{ const char * name; int id; bool id_auto; 结构设备Dev; u32 num_resources; 结构资源*资源; conststructplatform _ device _ id * id _ entry; char *driver_override;/* drivernametoforceamatch *//* mfdcellpointer */struct MFD _ cell * MFD _ cell;/* archspecificadditions */struct pdev _ archdataarchdata; (; 启动函数调用进程开发板平台设备进程设备树板级别:

dt_machine_start(imx6ul,' Freescale I.MX6ultralite (设备树) ).map_io=imx6ul_map_io, init_ . init _ machine=imx6ul _ init _ machine, init_late=imx6ul_init_late, dt_compat=imx6ul_dt_compat

静态void _ initi MX6ul _ init _ machine (void ) {结构设备* parent; parent=imx_soc_device_init (; if(parent==null ) pr _ warn (' failedtoinitializesocdevicen ' ); of _ platform _ default _ populate (null、null、parent ); imx6ul_enet_init (; imx_anatop_init (; imx6ul_pm_init (;

}

在下面的包裹函数中会调用创建平台设备的开始函数。

int of_platform_default_populate(struct device_node *root, const struct of_dev_auxdata *lookup, struct device *parent){ return of_platform_populate(root, of_default_bus_match_table, lookup, parent);}EXPORT_SYMBOL_GPL(of_platform_default_populate);

在下面的函数中会遍历root节点下的所有子节点,分别调用of_platform_bus_create()来创建平台设备。

drivers/of/platform.c:int of_platform_populate(struct device_node *root, const struct of_device_id *matches, const struct of_dev_auxdata *lookup, struct device *parent) {... for_each_child_of_node(root, child) { rc = of_platform_bus_create(child, matches, lookup, parent, true); if (rc) { of_node_put(child); break; } }...}

核心函数,这个函数的主要作用是为节点和它的子节点创建设备。

static int of_platform_bus_create(struct device_node *bus, const struct of_device_id *matches, const struct of_dev_auxdata *lookup, struct device *parent, bool strict){... /* Make sure it has a compatible property * /* 检查属性,上面的注释很明确的说明了需要有“compatible”属性。*/ if (strict && (!of_get_property(bus, "compatible", NULL))) { pr_debug("%s() - skipping %pOF, no compatible propn", __func__, bus); return 0; } /* 2.填充相关信息 */ auxdata = of_dev_lookup(lookup, bus); if (auxdata) { bus_id = auxdata->name; platform_data = auxdata->platform_data; } /* 3.创建平台设备 */ dev = of_platform_device_create_pdata(bus, bus_id, platform_data, parent); /* 4.递归调用本函数为子节点创建平台设备 */ for_each_child_of_node(bus, child) { rc = of_platform_bus_create(child, matches, lookup, &dev->dev, strict);... }...}

函数调用过程简览:

of_platform_populate(){-->of_platform_bus_create()-->of_platform_device_create_pdata()-->of_device_alloc()-->of_msi_configure()-->of_platform_bus_create()} 对比设备树和设备信息

首先查看设备树中关于lcd接口的信息:

再查看sysfs文件系统下面的platform的信息:

然后再查看lcdif的的设备树节点信息:

最后查看下clock-names,发现和我们的设备树信息是一致的。

总结 在设备树中描述的平台设备信息,会在内核代码中自动展开,生成对应的平台设备信息,添加到设备链表中。自动转换成平台设备的条件:
该节点必须含有compatible属性
根节点的子节点(节点必须含有compatible属性),也即根节点下含有compatible属性的子节点。
含有特殊compatible属性的节点的子节点(子节点必须含有compatible属性): 这些特殊的compatilbe属性为: “simple-bus”,“simple-mfd”,“isa”,“arm,amba-bus”不转化的条件:
1.根节点下子节点,没有上边的那4种属性,那么该子节点的子节点都不转化。
2.总线I2c,SPI节点下的子节点,由对应的总线驱动程序处理,不转化。
3.根节点是例外的,生成platfrom_device时,即使有compatible属性也不会处理。
注意:i2c, spi等总线节点会转换为platform_device,但是,spi、i2c下的子节点无论compatilbe是否为: “simple-bus”,“simple- mfd”,“isa”,"arm,amba-bus "都应该交给对应的总线驱动程序来处理而不会被转换为platform_device。 测试代码 /* mydrv.c */#include <linux/init.h>#include <linux/module.h>#include <linux/platform_device.h>#include <linux/property.h>//产生一个for循环用于检查所有的子节点#define device_for_each_child_node(dev, child) for (child = device_get_next_child_node(dev, NULL); child; child = device_get_next_child_node(dev, child))int myprobe(struct platform_device *pdev){ struct fwnode_handle *fwhandle; const char *str; u32 val; //获取设备子节点的个数 printk("child node count : %dn", device_get_child_node_count(&pdev->dev)); //获取设备属性autorepeat的值 printk("%dn", device_property_read_bool(&pdev->dev, "autorepeat")); //遍历设备的每个子节点 device_for_each_child_node(&pdev->dev, fwhandle) { //获取设备子节点的label属性值 fwnode_property_read_string(fwhandle, "label", &str); printk("label = %sn", str); //获取设备子节点的code属性值 fwnode_property_read_u32(fwhandle, "code", &val); printk("code = %xn", val); }; return 0;}int myremove(struct platform_device *pdev){ printk("in myremove ...n"); return 0;}struct of_device_id ids[] = { {.compatible = "mynodes"}, {},};struct platform_driver mydrv = { .probe = myprobe, .remove = myremove, .driver = { .owner = THIS_MODULE, .name = "mydrv" , .of_match_table = ids, },};module_platform_driver(mydrv);MODULE_LICENSE("GPL"); 参考

1.参考博文

版权声明:该文观点仅代表作者本人。处理文章:请发送邮件至 三1五14八八95#扣扣.com 举报,一经查实,本站将立刻删除。