一. 简介
前面一篇文章说明了 有设备树的plaform驱动实现思路,文章如下:
有设备树的plaform驱动注册实验:platform_driver驱动注册思路说明-CSDN博客
本文开始编写驱动代码,本文主要是实现 有设备树的platform驱动注册代码框架。
二. 有设备树的plaform驱动实验:platform_driver驱动注册框架
1. 创建工程 16_dtsplatform 目录
(1)创建 16_dtsplatform 工程目录,将 无设备树实验工程 16_platform拷贝到 16_dtsplatform 工程目录下:
wangtian@wangtian-virtual-machine:~/zhengdian_Linux/Linux_Drivers/16_dts_platform$ cp ../16_platform/* ./ -rf
(2)拷贝 16_platform工程下的 .vscode 拷贝到 16_dtsplatform 工程:
wangtian@wangtian-virtual-machine:~/zhengdian_Linux/Linux_Drivers/16_dts_platform$ cp ../16_platform/.vscode/ ./ -rf
(3)删除 platform_leddevice.c文件:
wangtian@wangtian-virtual-machine:~/zhengdian_Linux/Linux_Drivers/16_dts_platform$ rm platform_leddevice.c
删除 Makefile中编译 platform_leddevice.c的部分。涉及的一行如下:
obj-m := platform_leddriver.o
2. platform_driver驱动注册框架
注意:plaform_driver与设备树匹配时涉及 platform_driver中的 .driver的 .of_match_table成员, 假如这个成员中的最后要写一个空元素。
platform_leddriver.c文件实现 platform驱动注册代码框架后,代码如下:
#include <linux/kernel.h>
#include <linux/init.h>
#include <linux/fs.h>
#include <linux/uaccess.h>
#include <linux/io.h>
#include <linux/cdev.h>
#include <linux/device.h>
#include <linux/of.h>
#include <linux/of_address.h>
#include <linux/of_gpio.h>
#include <linux/types.h>
#include <linux/platform_device.h>
int platform_probe(struct platform_device * platform_dev)
{
printk("platform_probe!\n");
return 0;
}
int platform_remove(struct platform_device * platform_dev)
{
printk("platform_remove!\n");
return 0;
}
//of_device_id结构体,很重要!
struct of_device_id of_dev_id[] = {
//与设备树中Led节点的compatible一致,有设备树时驱动与设备匹配条件
{ .compatible = "alientek, gpioled", },
{/*Sentinel */},
};
//Platform_driver结构体
struct platform_driver plat_leddriver = {
.driver = {
.name = "imx6ull_led", //驱动名,在无设备树时驱动与设备匹配的条件
.of_match_table = of_dev_id,
},
.probe = platform_probe,
.remove = platform_remove,
};
/*模块加载 */
static int __init platform_driver_init(void)
{
//注册驱动
return platform_driver_register(&plat_leddriver);
}
/*模块卸载 */
static void __exit platform_driver_exit(void)
{
//卸载驱动
platform_driver_unregister(&plat_leddriver);
}
/*驱动加载与卸载 */
module_init(platform_driver_init);
module_exit(platform_driver_exit);
MODULE_LICENSE("GPL"); //模块 Licence
MODULE_AUTHOR("WeiWuXian"); //作者
三. 编译驱动代码
将上面驱动代码进行编译,编译成 .ko模块:
wangtian@wangtian-virtual-machine:~/zhengdian_Linux/Linux_Drivers/16_dts_platform$ make
make -C /home/wangtian/zhengdian_Linux/linux/kernel/linux-imx-rel_imx_4.1.15_2.1.0_ga M=/home/wangtian/zhengdian_Linux/Linux_Drivers/16_dts_platform modules
make[1]: 进入目录“/home/wangtian/zhengdian_Linux/linux/kernel/linux-imx-rel_imx_4.1.15_2.1.0_ga”
CC [M] /home/wangtian/zhengdian_Linux/Linux_Drivers/16_dts_platform/platform_leddriver.o
Building modules, stage 2.
MODPOST 1 modules
CC /home/wangtian/zhengdian_Linux/Linux_Drivers/16_dts_platform/platform_leddriver.mod.o
LD [M] /home/wangtian/zhengdian_Linux/Linux_Drivers/16_dts_platform/platform_leddriver.ko
make[1]: 离开目录“/home/wangtian/zhengdian_Linux/linux/kernel/linux-imx-rel_imx_4.1.15_2.1.0_ga”
wangtian@wangtian-virtual-machine:~/zhengdian_Linux/Linux_Drivers/16_dts_platform$
可以看出,驱动模块已正常编译通过。
接下来对驱动模块进行测试,测试 platform驱动是否与设备实现匹配。
这里对驱动模块进行加载测试后,当加载好 platform_leddriver.ko模块后,platfform_driver结构体的 .probe函数是运行的。
当卸载了 platform_leddriver.ko模块后,platfform_driver结构体的 .remove函数是运行的。说明驱动与设备已经匹配成功。
测试方法可以参考如下文章: