例程代码路径:ELF 1开发板资料包3-例程源码3-2 驱动例程源码6_platformplatform
示例源码
#include <linux/init.h>
#include <linux/module.h> #include <linux/platform_device.h> static int my_platform_probe(struct platform_device *pdev) { printk(KERN_INFO "my_platform_probe: Platform device probedn"); return 0; } static int my_platform_remove(struct platform_device *pdev) { printk(KERN_INFO "my_platform_remove: Platform device removedn"); return 0; } static const struct of_device_id of_platform_match[] = { { .compatible = "platform", }, {}, }; static struct platform_driver my_platform_driver = { .driver = { .name = "my_platform_driver", .owner = THIS_MODULE, .of_match_table = of_platform_match, }, .probe = my_platform_probe, .remove = my_platform_remove, }; module_platform_driver(my_platform_driver); MODULE_LICENSE("GPL"); MODULE_AUTHOR("Your Name"); MODULE_DESCRIPTION("Platform Driver Example"); |
上述示例定义了一个名为 "my_platform_driver" 的平台驱动程序。驱动程序中的 my_platform_probe() 函数是探测函数,my_platform_remove() 函数是移除函数。还定义了一个platform_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); int (*resume)(struct platform_device *); struct device_driver driver; const struct platform_device_id *id_table; bool prevent_deferred_probe; }; |
定义说明:
(一)probe:驱动探测函数指针,当设备与驱动匹配时调用。它接收一个指向structplatform_device的指针作为参数,返回一个整数类型的值。
(二)remove:驱动移除函数指针,当设备被移除时调用。它接收一个指向structplatform_device的指针作为参数,返回一个整数类型的值。
(三)shutdown:关机回调函数指针,当系统关机时调用。它接收一个指向struct platform_device的指针作为参数,无返回值。
(四)suspend:挂起回调函数指针,当系统进入挂起状态时调用。它接收一个指向struct platform_device的指针和pm_message_t类型的参数作为输入,返回一个整数类型的值。
(五)resume:恢复回调函数指针,当系统从挂起状态恢复时调用。它接收一个指向struct platform_device的指针作为参数,返回一个整数类型的值。
(六)driver:包含了驱动的名称、拥有者等信息的 struct device_driver 结构体。
(七)id_table:一个指向平台设备ID表的指针,用于与设备匹配。它可以为空,或者指向一个以NULL结尾的数组。
(八)prevent_deferred_probe:一个布尔值,用于指示是否禁止推迟的探测。如果设置为true,则在设备匹配时不会推迟探测过程。
通过使用module_platform_driver宏,我们可以将驱动程序的注册和注销过程简化为一行代码。宏会自动为驱动程序注册和注销函数,并处理必要的初始化和清理工作。
需要注意的是,驱动程序中的probe和remove回调函数必须与平台驱动程序的结构体字段对应,以正确地处理设备的探测和移除。
of_platform_match[]数组中定义了设备兼容性匹配项,当内核在设备初始化过程中加载驱动时,会遍历设备树中的设备节点,并将每个设备节点的compatible属性与驱动中的兼容属性进行匹配。只有当匹配成功时,才会执行相应的probe函数。
编译
复制上一节驱动中的Makefile文件,将其中的myirq_key.o修改为platform.o,效果如下:
. /opt/fsl-imx-x11/4.1.15-2.0.0/environment-setup-cortexa7hf-neon-poky-linux-gnueabi
elf@ubuntu:~/work/test/06_platform/platform$ make |
将编译生成的platform.ko模块拷贝到开发板中
修改设备树
在设备树根节点下添加设备,否则无法进行匹配。打开arch/arm/boot/dts/imx6ull-elf1-emmc.dts添加如下内容:
my_device {
compatible = "platform"; }; |
添加后效果如下:
编译设备树,单独替换设备树并重启。
测试
root@ELF1:~# insmod platform.ko
my_platform_probe: Platform device probed root@ELF1:~# rmmod platform.ko my_platform_remove: Platform device removed |
可以看到在驱动加载时,进入到了probe函数,在驱动卸载时进入到了remove函数。从上面示例中可以了解到使用 module_platform_driver 宏可以大大简化平台驱动程序的编写过程,并提高代码的可读性和可维护性。