以module的方式注册设备,并在驱动中调用设备的参数
在前面的博客我记录了如何注册设备和如何注册驱动,我们可以明显的看出设备的注册是很麻烦的,需要修改平台文件,需要配置menuconfig,需要重新编译内核,需要将编译好的zImage烧录到开发板,而驱动的注册就简单多了,只要执行insmod就可以了,那么在学习中有没有什么简单的注册设备的方式呢?有的,设备也可以作为module的方式来注册,虽然说做产品的话绝大多数还是会使用修改平台文件的方式,但是以module的方式来注册设备可以大大简化我们的学习过程,不用频繁的烧录内核
资料来源于网上和迅为提供的视频学习。
前面一节的设备注册使用的是CONFIG_HELLO_CTL的形式,通过结构体platform_device的调用直接配置,实现注册设备的功能。
本节通过直接调用的注册设备的函数来是其功能。
主要函数:
platform_device_register :drivers/base/platform.c
流程:
文件drivers/base/platform.c定义了设备的register函数,然后通过platform_device_add.
所以我们只需要会使用platform_device_register即可。
/**
* 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);
return platform_device_add(pdev);
}
EXPORT_SYMBOL_GPL(platform_device_register);
platform_device_unregister:同上
更详细的以后参考内核代码分析:
/**
* platform_device_unregister - unregister a platform-level device
* @pdev: platform device we're unregistering
*
* Unregistration is done in 2 steps. First we release all resources
* and remove it from the subsystem, then we drop reference count by
* calling platform_device_put().
*/
void platform_device_unregister(struct platform_device *pdev)
{
platform_device_del(pdev);
platform_device_put(pdev);
}
EXPORT_SYMBOL_GPL(platform_device_unregister);
还有一个结构体:platform_device,作为上面两个函数的使用参数,结构体类型具体如下:
下面的是调用具体函数的sample:
文件名:platform_device_test.c
#include <linux/init.h>
#include <linux/module.h>
#include <linux/platform_device.h>
static void leds_release(struct device *dev)
{
printk("leds_release\n");
}
struct platform_device platform_device_hello = {
.name = "my_code_led",
.id = -1,
.dev = {
.release = leds_release,
}
};
static int hello_init(void)
{
printk(KERN_EMERG "init \n");
platform_device_register(&platform_device_hello);
return 0;
}
static void hello_exit(void)
{
platform_device_unregister(&platform_device_hello); //unregister会查找release,如果找不到会报错
}
module_init(hello_init);
module_exit(hello_exit);
MODULE_LICENSE("Dual BSD/GPL");
MODULE_AUTHOR("NANZH");
编译
$ make
make -C /home/nan/iTOP4412/iTop4412_Kernel_3.0 M=/home/nan/iTOP4412/3 modules
make[1]: Entering directory '/home/nan/iTOP4412/iTop4412_Kernel_3.0'
CC [M] /home/nan/iTOP4412/3/platform_device_test.o
Building modules, stage 2.
MODPOST 1 modules
CC /home/nan/iTOP4412/3/platform_device_test.mod.o
LD [M] /home/nan/iTOP4412/3/platform_device_test.ko
make[1]: Leaving directory '/home/nan/iTOP4412/iTop4412_Kernel_3.0'
拷贝到开发板并查看
# insmod platform_device_test.ko
[ 544.778744] init
# ls /sys/devices/
platform/ system/ virtual/
# ls /sys/devices/platform/
my_code_led ...
至此达到和设备注册一中的mach-itop4412.c中注册方法达到相同的结果。
总结
1、除了最特殊的USB设备,其他的设备驱动,都徐亚驱动工程师注册设备,用module的方式注册设备只是为了方便学习和调试,在绝大多数情况下,都是以平台文件的方式统一在内核文件中来注册设备
2、驱动注册和设备注册都是将代码嵌入到Linux内核中,属于“对中”的部分(不是面向下层硬件,也没有对上层提供接口)
3、设备驱动中设备和驱动是分离的,无论是在平台文件中注册设备,还是以module的方式注册设备,设备都要优先驱动注册,否则驱动无法进入probe