天嵌 ARM开发社区

 找回密码
 注册
查看: 4289|回复: 17

按键中断驱动程序

[复制链接]
zhujunfengx 发表于 2009-11-17 20:24:29 | 显示全部楼层 |阅读模式
我照PDF书上写的按键中断驱动程序,按按键半天都没反应。这是怎么回事呀?:'(
折腾我一个月了。我搞不定了呀。大家帮帮我呀。
谢谢!
wangdawei_80 发表于 2009-11-17 22:55:03 | 显示全部楼层
1.基于什么内核,即内核版本号?
2.能不能把源代码贴出来呀。
 楼主| zhujunfengx 发表于 2009-11-18 19:44:34 | 显示全部楼层
内核版本:2.6.25.8
#include<linux/module.h>
#include<linux/kernel.h>
#include<linux/fs.h>
#include<linux/init.h>
#include<linux/delay.h>
#include<asm/irq.h>
#include<linux/interrupt.h>
#include<asm/uaccess.h>
#include<asm/arch/regs-gpio.h>
#include<asm/hardware.h>
#include<linux/device.h>
#include<linux/poll.h>

#define DEVICE_NAME  "ZJF-Buttons"

#define BUTTON_MAJOR 232

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

static struct button_irq_desc button_irqs[]=
{
                {IRQ_EINT1,S3C2410_GPF1, S3C2410_GPF1_EINT1,  1,"KEY1"},  //K1
                {IRQ_EINT2,S3C2410_GPF2, S3C2410_GPF2_EINT2,  2,"KEY2"},  //K2
                {IRQ_EINT3,S3C2410_GPF3, S3C2410_GPF3_EINT3,  3,"KEY3"},  //K3
};

static volatile int key_values[]={0,0,0,0};

static DECLARE_WAIT_QUEUE_HEAD(button_waitq);

static volatile int ev_press=0;

static irqreturn_t buttons_interrupt(int irq,void *dev_id)
{
        struct button_irq_desc *button_irqs=(struct button_irq_desc *)dev_id;

        int up=s3c2410_gpio_getpin(button_irqs->pin);
        if(up)
                key_values[button_irqs->number]=(button_irqs->number+1)+0x80;
        else
                key_values[button_irqs->number]=(button_irqs->number+1);

        ev_press=1;
        wake_up_interruptible(&button_waitq);
        return IRQ_RETVAL(IRQ_HANDLED);
}

static int EmbedSky_buttons_open(struct inode *inode,struct file *file)
{
        int i;
        int err;

        for(i=0;i<sizeof(button_irqs)/sizeof(button_irqs[0]);i++)
        {
                s3c2410_gpio_cfgpin(button_irqs[i].pin,button_irqs[i].pin_setting);
                err=request_irq(button_irqs[i].irq, buttons_interrupt, NULL,button_irqs[i].name,(void *)&button_irqs[i]);
                if(err)break;
        }
        if(err)
        {
                i--;
                for(;i>=0;i--)
                {
                        disable_irq(button_irqs[i].irq);
                        free_irq(button_irqs[i].irq,(void*)&button_irqs[i]);
                }
                return -EBUSY;
        }
        return 0;
}

static int EmbedSky_buttons_close(struct inode *inode,struct file *file)
{
        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]);
        }
        return 0;
}

static int EmbedSky_buttons_read(struct file *filp,char __user *buff,size_t count,loff_t *offp)
{
        unsigned long err;
        if(!ev_press)
        {
                if(filp->f_flags& O_NONBLOCK)
                        return -EAGAIN;
                else
                        wait_event_interruptible(button_waitq,ev_press);
        }
        ev_press=0;

        err=copy_to_user(buff,(const void *)key_values,min(sizeof(key_values),count));
        memset((void *)key_values,0,sizeof(key_values));
        return err ? -EFAULT:min(sizeof(key_values),count);
}

