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
- tiny6410按键驱动(三)---中断发
- Tiny6410 按键中断驱动笔记
- tiny6410 按键K0 中断
- Linux驱动开发之三----按键驱动(Tiny6410)
- TINY6410 按键驱动分析
- tiny6410按键驱动总结
- Linux驱动程序开发之三----按键驱动(Tiny6410)
- tiny6410 通过按键玩中断
- tiny6410按键驱动程序1.0(利用中断)
- tiny6410按键驱动(一)---驱动框架
- 外部中断按键驱动
- fl2440按键中断驱动
- 按键中断驱动实例
- s3c6410中断按键驱动
- s5pc100中断按键驱动
- TQ2440 中断按键驱动
- OK6410 按键中断驱动
- 按键中断驱动
- UVA:11426 GCD - Extreme (II)
- Java初学者必须知道的11条基础知识
- Java EE - useBean异常
- C语言中的递归和迭代
- web服务器和Application服务器---20141224
- tiny6410按键驱动(三)---中断发
- Ping pong
- Java正则表达式
- 定点绕定轴旋转
- 实验四: 字符串和多维数组 实验
- suds文档
- 从头认识C—关于数组名
- 子龙山人
- hdu1026(bfs + priority_queue + 寻找路径)