《驱动设计的思想:总线设备驱动模型》
1.分离分层的缺点
上一节通过分离的思想将led的硬件相关的放在led_source结构体,然后在led相关的驱动里面只需要调用这个结构体就可以,实现了驱动和硬件分离。
那么如果要做按键驱动,那么就要有一个key_source结构体。再做lcd驱动,还要有一个lcd_source结构体。
因此可以定义一个总的结构体platform_device。通过这个结构体来定义其他led_device,lcd_device等。
同样的道理,定义一个总的结构体platform_driver。通过这个结构体来实现驱动相关的操作。
2.总线设备驱动模型
通过上面引出了platform_device和platform_driver两个结构体,那么内核怎么将这两个结构体对应起来呢?
这就引出了总线的概念。
通过总线可以将platform_device和platform_drive两个结构体进行匹配。现在先讲个概念,后面再详细讲解。、
3.总线设备驱动模型的优缺点
优点:容易扩展,可以通过platform_device延伸出不同的外设结构。
缺点:当用platform_device定义一个led_device,那么就会有一个led_dev.c。如果再有一个lcd_device,还会有一个lcd_dev.c。而且对应不同的板卡,还会有不同的led.c以及lcd.c。这样源文件都在存放在linux内核中的,随着板卡的增多,这些文件也会越来越多。而且当我们修改一下相关的硬件资源,就要重新编译对应的.c文件。导致内核中有一堆重复的代码。
导致这一缺点的主要原因是:通过.c文件来定义platform_device。
解决方法:在内核外面,给每个单板都定义一个配置文件dts,也就是设备树。
4.设备树
dts文件里面会指定该单板的硬件资源。比如led使用哪个引脚,按键使用哪个引脚。
dts文件会被编译成dtb文件(二进制),然后传递给内核。内核根据dtb文件再构造出一系列的platform_device。这样就不需要我们自己去沟通每个platform_device结构体。
5.platform_device和platform_driver匹配
在第二点中指出,总线可以将platform_device和platform_drive两个结构体进行匹配。这总线就是platform_bus_type。其中platform_match就是用来匹配drv和dev。
当定义一个platform_device之后,要通过platform_register向内核注册,内核会将该platform_device放入一个dev的链表中。通过总线去drv链表中去一一匹配。当匹配成功,就会调用drv中的probe函数。
当定义一个platform_driver之后,也要通过platform_register向内核注册,内核会将该platform_driver放入一个drv的链表中。通过总线去dev链表中去一一匹配。当匹配成功,就会调用drv中的probe函数。
匹配的规则是:
首先需要搞清楚匹配用到的数据结构。
在platform_device结构体中name以及driver_override和platform_driver结构体中driver(是个结构体,里面有成员name)以及id_table(是一个数组,用来表示该驱动支持的所有设备)
1.如果platform_device中有定义driver_override,那么就会跟platform_driver中的driver中的name进行匹配。
2.如果没有定义driver_override,就会将platform_device中的name跟platform_driver中的id_table进行匹配。
3.如果id_table为空,就会比较platform_device中的name和platform_driver中的driver中的name。