• 内核中断及按键驱动程序


    寒假Linux学习笔记

    2015年1月25日 晚 20:00

    一、内核中断处理

    进程上下文:应用程序主动调用内核驱动的程序的跳转

    中断上下文:中断由硬件产生的,与应用程序无关

     

     

    1、注册中断

    Int request_irq(unsigned int irq,             //中断号

    void (*handler)(int ,void *, struct pt_regs*),    //中断处理函数

    unsigned long flags,            //与中断处理管理相关的各种选项

    const char * devname,        //设备名

    void * dev_id                //共享中断时使用的id号,唯一

    );

    Flags参数:

        IRQF_DISABLED(SA_INTERRUPT);    //若设置此位,则是一个快速中断,即中断为原子操作,不会被打断;未设置该位,则是一个慢速中断

        IRQF_SHARED(SA_SHIRQ);        //中断可以在设备间共享,申请共享中断必须设置此位为IRQF_SHARED

     

    注意:共享中断 不能使用 disable_irq(unsigned int irq),因为一旦使用该函数,则共享该中断线的全部都不能用

     

    2、中断处理函数流程

    Void short_sh_interrupt(int irq, void *dev_id, struct pt_regs *regs)

    {

        /*判断是否是本设备的中断,因为共享中断中使用的是同一个中断处理函数,此时内核就无法判断是哪一个设备发生的中断,可能产生误调用*/

        Value = inb(short_base);

    If(!value & 0x80) return;

     

    /*清除中断标志位(若设备支持自动清除,则不需要此位)*/

    Outb(value & 0x7f, short_base);

     

    /* 中断处理函数,数据处理 */

    ……

    /* 唤醒等待的进程 */

    Wake_up_interrruptible(&short_quue);

    }

     

    中断处理程序:(运行环境为中断上下文)

        1.不能向用户空间发送或接受数据,因为进程变了,用户就变了,中断不对应任何进程

        2.不能使用可能引起阻塞的函数

        3.不能使用可能引起调度的函数,中断中无进程,无法调度

     

     

    3、释放中断

    Void free_irq(unsigned int irq,void * dev_id);

    当被释放的是共享中断时,必须设定dev_id位,否则共享中断全线不能用

     

     

    二、按键驱动处理程序分析

    分析实现流程:

            //混杂设备结构体,主设备为10,次设备号不同的一类设备

    static struct miscdevice misc = {

        .minor = MISC_DYNAMIC_MINOR,        //次设备号

        .name = DEVICE_NAME,        //设备名

        .fops = &dev_fops            //字符设备的file_operation

    };

    1.初始化程序

    Static int __init dev_init(void){

        Int ret;

        ret = misc_register(&misc);        //注册混杂设备

        ……

        return ret;

    }

     

    2.file_operations 按键实现的操作

    static struct file_operations dev_fops = {

        .owner = buttons_open,    //打开操作

        .release = buttons_close,

        .poll = buttons_poll        //select,多路监控

    };

    //open 函数实现

    Static buttons_open(static inode *inode,struct(file *file)){

            //为六个中断线分别注册驱动程序 总的大小/单个的大小=个数

        For(I = 0, i<sizeof(button_irqs)/sizeof(button_irqs[0]);i++){    

            If(button_irqs[i].irq<0)        

                Continue;

    //制定中断处理程序, IRQ_TYPE_EDGE_BOTH:双边沿产生中断

        request_irq(button_irqs[i].irq,buttons_interrupt,IRQ_TYPE_EDGE_BOTH,button_irqs[i].name,(void *)&button_irqs[i]);

    }

    }

    //poll 函数实现

    static unsigned int buttons_poll(struct file *file,struct poll_table_struct *wait){

        poll_wait(file,&button_waitq,wait);        //指明要使用的等待队列

        if(ev_press)            //全局静态变量,初始值未按下为0,为1时按键按下

            mask |= POLLIN | POLLRDNORM;     //按键可读不可写

        return mask;        //返回掩码

    }

    //当按键按下,程序开始读,读函数实现

    static unsigned int buttons_read(struct file * filp,char __user *buff,size_t count,loff_t *offp){

        if(!ev_press)    {        //如果未按下

            if(filp->f_flags & O_NONBLOCK)    //O_NONBLOCK:用户通过此指定不阻塞

                return –EAGAIN;

            else

                wait_event_interruptible(button_wait,ev_press);//阻塞在等待队列

    }

    ev_press = 0; //此行语句之前,ev_press其实是1的,中断程序里设置为1

                        //读取键值

    err = copy_to_user(buff,(const void *)key_values,min(sizeof(key_values),count));

    return err ? –EFAULT : min(sizeof(key_values),count);

    }

     

    3.中断处理程序

    static irqreturn_t buttons_interrupt(int irq, void *dev_id){

            //读取按键gpio的数据寄存器的值

        down = !gpio_getpin(button_irqs->pin);//按下是值为0,而程序中1表示按下

            //key_values初始全是为0的,按下时变为1,则不再运行,可防止抖动

    if(down != (key_values[button_irqs->number] & 1)){    

            key_values[button_irqs->number] = '0' + down;

            ev_press = 1;        //有键按下

            wake_up_interruptible(&button_waitq);

    }

    return IRQ_RETVAL(IRQ_HANDLED);

    }

     

     

  • 相关阅读:
    mysql主从与mycat与MHA
    mycat+mysql集群:实现读写分离,分库分表
    centos7下扩展根分区(图文详解)
    MySQL高可用之MHA的搭建
    zabbix_agentd客户端安装与配置(windows操作系统)
    centos7手把手教你搭建zabbix监控
    有关添加System.Web的问题
    锚标签<a>
    MVC3出现“提供程序未返回 ProviderManifestToken 字符串”的解决办法
    解决.net后台调用js弹窗后,前台界面样式乱掉问题
  • 原文地址:https://www.cnblogs.com/lihaiyan/p/4274461.html
Copyright © 2020-2023  润新知