(linux自学笔记)linux按键中断驱动

发布时间:2024-09-23  

通常开发板自带按键中断的驱动,中断已被注册至内核。重新编译linux内核去掉自带驱动才能使用自己编写的驱动。

linux中断程序可分解为顶半部与底半部机制。顶半部完成尽可能少的紧急功能,底半部可以被新的中断打断。

驱动程序


#include

#include

#include

#include

#include

#include

#include

#include

#include

#include

#include

#include

#include

#include

#include

#include

#include

#include


#define DEVICE_NAME     'key_device'

#define DEVICE_MAJOR    240


void key_tasklet_func(void);


DECLARE_TASKLET(key_tasklet,key_tasklet_func,0);


struct key_irq_desc

{

    int irq;

    int pin;

    int pin_setting;

    int number;

    char *name;


};


static struct key_irq_desc key_irqs [] =

{

    {IRQ_EINT(0), S3C64XX_GPN(0) ,  S3C64XX_GPN0_EINT0 , 0, 'KEY0'},

    {IRQ_EINT(1), S3C64XX_GPN(1) ,  S3C64XX_GPN1_EINT1 , 1, 'KEY1'},

    {IRQ_EINT(2), S3C64XX_GPN(2) ,  S3C64XX_GPN2_EINT2 , 2, 'KEY2'},

    {IRQ_EINT(3), S3C64XX_GPN(3) ,  S3C64XX_GPN3_EINT3 , 3, 'KEY3'},

    {IRQ_EINT(4), S3C64XX_GPN(4) ,  S3C64XX_GPN4_EINT4 , 4, 'KEY4'},

    {IRQ_EINT(5), S3C64XX_GPN(5),   S3C64XX_GPN5_EINT5 , 5, 'KEY5'},

};

static volatile int key_values [] = {1, 1, 1, 1, 1, 1};


//初始化等待列对

static DECLARE_WAIT_QUEUE_HEAD(button_waitq);


static volatile int event_flag = 0;



static irqreturn_t buttons_interrupt(int irq, void *dev_id)

{

    struct key_irq_desc *dev_irqs = (struct key_irq_desc *)dev_id;

    int down;


    down = gpio_get_value(dev_irqs->pin);


    //按键发生了变化

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

    {

        // Changed


        key_values[dev_irqs->number] = 0 + down;


        event_flag = 1;

        //唤醒列对

        wake_up_interruptible(&button_waitq);

    }


    tasklet_schedule(&key_tasklet);


    return IRQ_RETVAL(IRQ_HANDLED);

}


void key_tasklet_func(void)

{

    printk('<0>=======task========n');

    printk('<0>task function test~n');

    printk('<0>===================n');

}


static int s3c6410_key_open(struct inode *inode, struct file *file)

{

    int i;

    int err = 0;


    //注册中断              结构体未注册完

    for (i = 0; i < sizeof(key_irqs)/sizeof(key_irqs[0]); i++)

    {

        if (key_irqs[i].irq < 0)

        {

            continue;

        }


        //                    中断号                 中断处理寒酸     中断处理属性

        err = request_irq(key_irqs[i].irq, buttons_interrupt, IRQ_TYPE_EDGE_BOTH,

                          key_irqs[i].name, (void *)&key_irqs[i]);

        if (err)

            break;

    }


    //如果注册中断过程中出错,则注销注册成功的中断

    if (err)

    {

        i--;

        for (; i >= 0; i--)

        {

            if (key_irqs[i].irq < 0)

            {

                continue;

            }

            disable_irq(key_irqs[i].irq);

            free_irq(key_irqs[i].irq, (void *)&key_irqs[i]);

        }

        return -EBUSY;

    }



    //显示一次主界面而已

    event_flag = 1;


    return 0;

}



static int s3c6410_keys_close(struct inode *inode, struct file *file)

{

    int i;

    //注销中断

    for (i = 0; i < sizeof(key_irqs)/sizeof(key_irqs[0]); i++)

    {

        if (key_irqs[i].irq < 0)

        {

            continue;

        }

        free_irq(key_irqs[i].irq, (void *)&key_irqs[i]);

    }


    return 0;

}



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

