linux主要有三种驱动框架:
##1.传统方法 2.设备总线驱动模型 3.设备树。
这三种方法共同点:分配,设置,注册file_operation结构体。
差异:如何指定硬件资源,如led引脚是哪个。
1.1传统方法:在驱动程序代码中写死硬件资源
1.2设备总线驱动模型:把驱动程序分为两部分。(platform_driver ,platform_device)。在platform_device指定硬件资源,在platform_driver中分配,设置,注册file_operation结构体。并从platform_device获取硬件资源。
1.3 设备树:设备树把驱动程序分成两部分。(platform_driver ,设备树)。在设备树*.dts中指定硬件资源。.dts是设备树的源文件,会被编译成.dto。在设备启动时,boootloader会把dto文件传给内核。内核根据dto会分配,设置,注册file_operation结构体。
##2.编写驱动程序中常用的接口。
register_chrdev(major, name, &fops);//向内核注册file_operation结构体。
unregister_chardev;//从内核注销file_operation
##3.设备树转换成platform_device的流程:
dts->dto->device_node->platform_device
dts是设备树的源文件,通过交叉编译生成dto文件。在设备启动的时候有bootloader传给内核。内核将dto文件先转换成device_node结构体,对于某些device_node结构体再转换platform_device结构体。
3.1需要转换成platform_device结构体的device_node结构体:
(下面是网络上找的笔记 :https://blog.csdn.net/Adrian503/article/details/105765062 )
a.根节点下含有compatile属性的子节点(一级子节点)。
b.含有特定compatile属性的节点的子节点(二级节点)
如果一个节点的compatile属性包含“simple-bus”,“simple-mfd”,“isa”,"arm amba-bus"之一,那么它的子节点(需有compatile属性)也可以转换为platform_device结构体
例子:
/ {
mytest {
compatile = “mytest”, “simple-bus”;
mytest@0 {
compatile = “mytest_0”;
};
};
}
/:根节点
mytest:一级节点
mytest@0:二级节点。根据规则,都可以转换成platform_device结构体。
c.总线i2c,spi节点下的子节点不转换为platform_device。某个总线下到子节点,应该交给对应的总线驱动程序来处理, 它们不应该被转换为platform_device。
例子:
/ {
i2c {
compatile = "samsung,i2c";
at24c02 {
compatile = "at24c02";
};
};
spi {
compatile = "samsung,spi";
flash@0 {
compatible = "winbond,w25q32dw";
spi-max-frequency = <25000000>;
reg = <0>;
};
};
};
i2c的节点表示i2c控制器。它会被转换为platform_device, 在内核中有对应的platform_driver;/i2c/at24c02节点不会被转换为platform_device, 它被如何处理完全由父节点的platform_driver决定, 一般是被创建为一个i2c_client。
##4.platform_device如何与platform_driver 匹配呢?
a.是否强制选择某个驱动。
设置platform_device.driver_overwrite成某个platform_driver.driver.name。强制使用某个驱动。
b.使用设备树信息判断dev和drv是否匹配:顺序为conpatile->type->name属性。
c.比较platform_device. name和platform_driver.id_table[i].name
d.platform_device.name 和 platform_driver.driver.name