tiny6410按键驱动(三)---中断发

来源:互联网 发布:卷积网络特征点提取 编辑:程序博客网 时间:2024/05/21 06:15

驱动代码如下:

#include <linux/module.h>#include <linux/kernel.h>#include <linux/fs.h>#include <linux/init.h>#include <linux/delay.h>#include <linux/poll.h>#include <linux/irq.h>#include <asm/irq.h>#include <asm/io.h>#include <linux/interrupt.h>#include <asm/uaccess.h>#include <mach/hardware.h>#include <linux/platform_device.h>#include <linux/cdev.h>#include <linux/miscdevice.h>#include <mach/map.h>#include <mach/regs-clock.h>#include <mach/regs-gpio.h>#include <plat/gpio-cfg.h>#include <mach/gpio-bank-n.h>#include <mach/gpio-bank-l.h>#include<linux/timer.h>static unsigned button_major;static dev_t button_id;  /*设备号*/static struct cdev button_cdev;static struct class *button_class;static struct device *button_device;static volatile char ev_press;           static DECLARE_WAIT_QUEUE_HEAD(button_waitq);  /*生成一个等待队列头wait_queue_head_t,名字为button_waitq*/struct buttons_irq_decs{                    int irq;char *name;                   };static struct buttons_irq_decs button_irqs[] = {{IRQ_EINT( 0),"K1"},{IRQ_EINT( 1),"K2"},{IRQ_EINT( 2),"K3"},{IRQ_EINT( 3),"K4"},  };static irqreturn_t buttons_irq(int irq, void *dev_id)  {struct buttons_irq_decs *irq_desc = (struct buttons_irq_decs*)dev_id ;printk("%s\n" ,irq_desc->name);ev_press = 1;wake_up_interruptible(&button_waitq);/*唤醒等待队列button_waitq里睡眠的进程*/return IRQ_HANDLED;}static int myButton_open(struct inode * inode, struct file * file){//printk("%d" , ev_press);int i;char err;for(i=0 ; i<sizeof(button_irqs)/sizeof(button_irqs[0]) ;i++){err = request_irq(button_irqs[i].irq , &buttons_irq ,IRQ_TYPE_EDGE_BOTH ,button_irqs[i].name ,&button_irqs[i] );                                                   /*IRQ_TYPE_EDGE_BOTH表示双边沿触发,即按键按下和松开都会触发中断*//*  request_irq()会自动把GPIO配置为中断引脚        request_irq()的第一个参数是硬件中断号,每种中断都对应一个硬件中断号             第二个参数是中断处理函数名,             第三个参数是中断触发的类型,也称为中断处理的属性,这个按键程序我们用的是双边沿触发,             第四个参数是出发中断的硬件名,可以随便取,cat /proc/interrupts中可以看到此名称             第五个参数是触发中断的硬件的相关信息*/   /*当发生中断时,IRQ_EINT( 0),&button_irqs[0]就会传进中断服务程序irqreturn_t buttons_irq(int irq, void *dev_id)*/  if(err){ printk("button_irqs[i] request faild\n");             continue;     }}printk("myButton_open end\n");return 0;}static int myButton_write(struct file *filp,const char __user *buf,size_t count,loff_t *f_pos){return 0;}static int myButton_read(struct file *file, char __user *userbuf, size_t bytes, loff_t *off){if(bytes != 1)   {    printk("you can read just one char from the decive\n");    return -1;   }printk("myButton_read start\n");wait_event_interruptible(button_waitq ,ev_press);/*当第二个参数不为0时,且button_waiq等待队列里的进程被唤醒,程序才会继续向下执行,  否则把当前进程放入等待队列button_waitq,让其休眠。  当发生中断时,在中断服务函数buttons_irq里会把ev_press置1,且唤醒等待队列button_waitq里休眠的进程(及当前进程)  程序继续向下执行。  可见当没有按键按下时,进程会在进入休眠。*/char value ;value = readl(S3C64XX_GPNDAT)&(0xf);   /*GPN0~3对应于按键K1~K4*/if(copy_to_user(userbuf, &value, bytes))    /*成功时返回0,失败时返回没有成功拷贝的字符个数*/       {        printk("copy_to_user error\n");return -1;   }ev_press =0 ;printk("myButton_read end\n");return 0;}static int myButton_release(struct inode *inode, struct file *file){int i;for(i=0 ; i<sizeof(button_irqs)/sizeof(button_irqs[0]) ;i++){     free_irq(button_irqs[i].irq, &button_irqs[i]);}printk("myButton_release\n");return 0;}struct file_operations button_fiops={.owner = THIS_MODULE,.open  = myButton_open,.write = myButton_write,.read  = myButton_read,.release = myButton_release,};static int myButton_init(void){   if(button_major){     button_id = MKDEV(button_major,0); register_chrdev_region(button_id, 2, "myButton_drv");}    else    {         alloc_chrdev_region(&button_id, 0, 2,"myButton_drv" ); button_major = MAJOR(button_id);    }cdev_init(&button_cdev, &button_fiops);cdev_add(&button_cdev, button_id, 2);       /*添加2个设备*/button_class = class_create(THIS_MODULE, "myButton");button_device = device_create(button_class, NULL, MKDEV(button_major , 0), NULL, "myButton0");  /*创建设备节点/dev/myButton0*/button_device = device_create(button_class, NULL, MKDEV(button_major , 1), NULL, "myButton1");  /*创建设备节点/dev/myButton1*/      printk("myButton init succeed\n");    return 0;}static void myButton_exit(void){device_destroy(button_class, MKDEV(button_major , 0));device_destroy(button_class, MKDEV(button_major , 1));class_destroy(button_class);cdev_del(&button_cdev);unregister_chrdev_region(button_id, 2);printk("myButton exit succeed\n");}module_init(myButton_init);module_exit(myButton_exit);MODULE_LICENSE("GPL");

Makefile文件如下:

obj-m := mybutton_drv3.oKDIR :=/home/lijunliang/windows-files/linux-tiny6410all :make -C $(KDIR) M=$(PWD) modules CROSS_COMPILE=arm-linux- ARCH=armclean :rm -f *.ko *.o *.mod.o *.mod.c *.symvers *.bak *.order

测试程序如下:

#include <stdio.h>  #include <sys/types.h>  #include <sys/stat.h>  #include <fcntl.h>  int main(void){int fd;char keyValue ; fd = open("/dev/myButton0",O_RDWR);while(1){   //read(fd ,userbuffer,bufferSize);   read(fd ,&keyValue ,1);   #if 0    switch(userbuffer[0])   {              case 0xe: printf("K1 按下\n");             break;   case 0xd: printf("K2 按下\n");     break;  case 0xb: printf("K3 按下\n");     break;  case 0x7: printf("K4 按下\n");     break;  default : break;    }  #endif              } //printf("%x\n",userbuffer0[0]);return 0;}


0 0
原创粉丝点击