TQ2440 中断按键驱动

来源:互联网 发布:用java代码输出我爱你 编辑:程序博客网 时间:2024/05/16 08:59

按键驱动程序:

#include<linux/module.h>#include<linux/kernel.h>#include<linux/fs.h>#include<linux/init.h>#include<linux/delay.h>#include<asm/irq.h>#include<linux/poll.h>#include<linux/irq.h>#include<asm/irq.h>#include<linux/interrupt.h>#include<asm/uaccess.h>#include<mach/regs-gpio.h>#include<mach/hardware.h>#include<linux/device.h>#include<linux/miscdevice.h>#include<linux/cdev.h>#define DEVICE_NAME "mybuttons"struct button_irq_desc{int irq;//中断号,中断号唯一表示一个中断int pin;//中断控制的寄存器,该寄存器的值由中断引脚设置,我们希望从该寄存器读出控制信息int pin_setting;//中断的引脚,该引脚的电平由按键来控制,从而最终我们由按键控制了寄存器的值int number;//编号char *name;//名称};//用来指定按键所用的外部中断引脚及中断触发方式、名字static struct button_irq_desc button_irqs[] ={{IRQ_EINT1, S3C2410_GPF1, S3C2410_GPF1_EINT1, 0, "KET1"},{IRQ_EINT4, S3C2410_GPF4, S3C2410_GPF4_EINT4, 1, "KET2"},{IRQ_EINT2, S3C2410_GPF2, S3C2410_GPF2_EINT2, 2, "KET3"},{IRQ_EINT0, S3C2410_GPF0, S3C2410_GPF0_EINT0, 3, "KET4"},};//按键值static volatile int key_values;//等待队列:当没有按键被按下,即没有触发中断时,如果有进程调用read函数,则该进程进入休眠static DECLARE_WAIT_QUEUE_HEAD(button_waitq);//定义了一个整型变量用于判定按键是否被按下,0未按下,1按下,中断事件标志,中断服务程序将它置1,read函数将其清0static volatile int ev_press = 0;//中断服务程序static irqreturn_t irq_interrupt(int irq,void *dev_id){struct button_irq_desc *button_irqs = (struct button_irq_desc *)dev_id;int up;up = s3c2410_gpio_getpin(button_irqs->pin);if(up)key_values = (button_irqs->number+1)+0x80;elsekey_values = (button_irqs->number+1);ev_press = 1;//表示中断发生wake_up_interruptible(&button_waitq);//唤醒休眠的进程return IRQ_RETVAL(IRQ_HANDLED);}static int irq_open(struct inode *inode,struct file *file){        int i;int err = 0;        for(i = 0;i < sizeof(button_irqs)/sizeof(button_irqs[0]);i++)        {//设置引脚            s3c2410_gpio_cfgpin(button_irqs[i].pin,button_irqs[i].pin_setting);//注册中断err = request_irq(button_irqs[i].irq,irq_interrupt,IRQ_TYPE_EDGE_BOTH,button_irqs[i].name,(void *)&button_irqs[i]);// request_irq 的返回值: 0 指示成功,或返回一个负的错误码,如 -EBUSY 表示另一个驱动已经占用了你所请求的中断线。if(err)break;        }if(err){i--;for(;i >= 0; i--){if(button_irqs[i].irq < 0)continue;//释放已注册的中断disable_irq(button_irqs[i].irq);free_irq(button_irqs[i].irq,(void *)&button_irqs[i]);}return -EBUSY;}ev_press = 1;        return 0;}static int irq_close(struct inode *inode,struct file *file){int i;for(i = 0; i < sizeof(button_irqs)/sizeof(button_irqs[0]); i++){//释放已注册的中断disable_irq(button_irqs[i].irq);free_irq(button_irqs[i].irq,(void *)&button_irqs[i]);}return 0;}static int irq_read(struct file *file,char __user *buff,size_t count,loff_t *offp){unsigned long err;if(!ev_press){if(file->f_flags & O_NONBLOCK)return -EAGAIN;else//如果ev_press等于0,则进入休眠wait_event_interruptible(button_waitq,ev_press);}//按键状态复制给用户进程err = copy_to_user(buff,&key_values,1);//这里ev_press等于1,将它清0ev_press = 0;return 1;}//当用户程序调用select函数时,本函数被调用,如果有按键数据,则select函数会立刻返回,如果没有按键数据,本函数使用poll_wait等待static unsigned int irq_poll(struct file *file,struct poll_table_struct *wait){unsigned int mask = 0;poll_wait(file,&button_waitq,wait);if(ev_press)mask |= POLLIN | POLLRDNORM;return mask;}static struct file_operations buttons_fops ={        .owner = THIS_MODULE,        .open  = irq_open,        .release = irq_close,.read  = irq_read,.poll  = irq_poll,};static struct miscdevice misc = {        .minor =MISC_DYNAMIC_MINOR,        .name = DEVICE_NAME,        .fops = &buttons_fops,};static int __init buttons_init(void){        int reg;        reg = misc_register(&misc);        printk(DEVICE_NAME" initialized\n");        return reg;}static void __exit buttons_exit(void){        misc_deregister(&misc);        printk("deregister\n");}module_init(buttons_init);module_exit(buttons_exit);MODULE_AUTHOR("xh");MODULE_DESCRIPTION("learn");MODULE_LICENSE("GPL");


Makefile:

ifneq($(KERNELRELEASE),)obj-m :=key.oelse#KERNELDIR :=/lib/modules/2.6.32-21-generic/buildKERNELDIR :=/opt/EmbedSky/linux-2.6.30.4PWD :=$(shell pwd)default:$(MAKE) -C $(KERNELDIR) M=$(PWD) modulesendifclean:rm -f *.o *.ko.PHONY:clean



按键测试程序:

#include<stdlib.h>#include<stdio.h>#include<unistd.h>#include<sys/ioctl.h>#include<sys/types.h>#include<sys/stat.h>#include<fcntl.h>#include<sys/select.h>#include<sys/time.h>#include<errno.h>#define DEV "/dev/mybuttons"int main(void){int i;int buttons_fd;int key_value = 0;struct timeval tv;//打开设备文件buttons_fd = open(DEV,O_RDWR);if(buttons_fd < 0){perror(DEV);exit(1);}while(1){fd_set rds;int ret;FD_ZERO(&rds);FD_SET(buttons_fd,&rds);//设置select超时时间,1stv.tv_sec = 1;tv.tv_usec = 0;//调用selectret = select(buttons_fd+1,&rds,NULL,NULL,&tv);if(ret < 0){perror("select");exit(1);}if(ret == 0){printf("Timeout\n");}//能读到数据else if(FD_ISSET(buttons_fd,&rds)){//调用read,读取键盘数据int ret = read(buttons_fd,&key_value,1);if(ret != 1){if(errno != EAGAIN)perror("read buttons\n");continue;}else{//打印printf("key_val = 0x%x\n",key_value);}}}return 0;}







原创粉丝点击