📄 irint2.c
字号:
/********************************************************** * s3c2440-ts.c * * keyboard driver for S3C2440 based PDA * * * History: * * ***********************************************************/#include <linux/config.h>#include <linux/module.h>#include <linux/kernel.h>#include <linux/init.h>#include <linux/miscdevice.h>#include <linux/sched.h>#include <linux/delay.h>#include <linux/poll.h>#include <linux/spinlock.h>#include <asm/irq.h>#include <asm/arch/irq.h>#include <asm/arch/irqs.h>#include <asm/arch/clocks.h>#include <asm/hardware.h>#include <asm/arch/S3C2440.h>#define DEVICE_NAME "s3c2440-irint" //键盘设备名#define IRINT_MAJOR 96static int kbMajor = IRINT_MAJOR; //默认的主设备号static u_short eint2_value = 0;static u_short eint_number = 0;static int TimerCount = 0; //超时标志#define TIMER_DELAY (HZ/50) /* 消都延时:1秒*/#define TIMEOUT 3static struct timer_list ring_timer;static wait_queue_head_t wq ; //声明等待队列//spinlock_t repeat_lock;spinlock_t lock; //声明自旋锁#define BLOCK 1#define NONBLOCK 0static u_int FileMode=NONBLOCK;//#define USE_ASYNC 1#undef USE_ASYNC#ifdef USE_ASYNCstatic struct fasync_struct *AsyncQueue =NULL;#endifstatic int requestIrq();#ifdef USE_ASYNCstatic int s3c2440_irint_fasync(struct inode *inode, struct file *filp, int mode){ return fasync_helper(inode, filp, mode, &AsyncQueue);}#endif/*----------------------------------------------------* func: 读取eint2当前值* param: * * return: if key is down, return 1; else 0* ------------------------------------------------------*/int get_eint2_value(){ unsigned long IOValue; IOValue = GPFDAT ; if ( IOValue & 0x00000004) return 0; else return 1; }static inline void timer_handler(unsigned long data){ if (!get_eint2_value()) /* if key is not down*/ { TimerCount=0; del_timer(&ring_timer); enableIrq(); } TimerCount++; if (TimerCount==TIMEOUT) { #ifdef USE_ASYNC if(AsyncQueue) kill_fasync(&(AsyncQueue), SIGIO, POLL_IN); #endif eint2_value =1; //来了中断,将其值置为1; eint_number=eint_number+1; printk("int coming %d\n",eint_number); if(FileMode == BLOCK) //如果是阻塞方式,唤醒在wq上的事件 wake_up_interruptible(&wq); del_timer(&ring_timer); TimerCount=0; enableIrq(); } else { ring_timer.expires = jiffies + TIMER_DELAY; add_timer(&ring_timer); } }/*static inline void timer_handler(unsigned long data){#ifdef USE_ASYNC if(AsyncQueue) {// if(eint2_value ==0) kill_fasync(&(AsyncQueue), SIGIO, POLL_IN); }#endif eint2_value = 1; TimeOut = 1;}*//*----------------------------------------------------* func: 使能中断* param: * return: * ------------------------------------------------------*///使能中断static void enableIrq(){ //清除SRCPND寄存器中eint2相应位 SRCPND= 0x00000004; //使能中断 enable_irq(IRQ_EINT2); }/*----------------------------------------------------* func: 对应文件读的函数,如果循环队列中有键码, 则将键码拷贝到用户空间的buffer中* param: * * return: * 返回从循环队列中读取的键码的字节数** ------------------------------------------------------*/static ssize_tS3C2440_irint_read(struct file *filp, char *buffer, size_t count, loff_t * ppos){ // printk("<0>,eint_number %d\n",eint_number); if(FileMode == BLOCK) //如果是阻塞方式 { if (eint2_value ==0) //如果没有数据 { interruptible_sleep_on(&wq); //一直睡眠等待 // if(signal_pending(current))// return -ERESTARTSYS; } } count = sizeof(eint_number); copy_to_user(buffer,&eint_number,count); //将按键的值eint_number拷贝到用户空间 eint2_value =0; //数据读完后,再次清除 return count; }/*----------------------------------------------------* func: 与打开文件对应的open函数,初始化全局变量和定* 时器以及请求中断* param: * ** return: * ------------------------------------------------------*/static int S3C2440_irint_open(struct inode *inode, struct file *filp){ // printk("<0> open\n"); if(filp->f_flags & O_NONBLOCK) { FileMode = NONBLOCK; } else { FileMode = BLOCK; } //初始化定时器// init_timer(&ring_timer);// ring_timer.function = timer_handler;// lock = SPIN_LOCK_UNLOCKED;// init_waitqueue_head(&wq); //sjw// enableIrq(); MOD_INC_USE_COUNT; return 0;}static int s3c2440_irint_release(struct inode *inode, struct file *filp){// disable_irq(IRQ_EINT2); #ifdef USE_ASYNC s3c2440_irint_fasync(inode,filp,0); #endif printk("release device\n"); MOD_DEC_USE_COUNT; return 0;}static struct file_operations ring_fops = { owner: THIS_MODULE, open: S3C2440_irint_open, read: S3C2440_irint_read, release: s3c2440_irint_release,#ifdef USE_ASYNC fasync: s3c2440_irint_fasync,#endif};/*----------------------------------------------------* func: 中断处理程序,关闭中断,开启键盘扫描定时器* param: * ** return: * ------------------------------------------------------*/static void irint_interrupt(int irq, void *dev_id, struct pt_regs *regs){ spin_lock_irq(&lock); disable_irq(IRQ_EINT2);// printk("<0>,interrupt is coming\n");/*#ifdef USE_ASYNC if(AsyncQueue) { // if(eint2_value ==0) kill_fasync(&(AsyncQueue), SIGIO, POLL_IN); } #endif*/ // eint2_value =1; //来了中断,将其值置为1;// eint_number=eint_number+1;//// if(FileMode == BLOCK) //如果是阻塞方式,唤醒在wq上的事件// wake_up_interruptible(&wq);/* if(!TimeOut) { //printk("<0> interrupt\n"); del_timer(&ring_timer); }*/ //启动定时器 TimerCount = 0; ring_timer.expires = jiffies + TIMER_DELAY; add_timer(&ring_timer);// enableIrq(); spin_unlock_irq(&lock);}/*----------------------------------------------------* func: 初始化eint2中断相关寄存器,安装中断处理程序* param: * ** return: * ------------------------------------------------------*/static int requestIrq(){ int ret; ret = set_external_irq(IRQ_EINT2,EXT_FALLING_EDGE,GPIO_PULLUP_DIS); if(ret) goto eint_failed ; ret = request_irq(IRQ_EINT2, irint_interrupt, SA_INTERRUPT, DEVICE_NAME, NULL); if(ret) goto eint2_failed; printk("requestIrq\n"); return 0;eint2_failed: free_irq(IRQ_EINT2, NULL);eint_failed: printk(DEVICE_NAME ": IRQ Requeset Error\n"); return ret;}/*----------------------------------------------------* func: 初始化键盘驱动,注册字符设备* param: * ** return: >=0 : 初始化键盘驱动成功 <0: 失败* ------------------------------------------------------*/static int __init s3c2440_irint_init(void){ int ret; /*注册设备*/ ret = register_chrdev(kbMajor, DEVICE_NAME, &ring_fops); if(ret < 0) { printk(DEVICE_NAME " can't get major number\n"); return ret; } eint_number=0; printk("%s: major number=%d\n",DEVICE_NAME,kbMajor); if(requestIrq() !=0) { unregister_chrdev(kbMajor, DEVICE_NAME); return -1; } init_timer(&ring_timer); ring_timer.function = timer_handler; lock = SPIN_LOCK_UNLOCKED; init_waitqueue_head(&wq); //sjw enableIrq(); //暂时禁止所有中断,等到open时再打开// disable_irq(IRQ_EINT2); return 0;}/*----------------------------------------------------* func: 注销字符设备,释放中断* param: * ** return: * ------------------------------------------------------*/static void __exit s3c2440_irint_exit(void){ /*注销设备*/ unregister_chrdev(kbMajor, DEVICE_NAME); /*释放中断*/ free_irq(IRQ_EINT2, NULL);}module_init(s3c2440_irint_init);module_exit(s3c2440_irint_exit);
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -