| 
 | 
 
 本帖最后由 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打开设备文件,可以正常打开,我就不贴了... |   
 
 
 
 |