static unsigned int EmbedSky_buttons_poll(struct file *file,struct poll_table_struct *wait)
{
        unsigned int mask=0;
        poll_wait(file,&button_waitq,wait);
        if(ev_press)
                mask|=POLLIN|POLLRDNORM;
        return mask;
}

static struct file_operations EmbedSky_buttons_fops=
{
                .owner =  THIS_MODULE,
                .open  =  EmbedSky_buttons_open,
                .release= EmbedSky_buttons_close,
                .read  =  EmbedSky_buttons_read,
                .poll  =  EmbedSky_buttons_poll,
};

static char __initdata banner[]="TQ2440/SKY2440 LEDS,(c)2008,2009www.embedsky.net\n";
//static struct class *button_class;

static int __init EmbedSky_buttons_init(void)
{
        int ret;
        printk(banner);
        ret=register_chrdev(BUTTON_MAJOR,DEVICE_NAME,&EmbedSky_buttons_fops);
        if(ret<0)
        {
                printk(DEVICE_NAME"can't register major number\n");
                return ret;
        }
        //注册一个类,使mdev可以在"/dev/"目录下面建立设备 节点
/*        button_class=class_create(THIS_MODULE,DEVICE_NAME);
        if(IS_ERR(button_class))
        {
      printk("Err:failed in EmbedSky-leds class.\n");
      return -1;
        }
        class_device_create(button_class,NULL,MKDEV(BUTTON_MAJOR,0),NULL,DEVICE_NAME);
*/
        printk(DEVICE_NAME"initialized\n");
        return 0;

}

static void __exit EmbedSky_buttons_exit(void)
{
        unregister_chrdev(BUTTON_MAJOR,DEVICE_NAME);
        class_device_destroy(button_class,MKDEV(BUTTON_MAJOR,0));  //删掉设备节点节点
        class_destroy(button_class);       //注销类类
}

module_init(EmbedSky_buttons_init);
module_exit(EmbedSky_buttons_exit);

谢谢!
wangdawei_80 发表于 2009-11-19 09:48:34 | 显示全部楼层
1.为什么要在初始化模块代码中注视掉class_create()和class_device_create()?这两个内核API用于在/dev下动态创建设备节点的。难道你手动添加设备节点了?
2.用户态程序?
亚瑟王 发表于 2009-11-19 11:01:52 | 显示全部楼层
1、你说你按照移植手册里面的中断驱动写的,那么手册里面在下面列出的这部分代码中根本没有屏蔽这些代码,而你屏蔽了,说明你没有按照手册做,所以你出错了。
       //注册一个类,使mdev可以在"/dev/"目录下面建立设备 节点
/*        button_class=class_create(THIS_MODULE,DEVICE_NAME);
        if(IS_ERR(button_class))
        {
      printk("Err:failed in EmbedSky-leds class.\n");
      return -1;
        }
        class_device_create(button_class,NULL,MKDEV(BUTTON_MAJOR,0),NULL,DEVICE_NAME);
*/
        printk(DEVICE_NAME"initialized\n");
        return 0;

}
2、应用程序你没有贴出来,情况就不知道了。
 楼主| zhujunfengx 发表于 2009-11-19 21:56:33 | 显示全部楼层
下面是测试程序,节点我是自己用mknod建立的。mknod /dev/ZJF-Buttons c 232 0

#include<stdio.h>
#include<stdlib.h>
#include<unistd.h>
#include<sys/ioctl.h>
#include<sys/types.h>
#include<sys/stat.h>
#include<fcntl.h>
#include<sys/select.h>
#include<sys/time.h>
#include<erno.h>

int main(void)
{
        int i;
        int buttons_fd;
        int key_value[4];

        buttons_fd=open("/dev/ZJF-Buttons",0);
        if(buttons_fd<0)
        {
           perror("open device buttons");
           exit(1);
        }
        while(1);
}
wangdawei_80 发表于 2009-11-19 22:40:30 | 显示全部楼层
光有open是不够用的,还得加read,从内核读取数据到用户空间。你的内核代码中将数据返回给用户空间的部分在read()函数中实现的,因此若没有read部分则内核数据无法反馈到用户态。
 楼主| zhujunfengx 发表于 2009-11-20 07:26:31 | 显示全部楼层
