Linux内核必备知识点 platform_driver( 二 )


void (*release)(struct device *dev);不能是空 。
2.如何注册向注册平台驱动的步骤
1)注册设备平台_设备_注册
/** * platform_device_register - add a platform-level device * @pdev: platform device we're adding */int platform_device_register(struct platform_device *pdev){ device_initialize(&pdev->dev); arch_setup_pdev_archdata(pdev); return platform_device_add(pdev);}2)注册驱动平台_驱动程序_注册
#define platform_driver_register(drv) \ __platform_driver_register(drv, THIS_MODULE)三 。例子1.开发步骤平台总线下驱动程序的开发步骤如下:
装备要实现的结构是:平台_设备 。
1)初始化资源结构变量
2)初始化平台_设备结构变量
3)向系统注册设备:平台_设备_注册 。
在加载设备驱动之前,也就是在执行platform_driver_register()之前,必须完成以上三个步骤,因为驱动注册需要匹配内核中所有注册的设备名称 。
将platform_driver_register()中的device添加到内核最终调用的device_add函数中 。
Platform_device_add和device_add的主要区别在于多了一步insert_resource(p,r),即把平台资源加入内核,由内核管理 。
驱动器在驱动注册中,要实现的结构是:platform_driver 。
在驱动程序的初始化函数中,调用了platform_driver_register()来注册platform_driver 。
需要注意的是,platform_driver和platform_device中name变量的值必须相同【不考虑设备树,我们后面会写一篇关于设备树的新文章】 。
这样,当注册platform_driver_register()时,当前注册的platform_driver中的name变量的值将与所有注册的platform_devices中的name变量的值进行比较 。只有找到同名的platform _ device才能注册成功 。
注册成功后,将调用platform_driver结构元素的探针函数指针 。
示例1这个例子比较简单,只用来测试platform_driver和platform_device是否能匹配成功 。

左边是platform_device结构注册的代码,右边是platform_driver结构注册的代码 。
平台_驱动程序定义和注册:
1 #include2 #include3 #include4 #include56 static int hello_probe(struct platform_device *pdev)7 {8printk("match ok \n");9return 0; 10 } 11 staticint hello_remove(struct platform_device *pdev) 12 { 13printk("hello_remove \n"); 14return 0; 15 } 16 static struct platform_driver hello_driver = 17 { 18.probe = hello_probe, 19.driver.name = "duang", 20.remove = hello_remove,21 }; 22 static int hello_init(void) 23 { 24printk("hello_init \n"); 25return platform_driver_register(&hello_driver); 26 } 27 static void hello_exit(void) 28 { 29printk("hello_exit \n"); 30platform_driver_unregister(&hello_driver); 31return; 32 } 33 MODULE_LICENSE("GPL"); 34 module_init(hello_init); 35 module_exit(hello_exit);平台_设备定义和注册:
1 #include2 #include3 #include4 #include56 static void hello_release(struct device *dev)7 {8return;9 } 10 static struct platform_device hello_device = 11 { 12.name = "duang", 13.id = -1, 14.dev.release = hello_release, 15 }; 161718 static int hello_init(void) 19 { 20printk("hello_init \n"); 21return platform_device_register(&hello_device); 2223 } 24 static void hello_exit(void) 25 { 26printk("hello_exit \n"); 27platform_device_unregister(&hello_device); 28return; 29 } 30 MODULE_LICENSE("GPL"); 31 module_init(hello_init); 32 module_exit(hello_exit);这个程序只是用来测试平台框架能否匹配成功 。struct platform _ Device hello _ Device不设置任何硬件信息 。
Makfile
1 ifneq ($(KERNELRELEASE),)2 obj-m:=device.o driver.o3 else4 KDIR :=/lib/modules/$(shell uname -r)/build5 PWD:=$(shell pwd)6 all:7make -C $(KDIR) M=$(PWD) modules8 clean:9rm -f *.ko *.o *.mod.o *.symvers *.cmd*.mod.c *.order 10 endifmakefile可以同时将两个C文件编译成ko文件 。
编译:
编辑和翻译
生成的文件:

输入程序片
清空log信息sudo dmesg -c
匹配成功
示例2在结构platform_device中加入硬件信息,可以在内核中读出 。此示例将以下信息添加到结构hello_device中:
基址寄存器0x139d0000的地址是0x4,在空之间 。
199号中断【注意】在实际内核中,会根据HW id计算出一个新的中断号(通常soc厂商的设备为soc时,会为每个中断源定义一个唯一的id),这个中断号会被cpu识别 。
设备. c
struct resource res[]={ [0] ={.start = 0x139d0000,.end= 0x139d0000 + 0x3,.flags = IORESOURCE_MEM, }, [1] ={.start = 199,.end= 199,.flags = IORESOURCE_IRQ, }, };static struct platform_device hello_device = { .name = "duang", .id = -1, .dev.release = hello_release,.num_resources = ARRAY_SIZE(res), .resource = res,};司机. c
static int hello_probe(struct platform_device *pdev){ printk("match ok \n"); printk("mem = %x \n",pdev->resource[0].start); printk("irq = %d \n",pdev->resource[1].start); //注册中断、申请内存 return 0;}再次编译,卸载第一个示例的模块,并清除日志:


推荐阅读