平台设备总线
平台设备总线是内核虚拟的一条总线,早期没有设备树时,通过名字匹配设备信息,如今有设备树通过设备树里的complitable属性匹配,下图是平台设备总线的结构体描述。
much函数是完成信息匹配的,
总线就是使用 match函数来根据注册的设备来查找对应的驱动,或者根据注册的驱动来查找相应的设备,因此每一条总线都必须实现此函数。 match函数有两个参数: dev和 drv,这两个参数分别为 device和 device_driver类型,也就是设备和驱动。
platform总线是bus_type的一个具体实例。
既然match是完成信息匹配的我们来重点关注这个函数
不难发现,先通过of方法匹配设备树里的 节点(通过compatible)不断往里跳
然后再匹配其他,最后通过name匹配。
下面是platform_driver结构体
这个我们是很熟悉的
probe函数,驱动和设备匹配成功以后会执行
driver成员,面向对象,device_driver为基类,platform_driver集成了这个基类并添加了一些特有的成员变量
of_match_table这个结构体我我们需要提供compatible 信息
由这个函数可以看出来(往里跳)
compatible非常重要,对于设备树而言,就是通过设备节点的compatiable属性值和of_match_table中每个项目的compatible成员变量进行比较,如果有相等的就表示设备和此驱动匹配成功
代码实现
定义一个平台驱动,实现probe和remove函数,分别在加载和卸载的时候会自动执行,
然后在driver里定义名子(一定要写,不然加载驱动会加载不上如下图),最后写出匹配表格
然后在 myprobe里实现 设备注册,在myremove里实现设备卸载
代码实列
#include "linux/device/class.h" #include "linux/gpio.h" #include "linux/of_gpio.h" #include "linux/platform_device.h" #include "linux/printk.h" #include <linux/module.h> #include "linux/device/driver.h" #include "linux/cdev.h" uint32_t pin1; uint32_t pin2; struct class *cls; struct cdev *cdev; static dev_t dev_num; static int open (struct inode *i, struct file *f) { gpio_set_value(pin1,0); gpio_set_value(pin2,0); return 0; } static int close (struct inode *i, struct file *f) { gpio_set_value(pin1,1); gpio_set_value(pin2,1); return 0; } struct file_operations fops={ .owner=THIS_MODULE, .open=open, .release=close, }; int myprobe(struct platform_device *a) { pin1=of_get_named_gpio(a->dev.of_node,"led_pin",0); pin2=of_get_named_gpio(a->dev.of_node,"led_pin",1); gpio_request(pin1,"led"); gpio_request(pin2,"led"); gpio_direction_output(pin1, 0); gpio_direction_output(pin2, 0); alloc_chrdev_region(&dev_num, 0, 1, "led"); cdev= cdev_alloc(); cdev->ops=&fops; cdev_add(cdev, dev_num,1); cls= class_create(THIS_MODULE, "led"); device_create(cls,NULL,dev_num,NULL,"led"); return 0; } int myremove (struct platform_device *dev){ device_destroy(cls, dev_num); class_destroy(cls); unregister_chrdev_region(dev_num,1); gpio_free(pin1); gpio_free(pin2); printk(KERN_INFO "Goodbye, world!\n"); return 0; } static struct of_device_id mymatch={ .compatible="led", }; struct platform_driver driver={ .probe=myprobe, .remove=myremove, .driver={ .name="led", .of_match_table=&mymatch, }, }; static int __init start(void) { platform_driver_register(&driver); printk("hahaa\r\n"); return 0; } static void __exit stop(void) { platform_driver_unregister(&driver); printk("gun\r\n"); } module_init(start); module_exit(stop); MODULE_LICENSE("GPL");