按键驱动代码:
#include <linux/module.h> #include <linux/fs.h> #include <linux/miscdevice.h> #include <linux/interrupt.h> #include <linux/irq.h> #include <linux/gpio.h> #include <asm/uaccess.h> #include <linux/delay.h> #include <linux/sched.h> #define DEVICE_BUTTON "mybtn" #define BTN_MAJOR 255 static char keybuf[] = {"0"}; static struct miscdevice misc = { .minor = BTN_MAJOR, .name = DEVICE_BUTTON, }; irqreturn_t key_isr(int irq, void* dev) { int btn = 0; //读取按键状态 btn= !gpio_get_value(GPIOL(14)); printk("key %s\r\n", btn ? "down" : "up"); //把按键状态更新到对应的按缓冲中 keybuf = “0” + btn; return IRQ_HANDLED; } static ssize_t btn_read (struct file *flp, char __user *buff, size_t count, loff_t * off) { int ret ; if(!count) { return 0; } ret = copy_to_user(buff, keybuf, count); if(ret) { printk("error:copy_to_user\r\n"); return -EFAULT; } return count; } static const struct file_operations dev_fops = { .read = btn_read , .owner = THIS_MODULE, }; static int __init btn_init(void) { int ret; int irq; int flags; flags = IRQ_TYPE_EDGE_BOTH; irq = gpio_to_irq( GPIOL(14) ); //发生中断号为irq的中断会执行key_isr函数。注册成功会在/proc/irq号/KEY文件夹出现或 cat /proc/interrupts, 记录了本中断发生的次数cat /proc/irq/442/spurious ret = request_irq(irq,key_isr, flags, "KEY",NULL); if(ret < 0) { irq = gpio_to_irq( GPIOL(14) ); disable_irq(irq); free_irq(irq, NULL); return ret; } ret = misc_register(&misc); printk(KERN_EMERG " Device registered \n "); return ret; } static void __exit btn_exit(void) { int irq; irq = gpio_to_irq( GPIOL(14) ); disable_irq(irq); free_irq(irq, NULL); misc_deregister(&misc); printk(KERN_EMERG " Equipment logged out \n"); } module_init(btn_init); module_exit(btn_exit); MODULE_LICENSE("GPL");测试应用代码:
#include <stdio.h> #include <stdlib.h> #include <string.h> #include <sys/types.h> #include <sys/stat.h> #include <fcntl.h> #include <unistd.h> #include <sys/ioctl.h> #include <sys/types.h> #include <errno.h> #define DEV_NAME "/dev/mybtn" int main(int argc, char *args[]) { int fd = 0; int ret = 0; unsigned char recv_buf[1] = {"0"}; fd = open(DEV_NAME, O_RDONLY); //fd = open(DEV_NAME, O_RDONLY|O_NONBLOCK); if(fd < 0) { perror("open"); } while(1) { strcpy(recv_buf, "0000"); //读取按键数据 ret = read(fd, recv_buf, 1); if((ret < 0) && (errno != EAGAIN)) { perror("read"); exit(-1); } //输出按键状态 printf("%s\r\n", recv_buf); } return 0; }
Makefile代码:
KERN_DIR = /work/lichee/linux-3.4 all: make -C $(KERN_DIR) M=`pwd` modules arm-none-linux-gnueabi-gcc btntest.c -o btntest clean: make -C $(KERN_DIR) M=`pwd` modules clean rm -rf modules.order obj-m += btn_drv.o
遗憾的是,代码虽然能编译成功,但是驱动加载有错误,等找出原因再发帖补充,
开发板交流群 QQ:641395230