Linux驱动——函数浅析(二)

我在人间凑数的日子

在Linux驱动中设备树用于指定硬件的信息。
开发板加载时,u-boot 先运行,它的作用是启动内核。U-boot 会把内核和设备树文件都读入内存,然后启动内核。在启动内核时会把设备树在内存中的地址告诉内核。
当设备树节点被转换成platform_device

浅谈platform_device 如何与 platform_driver 匹配

platfrom_device
可用于指定设备资源

struct platform_device {
	const char*name;
	int    id;
	bool   id_auto;
	struct device dev;
	u32 num_resources;
	struct  resource   *resource;
	const  struct platform_device_id   *id_entry;
	char  *driver_override; /* Driver name to force a match */
	/* MFD cell pointer */
	struct mfd_cell *mfd_cell;
	/* arch specific additions */
	struct pdev_archdata      archdata;
};

platfrom_driver

struct platform_driver {
	int (*probe)(struct platform_device *);
	int (*remove)(struct platform_device *);
	void (*shutdown)(struct platform_device *);
	int (*suspend)(struct platform_device *, pm_message_t state);
	int (*resume)(struct platform_device *);
	struct device_driver driver;
	const struct platform_device_id *id_table;
	bool prevent_deferred_probe;
};

在驱动的入口函数中注册platform_driver 结构体,platfrom_device结构体。
匹配规则

最先比较的:
platform_device. driver_override 和 platform_driver.driver.name
然后比较:
platform_device. name 和 platform_driver.id_table[i].name
最后比较:
platform_device.name 和 platform_driver.driver.name

关于函数的调用关系分析及需要查看Linux源码,逐步分析;
可以得出的结论是:当dev和drv匹配时,自动调用drv的probe函数。

常用的函数:
platform_device_register (参数为一个platform_device 结构体)
platform_driver_register (参数为一个platform_driver结构体)
platform_get_resource(dev, type, num); 获取资源

浅谈设备树

设备树的基础
常用属性:
address-cells:address 要用多少个 32 位数来表示地址;

size-cells:size 要用多少个 32 位数来表示大小。

compatible:兼容,在设备树经内核解析后与drv匹配,用来指定内核中哪个 machine_desc 可以支持本设备

status :用于描述设备的状态,如:okay;disabled;fail等

reg:寄存器地址

设备树只允许有一个根节点,和许多子节点。

1、DTS在PC机(ubuntu中)被编译为DTB文件;

2、将DTB拷贝到开发板 /boot目录下,u-boot会将dtb文件传送给内核zImage;

3、内核将DTB文件中的每一个节点都转换成 struct device_node结构体;

4、将子节点中含有compatile 属性,若子节点中compatile属性的值为“simple-bus",“simple-mfd”,“isa”,“arm,amba-bus”,子节点的子节点也可转换成platform_device。

(ps:总线中I2C、SPI节点下的子节点不转换成platform_device)

对于如何转换这个问题,的比较复杂,能力有限,暂不能窥测。

设备树节点转换成platfrom_device后与platfrom_driver配对
根据这个分析

static int platform_match(struct device *dev, struct device_driver *drv)
{
	struct platform_device *pdev = to_platform_device(dev);
	struct platform_driver *pdrv = to_platform_driver(drv);

	/* Attempt an OF style match first */
	if (of_driver_match_device(dev, drv))
		return 1;

	/* Then try ACPI style match */
	if (acpi_driver_match_device(dev, drv))
		return 1;

	/* Then try to match against the id table */
	if (pdrv->id_table)
		return platform_match_id(pdrv->id_table, pdev) != NULL;

	/* fall-back to driver name match */
	return (strcmp(pdev->name, drv->name) == 0);
}

简单描述设备树与drv配对:
1、pdev.driver_overrided和pdrv.drv.name
2、比较设备树信息pdev.dev.of_node 和pdrv.drv.of_match_table
3、pdev.name和pdrv.id_table[].name
4、pdev.name和pdrv.name

得出的结论为:
使用platform_driver.driver_driver.of_device_id->compatible和设备树中的compatible进行匹配,所以想要添加驱动,只需要在设备树文件中添加节点,指定device的compatible,然后在代码中再指定driver的compatible即可完成匹配,执行probe函数。

最新修改时间:2020/7/12 17:00

你可能感兴趣的:(嵌入式的学习入门)