当前位置:首页 > 芯闻号 > 充电吧
[导读]一、总线模型 随着技术的不断进步,系统的拓扑结构也越来越复杂,对热插拔,跨平台移植性的要求也越来越高,2.4内核已经难以满足这些需求。为适应这种形势的需要,从Linux 2.6内核开始提供了全新的设备

一、总线模型
随着技术的不断进步,系统的拓扑结构也越来越复杂,对热插拔,跨平台移植性的要求也越来越高,2.4内核已经难以满足这些需求。为适应这种形势的需要,从Linux 2.6内核开始提供了全新的设备模型。

2.1 描述结构
在 Linux 内核中, 总线由 bus_type 结构表示, 定义在 struct bus_type { const char *name; /*总线名称*/ int (*match) (struct device *dev, struct device_driver *drv); /*驱动与设备的匹配函数*/ ……… }

int (*match)(struct device * dev, struct device_driver * drv); 当一个新设备或者新驱动被添加到这个总线时,该函数被调用。用于判断指定的驱动程序是否能处理指定的设备。若可以,则返回非零。

2.2 总线注册与注销
总线的注册使用如下函数 bus_register(struct bus_type *bus); 若成功,新的总线将被添加进系统,并可在/sys/bus 下看到相应的目录。 总线的注销使用: void bus_unregister(struct bus_type *bus);
3.1 描述结构
在 Linux内核中, 驱动由 device_driver结构表示。 struct device_driver { { const char *name; /*驱动名称*/ struct bus_type *bus; /*驱动程序所在的总线*/ int (*probe) (struct device *dev); ……… }

3.2 驱动注册与注销
 驱动的注册使用如下函数

int driver_register(struct device_driver *drv);  驱动的注销使用: void driver_unregister(struct device_driver *drv);

4.1 描述结构
在 Linux内核中, 设备由struct device结构表示。 struct device { { const char *init_name; /*设备的名字*/ struct bus_type *bus; /*设备所在的总线*/ ……… }

4.2 驱动注册与注销  设备的注册使用如下函数 int device_register(struct device *dev);  设备的注销使用: void device_unregister(struct device *dev);

5.编写代码
bus.c
#include
#include
#include
#include

MODULE_LICENSE("GPL");

int my_match(struct device *dev, struct device_driver *drv)
{
    return !strncmp(dev->kobj.name, drv->name, strlen(drv->name));
}

struct bus_type my_bus_type = {
    .name = "my_bus",
    .match = my_match,
};
EXPORT_SYMBOL(my_bus_type);

int my_bus_init()
{
    int ret;
    ret = bus_register(&my_bus_type);

    return ret;
}

void my_bus_exit()
{
    bus_unregister(&my_bus_type);

}

module_init(my_bus_init);
module_exit(my_bus_exit); device.c:
#include
#include
#include
#include

MODULE_LICENSE("GPL");

extern struct bus_type my_bus_type;

struct device my_device = {
    .init_name = "my_dev",
    .bus = &my_bus_type,
};

int my_device_init()
{
    int ret;
    ret = device_register(&my_device);
    return ret;
}

void my_device_exit()
{
    device_unregister(&my_device);
}

module_init(my_device_init);
module_exit(my_device_exit); device.c:
#include
#include
#include
#include

MODULE_LICENSE("GPL");

extern struct bus_type my_bus_type;

int my_probe(struct device *dev)
{
    printk("driver found the device it can handle!n");
    return 0;
}

struct device_driver my_driver = {
    .name = "my_dev",
    .bus = &my_bus_type,
    .probe = my_probe,
};

int my_driver_init()
{
    int ret;
    ret = driver_register(&my_driver);
    return ret;
}

void my_driver_exit()
{
    driver_unregister(&my_driver);
}

module_init(my_driver_init);
module_exit(my_driver_exit)
1.平台总线概述
平台总线(Platform bus)是linux2.6内核加入的一种虚拟总线,其优势在于采用了总线的模型对设备与驱动进行了管理,这样提高了程序的可移植性。
通过平台总线机制开发设备驱动的流程如图:


2.平台设备
平台设备使用struct platform_device来描述: struct platform_device { const char *name; /*设备名*/ int id; /*设备编号,配合设备名使用*/ struct device dev; u32 num_resources; struct resource *resource; /*设备资源*/ }
struct resource { resource_size_t start; resource_size_t end; const char *name; unsigned long flags; /*资源的类型*/ struct resource *parent, *sibling, *child; };
注册平台设备,使用函数: int platform_device_register(struct platform_device *pdev);
3.平台驱动 平台驱动使用struct platform_driver 描述: struct platform_driver { int (*probe)(struct platform_device *); int (*remove)(struct platform_device *); …… }
平台驱动注册使用函数: int platform_driver_register(struct platform_driver *);

将按键驱动修改为平台驱动模型
key_dev.c:
#include
#include
#include
#include

MODULE_LICENSE("GPL");

#define GPFCON 0x56000050

struct resource key_resource[] = {                                                             //设置资源,对应2440的芯片地址
    [0] = {
        .start = GPFCON,
    .end = GPFCON + 8,
    .flags = IORESOURCE_MEM,
        },
    [1] = {
        .start = IRQ_EINT0,
    .end = IRQ_EINT2,
    .flags = IORESOURCE_IRQ,
        },
};

struct platform_device key_device = {                                                           //这个是平台设备结构
    .name = "my-key",
    .id = 0,
    .num_resources = 2,
    .resource = key_resource,
};

int keydev_init()
{
    platform_device_register(&key_device);                                                  //注册平台设备
}

void keydev_exit()
{
    platform_device_unregister(&key_device);                                              //注销平台设备
}

module_init(keydev_init);
module_exit(keydev_exit); key_drv.c:
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include

MODULE_LICENSE("GPL");

#define GPFCON (volatile unsigned long*) 0x56000050
#define GPFDAT (volatile unsigned long*) 0x56000054

unsigned int *gpio_data;

struct work_struct *work1;
struct timer_list key_timer;
wait_queue_head_t key_q;

struct resource *res_irq;
struct resource *res_mem;
unsigned int *key_base;

unsigned int key_num = 0;

void key_timer_func(unsigned long data)
{
    unsigned int key_val;
    key_val = readw(key_base+1);
    if((key_val & 0x01) == 0)
    {
        key_num = 4;
    }
    else if((key_val& 0x02) == 0)
    {
        key_num = 1;
    }
    else if((key_val & 0x04) == 0)
    {
        key_num = 3;
    }
    else if((key_val & 0x10) == 0)
    {
        key_num = 2;
    }

    wake_up(&key_q);
}

void work1_func(struct work_struct *work)
{
    mod_timer(&key_timer, jiffies + HZ/10);
}

irqreturn_t key_int(int irq, void *dev_id)
{
    //1.检测是否发生了按键中断
    
    //2.清除已经发生的按键中断
  
    //3.提交下半部
    schedule_work(work1);

    return 0;
}

void key_hw_init()
{
    unsigned short data;
    
    data = readw(key_base);
    data &= ~0x33f;
    data |= 0x22a;
    writew(data, key_base);
}

int key_open(struct inode *inode, struct file *filp)
{
    return 0;
}

ssize_t key_read(struct file *filp, char __user *buf, size_t size, loff_t *pos)
{
    wait_event(key_q, key_num);

    printk("in kernel :key num is %dn",key_num);
    copy_to_user(buf, &key_num, 4);

    key_num = 0;

    return 4;
}

struct file_operations key_fops = {
    .open = key_open,
    .read = key_read,
};

struct miscdevice key_miscdev = {
    .minor = 200,
    .name = "tq2440key",
    .fops = &key_fops,
};

int key_probe(struct platform_device *pdev)
{
    int ret,size;
    
    
    ret = misc_register(&key_miscdev);
    
    if (ret !=0)
        printk("register fail!n");
    
    //注册中断处理程序
    
    res_irq = platform_get_resource(pdev, IORESOURCE_IRQ, 0);                                            //获取资源
    
    request_irq(res_irq->start,key_int,IRQF_TRIGGER_FALLING,"key",(void *)4);                          //设置中断
    request_irq(res_irq->end,key_int,IRQF_TRIGGER_FALLING,"key",(void *)3);
    
    //按键初始化
    res_mem = platform_get_resource(pdev, IORESOURCE_MEM, 0);
    size = (res_mem->end - res_mem->start) + 1;
    key_base = ioremap(res_mem->start, size);
    
    key_hw_init();
    
    //. 创建工作
    work1 = kmalloc(sizeof(struct work_struct),GFP_KERNEL);
    INIT_WORK(work1, work1_func);
    
    /* 初始化定时器 */
    init_timer(&key_timer);
    key_timer.function = key_timer_func;
    
    /* 向内核注册一个定时器 */
    add_timer(&key_timer);
    
    /*初始化等待队列*/
    init_waitqueue_head(&key_q);
    
    return 0;
}

int key_remove(struct paltform_device *pdev)
{
    misc_deregister(&key_miscdev);
    //注销中断处理函数
    //free_irq(IRQ_EINT0, 0);
    //free_irq(IRQ_EINT1, 0);
    //free_irq(IRQ_EINT2, 0);
    //free_irq(IRQ_EINT4, 0);
    return 0;
}

struct platform_driver key_driver = {                                                         //这里是平台驱动结构,与平台设备结构通过name进行对接
    .probe = key_probe,
    .remove = key_remove,
    .driver = {
        .owner = THIS_MODULE,
        .name = "my-key",
    },
};

static int button_init()
{
    return platform_driver_register(&key_driver);                                         //注册平台驱动
    
}

static void button_exit()
{
    platform_driver_unregister(&key_driver);                                               //注销平台驱动
}

module_init(button_init);
module_exit(button_exit);


阅读(40) | 评论(0) | 转发(0) | 0

上一篇:阻塞型驱动设计

下一篇:tty驱动程序架构

相关热门文章 SHTML是什么_SSI有什么用... 查看linux中某个端口(port)... 卡尔曼滤波的原理说明... shell中字符串操作 关于java中的“错误:找不到或... 给主人留下些什么吧!~~ 评论热议
本站声明: 本文章由作者或相关机构授权发布,目的在于传递更多信息,并不代表本站赞同其观点,本站亦不保证或承诺内容真实性等。需要转载请联系该专栏作者,如若文章内容侵犯您的权益,请及时联系本站删除。
关闭
关闭