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

📄 buttondrv.c

📁 linux下面 drv button 设计 定时器使用
💻 C
字号:
/*+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++File Name:	buttondrv.cAbstract: 	device driver for bond/restore button(conneted to gpf2/gpf0)   Author:	Huiqing GuoRevision History:	2007.10		created	2007.12		sleep_on() changed to interruptible_sleep_on();				wake_up() changed to wake_up_interruptible();				free_irq(irq,NULL) changed to free_irq(irq,pdata);				add s3c_irq_*() function.	2008.1		add s3c_gpio_setmode() function.				reimplement button check mechanism.---------------------------------------------------------------------------*/#include <linux/module.h>#include <linux/kernel.h>#include <linux/sched.h>#include <asm/io.h>#include <asm/uaccess.h>#include <linux/interrupt.h>#include <linux/fs.h>#include <linux/init.h>#include <asm/arch/regs-gpio.h>#include <asm/arch/regs-irq.h>MODULE_AUTHOR("lxt"); MODULE_LICENSE("Dual BSD/GPL"); MODULE_ALIAS("led"); MODULE_LICENSE("GPL"); // ========== Constant definitions==========#define constant0 	0x1#define constant2 	0x4#define input_mode	0x0#define extint_mode	0x2//#define delay		HZ/10							//	100ms//#define delay		HZ/50	//#### modify my ttaaoo			20ms#define delay		HZ/HZ	//#### modify my ttaaoo			1ms// ========== dev number definitions========#define button_dev_num 230struct button_data_struct{	unsigned int readvalue;	unsigned int irq;	wait_queue_head_t readwaitqueue;	struct timer_list timer;	};static int button_open(struct inode * inode, struct file * filp);static int button_release(struct inode * inode, struct file * filp);static ssize_t button_read(struct file * filp, int * buf,size_t count,loff_t * l);static struct button_data_struct button_data[2];static struct file_operations button_fops = {	.owner = THIS_MODULE,	.open = button_open,	.release = button_release,	.read =  button_read,	};static void s3c_gpio_setmode(unsigned int irqno,unsigned char mode){	unsigned long value;	unsigned long offset = (irqno - IRQ_EINT0) * 2;		value = __raw_readl(S3C2410_GPFCON);	value = (value & ~(3 << offset)) | (mode << offset);	__raw_writel(value, S3C2410_GPFCON);}static void s3c_irq_mask(unsigned int irqno){	unsigned long mask;	irqno -= IRQ_EINT0;	mask = __raw_readl(S3C2410_INTMSK);	mask |= 1UL << irqno;	__raw_writel(mask, S3C2410_INTMSK);}static void s3c_irq_ack(unsigned int irqno){	unsigned long bitval = 1UL << (irqno - IRQ_EINT0);	__raw_writel(bitval, S3C2410_SRCPND);	__raw_writel(bitval, S3C2410_INTPND);}static void s3c_irq_unmask(unsigned int irqno){	unsigned long mask;	irqno -= IRQ_EINT0;	mask = __raw_readl(S3C2410_INTMSK);	mask &= ~(1UL << irqno);	__raw_writel(mask, S3C2410_INTMSK);}static void button_timer(unsigned long data){	struct button_data_struct *pdata = (struct button_data_struct *)data;	unsigned long value;	unsigned long mask;	if(pdata->irq == IRQ_EINT0)		mask = constant0;	else		mask = constant2;		value = __raw_readl(S3C2410_GPFDAT);	value &= mask;	if(value)										//unnormal interrupt	{				printk(KERN_EMERG"timer  %ld  , value = %d,  readvalue = %d  \n", jiffies, value, pdata->readvalue);		s3c_gpio_setmode(pdata->irq,extint_mode);		s3c_irq_unmask(pdata->irq);		del_timer(&pdata->timer);		wake_up_interruptible(&pdata->readwaitqueue);				}	else											//normal interrupt	{		// printk(KERN_EMERG"timer  %ld  , value = %d\n", jiffies, value);		mod_timer(&pdata->timer,jiffies + delay);		pdata->readvalue ++;	}		}static irqreturn_t button_interrupt_handler(int irq,void * dev_id){	struct button_data_struct * pdata = (struct button_data_struct *)dev_id;	printk(KERN_EMERG"\nenter interrupt  %ld \n", jiffies);	pdata->readvalue = 0;		s3c_irq_mask(irq);	s3c_gpio_setmode(irq,input_mode);	/* 设置io 为输入模式 */	del_timer(&pdata->timer);	pdata->timer.expires = jiffies + delay;		add_timer(&pdata->timer);out:		return IRQ_HANDLED;}static int button_open(struct inode * inode, struct file * filp){	unsigned char devnum = MINOR(inode->i_rdev);	struct button_data_struct * pdata = &(button_data[devnum]);		filp->private_data = pdata;		return 0;}static int button_release(struct inode * inode,struct file * filp){	unsigned char devnum = MINOR(inode->i_rdev);	struct button_data_struct * pdata = filp->private_data;	unsigned int irq;	if(devnum==0)				irq = IRQ_EINT2;	else		irq = IRQ_EINT0;		free_irq(irq,pdata);	del_timer(&pdata->timer);		return 0;}static ssize_t button_read(struct file * filp, int * buf, size_t count, loff_t * l){	struct button_data_struct * pdata = filp->private_data;	interruptible_sleep_on(&pdata->readwaitqueue);	if(copy_to_user(buf, &pdata->readvalue, 1))		return -EFAULT;	pdata->readvalue = 0;	return 0;}static int __init button_init(void){	int rc;		if (register_chrdev(button_dev_num, "buttondrv", &button_fops) < 0)	{		printk("Can not allocate char type main device number %d\n",button_dev_num);		return -1;  	}		rc=request_irq(IRQ_EINT2, &button_interrupt_handler, IRQF_SHARED, "button", &(button_data[0])); 	 if(rc<0)	 {  		printk("Can not allocate irq number %d,error number is %d\n",IRQ_EINT2, rc); 		return -1;  	}	rc=request_irq(IRQ_EINT0,&button_interrupt_handler,IRQF_SHARED,"button",&(button_data[1])); 	 if(rc<0)	 {  		printk("Can not allocate irq number %d,error number is %d\n",IRQ_EINT0, rc); 		return -1;  	}	s3c_irq_mask(IRQ_EINT2);	s3c_irq_ack(IRQ_EINT2);	s3c_irq_unmask(IRQ_EINT2);		init_timer(&button_data[0].timer);	button_data[0].timer.function = &button_timer;	button_data[0].timer.data = (unsigned long)(&(button_data[0]));	button_data[0].irq = IRQ_EINT2;	button_data[0].readvalue = 0;	init_waitqueue_head(&button_data[0].readwaitqueue);		s3c_irq_mask(IRQ_EINT0);	s3c_irq_ack(IRQ_EINT0);	s3c_irq_unmask(IRQ_EINT0);	init_timer(&button_data[1].timer);	button_data[1].timer.function = &button_timer;	button_data[1].timer.data = (unsigned long)(&(button_data[1]));	button_data[1].irq = IRQ_EINT0;	button_data[1].readvalue = 0;	init_waitqueue_head(&button_data[1].readwaitqueue);	 printk("######################################### register button\n ");	 printk("######################################### register button\n ");	 printk("######################################### register button\n ");		return 0;}static void __exit button_cleanup(void){	unregister_chrdev(button_dev_num,"buttondrv");  	return;}module_init (button_init);module_exit (button_cleanup);

⌨️ 快捷键说明

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