6410之中断处理编写代码(1)

来源:互联网 发布:mac eclipse真机调试 编辑:程序博客网 时间:2024/06/14 14:36

代码如下,在open中申请中断,在release中释放中断。

#include <linux/module.h>#include <linux/kernel.h>#include <linux/fs.h>#include <linux/init.h>#include <asm/uaccess.h>#include <linux/device.h>#include <asm/io.h>#include <linux/interrupt.h>struct class *buttons_class;struct device *buttons_dev;volatile unsigned long *gpncon = NULL;volatile unsigned long *gpndat = NULL;static irqreturn_t button_irq_handle(int irq, void *devid){printk("irq = %d\n",irq);return IRQ_HANDLED;}static int buttons_drv_open(struct inode *inode, struct file *file){printk("buttons_drv_open \n");//配置按键gpio引脚为输入引脚//*gpncon &= ~0xfff;request_irq(IRQ_EINT(0),button_irq_handle,IRQF_TRIGGER_FALLING|IRQF_TRIGGER_RISING, "PAD1", 1);request_irq(IRQ_EINT(1),button_irq_handle,IRQF_TRIGGER_FALLING|IRQF_TRIGGER_RISING, "PAD2", 1);request_irq(IRQ_EINT(2),button_irq_handle,IRQF_TRIGGER_FALLING|IRQF_TRIGGER_RISING, "PAD3", 1);request_irq(IRQ_EINT(3),button_irq_handle,IRQF_TRIGGER_FALLING|IRQF_TRIGGER_RISING, "PAD4", 1);return 0;}static ssize_t buttons_drv_read( struct file *file,  char __user *buffer,  size_t len,  loff_t *offset ){//printk("buttons_drv_read \n");char reg_val[6];if(len != sizeof(reg_val)){return -EINVAL;}int i;for(i = 0 ; i < 6 ; i++){reg_val[i] = (*gpndat & 1 << i ) ? 1 : 0;}copy_to_user(buffer,reg_val,sizeof(reg_val));return sizeof(reg_val);}int buttons_drv_release(struct inode *inode, struct file *file){free_irq(IRQ_EINT(0),1);free_irq(IRQ_EINT(1),1);free_irq(IRQ_EINT(2),1);free_irq(IRQ_EINT(3),1);return 0;}static struct file_operations buttons_fops = {    .owner   =   THIS_MODULE,        .open    =   buttons_drv_open,    .read    =   buttons_drv_read,    .release =   buttons_drv_release,};int major;static int __init buttons_drv_init(void){printk("buttons_drv_init \n");major = register_chrdev(0,"buttons",&buttons_fops);buttons_class = class_create(THIS_MODULE,"buttons");buttons_dev = device_create(buttons_class,NULL,MKDEV(major,0),NULL,"buttons");gpncon = (volatile unsigned long *)ioremap(0x7F008830 ,16);gpndat = gpncon + 1;return 0;}static void __exit buttons_drv_exit(void){device_destroy(buttons_class,MKDEV(major,0));class_destroy(buttons_class);unregister_chrdev(major,"buttons");iounmap(gpncon);}module_init(buttons_drv_init);module_exit(buttons_drv_exit);MODULE_LICENSE("GPL"); 

编译后,

执行

/test # insmod buttons_drv_irq.ko                                               
buttons_drv_init                                                                
/test # lsmod                                                                   
buttons_drv_irq 1788 0 - Live 0xbf000000                                        
/test # exec 5</dev/buttons                                                     
buttons_drv_open


其中的PAD1-PAD4就是申请的中断


关闭exec 5<&-


优化代码:

#include <linux/module.h>#include <linux/kernel.h>#include <linux/fs.h>#include <linux/init.h>#include <asm/uaccess.h>#include <linux/device.h>#include <asm/io.h>#include <linux/interrupt.h>#include <mach/regs-gpio.h>#include <linux/gpio.h>struct class *buttons_class;struct device *buttons_dev;volatile unsigned long *gpncon = NULL;volatile unsigned long *gpndat = NULL;static unsigned char key_val;struct pin_desc{unsigned int pin;unsigned int key_val;};struct pin_desc pins_desc[4] = {{S3C64XX_GPN(0),0x01},{S3C64XX_GPN(1),0x02},{S3C64XX_GPN(2),0x03},{S3C64XX_GPN(3),0x04},};static irqreturn_t button_irq_handle(int irq, void *devid){printk("irq = %d\n",irq);struct pin_desc * pindesc = (struct pin_desc *)devid;unsigned int pinval;pinval = gpio_get_value(pindesc->pin);if (pinval){key_val = 0x80 | pindesc->key_val;printk("songkai\n");}else{key_val = pindesc->key_val;printk("anxia\n");}return IRQ_HANDLED;}static int buttons_drv_open(struct inode *inode, struct file *file){printk("buttons_drv_open \n");request_irq(IRQ_EINT(0),button_irq_handle,IRQF_TRIGGER_FALLING|IRQF_TRIGGER_RISING, "PAD1", &pins_desc[0]);request_irq(IRQ_EINT(1),button_irq_handle,IRQF_TRIGGER_FALLING|IRQF_TRIGGER_RISING, "PAD2", &pins_desc[1]);request_irq(IRQ_EINT(2),button_irq_handle,IRQF_TRIGGER_FALLING|IRQF_TRIGGER_RISING, "PAD3", &pins_desc[2]);request_irq(IRQ_EINT(3),button_irq_handle,IRQF_TRIGGER_FALLING|IRQF_TRIGGER_RISING, "PAD4", &pins_desc[3]);return 0;}static ssize_t buttons_drv_read( struct file *file,  char __user *buffer,  size_t len,  loff_t *offset ){if (len != 1)return -EINVAL;copy_to_user(buffer, &key_val, 1);return 1;}int buttons_drv_release(struct inode *inode, struct file *file){free_irq(IRQ_EINT(0),&pins_desc[0]);free_irq(IRQ_EINT(1),&pins_desc[1]);free_irq(IRQ_EINT(2),&pins_desc[2]);free_irq(IRQ_EINT(3),&pins_desc[3]);return 0;}static struct file_operations buttons_fops = {    .owner   =   THIS_MODULE,        .open    =   buttons_drv_open,    .read    =   buttons_drv_read,    .release =   buttons_drv_release,};int major;static int __init buttons_drv_init(void){printk("buttons_drv_init \n");major = register_chrdev(0,"buttons",&buttons_fops);buttons_class = class_create(THIS_MODULE,"buttons");buttons_dev = device_create(buttons_class,NULL,MKDEV(major,0),NULL,"buttons");return 0;}static void __exit buttons_drv_exit(void){device_destroy(buttons_class,MKDEV(major,0));class_destroy(buttons_class);unregister_chrdev(major,"buttons");}module_init(buttons_drv_init);module_exit(buttons_drv_exit);MODULE_LICENSE("GPL"); 

