免费注册 查看新帖 |

Chinaunix

  平台 论坛 博客 文库
最近访问板块 发新帖
查看: 3622 | 回复: 7
打印 上一主题 下一主题

[驱动] mini6410按键驱动问题!!!! [复制链接]

论坛徽章:
0
跳转到指定楼层
1 [收藏(0)] [报告]
发表于 2011-10-18 15:59 |只看该作者 |倒序浏览
#include <linux/module.h>
#include <linux/kernel.h>
#include <linux/fs.h>
#include <linux/init.h>
#include <linux/delay.h>
#include <linux/input.h>
#include <linux/poll.h>
#include <linux/irq.h>
#include <asm/irq.h>
#include <asm/io.h>
#include <linux/interrupt.h>
#include <asm/uaccess.h>
#include <mach/hardware.h>
#include <linux/platform_device.h>
#include <linux/cdev.h>
#include <linux/miscdevice.h>
#include <mach/map.h>

#include <plat/gpio-cfg.h>
#include <plat/regs-clock.h>
#include <plat/regs-gpio.h>
#include <mach/gpio.h>

#include <plat/gpio-bank-n.h>

MODULE_AUTHOR("HaNdAEr";
MODULE_LICENSE("GPL";



struct input_dev* button_devp;
static char *name = "s3c6410_buttons";

struct button_irq_desc{
        int irq;
        //int pin;
        int number;
        char *name;
};

static struct button_irq_desc button_irqs[] = {
        { IRQ_EINT(0),  /*S3C64XX_GPN(0), */  0,  "KEY1"},
        { IRQ_EINT(1),  /*S3C64XX_GPN(1), */  1,  "KEY2"},
        { IRQ_EINT(2),  /*S3C64XX_GPN(2), */  2,  "KEY3"},
        { IRQ_EINT(3),  /*S3C64XX_GPN(3), */  3,  "KEY4"},
        { IRQ_EINT(4),  /*S3C64XX_GPN(4), */  4,  "KEY5"},
        { IRQ_EINT(5),  /*S3C64XX_GPN(5), */  5,  "KEY6"},
        { IRQ_EINT(19), /*S3C64XX_GPL(19),*/  19, "KEY7"},
        { IRQ_EINT(20), /*S3C64XX_GPL(20),*/  20, "KEY8"},
};

static irqreturn_t  button_interrupt(int irq, void* dev_id)
{

        struct button_irq_desc *button_irqs = (struct button_irq_desc*)dev_id;
        int updown,reportval;
        if(button_irqs->number <0){
                return -1;
        }

        if(button_irqs->number <=5){
                updown = readl(S3C64XX_GPNDAT) & ( 0x1 << button_irqs->number);
        }else{
                updown = readl(S3C64XX_GPLDAT) & ( 0x1 << button_irqs->number);
        }

        reportval = updown ? 0 : 1;

        switch(button_irqs->number)
        {
                case 0:
                        input_report_key(button_devp, BTN_0, reportval);
                        break;
                case 1:
                        input_report_key(button_devp, BTN_1, reportval);
                        break;
                case 2:
                        input_report_key(button_devp, BTN_2, reportval);
                        break;
                case 3:
                        input_report_key(button_devp, BTN_3, reportval);
                        break;
                case 4:
                        input_report_key(button_devp, BTN_4, reportval);
                        break;
                case 5:
                        input_report_key(button_devp, BTN_5, reportval);
                        break;
                case 6:
                        input_report_key(button_devp, BTN_6, reportval);
                        break;
                case 7:
                        input_report_key(button_devp, BTN_7, reportval);
                        break;
                default:
                        break;
        }   
        input_sync(button_devp);
        return IRQ_RETVAL(IRQ_HANDLED);

}

static int __init button_init(void)
{
        int i;
        int err = 0;
        int ret = 0;

        struct input_dev *input_dev;

        input_dev = input_allocate_device();
        if(!input_dev){
                printk(KERN_ERR"Unable to alloc the input device!!\n";
        }

        button_devp = input_dev;

        button_devp->evbit[0] = BIT(EV_KEY) | BIT(EV_SYN);
        button_devp->keybit[BIT_WORD(BTN_0)] = BIT_MASK(BTN_0) | BIT_MASK(BTN_1) | BIT_MASK(BTN_2) |
                BIT_MASK(BTN_3) | BIT_MASK(BTN_4) | BIT_MASK(BTN_5) | BIT_MASK(BTN_6) | BIT_MASK(BTN_7);

        button_devp->name = name;
        for(i = 0; i < sizeof(button_irqs)/sizeof(button_irqs[0]); i++)
        {
                err = request_irq(button_irqs[i].irq, button_interrupt, IRQ_TYPE_EDGE_BOTH, button_irqs[i].name, (void *)&button_irqs[i]);
                if(err)
                {
                        break;
                }
        }

        if(err)
        {
                i--;
                for(; i >= 0; i--)
                {
                        if(button_irqs[i].irq < 0)
                        {
                                continue;
                        }
                        disable_irq(button_irqs[i].irq);
                        free_irq(button_irqs[i].irq, (void*)&button_irqs[i]);
                }
                return -EBUSY;
        }
        /*
        set_bit(EV_KEY, button_devp->evbit);
        set_bit(BTN_0,  button_devp->keybit);
        set_bit(BTN_1,  button_devp->keybit);
        set_bit(BTN_2,  button_devp->keybit);
        set_bit(BTN_3,  button_devp->keybit);
        set_bit(BTN_4,  button_devp->keybit);
        set_bit(BTN_5,  button_devp->keybit);
        set_bit(BTN_6,  button_devp->keybit);
        set_bit(BTN_7,  button_devp->keybit);
*/
        ret = input_register_device(button_devp);
       
        if(ret < 0){
                printk("input_register_device(): failed !! \n";
        }

        return ret;
}

static void __exit button_exit(void)
{
        int i;
        for(i = 0; i < sizeof(button_irqs)/sizeof(button_irqs[0]); i++)
        {
                disable_irq(button_irqs[i].irq);
                free_irq(button_irqs[i].irq, (void*)&button_irqs[i]);
        }
        input_unregister_device(button_devp);
}

module_init(button_init);
module_exit(button_exit);







每按下或者抬起都多出现一次空数据!!!!
大家帮忙测一下为什么出现问题!

论坛徽章:
0
2 [报告]
发表于 2011-10-18 16:06 |只看该作者
mini6410的板子,
8个按键,
EINT0 ------ GPN0
.                    .
.                    .
.                    .
EINT5--------GPN5

EINT19-------GPL(19)
EINT20-------GPL(20)

论坛徽章:
0
3 [报告]
发表于 2011-10-19 09:55 |只看该作者
本帖最后由 npuazm 于 2011-10-19 10:30 编辑

帮楼主顶顶{:3_189:}

论坛徽章:
0
4 [报告]
发表于 2011-10-19 10:58 |只看该作者
有个疑惑

request_irq(button_irqs[i].irq, button_interrupt, IRQ_TYPE_EDGE_BOTH, button_irqs[i].name, (void *)&button_irqs[i]);
楼主的意思采用上升和下降产生中断
好像GPIO中断的属性(上升沿,下降沿)不是这样定义的吧
应该是初始化板级信息的时候,采用如下方式初始化的
set_irq_type(IXP4XX_GPIO_IRQ(INTD), IRQ_TYPE_LEVEL_LOW);

建议楼主,在代码init 中添加类似的初始化代码

另外修改
err = request_irq(button_irqs[i].irq, button_interrupt, IRQ_TYPE_EDGE_BOTH, button_irqs[i].name, (void *)&button_irqs[i]);
变为
err = request_irq(button_irqs[i].irq, button_interrupt, IRQF_DISABLED, button_irqs[i].name, (void *)&button_irqs[i]);

论坛徽章:
0
5 [报告]
发表于 2011-10-19 13:28 |只看该作者
经过测试没什么问题啊!驱动没问题,另外改一下
EINT19----GPL11
EINT20----GPL20

论坛徽章:
0
6 [报告]
发表于 2011-10-19 13:29 |只看该作者
回复 4# npuazm


    IRQF_DISABLED 这不是禁止中断吗,我没用过,请教了!

论坛徽章:
0
7 [报告]
发表于 2011-10-19 14:27 |只看该作者
IRQF_DISABLED - keep irqs disabled when calling the action handler
我也不知道行不行,如果你已经解决该问题,请帮忙分享一下

论坛徽章:
0
8 [报告]
发表于 2011-10-19 14:51 |只看该作者
我博客里有最终的驱动代码和测试函数!一开始不知道为什么不行,现在能用了!
您需要登录后才可以回帖 登录 | 注册

本版积分规则 发表回复

  

北京盛拓优讯信息技术有限公司. 版权所有 京ICP备16024965号-6 北京市公安局海淀分局网监中心备案编号:11010802020122 niuxiaotong@pcpop.com 17352615567
未成年举报专区
中国互联网协会会员  联系我们:huangweiwei@itpub.net
感谢所有关心和支持过ChinaUnix的朋友们 转载本站内容请注明原作者名及出处

清除 Cookies - ChinaUnix - Archiver - WAP - TOP