📄 interrupt.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-Ring" //键盘设备名static int kbMajor = 0; //默认的主设备号static u_short Eint19_Value = 1;static int TimeOut = 0; //超时标志#define TIMER_DELAY (6*HZ) /* 自动重复开始延时:1秒*/static struct timer_list ring_timer;static wait_queue_head_t wq ; //声明等待队列//spinlock_t repeat_lock;spinlock_t lock;static u_int FileMode;#define BLOCK 1#define NONBLOCK 0#define USE_ASYNC 1#ifdef USE_ASYNCstatic struct fasync_struct *AsyncQueue =NULL;#endifstatic int requestIrq();#ifdef USE_ASYNCstatic int s3c2440_Ring_fasync(struct inode *inode, struct file *filp, int mode){ return fasync_helper(inode, filp, mode, &AsyncQueue);}#endif/*----------------------------------------------------* func: 读取eint19当前值* param: * * return: * ------------------------------------------------------*//*int get_eint19_value(){ u_int IOValue; IOValue = GPGDAT ; IOValue &= 0xF7FF; IOValue >>= 11; return IOValue; }*/static inline void timer_handler(unsigned long data){#ifdef USE_ASYNC if(AsyncQueue) { if(Eint19_Value ==0) kill_fasync(&(AsyncQueue), SIGIO, POLL_HUP); }#endif Eint19_Value = 1; TimeOut = 1;}/*----------------------------------------------------* func: 使能中断* param: * return: * ------------------------------------------------------*///使能中断static void enableIrq(){ //清除SRCPND寄存器中eint19相应位 SRCPND = 0x00000002; //SRCPND= 0x00000020; //使能中断 //enable_irq(IRQ_EINT1); enable_irq(IRQ_EINT1); }/*----------------------------------------------------* func: 对应文件读的函数,如果循环队列中有键码, 则将键码拷贝到用户空间的buffer中* param: * * return: * 返回从循环队列中读取的键码的字节数** ------------------------------------------------------*/static ssize_tS3C2440_Ring_read(struct file *filp, char *buffer, size_t count, loff_t * ppos){ if(FileMode == BLOCK) { if (Eint19_Value ==1) { interruptible_sleep_on(&wq); if(signal_pending(current)) return -ERESTARTSYS; } } count = sizeof(Eint19_Value); copy_to_user(buffer,&Eint19_Value,count); return count; }/*----------------------------------------------------* func: 与打开文件对应的open函数,初始化全局变量和定* 时器以及请求中断* param: * ** return: * ------------------------------------------------------*/static int S3C2440_Ring_open(struct inode *inode, struct file *filp){ lock = SPIN_LOCK_UNLOCKED; printk("<0> open\n"); if(filp->f_flags & O_NONBLOCK) { FileMode = BLOCK; } else { FileMode = NONBLOCK; } //初始化定时器 init_timer(&ring_timer); ring_timer.function = timer_handler; enableIrq(); MOD_INC_USE_COUNT; return 0;}static int s3c2440_Ring_release(struct inode *inode, struct file *filp){ disable_irq(IRQ_EINT1); s3c2440_Ring_fasync(inode,filp,0); MOD_DEC_USE_COUNT; return 0;}static struct file_operations ring_fops = { owner: THIS_MODULE, open: S3C2440_Ring_open, read: S3C2440_Ring_read, release: s3c2440_Ring_release,#ifdef USE_ASYNC fasync: s3c2440_Ring_fasync,#endif};/*----------------------------------------------------* func: 中断处理程序,关闭中断,开启键盘扫描定时器* param: * ** return: * ------------------------------------------------------*/static void Ring_interrupt(int irq, void *dev_id, struct pt_regs *regs){ //spin_lock_irq(&lock); printk("<0> interrupt\n");#ifdef USE_ASYNC if(AsyncQueue) { if(Eint19_Value ==1) kill_fasync(&(AsyncQueue), SIGIO, POLL_IN); } #endif Eint19_Value = -1; if(FileMode == BLOCK) wake_up_interruptible(&wq); if(!TimeOut) { del_timer(&ring_timer); } //启动定时器 TimeOut = 0; ring_timer.expires = jiffies + TIMER_DELAY; add_timer(&ring_timer); //spin_unlock_irq(&lock);}/*----------------------------------------------------* func: 初始化eint19中断相关寄存器,安装中断处理程序* param: * ** return: * ------------------------------------------------------*/static int requestIrq(){ int ret; ret = set_external_irq(IRQ_EINT1,EXT_FALLING_EDGE,GPIO_PULLUP_DIS); if(ret) goto eint_failed ; ret = request_irq(IRQ_EINT1, Ring_interrupt, SA_INTERRUPT, DEVICE_NAME, NULL); if(ret) goto eint19_failed; printk("requestIrq\n"); return 0;eint19_failed: free_irq(IRQ_EINT1, NULL);eint_failed: printk(DEVICE_NAME ": IRQ Requeset Error\n"); return ret;}/*----------------------------------------------------* func: 初始化键盘驱动,注册字符设备* param: * ** return: >=0 : 初始化键盘驱动成功 <0: 失败* ------------------------------------------------------*/static int __init s3c2440_Ring_init(void){ int ret; /*注册设备*/ ret = register_chrdev(98, DEVICE_NAME, &ring_fops); if(ret < 0) { printk(DEVICE_NAME " can't get major number\n"); return ret; } printk("%s: major number=98\n",DEVICE_NAME); kbMajor = ret; if(requestIrq() !=0) { unregister_chrdev(kbMajor, DEVICE_NAME); return -1; } //暂时禁止所有中断,等到open时再打开 //disable_irq(IRQ_EINT1); return 0;}/*----------------------------------------------------* func: 注销字符设备,释放中断* param: * ** return: * ------------------------------------------------------*/static void __exit s3c2440_Ring_exit(void){ /*注销设备*/ unregister_chrdev(kbMajor, DEVICE_NAME); /*释放中断*/ free_irq(IRQ_EINT1, NULL);}module_init(s3c2440_Ring_init);module_exit(s3c2440_Ring_exit);
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -