tiny6410_按键驱动程序_中断
2012-11-11 11:01
387 查看
key_drv_int.c: (采用双边沿触发)
key_app_int.c
Makefile
结果
#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> #define S3C6410_GPNDAT_PA (0x7F008834) #define S3C6410_GPLDAT_PA (0x7F008818) static volatile unsigned long* gpndat = NULL; static volatile unsigned long* gpldat = NULL; struct key_irq_desc{ int irq; int num; char *name; }; static struct key_irq_desc key_irqs[] = { {IRQ_EINT(0), 0, "KEY0"}, \ {IRQ_EINT(1), 1, "KEY1"}, \ {IRQ_EINT(2), 2, "KEY2"}, \ {IRQ_EINT(3), 3, "KEY3"}, \ {IRQ_EINT(4), 4, "KEY4"}, \ {IRQ_EINT(5), 5, "KEY5"}, \ {IRQ_EINT(19), 6, "KEY6"}, \ {IRQ_EINT(20), 7, "KEY7"} }; static volatile char key_values[] = {'0', '0', '0', '0', '0', '0', '0', '0'}; static int major = 0; static struct class* key_drv_int_class; static DECLARE_WAIT_QUEUE_HEAD(key_waitq); static volatile int ev_press = 0; static irqreturn_t key_drv_irq(int irq, void* dev_id) { int down; int key_num; struct key_irq_desc *key_irqs = (struct key_irq_desc *)dev_id; key_num = key_irqs->num; switch(key_num) { case 0: case 1: case 2: case 3: case 4: case 5: down = !(*gpndat & (1<<key_num)); break; case 6: case 7: down = !(*gpldat & (1 << (key_num + 5))); break; default: down = 0; break; } if (down != (key_values[key_num] & 1)) { key_values[key_num] = '0' + down; ev_press = 1; wake_up_interruptible(&key_waitq); } return IRQ_HANDLED; } static int key_drv_int_open(struct inode *inode, struct file *filp) { int i; int ret = 0; for (i=0; i<sizeof(key_irqs)/sizeof(key_irqs[0]); i++) { if(key_irqs[i].irq < 0) { continue; } ret = request_irq(key_irqs[i].irq, key_drv_irq, IRQ_TYPE_EDGE_BOTH, \ key_irqs[i].name, (void *)&key_irqs[i]); if (ret) break; } /* handle error */ if(ret) { i--; for( ; i>=0; i--) { if(key_irqs[i].irq < 0) { continue; } disable_irq(key_irqs[i].irq); free_irq(key_irqs[i].irq, (void *)&key_irqs[i]); } return -EBUSY; } ev_press = 1; /* map gpio pth_address to virtual address*/ gpndat= ioremap(S3C6410_GPNDAT_PA, 4); gpldat= ioremap(S3C6410_GPLDAT_PA, 4); return 0; } static ssize_t key_drv_int_read(struct file *file, char __user *buf, size_t count, loff_t *ppos) { unsigned long ret; if (!ev_press) { if (file->f_flags & O_NONBLOCK) { return -EAGAIN; } else { wait_event_interruptible(key_waitq, ev_press); } } ev_press = 0; ret = copy_to_user(buf, &key_values, sizeof(key_values)<count?sizeof(key_values):count); return ret ? (-EFAULT):(sizeof(key_values)<count?sizeof(key_values):count); } static int key_drv_int_close(struct inode *inode, struct file *file) { int i; for (i=0; i<sizeof(key_irqs)/sizeof(key_irqs[0]); i++) { if (key_irqs[i].irq < 0) { continue; } free_irq(key_irqs[i].irq, (void *)&key_irqs[i]); } iounmap(gpndat); iounmap(gpldat); return 0; } static struct file_operations key_drv_int = { .owner = THIS_MODULE, .open = key_drv_int_open, .read = key_drv_int_read, .release = key_drv_int_close, }; static int key_drv_int_init(void) { major = register_chrdev(0, "key_drv_int", &key_drv_int); if(major < 0) { printk(KERN_ALERT "Register key_drv_int failed!\n"); return -1; } printk(KERN_ALERT "Register key_drv_int succeed!\n"); /* 动态创建设备号,根据创建的设备号创建设备节点(/dev/key_drv_poll) */ key_drv_int_class= class_create(THIS_MODULE, "key_drv_int"); /* sysfs */ device_create(key_drv_int_class, NULL, MKDEV(major, 0), NULL, "key_drv_int"); /* /dev/key_drv_int */ return 0; } static void key_drv_int_exit(void) { device_destroy(key_drv_int_class, MKDEV(major, 0)); class_destroy(key_drv_int_class); unregister_chrdev(major, "key_drv_int"); printk(KERN_ALERT "Unregister key_drv_int succeed!\n"); } module_init(key_drv_int_init); module_exit(key_drv_int_exit); MODULE_LICENSE("GPL"); MODULE_DESCRIPTION("key driver use int"); MODULE_AUTHOR("dl CS0921 WTU");
key_app_int.c
#include <stdio.h> #include <stdlib.h> #include <unistd.h> #include <fcntl.h> #define DEVICE_NAME "/dev/key_drv_int" int main(int argc, char* argv[]) { int fd; fd = open(DEVICE_NAME, O_RDWR); if(fd < 0) { printf("Open %s failed!\n", DEVICE_NAME); exit(-1); } unsigned char key_values[8]; for( ; ; ) { read(fd, key_values, sizeof(key_values)); printf("key(1~8) value: %c %c %c %c %c %c %c %c\n", \ key_values[0], key_values[1], key_values[2], key_values[3],\ key_values[4], key_values[5], key_values[6], key_values[7]); } close(fd); return 0; }
Makefile
KERNELDIR = /sdb/kernel/linux-2.6.38-tiny6410/linux-2.6.38/ PWD := $(shell pwd) modules: $(MAKE) -C $(KERNELDIR) M=$(PWD) modules clean: rm -rf *.o *~ core .depend .*.cmd *.ko *.mod.c .tmp_versions .PHONY: modules clean obj-m := key_drv_int.o
结果
相关文章推荐
- tiny6410按键驱动程序1.0(利用中断)
- tiny6410 按键K0 中断
- 中断-----按键中断驱动程序
- Linux驱动程序学习笔记(4)——使用中断的按键驱动程序
- Linux按键驱动程序设计(2)-Linux中断处理程序
- 中断按键驱动程序
- 8.中断按键驱动程序之poll机制(详解)
- 07-S3C2440驱动学习(一)嵌入式linux字符设备驱动-查询+中断+引入poll机制的按键驱动程序
- linux按键中断驱动程序——S3C2440
- 韦东山驱动视频笔记——2.字符设备驱动程序之中断方式的按键驱动程序
- 内核中断及按键驱动程序
- tiny6410_按键驱动程序_轮询
- 字符设备驱动程序按键驱动---中断方式
- Hi3515按键中断驱动程序
- <2012 11 6 > linux设备驱动程序开发初探(4) linux的中断体系_按键中断驱动程序编写
- ok6410按键中断驱动程序
- 12.按键驱动程序设计(2)-Linux中断处理
- 字符设备驱动之按键处理二(中断处理的按键驱动程序)
- linux2.6内核下的一个按键中断驱动程序示例
- 【Tiny6410 And Linux】—(2.3)—使用工作队列处理按键中断——原理