总览:

Koject & Kset

设备驱动模型

platform驱动程序

中断处理

按键驱动程序

 

1、platform总线:由两部分组成:platform_device和platform_driver

2、工作流程:

定义设备:platform_device

注册设备:platform_device

定义驱动:platform_driver

注册驱动:platform_driver

 

3、平台设备描述

struct platform_device {

  const char *name;

  int id;设备编号

  struct device dev;

  u32 num_resource;

  struct resource *resource; 设备资源这个参数比较重要,用来表示中断号还是GPIO地址

}

4、如何分配创建一个平台设备

struct platform_device *platfrom_device_alloc(const char *name, int fd);

创建完之后再赋值其他信息。

5、如何注册到内核

int platform_device_add(struct platform_device *pdev);

6、资源信息赋值

struct resource{

  resource_size_t start;

  resource_size_t end;

  const char *name;

  unsigned long flags;//资源类型 MEM IO IRQ等等

  struct resource *parent, sibing, *child;//资源链表信息

}

举例怎么赋值:

struct resource{ s3c_wet_resource1={
  .start = 0x44100000,
  .end = 0x44200000.
.  flags=OPRESOURCE_MEM,

}
struct resource{ s3c_wet_resource2={
  .start = 20,
  .end = 20.
.flags=OPRESOURCE_IRQ,

}

7、获取资源信息的接口

struct resource *platform_get_resource(struct platform_device *dev, unsigned int type, unsigned int num);

 

8、平台驱动

struct platform_driver{
  int (*probe)(struct platform_device*);
  int (*remove)(struct platform_driver*);  
  void (*shutdown)(struct platform_device *);
  int (*suspend)(struct platform_device *,pm_messgae_t state);
  ...
  int (*resume_early)(struct platform_device*)
  int (*resume)(struct platform_device *);
  struct device_driver driver;
}

9、平台驱动注册

int platform_driver_register(struct platform_driver * pdriver)

10、创建实例

(1)注册平台驱动

#include <linux/device.h>
#include <linix/module.h>
#include <linux/kernel.h>
#include <linux/init.h>
#include <linux/string.h>
#include <linux/platform_device.h>

MODULE_LICENSE("GPL");

int my_probe(struct device *dev)
{
    printk("driver found device which my driver can handle\n");
}

int my_remove(struct device *dev)
{
    printk("driver found device remove~\n");
}
struct platform_driver my_driver={
    .probe        = my_probe,
    .remove        = my_remove,
    .driver        = {
        .owner    =THIS_MODULE,
        .name    "my_dev",
    },
};

int __init my_driver_init(void)
{
    return platform_driver_register(&my_driver);
}

void __exit my_driver_exit(void)
{
    platform_driver_unregister(&my_driver);
}

module_init(my_driver_init);
module_exit(my_driver_exit);

(2)注册平台设备

#include <linux/device.h>
#include <linix/module.h>
#include <linux/kernel.h>
#include <linux/init.h>
#include <linux/string.h>
#include <linux/platform_device.h>
MODULE_LICENSE("GPL");

struct platform_device *my_device;
int __init my_device_init(void)
{
    my_device = platform_device_alloc("my_dev",-1);
    platform_device_add(my_device);
}
void __exit my_device_exit(void)
{
    platform_device_unregister(my_device);
}

module_init(my_device_exit);
module_exit(my_device_exit);

(3)效果

insmod platform_dev.ko之后

注册平台设备之后,会在/sys/bus/platform/devices/生成my_dev文件

insmod platform_drv.ko

直接调用平台驱动的probe函数

注册平台驱动之后,会在/sys/bus/platform/drivers/生成my_dev文件

但是,/dev目录下没有设备文件,因为不确定你的设备文件是字符设备还是块设备还是网卡。

 

总结:

总线,驱动,设备之间的关系?专题2-总线设备驱动模型-总线设备驱动模型 - 六月下大雨 - 博客园 (cnblogs.com)
在总线的学习中,我们知道总线模型分为三步:注册总线(struct bus_type my_bus_type),注册驱动(strucrt device_driver *drv),注册设备(struct device *dev)
引申到平台总线(struct bus_type platform_bus_type),平台驱动(struct platform_driver *drv),平台设备(struct platform_device *my_device;)之间的关系?
1、平台总线有一个match函数,需要平台设备和驱动设备作为入参进行匹配。
2、平台驱动里面有一个driver_device,和平台设备之间需要名字一样进行匹配。
3、平台设备的添加实际上是驱动设备的注册,

平台驱动是什么时候注册的?如何注册的?

#define platform_driver_register(drv) \
    __platform_driver_register(drv, THIS_MODULE)
int __platform_driver_register(struct platform_driver *drv,
                struct module *owner)
{
    drv->driver.owner = owner;
    drv->driver.bus = &platform_bus_type; //平台总线结构体
    drv->driver.probe = platform_drv_probe;
    drv->driver.remove = platform_drv_remove;
    drv->driver.shutdown = platform_drv_shutdown;
    return driver_register(&drv->driver); //注册设备驱动实际上就是之前的driver_register(&my_driver);
}

总线设备结构体是在内核中已经有的定义,注册平台驱动的时候,需要把自己的平台驱动挂载在平台总线上。当平台驱动加载的时候,实际上是调用了平台总线上的probe函数,在注册平台驱动的时候,把平台驱动的probe函数被赋值了平台总线的probe函数。

int driver_register(struct device_driver *drv)
{
    int ret;
    struct device_driver *other;
    other = driver_find(drv->name, drv->bus);
    ret = bus_add_driver(drv);
    ret = driver_add_groups(drv, drv->groups);
    kobject_uevent(&drv->p->kobj, KOBJ_ADD);
    return ret;
}