基于韦东山的驱动修改的,由于内核版本不一样,包含到头文件有所变化,内核API函数也有所改变。
#include <linux/module.h> #include <linux/kernel.h> #include <linux/fs.h> #include <linux/init.h> #include <linux/delay.h> #include <linux/irq.h> #include <asm/uaccess.h> #include <asm/irq.h> #include <asm/io.h> #include <mach/regs-gpio.h> //修改 #include <mach/hardware.h> //修改 #include <linux/device.h> //增加 #include <mach/irqs.h> #include <linux/interrupt.h> #include <mach/gpio-fns.h> //修改 #include <linux/sched.h> //增加 static struct class *buttondrv_class; static struct class_device *buttondrv_class_dev; volatile unsigned long *gpfcon; volatile unsigned long *gpfdat; static DECLARE_WAIT_QUEUE_HEAD(button_waitq); /* 中断事件标志, 中断服务程序将它置1,button_drv_read将它清0 */ //static volatile int ev_press = 0; int err = 0; struct pin_desc{ unsigned int pin; unsigned int key_val; }; /* 键值: 按下时, 0x01 */ /* 键值: 松开时, 0x81 */ static unsigned char key_val; struct pin_desc pins_desc[] = {{S3C2410_GPF(5), 0x01},}; /* * 确定按键值 */ static irqreturn_t buttons_irq(int irq, void *dev_id) { struct pin_desc * pindesc = (struct pin_desc *)dev_id; unsigned int pinval; pinval = s3c2410_gpio_getpin(pindesc->pin); if (pinval) { /* 松开 */ key_val = 0x80 | pindesc->key_val; } else { /* 按下 */ key_val = pindesc->key_val; } // ev_press = 1; /* 表示中断发生了 */ // wake_up_interruptible(&button_waitq); /* 唤醒休眠的进程 */ return IRQ_RETVAL(IRQ_HANDLED); } static int button_drv_open(struct inode *inode, struct file *file) { /* 配置GPF5为输入引脚 */ err = request_irq(IRQ_EINT5, buttons_irq, IRQF_TRIGGER_HIGH, "S2", &pins_desc[0]); if(err < 0) { printk("fail to request_irq\n"); } return 0; } ssize_t button_drv_read(struct file *file, char __user *buf, size_t size, loff_t *ppos) { if (size != 1) return -EINVAL; /* 如果没有按键动作, 休眠 */ // wait_event_interruptible(button_waitq, ev_press); /* 如果有按键动作, 返回键值 */ err = copy_to_user(buf, &key_val, 1); if(err < 0) { printk("fail to copy_to_user\n"); } //ev_press = 0; return 1; } int button_drv_close(struct inode *inode, struct file *file) { free_irq(IRQ_EINT5, &pins_desc[0]); return 0; } static struct file_operations sencod_drv_fops = { .owner = THIS_MODULE, /* 这是一个宏,推向编译模块时自动创建的__this_module变量 */ .open = button_drv_open, .read = button_drv_read, .release = button_drv_close, }; int major; static int button_drv_init(void) { major = register_chrdev(0, "button_drv", &sencod_drv_fops); buttondrv_class = class_create(THIS_MODULE, "button_drv"); buttondrv_class_dev = device_create(buttondrv_class, NULL, MKDEV(major, 0), NULL, "buttons"); /* /dev/buttons */ gpfcon = (volatile unsigned long *)ioremap(0x56000050, 16); gpfdat = gpfcon + 1; return 0; } static void button_drv_exit(void) { unregister_chrdev(major, "button_drv"); device_unregister(buttondrv_class_dev); class_destroy(buttondrv_class); iounmap(gpfcon); return 0; } module_init(button_drv_init); module_exit(button_drv_exit); MODULE_LICENSE("GPL");
<pre name="code" class="cpp">S3C2410_GPF5修改为 S3C2410_GPF(5) 具体可以参阅kernel/Documentation/arm/Samsung-S3C24XX/GPIO.txtrequest_irq 第三个参数,中断触发方式到宏有所改变 改为 kernel/include/linux/interrupt.h中
/* * These correspond to the IORESOURCE_IRQ_* defines in * linux/ioport.h to select the interrupt line behaviour. When * requesting an interrupt without specifying a IRQF_TRIGGER, the * setting should be assumed to be "as already configured", which * may be as per machine or firmware initialisation. */ #define IRQF_TRIGGER_NONE 0x00000000 #define IRQF_TRIGGER_RISING 0x00000001 //上升沿触发 #define IRQF_TRIGGER_FALLING 0x00000002 #define IRQF_TRIGGER_HIGH 0x00000004 //高点平触发 #define IRQF_TRIGGER_LOW 0x00000008 #define IRQF_TRIGGER_MASK (IRQF_TRIGGER_HIGH | IRQF_TRIGGER_LOW | IRQF_TRIGGER_RISING | IRQF_TRIGGER_FALLING) #define IRQF_TRIGGER_PROBE 0x00000010
测试程序:
#include <sys/types.h> #include <sys/stat.h> #include <fcntl.h> #include <stdio.h> #include <unistd.h> /* thirddrvtest */ int main(int argc, char **argv) { int fd; unsigned char key_val; fd = open("/dev/buttons", O_RDWR); if (fd < 0) { printf("can't open!\n"); } while (1) { read(fd, &key_val, 1); //读取内核空间中的key_val值 //printf("key_val = 0x%x\n", key_val); sleep(1); if( key_val == 0x01 ) { printf("power off!\n"); } } return 0; }
下载到板子:
Linux操作
① # exec5</dev/key
② # cat /proc/interrupts
原文地址:http://blog.csdn.net/hanglinux/article/details/45056525