zoukankan      html  css  js  c++  java
  • 6410-混杂设备驱动模型

    1.混杂设备驱动模型
    a.混杂设备描述
    混杂设备概念:
    在Linux系统中,存在一类字符设备,它们拥有相同的主设备号(10),但次设备号不同,我们称这类设备为混杂设备(miscdevice)。所有的混杂设备形成一个链表,对设备访问时内核根据混杂设备形成一个链表,对设备访问时内核根据次设备号查找到相应的混杂设备。
    设备描述:
    struct miscdevice {
    int minor;//次设备号
    const char *name;//设备名
    const struct file_operations *fops;//文件操作
    struct list_head list;
    struct device *parent;
    struct device *this_device;
    const char *nodename;
    mode_t mode;
    };

    b.混杂设备注册
    int misc_register(struct miscdevice * misc)
    也就是分为两步:首先初始化混杂设备,然后利用misc_register去注册混杂设备。

    2.linux中断处理
    a.裸机中断处理程序流程回顾
    a.1中断有一个统一的入口:在linux内核中同样有一个统一的入口,它在entry_armv.S里面的irq_svc:->拿到产生中断源的编号-》根据中断号找到irq_desc(对应的中断)->irq_desc中取出事先注册好的中断处理函数-》action->action会直接找到handler(里面存放有用户的中断处理程序)。
    驱动程序做的事:1.实现中断处理程序;2.注册中断;3.注销处理

    a.2事先注册中断处理程序
    注册中断:
    request_irq(unsigned int irq, irq_handler_t handler, unsigned long flags,const char *name, void *dev)
    返回0表示成功,否则返回乱码.
    unsigned int irq //中断号。
    void (*handler)(int,void *) //中断处理函数。
    unsigned long flags //与中断管理有关的各种选项。
    const char * devname //设备名
    void *dev_id //共享中断时使用

    在flags参数中,可以选择一些与中断管理有关的选项,如:
    ? IRQF_DISABLED(SA_INTERRUPT)
    如果设置该位,表示是一个“快速”中断处理程序;如果没有设置这位,那么是一个“慢速”中断处理程序。
    ? IRQF_SHARED(SA_SHIRQ)
    该位表明该中断号是多个设备共享的

    快/慢速中断的主要区别在于:快速中断保证中断处理的原子性(不被打断),而慢速中断则不保证。换句话说,也就是“开启中断”标志位(处理器IF)在运行快速中断处理程序时是关闭的,因此在服务该中断时,不会被其他类型的中断打断;而调用慢速中断处理时,其它类型的中断仍可以得到服务。

    中断处理程序的特别之处是在中断上下文中运行的,它的行为受到某些限制:
    1.不能使用可能引起阻塞的函数
    2.不能使用可能引起调度的函数

    a.3根据中断源编号调用中断处理程序
    检查设备是否产生了中断-》清除中断产生标志-》相应的硬件操作。
    注销中断:当设备不再需要使用中断时(通常在驱动卸载时), 应当把它们注销, 使用函数:
    void free_irq(unsigned int irq, void *dev_id):对于共享中断,需要提供中断号和dev_id号。

    b.linux中断处理流程分析
    c.linux中断处理程序设计
    irqreturn_t key_int(int irq,void *dev_id)
    {
    //1.检查是否发生了按键中断,因为此处只有一个中断,因此不需要进行检测。

    //2.清除已经发生的按键中断,硬件内部的需要清除中断,但按键属于处理器级别,因此不需要清除中断。如网卡芯片就需要清除中断。

    //3.打印按键值
    }

    3.按键驱动硬件操作实现
    参考裸机中断的代码:button.c:gpio功能的选择,设为外部中断;硬件的初始化可以在open函数和模块初始化的函数中完成。

    c.范例驱动分析
    touch key.c
    chmod 777 -R ./

    #include<linux/module.h>
    #include<linux/init.h>
    #include<linux/miscdevice.h>
    #include<linux/interrupt.h>
    #include<linux/io.h>
    #include<linux/fs.h>


    #define GPFCON 0x7F880030 //驱动程序中不能使用物理地址,必须将其转化为虚拟地址。

    irqreturn_t key_int(int irq,void *dev_id)//使用前面的类型需要加头文件
    {
    //1.检查是否发生了按键中断

    //2.清除已经发生的按键中断

    //3.打印按键值
    printk("key_down! ");
    }

    void key_hw_init()
    {
    unsigned int = gpio_config;
    unsigned short data;
    //将物理地址转化为虚拟地址
    gpio_config = ioremap(GPFCON,4);
    data = readw(gpio_config);//取出寄存器中的值
    data &= ~0b11;//对寄存器中的相应的位进行清除
    data |= 0b10;//对相应的位进行设置
    writew(data,gpio_config);将data的值写入寄存器中
    }

    int key_open(struct inode *node,struct file *file)
    {
    return 0;
    }
    stuct miscdevice key_miscdev = {
    .minor = 200,
    .name = "key",
    .fops = &key_fops,
    };

    struct file_operations key_fops = //加头文件fs.h
    {
    .open = key_open,

    };
    static int key_init()
    {
    //注册混杂设备
    misc_register(&key_miscdev);
    //注册中断处理程序IRQF_TRIGGER_FALLING//表示中断是由高电平到低电平时产生的中断。也就是按键按下的时候产生的中断。中断号:不同于裸机,首先我们要找与开发板对应的irqs.h头文件,在头文件中有
    register_irq(S3C_EINT(0),key_int,IRQF_TRIGGER_FALLING,"key",0);
    //按键初始化
    key_hw_init();
    }

    static void key_exit()
    {
    //注销混杂设备
    misc_deregister(&key_miscdev);
    //注销中断处理程序
    free_irq(S3C_EINT(0),0);
    }

    module_init(key_init);
    module_exit(key_exit);

  • 相关阅读:
    Linux 进程间通信(包含一个经典的生产者消费者实例代码)
    Linux多进程编程实例
    web开发中的mysql使用
    Linux 网络编程中的read和write函数正确的使用方式
    Linux 使用tcpdump观察arp通信过程
    Linux 开启echo等服务
    Linux send和recv
    自己动手写http服务器——主程序(三)
    自己动手写http服务器——线程池(一)
    http请求报文格式和响应报文格式
  • 原文地址:https://www.cnblogs.com/defen/p/4823969.html
Copyright © 2011-2022 走看看