|
本帖最后由 vanbreaker 于 2012-2-17 14:42 编辑
看了TQ得例程,有点疑问,例程在驱动里好像没有配置那4个按键口的模式,也没有配置中端的触发方式呀,就是GPFCON和EINT0这2个寄存器,难道都不用配置么?我自己写了一个,但是好像不行,没有配置这2个寄存器的话,4个按键中端刚注册就会各触发一次,但是后面按键就进不去了!加了配置的话就从头到尾都不会触发了。。不过我不知道访问EINT0这个寄存器可不可以用ioremap..还没看内存这部分。。找了半天了还是没找到问题。。前面那些字符设备注册部分应该没问题,都是以前的模板。。麻烦写过按键驱动的兄台帮小弟看看吧,给点意见……!感谢!
#include<linux/module.h>
#include<linux/init.h>
#include<linux/types.h>
#include<linux/fs.h>
#include<linux/mm.h>
#include<linux/cdev.h>
#include<linux/slab.h>
#include<linux/irq.h>
#include<linux/interrupt.h>
#include<linux/platform_device.h>
#include<mach/regs-gpio.h>
#include<mach/hardware.h>
#include<asm/irq.h>
#include<asm/system.h>
#include<asm/io.h>
#include<asm/uaccess.h>
#define KEY_MAJOR 245
#define GPFCON_CFG_VAL ( (2<<0) | (2<<2) | (2<<4) | (2<<8) )
#define EINT0_CFG_VAL ( (2<<0) | (2<<4) | (2<<8) | (2<<16) )
volatile unsigned int *GPFCON = NULL;
volatile unsigned int *EINT0 = NULL;
static unsigned long key_major = KEY_MAJOR;
struct key_info
{
int irq_num;
int pin;
char* name;
int key_num;
};
struct key_dev
{
struct cdev cdev;
struct key_info key[4];
};
struct key_info key_init_info[4]=
{
{IRQ_EINT1,S3C2410_GPF1,"key1_irq",1},
{IRQ_EINT4,S3C2410_GPF4,"key2_irq",2},
{IRQ_EINT2,S3C2410_GPF2,"key3_irq",3},
{IRQ_EINT0,S3C2410_GPF0,"key4_irq",4}
};
struct key_dev *key_devp;
int press_num = 0;
int press_flag = 0;
irqreturn_t key_interrupt_handler(int irq,void *dev_id)
{
int ret;
struct key_info *key = (struct key_info*)dev_id;
ret = s3c2410_gpio_getpin(key->pin);
printk(KERN_NOTICE "Trig,%d\n",ret);
if(ret == 0)
{
printk(KERN_NOTICE "key %d press\n",key->key_num);
press_flag = 1;
}
return IRQ_RETVAL(IRQ_HANDLED);
}
static void load_keyinfo(void)
{
int i;
for(i=0;i<4;i++)
{
key_devp->key = key_init_info;
}
}
static int key_open(struct inode *inode,struct file *filp)
{
int i;
int ret;
for(i=0;i<4;i++)
{
ret = request_irq(key_devp->key.irq_num,
key_interrupt_handler,
IRQF_TRIGGER_FALLING,
key_devp->key.name,
(void*)&key_devp->key);
if(ret != 0)
{
printk(KERN_NOTICE "key %d irq register error!\n",i+1);
}
}
return 0;
}
static int key_release(struct inode *inode, struct file *filp)
{
int i;
for(i=0;i<4;i++)
{
free_irq(key_devp->key.irq_num,
(void*)&key_devp->key);
}
return 0;
}
static ssize_t key_read(struct file *filp, char __user *buf,
size_t size, loff_t *ppos)
{
return 0;
}
static const struct file_operations key_fops =
{
.owner = THIS_MODULE,
.read = key_read,
.open = key_open,
.release = key_release,
};
static void key_setup_cdev(struct key_dev *dev, int index)
{
int err,devno = MKDEV(key_major,index);
cdev_init(&dev->cdev,&key_fops);
dev->cdev.owner = THIS_MODULE;
err = cdev_add(&dev->cdev,devno,1);
if(err)
{
printk(KERN_NOTICE "Error %d adding %d\n",err,index);
}
}
static int key_irq_init(void)
{
int result;
dev_t devno = MKDEV(key_major,0);
if(key_major)
result = register_chrdev_region(devno,1,"key");
else
{
result = alloc_chrdev_region(&devno,0,1,"key");
key_major = MAJOR(devno);
}
if(result<0)
{
printk("register failed!");
return result;
}
/*涓鸿?澶囨弿杩扮粨鏋勫垎閰嶅唴瀛?/
key_devp =(struct key_dev*)kmalloc(sizeof(struct key_dev),GFP_KERNEL);
if(!key_devp)
{
result = -ENOMEM;
unregister_chrdev_region(devno,1);
}
memset(key_devp, 0 ,sizeof(struct key_dev));
key_setup_cdev(key_devp,0);
GPFCON = (volatile unsigned int*)ioremap(0x56000050,16);
*GPFCON = GPFCON_CFG_VAL;
EINT0 = (volatile unsigned int *)ioremap(0x56000088,32);
*EINT0 = EINT0_CFG_VAL; // falling trigger
load_keyinfo();
return 0;
}
static void key_irq_exit(void)
{
cdev_del(&key_devp->cdev);
kfree(key_devp);
unregister_chrdev_region(MKDEV(key_major,0),1);
}
MODULE_LICENSE("GPL");
module_init(key_irq_init);
module_exit(key_irq_exit);
只写了最基本的部分,只是测试一下能不能正常触发中断和读按键,在测试程序里就是直接调用open打开设备文件,可以正常打开,我就不贴了... |
|