本节知识点:
基础知识:
1.把最近学的东西串串线,首先学的是kobject,这个东西是在sysfs文件系统中,创建一个目录的基类,在这点上linux有着面向对象的编程思想,也就是什么kset,总线,platform都是继承了kobject的特性,在sys目录中创建目录。
2.学习kobject和kset是为了学习总线设备驱动模型的,因为创建总线,设备,驱动实际就是在/sys/bus目录中创建kobject,其实质也是kobject和kset完成的。
3.platform平台总线驱动模型,其实就是linux内核把,上节那个总线设备驱动模型进行了封装。把本应该自己创建的一条总线,变成了linux替你创建好的一条platform总线而已。
4.这里有一个很迷茫的一点就是,这个platform平台总线驱动模型到底有什么用??我现在的理解是这样的,希望在读了宋宝华的linux设备驱动之后还有体会。
第一:platform将设备本身的资源注册进入内核,由内核统一管理,在驱动程序使用这些资源的时候使用统一的接口,提高驱动的可移植性。
第二:这是一个很常用的驱动模型,也叫框架吧,linux设备驱动 叫他是工程中的驱动。
第三:这模型仅仅是将驱动和设备分开,然后当有新设备或者新驱动的时候,去匹配,匹配成功再调用driver模块中的probe函数,完成具体的驱动程序。也就是说platform仅仅是一个框架,功能驱动在probe函数里面,是字符驱动,还是块驱动啊 都是在probe函数里面完成。
驱动结构及重要函数:
在platform_device里面:
1.在struct platform_device结构体中 填写设备名称,id,设备资源结构,或者通过struct platform_device *platform_device_alloc(const char *name,int id)函数来定义platform_device
2.platform_device_register(&led_dev)注册平台设备进入内核
在platform_driver里面:
1.在struct platform_driver led_drv={
.probe=led_drv_probe,
.remove=led_drv_remove,
.driver={
.owner=THIS_MODULE,
.name="plat_led", //platform总线 里面驱动的名字 这个名字要和设备的名字一样
}
};里面定义 驱动名字 ,probe函数等
2.利用platform_driver_register(&led_drv) 注册驱动进入内核
其实国嵌在这里的时候看了内核代码的,有几个结论如下:
1.platform总线,就是内核定义的一条总线,并且将他的设备和驱动进行了封装
2.找到了bus_for_each_dev, 这个函数是总线在不断的轮询总线中的dev设备,然后通过match函数,判断设备和驱动是否匹配
3.platform的match就是比较platform_device.name和platform_driver.driver.name
本节代码:
plat-dev.c:
#include <linux/device.h>
#include <linux/module.h>
#include <linux/kernel.h>
#include <linux/init.h>
#include <linux/string.h>
#include <linux/init.h>
#include <linux/platform_device.h>
MODULE_AUTHOR("Hao");
MODULE_LICENSE("Dual BSD/GPL");
struct platform_device led_dev={
.name="plat_led", //platform总线 里面设备的名字 这个名字要和驱动的名字一样
.id=-1,
};
static int __init platform_led_dev_init(void)
{
int ret=0;
ret=platform_device_register(&led_dev);
if(ret)
{
printk("platform_device_register failed!!\n");
}
return ret;
}
static void __exit platform_led_dev_exit(void)
{
platform_device_unregister(&led_dev);
}
module_init(platform_led_dev_init);
module_exit(platform_led_dev_exit);
plat-drv.c:
#include <linux/device.h>
#include <linux/module.h>
#include <linux/kernel.h>
#include <linux/init.h>
#include <linux/string.h>
#include <linux/init.h>
#include <linux/platform_device.h>
MODULE_AUTHOR("Hao");
MODULE_LICENSE("Dual BSD/GPL");
static int led_drv_probe(struct platform_device *dev) //这里面写功能驱动
{
printk("Driver found device which my driver can handle!\n");
return 0;
}
static int led_drv_remove(struct platform_device *dev)
{
printk("Driver found device unpluged!\n");
return 0;
}
struct platform_driver led_drv={
.probe=led_drv_probe,
.remove=led_drv_remove,
.driver={
.owner=THIS_MODULE,
.name="plat_led", //platform总线 里面驱动的名字 这个名字要和设备的名字一样
}
};
static int __init platform_led_drv_int(void)
{
return platform_driver_register(&led_drv);
}
static void __exit platform_led_drv_exit(void)
{
platform_driver_unregister(&led_drv);
}
module_init(platform_led_drv_int);
module_exit(platform_led_drv_exit);