设备驱动开发实验教程(5)_注册驱动到平台总线

        本文在已向平台总线注册设备“hello_ctl”的基础上展开,注册设备到平台总线的流程可参见上一篇(嵌入式Linux系统:驱动编程_注册设备到平台总线 )。

      在 Linux2.6 之后,Linux 设备驱动分为三个实体:总线、设备、驱动,平台总线将设备和驱动匹配。在系统注册任意一个驱动的时候,都会寻找对应的设备;当系统注册设备的时候,系统也会寻找对应的驱动进行匹配。

        在 Linux 系统中,任何一个 Linux 设备和 Linux 驱动都是需要挂载到一种总线中。有一些常规的大家容易理解的总线,例如 media 总线、spi 总线、hid 输入子系统总线、eMMC 存储设备总线等等。假如说设备本身就是一个总线设备,那么挂载到对应的总线上,那是容易理解的。

        但是还有一些例如 led、蜂鸣器等等一些设备,都不是从字面上理解的总线设备。针对这个情况,Linux 创立了一种虚拟总线,也叫平台总线或者 platform 总线,这个总线也有对应的设备 platform_device,对应的驱动叫 platform_driver。

        这里介绍的平台总线,不能够直接和常规的总线对应,只是 Linux 系统提供的一种附加手段,防止 linux 驱动的碎片化,降低 Linux 的使用难度。

        下图是总线、设备、驱动的框架图。

        这里只讨论先注册设备再注册驱动的情况。在注册驱动的时候,系统会通过 platform_match 函数匹配设备和驱动。
        注册设备的结构体为 platform_device,注册驱动的结构体为 platform_driver。设备和和驱动结构体的成员 name 字段,相同则匹配。如果匹配了则会调用 platform_driver 中的 probe 函数,注册驱动。也就是在上图注册驱动的时候要添加一个判断,如下图所示。

   

 

 

 

 

驱动注册——头文件

        驱动注册使用结构体platform_driver,该结构体在头文件“include/linux/platform_device.h”中定义。
        驱动注册platform_driver_register,驱动卸载函数platform_driver_unregister也在这个头文件中– 这两个函数的参数都只有结构体platform_driver。
 

驱动注册——注册结构体

        驱动常见的几种状态,初始化,移除,休眠,复位– 就像PC一样,有的驱动休眠之后无法使用,有的可以使用;有的系统唤
醒之后,驱动需要重新启动才能正常工作,也有直接就可以使用等等。

        probe函数– platform_match函数匹配之后,驱动调用的初始化函数。

        remove函数– 移除驱动函数。 

        suspend函数– 悬挂(休眠)驱动函数。

        resume函数– 休眠后恢复驱动。

        device_driver数据结构的两个参数:– name和注册的设备name要一致;– owner一般赋值THIS_MODULE。

 

 

 

        如下,是完整的注册驱动到平台总线的代码:probe_linux_module.c

        以下代码实现的功能是将驱动“hello_ctl”注册到平台总线,前提是已将设备“hello_ctl”注册到平台总线(见博文:嵌入式Linux系统:驱动编程_注册设备到平台总线 )。

#include <linux/init.h>
#include <linux/module.h>

/*驱动注册的头文件,包含驱动的结构体和注册和卸载的函数*/
#include <linux/platform_device.h>

#define DRIVER_NAME "hello_ctl"

MODULE_LICENSE("Dual BSD/GPL");
MODULE_AUTHOR("santiren");

static int hello_probe(struct platform_device *pdv){
	
	printk(KERN_EMERG "\tinitialized\n");
	
	return 0;
}

static int hello_remove(struct platform_device *pdv){
	
	return 0;
}

static void hello_shutdown(struct platform_device *pdv){
	
	;
}

static int hello_suspend(struct platform_device *pdv){
	
	return 0;
}

static int hello_resume(struct platform_device *pdv){
	
	return 0;
}

struct platform_driver hello_driver = {
	.probe = hello_probe,
	.remove = hello_remove,
	.shutdown = hello_shutdown,
	.suspend = hello_suspend,
	.resume = hello_resume,
	.driver = {
		.name = DRIVER_NAME,
		.owner = THIS_MODULE,
	}
};


static int hello_init(void)
{
	int DriverState;
	
	printk(KERN_EMERG "HELLO WORLD enter!\n");
	DriverState = platform_driver_register(&hello_driver);
	
	printk(KERN_EMERG "\tDriverState is %d\n",DriverState);
	return 0;
}

static void hello_exit(void)
{
	printk(KERN_EMERG "HELLO WORLD exit!\n");
	
	platform_driver_unregister(&hello_driver);	
}

module_init(hello_init);
module_exit(hello_exit);

        代码中,定义的宏变量 DRIVER_NAME  “hello_ctl”,和前面注册的 hello 设备的名称相同。

        设备和驱动匹配成功就会进入函数 hello_probe 打印“initialized”。

 

 

        Makefile 文件如下图所示。

       

        在 Ubuntu 中的目录“/home/topeet”中新建目录“probe_linux_module”,拷贝驱动文件“probe_linux_module.c”和编译文件“Makefile”到新建中,如下图所示。

       

        进入“probe_linux_module”目录,使用命令“make”编译“probe_linux_module.c”,如下图所示,生成模块文件“probe_linux_module.ko”。

 

        启动开发板,拷贝“probe_linux_module.ko”到 U 盘,将 U 盘插入开发板,加载驱动文件“probe_linux_module.ko”,如下图所示,可以看到打印出了“initialized”,表明进入了probe 函数。

 

        使用命令“rmmod probe_linux_module”卸载驱动,可以看到打印“HELLO WORLD exit!”,表明卸载成功。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值