按键驱动代码:
#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
我要赚赏金