{

    unsigned long err;


    if (!event_flag)

    {

        //没有新按键事件处理,如果用户要求不阻塞就直接返回,否则阻塞在button_waitq队列上。

        if (filp->f_flags & O_NONBLOCK)

            return -EAGAIN;

        else

            wait_event_interruptible(button_waitq, event_flag);

    }


    event_flag = 0;


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


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

}




static struct file_operations key_device_fops =

{

    .owner      =   THIS_MODULE,

    .open       =   s3c6410_key_open,

    .release    =   s3c6410_keys_close,

    .read       =   s3c6410_keys_read,

};




static int __init key_device_init(void)

{

    int ret;

    printk ('<0>key initn');

    //注册字符设备

    ret = register_chrdev(DEVICE_MAJOR,DEVICE_NAME,&key_device_fops);

    if (ret <0)

    {

        printk ('<0>register %s char dev errorn','key');

        return -1;

    }

    printk ('<0>successn');

    return 0;

}


static void __exit key_device_exit(void)

{

    //注销设备

    unregister_chrdev(DEVICE_MAJOR,DEVICE_NAME);

    printk ('<0>module exitn');

}


module_init(key_device_init);

module_exit(key_device_exit);


MODULE_LICENSE('GPL');

MODULE_AUTHOR('hebaichuan');


测试程序,按6键退出死循环。


#include   

#include   

#include   

#include   

  

#define key_exit 5


int main(int argc, char **argv)  

{  

    int fd,ret,i,key_value[6];  

        

    fd = open('/dev/key_device',0);  

    if(fd<0) 

    {  

        printf('open devie errorn');  

        return -1;  

    }  

  

    while(1)

    {  

        ret = read(fd,key_value, sizeof(key_value));  

        if(ret<0) 

        {  

            printf('read errorn');  

            continue;  

        }  

        else if(!key_value[key_exit])

            exit(0);


        for(i=0;i<5;i++)

        {  

            if(key_value[i])

            {

                printf('KEY%d releasedn',(i+1),key_value[i]);

            }  

            else  

            {

                printf('KEY%d pressed n',(i+1),key_value[i]);  

            }    

        }    

        printf('----------------key event----------------n');  

    }  

    close(fd);  

    return 0;  

}  


运行结果:


文章来源于:电子工程世界    原文链接
本站所有转载文章系出于传递更多信息之目的,且明确注明来源,不希望被转载的媒体或个人可与我们联系,我们将立即进行删除处理。

我们与500+贴片厂合作,完美满足客户的定制需求。为品牌提供定制化的推广方案、专属产品特色页,多渠道推广,SEM/SEO精准营销以及与公众号的联合推广...详细>>

利用葫芦芯平台的卓越技术服务和新产品推广能力,原厂代理能轻松打入消费物联网(IOT)、信息与通信(ICT)、汽车及新能源汽车、工业自动化及工业物联网、装备及功率电子...详细>>

充分利用其强大的电子元器件采购流量,创新性地为这些物料提供了一个全新的窗口。我们的高效数字营销技术,不仅可以助你轻松识别与连接到需求方,更能够极大地提高“闲置物料”的处理能力,通过葫芦芯平台...详细>>

我们的目标很明确:构建一个全方位的半导体产业生态系统。成为一家全球领先的半导体互联网生态公司。目前,我们已成功打造了智能汽车、智能家居、大健康医疗、机器人和材料等五大生态领域。更为重要的是...详细>>

我们深知加工与定制类服务商的价值和重要性,因此,我们倾力为您提供最顶尖的营销资源。在我们的平台上,您可以直接接触到100万的研发工程师和采购工程师,以及10万的活跃客户群体...详细>>

凭借我们强大的专业流量和尖端的互联网数字营销技术,我们承诺为原厂提供免费的产品资料推广服务。无论是最新的资讯、技术动态还是创新产品,都可以通过我们的平台迅速传达给目标客户...详细>>

我们不止于将线索转化为潜在客户。葫芦芯平台致力于形成业务闭环,从引流、宣传到最终销售,全程跟进,确保每一个potential lead都得到妥善处理,从而大幅提高转化率。不仅如此...详细>>