目前中断程序还没有完成,如果使用之前查询方式的测试程序,还会出现不断的读取键值的现象。这就需要引入休眠唤醒操作

休眠的API为:

wait_event_interruptible(button_waitq, ev_press);

定义如下:

#define wait_event_interruptible(wq, condition) \
({ \
int __ret = 0;\
if (!(condition))\
__wait_event_interruptible(wq, condition, __ret);\    //当condition为0的时候,应用程序就进入休眠
__ret; \
})

唤醒的API为:

wake_up_interruptible(&button_waitq);

代码如下:

#include <linux/module.h>#include <linux/kernel.h>#include <linux/fs.h>#include <linux/init.h>#include <asm/uaccess.h>#include <linux/device.h>#include <asm/io.h>#include <linux/interrupt.h>#include <mach/regs-gpio.h>#include <linux/gpio.h>struct class *buttons_class;struct device *buttons_dev;static DECLARE_WAIT_QUEUE_HEAD(button_waitq);//定义休眠队列static volatile int ev_press = 0; //初始值为0,处于休眠状态static unsigned char key_val;struct pin_desc{unsigned int pin;unsigned int key_val;};struct pin_desc pins_desc[4] = {{S3C64XX_GPN(0),0x01},{S3C64XX_GPN(1),0x02},{S3C64XX_GPN(2),0x03},{S3C64XX_GPN(3),0x04},};static irqreturn_t button_irq_handle(int irq, void *devid){printk("irq = %d\n",irq);struct pin_desc * pindesc = (struct pin_desc *)devid;unsigned int pinval;pinval = gpio_get_value(pindesc->pin);if (pinval){key_val = 0x80 | pindesc->key_val;printk("songkai\n");}else{key_val = pindesc->key_val;printk("anxia\n");}ev_press = 1;   //唤醒                  wake_up_interruptible(&button_waitq);  return IRQ_HANDLED;}static int buttons_drv_open(struct inode *inode, struct file *file){printk("buttons_drv_open \n");request_irq(IRQ_EINT(0),button_irq_handle,IRQF_TRIGGER_FALLING|IRQF_TRIGGER_RISING, "PAD1", &pins_desc[0]);request_irq(IRQ_EINT(1),button_irq_handle,IRQF_TRIGGER_FALLING|IRQF_TRIGGER_RISING, "PAD2", &pins_desc[1]);request_irq(IRQ_EINT(2),button_irq_handle,IRQF_TRIGGER_FALLING|IRQF_TRIGGER_RISING, "PAD3", &pins_desc[2]);request_irq(IRQ_EINT(3),button_irq_handle,IRQF_TRIGGER_FALLING|IRQF_TRIGGER_RISING, "PAD4", &pins_desc[3]);return 0;}static ssize_t buttons_drv_read( struct file *file,  char __user *buffer,  size_t len,  loff_t *offset ){if (len != 1)return -EINVAL;wait_event_interruptible(button_waitq, ev_press);//进入睡眠copy_to_user(buffer, &key_val, 1);ev_press = 0;return 1;}int buttons_drv_release(struct inode *inode, struct file *file){free_irq(IRQ_EINT(0),&pins_desc[0]);free_irq(IRQ_EINT(1),&pins_desc[1]);free_irq(IRQ_EINT(2),&pins_desc[2]);free_irq(IRQ_EINT(3),&pins_desc[3]);return 0;}static struct file_operations buttons_fops = {    .owner   =   THIS_MODULE,        .open    =   buttons_drv_open,    .read    =   buttons_drv_read,    .release =   buttons_drv_release,};int major;static int __init buttons_drv_init(void){printk("buttons_drv_init \n");major = register_chrdev(0,"buttons",&buttons_fops);buttons_class = class_create(THIS_MODULE,"buttons");buttons_dev = device_create(buttons_class,NULL,MKDEV(major,0),NULL,"buttons");return 0;}static void __exit buttons_drv_exit(void){device_destroy(buttons_class,MKDEV(major,0));class_destroy(buttons_class);unregister_chrdev(major,"buttons");}module_init(buttons_drv_init);module_exit(buttons_drv_exit);MODULE_LICENSE("GPL");

使用top发现该程序使用的资源很少:






原创粉丝点击