⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 key_tasklet.c~

📁 一个基于s3c2440-linux2.6按键驱动程序的tasklet的典型运用并附带软中断定时器timerlist的用法。标准的中断上半部
💻 C~
字号:
#include <linux/module.h>#include <linux/types.h>#include <linux/fs.h>#include <linux/errno.h>#include <linux/mm.h>#include <linux/sched.h>#include <linux/init.h>#include <linux/cdev.h>#include <linux/input.h>#include <linux/interrupt.h>#include <asm/io.h>#include <asm/system.h>#include <asm/uaccess.h>#include <asm/arch/regs-gpio.h>#include <asm/arch/hardware.h>#define DEVICE_NAME "utukey"#define KEY_TIME_DELAY (HZ/5)//200ms#define KEY_TIME_DELAY1 (HZ/250)//4ms#define KEYSTATUS_DOWNX 0 //刚被按下#define KEYSTATUS_DOWN 1 //一直被按着hold#define KEYSTATUS_UP 2   //按键抬起了static void utu2440button_timer_callback(unsigned long data);//时间软中断定时器处理函数static irqreturn_t utu2440_isr_kbd(int irq, void *dev_id, struct pt_regs *reg);//按键中断处理函数static int utukey_open(struct inode *inode, struct file *filp);static int utukey_release(struct inode *inode, struct file *filp);void my_tasklet_func(unsigned long t);int tasklet_time;DECLARE_TASKLET(my_tasklet,my_tasklet_func,&tasklet_time);static dev_t utukey_major=252;//主设备号自设定unsigned int keynumber=6;//只是作为标记所用struct utukey_dev_t{    struct cdev cdev;    unsigned int keyStatus;};struct utukey_dev_t utukey_dev;struct timer_list key_timer;static const struct file_operations utukey_fops ={    .owner = THIS_MODULE,    .open  = utukey_open,    .release = utukey_release,};/*打开函数*/static int utukey_open(struct inode *inode, struct file *filp){    filp->private_data = &utukey_dev;    printk(KERN_NOTICE "utukey opened\n");    return 0;}/*释放函数*/static int utukey_release(struct inode *inode, struct file *filp){    printk(KERN_NOTICE "utukey released\n");    return 0;}/*中断服务程序*/static irqreturn_t utu2440_isr_kbd(int irq, void *dev_id, struct pt_regs *reg){   // int *key = (int*)dev_id;    //printk(KERN_NOTICE "utukey interrupt key number is %d\n",*key);//传进了keynumber    printk(KERN_NOTICE "utukey interrupt key number is %d\n",keynumber);    if (IRQ_EINT19!= irq)     {      printk(KERN_NOTICE"bad irq %d in button\n", irq);      return IRQ_NONE;    }    disable_irq(IRQ_EINT19);//先屏蔽此中断    utukey_dev.keyStatus= KEYSTATUS_DOWNX; //表示刚被按下    key_timer.expires = jiffies + KEY_TIME_DELAY1;//通过这个来实现去抖,并判断是否一直被按下,百分之一秒    add_timer(&key_timer); //开始计时    tasklet_schedule(&my_tasklet);      return IRQ_HANDLED;//表示处理好了 和 IRQ_NONE对应}/*timer 延时处理函数data参数来自于定时器结构中的data变量*/static void utu2440button_timer_callback(unsigned long data){        if (s3c2410_gpio_getpin(S3C2410_GPG11) == 0)    {        if (utukey_dev.keyStatus== KEYSTATUS_DOWNX)//从中断进入        {            printk(KERN_NOTICE "utukey is down\n");            utukey_dev.keyStatus= KEYSTATUS_DOWN;//从中断进入的,证明按键已经被按下expires时间了,一直在被按着            key_timer.expires = jiffies + KEY_TIME_DELAY; //判断是否还被按着,五分之一秒                      add_timer(&key_timer);        }	 else //不是第一次进入定时器,表示按键一直被按着        {            printk(KERN_NOTICE "utukey is hold\n");            key_timer.expires = jiffies + KEY_TIME_DELAY;//HOLD key,每隔200MS发送一次                       add_timer(&key_timer);        }    }    else    {        utukey_dev.keyStatus= KEYSTATUS_UP;        printk(KERN_NOTICE "utukey is up\n");        enable_irq(IRQ_EINT19);//按键抬起的时候,重新开中断    }}//中断下半部taskletvoid my_tasklet_func(unsigned long t){  int data=*(int*)t;  printk("tasklet is executing  %d\n",data);  (*(int*)t)++;}//insmodstatic int __init utukey_init(void){    int result,ret;    dev_t devno = MKDEV(utukey_major,0);    if (utukey_major)    {        result = register_chrdev_region(devno, 1, DEVICE_NAME);	/*int register_chrdev_region(dev_t first, unsigned int count, char *name)	First :要分配的设备编号范围的初始值(次设备号常设为0);	Count:连续编号范围.(被使用只是一个要请求的范围,最终只能分配给你一个号码)	Name:编号相关联的设备名称. (/proc/devices);	*/    }    else    {        result = alloc_chrdev_region(&devno, 0, 1, DEVICE_NAME);	/*Int alloc_chrdev_region(dev_t *dev,unsigned int firstminor,unsigned int count,char *name);动态分配	Firstminor : 通常为0;	*dev:存放返回的设备号;	*/        utukey_major = MAJOR(devno);    }    if (result < 0)    {        return result;    }    cdev_init(&utukey_dev.cdev,&utukey_fops);//字符设备初始化    utukey_dev.cdev.owner = THIS_MODULE;    utukey_dev.cdev.ops = &utukey_fops;    utukey_dev.keyStatus = KEYSTATUS_UP;//按键初始状态为抬起    ret = cdev_add(&utukey_dev.cdev, devno, 1);    if (ret)    {        printk(KERN_NOTICE "Error %d adding utukey",ret);           }        s3c2410_gpio_cfgpin(S3C2410_GPG11, S3C2410_GPG11_EINT19);//申请中断    set_irq_type(IRQ_EINT19, IRQT_FALLING);//设置为下降沿触发    if (ret=request_irq(IRQ_EINT19, utu2440_isr_kbd, SA_INTERRUPT, DEVICE_NAME, NULL))//注册的中断号,中断服务程序,快速中断,设备名,传递的参数	{                      printk(KERN_NOTICE"request irq in button failed key is %d,return is %d\n",keynumber,ret);         return -1;        }    printk(KERN_NOTICE"request irq in button,successed\n");     /*timer结构初始化*/               key_timer.function = utu2440button_timer_callback;//timer的调用函数    key_timer.data =keynumber;    init_timer(&key_timer);    return 0;}//rmmodstatic void __exit utukey_exit(void){    cdev_del(&utukey_dev.cdev);    del_timer(&key_timer);    free_irq(IRQ_EINT19,NULL);//释放irq中断void free_irq(unsigned int irq,void *dev_id); dev_id用于多个设备的中断共享    unregister_chrdev_region(MKDEV(utukey_major,0),1);}/*释放:Void unregist_chrdev_region(dev_t first,unsigned int count);调用Documentation/devices.txt中能够找到已分配的设备号.*/MODULE_AUTHOR("lwcheng");MODULE_LICENSE("Dual BSD/GPL");module_init(utukey_init);module_exit(utukey_exit)

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -