|
我是刚刚学习linux驱动开发,写了这个按键中断方式的驱动,在按下按键时,唤醒测试程序。这个例子是根据韦东山老师的按键驱动写的,我在中断函数中加入了打印,6个按键都可以正确触发,并打印中断号。但是就是测试程序没反应,啥都没见打印,我查看了进程显示一直在休眠!下面是驱动和测试程序,大侠们帮我这个菜鸟看看!
1:驱动
#include <linux/miscdevice.h>
#include <linux/delay.h>
#include <mach/regs-gpio.h>
#include <mach/hardware.h>
#include <linux/kernel.h>
#include <linux/module.h>
#include <linux/init.h>
#include <linux/mm.h>
#include <linux/fs.h>
#include <linux/types.h>
#include <linux/delay.h>
#include <linux/moduleparam.h>
#include <linux/slab.h>
#include <linux/errno.h>
#include <linux/ioctl.h>
#include <linux/cdev.h>
#include <linux/string.h>
#include <linux/list.h>
#include <linux/pci.h>
#include <linux/gpio.h>
#include <linux/device.h>
#include <linux/interrupt.h>
#include <linux/irq.h>
#include <linux/sched.h>
#include <linux/poll.h>
//#include <linux/irqreturn.h>
#include <linux/wait.h>
#include <asm/irq.h>
#include <asm/uaccess.h>
#include <asm/atomic.h>
#include <asm/unistd.h>
/*定义一个等待队列头*/
static DECLARE_WAIT_QUEUE_HEAD(button_waitq);
/*中断事件标志,中断服务程序将其置1,read函数将其置0*/
static volatile ev_press = 0;
/*设备号*/
int major;
/*保存按键值*/
static unsigned char key_value;
/*GPG配置寄存器和数值寄存器*/
#define GPGCONADDR 0x56000060 //GPBCON物理地址
#define GPGDATADDR 0x56000064
volatile unsigned long *gpgcon;
volatile unsigned long *gpgdat;
static struct class *thirddrv_class;
static struct device *thirddrv_class_dev;
static struct pin_desc{
int pin;
int key_value;
};
/*
*按键按下时值:0x01,0x02,0x03,....0x06
*按键松开时值:0x81,0x82,0x83,....0x86
*/
struct pin_desc pins_desc[6] = {
{S3C2410_GPG(0), 1 },
{S3C2410_GPG(3), 2 },
{S3C2410_GPG(5), 3 },
{S3C2410_GPG(6), 4 },
{S3C2410_GPG(7), 5 },
{S3C2410_GPG(11), 6 },
};
static irqreturn_t buttons_irq (int irq, void *dev_id)
{
struct pin_desc *pin_descs= (struct pin_desc *)dev_id;
unsigned char value;
value = s3c2410_gpio_getpin(pin_descs->pin);
if(value == 1)
{
key_value = pin_descs->key_value |0x80;
}
else
{
key_value = pin_descs->key_value;
}
ev_press = 1;
wake_up_interruptible(&button_waitq);
printk("irq = %d\n",irq); //这个可以打印出中断号,测试正确,说明进中断了
return IRQ_RETVAL(IRQ_HANDLED);
}
static int third_driver_open(struct inode *inode, struct file *file)
{
printk("third_driver_open\r\n");
/*读取键值key1=GPG0,key2=GPG3,key3=GPG5,KEY4=GPG6,KEY5=GPG7,KEY6=GPG11*/
request_irq(IRQ_EINT8, buttons_irq, IRQ_TYPE_EDGE_BOTH, "key1",&pins_desc[0]);
request_irq(IRQ_EINT11, buttons_irq, IRQ_TYPE_EDGE_BOTH, "key2",&pins_desc[1]);
request_irq(IRQ_EINT13, buttons_irq, IRQ_TYPE_EDGE_BOTH, "key3",&pins_desc[2]);
request_irq(IRQ_EINT14, buttons_irq, IRQ_TYPE_EDGE_BOTH, "key4",&pins_desc[3]);
request_irq(IRQ_EINT15, buttons_irq, IRQ_TYPE_EDGE_BOTH, "key5",&pins_desc[4]);
request_irq(IRQ_EINT19, buttons_irq, IRQ_TYPE_EDGE_BOTH, "key6",&pins_desc[5]);
return 0;
}
static int third_driver_read(struct file *flie, const char __user *buf, size_t count, loff_t *ppos)
{
if(count != 1)
{
printk("length err!");
return -EINVAL;
}
/*如果没有中断就进入休眠*/
wait_event_interruptible(button_waitq, ev_press);
ev_press = 0;
/*如果有中断就直接返回键值*/
copy_to_user(buf, &key_value, 1);//copy_to_user实现从用户空间读取参数到内核空间
return 1;
}
static int third_driver_close(struct inode *inode, struct file *file)
{
printk("third_driver_close\r\n");
free_irq(IRQ_EINT8, &pins_desc[0]);
free_irq(IRQ_EINT11, &pins_desc[1]);
free_irq(IRQ_EINT13, &pins_desc[2]);
free_irq(IRQ_EINT14, &pins_desc[3]);
free_irq(IRQ_EINT15, &pins_desc[4]);
free_irq(IRQ_EINT19, &pins_desc[5]);
return 0;
}
static struct file_operations third_driver_fops =
{
.owner = THIS_MODULE,
.open = third_driver_open,
.read = third_driver_read,
.release = third_driver_close,
};
int third_driver_init(void)
{
major = register_chrdev(0, "third_drv", &third_driver_fops);
thirddrv_class = class_create(THIS_MODULE, "thirddrv");
if (IS_ERR(thirddrv_class))
return PTR_ERR(thirddrv_class);
thirddrv_class_dev = device_create(thirddrv_class, NULL, MKDEV(major, 0),NULL, "buttons");
if(unlikely(IS_ERR(thirddrv_class_dev)))
return PTR_ERR(thirddrv_class_dev);
gpgcon = (volatile unsigned long *)ioremap(GPGCONADDR,16); //ioremap实现物理地址到虚拟地址的转换
gpgdat = gpgcon+1;
return 0;
}
static void third_driver_exist(void)
{
unregister_chrdev(major, "third_drv");
device_destroy(thirddrv_class, MKDEV(major, 0));
class_destroy(thirddrv_class);
iounmap(gpgcon);
return;
}
module_init(third_driver_init);
module_exit(third_driver_exist);
MODULE_LICENSE("GPL");
2:测试程序
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <stdio.h>
int main(int argc, const char * argv [ ])
{
int fd;
int key_value;
int resualt;
unsigned int cnt;
fd = open("/dev/buttons",O_RDWR);
if(fd<0)
{
printf("can't open file!\n");
return 0;
}
while(1)
{
resualt = read(fd,&key_value,1,NULL);
if(resualt==1)
{
printf("%d:key_value = 0x%x",cnt++,key_value);
}
else
{
printf("data length error!\n");
}
}
return 0;
}
|
阿莫论坛20周年了!感谢大家的支持与爱护!!
你熬了10碗粥,别人一桶水倒进去,淘走90碗,剩下10碗给你,你看似没亏,其实你那10碗已经没有之前的裹腹了,人家的一桶水换90碗,继续卖。说白了,通货膨胀就是,你的钱是挣来的,他的钱是印来的,掺和在一起,你的钱就贬值了。
|