但是我把中断处理函数中加了一条  printk("intterrupt \n");
也就是光测试中断有没有产生呀。但是它也没有输出这条指令呀。
wangdawei_80 发表于 2009-11-20 13:50:33 | 显示全部楼层
中断上下文是不能用printk()的,因为printk会睡眠,不能在中断上下文中使用。
 楼主| zhujunfengx 发表于 2009-11-20 22:36:31 | 显示全部楼层
我在中断置个标志,用读函数将中断打印出来。但是还是不行。驱动程序如下:

#include<linux/module.h>
#include<linux/kernel.h>
#include<linux/fs.h>
#include<linux/init.h>
#include<linux/delay.h>
#include<asm/irq.h>
#include<linux/interrupt.h>
#include<asm/uaccess.h>
#include<asm/arch/regs-gpio.h>
#include<asm/hardware.h>
#include<linux/device.h>
#include<linux/poll.h>

#define DEVICE_NAME  "buttons"

#define BUTTON_MAJOR 232

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

static struct button_irq_desc button_irqs[]=
{
                {IRQ_EINT1,S3C2410_GPF1, S3C2410_GPF1_EINT1,  1,"KEY1"},  //K1
                {IRQ_EINT2,S3C2410_GPF2, S3C2410_GPF2_EINT2,  2,"KEY2"},  //K2
                {IRQ_EINT3,S3C2410_GPF3, S3C2410_GPF3_EINT3,  3,"KEY3"},  //K3
};

static volatile int key_values[]={0,0,0,0};

//static DECLARE_WAIT_QUEUE_HEAD(button_waitq);

static volatile int ev_press=0;

static irqreturn_t buttons_interrupt(int irq,void *dev_id)
{
        struct button_irq_desc *button_irqs=(struct button_irq_desc *)dev_id;

        int up=s3c2410_gpio_getpin(button_irqs->pin);
       

        ev_press=1;

        return IRQ_RETVAL(IRQ_HANDLED);
}

static int EmbedSky_buttons_open(struct inode *inode,struct file *file)
{
        int i;
        int err;

        for(i=0;i<sizeof(button_irqs)/sizeof(button_irqs[0]);i++)
        {
                s3c2410_gpio_cfgpin(button_irqs[i].pin,button_irqs[i].pin_setting);
                err=request_irq(button_irqs[i].irq, buttons_interrupt, NULL,button_irqs[i].name,(void *)&button_irqs[i]);
                if(err)break;
        }
        if(err)
        {
                i--;
                for(;i>=0;i--)
                {
                        disable_irq(button_irqs[i].irq);
                        free_irq(button_irqs[i].irq,(void*)&button_irqs[i]);
                }
                return -EBUSY;
        }
        return 0;
}

static int EmbedSky_buttons_close(struct inode *inode,struct file *file)
{
        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]);
        }
        return 0;
}

static int EmbedSky_buttons_read(struct file *filp,char __user *buff,size_t count,loff_t *offp)
{
        unsigned long err;
        if(ev_press)
        {
                ev_press=0;
                return 1;
        }
        else
        return 0;     //err ? -EFAULT:min(sizeof(key_values),count);
}

static unsigned int EmbedSky_buttons_poll(struct file *file,struct poll_table_struct *wait)
{
        unsigned int mask=0;
        poll_wait(file,&button_waitq,wait);
        if(ev_press)
                mask|=POLLIN|POLLRDNORM;
        return mask;
}

static struct file_operations EmbedSky_buttons_fops=
{
                .owner =  THIS_MODULE,
                .open  =  EmbedSky_buttons_open,
                .release= EmbedSky_buttons_close,
            .read  =  EmbedSky_buttons_read,
//                .poll  =  EmbedSky_buttons_poll,
};

static char __initdata banner[]="TQ2440/SKY2440 LEDS,(c)2008,2009www.embedsky.net\n";

static int __init EmbedSky_buttons_init(void)
{
        int ret;
        printk(banner);
        ret=register_chrdev(BUTTON_MAJOR,DEVICE_NAME,&EmbedSky_buttons_fops);
        if(ret<0)
        {
                printk(DEVICE_NAME"can't register major number\n");
                return ret;
        }

        printk(DEVICE_NAME"initialized\n");
        return 0;

}

static void __exit EmbedSky_buttons_exit(void)
{
        unregister_chrdev(BUTTON_MAJOR,DEVICE_NAME);

}

module_init(EmbedSky_buttons_init);
module_exit(EmbedSky_buttons_exit);


/////////////////////////////////////////////////////////////////////////////
测试程序如下:
#include<stdio.h>
#include<stdlib.h>
#include<unistd.h>
#include<sys/ioctl.h>
#include<sys/types.h>
#include<sys/stat.h>
#include<fcntl.h>
#include<sys/select.h>
#include<sys/time.h>
#include<errno.h>

int main(void)
{
        int i;
        int buttons_fd;
        int key_value[4];

        int ret;
        buttons_fd=open("/dev/buttons",0);
        if(buttons_fd<0)
        {
           perror("open device buttons");
           exit(1);
        }
        while(1)
        {

                 ret=read(buttons_fd,key_value,sizeof(key_value));
                 if(ret)
                   {
                         printf("interrup occs\n");
                   }
        }
        close(buttons_fd);
        return 0;

}
还是不行呀。大家帮帮我呀。谢谢!
 楼主| zhujunfengx 发表于 2009-11-23 22:13:01 | 显示全部楼层
装PDF的按键中断加载到内核出现如下提示,是怎么回事呀?
我把注册设备号的程序给屏蔽后,它就不出现了,但是运行测试程序时,屏幕还是没反应。我晕啦。
谢谢大家!帮我整整呀。
[root@ZhuJunFeng /]#insmod myKey.ko
myKey: module license 'unspecified' taints kernel.
myKey: Unknown symbol class_device_create
myKey: Unknown symbol class_device_destroy
myKey: Unknown symbol class_create
myKey: Unknown symbol class_destroy
insmod: cannot insert 'myKey.ko': unknown symbol in module, or unknown parameter
[root@ZhuJunFeng /]#
亚瑟王 发表于 2009-11-24 14:41:36 | 显示全部楼层
你下载我们提供的内核源码,然后编译里面的中断按键的驱动,然后运行看看有没有问题出现。
出现你最后贴出来的这个错误,应该是内核配置时缺少了系统组件导致的,建议你先使用我们提供的内核试试。
 楼主| zhujunfengx 发表于 2009-11-24 20:52:12 | 显示全部楼层
我就是想用自己的系统写自己的驱动呀。:'(
亚瑟王 发表于 2009-11-25 17:30:01 | 显示全部楼层
你先用我们提供的试一下,如果我们提供的能用,而你的不能用,然后就去找你的代码的问题;如果我们提供的不能用,我们就找我们提供的代码的问题;
 楼主| zhujunfengx 发表于 2009-12-1 22:56:38 | 显示全部楼层
原来是我的按键按地不良。所以不能产生中断。呵呵。现在搞 定了。谢谢大家。
您需要登录后才可以回帖 登录 | 注册

本版积分规则

关闭

i.MX8系列ARM cortex A53 M4 工控板上一条 /1 下一条

Archiver|手机版|小黑屋|天嵌 嵌入式开发社区 ( 粤ICP备11094220号-2 )

GMT+8, 2024-7-7 22:22 , Processed in 1.031250 second(s), 18 queries .

Powered by Discuz! X3.4 Licensed

Copyright © 2001-2020, Tencent Cloud.

快速回复 返回顶部 返回列表