主题 : 2440按键驱动程序---不知道错在哪里---求助--哪位大大帮忙 复制链接 | 浏览器收藏 | 打印
级别: 新手上路
UID: 8921
精华: 0
发帖: 3
金钱: 30 两
威望: 15 点
综合积分: 6 分
注册时间: 2009-09-11
最后登录: 2009-10-19
楼主  发表于: 2009-10-14 19:27

 2440按键驱动程序---不知道错在哪里---求助--哪位大大帮忙

这是案件程序:#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/cdev.h>

#define DEVICE_NAME     "buttons"   /* 加载模式后,执行”cat /proc/devices”命令看到的设备名称 */
#define BUTTON_MAJOR    231         /* 主设备号 */
#define MAX_KEY_BUF     16
#define KEY_NUM            4
#define KEYSTATUS_UP    1
#define KEYSTATUS_DOWN  0
#define KEYSTATUS_DOWNX  2
#define KEY_TIMER_DELAY1 (HZ/50)
#define KEY_TIMER_DELAY (HZ/10)
#define BUF_HEAD       (key_dev->buf[key_dev->head])
#define BUF_TAIL       (key_dev->buf[key_dev->tail])
#define INCBUF(x,mod)  ((++(x))&((mod)-1))
static volatile int *key;

void (*keyEvent)(int);

struct button_irq_desc {
    int irq;
    unsigned long flags;
    char *name;
    int pin;
};

/* 用来指定按键所用的外部中断引脚及中断触发方式, 名字 */
static struct button_irq_desc button_irqs [] = {
    {IRQ_EINT19, IRQF_TRIGGER_FALLING, "KEY1",S3C2410_GPG11}, /* K1 */
    {IRQ_EINT11, IRQF_TRIGGER_FALLING, "KEY2",S3C2410_GPG3}, /* K2 */
    {IRQ_EINT2,  IRQF_TRIGGER_FALLING, "KEY3",S3C2410_GPF2}, /* K3 */
    {IRQ_EINT0,  IRQF_TRIGGER_FALLING, "KEY4",S3C2410_GPF0}, /* K4 */
};

typedef unsigned char KEY_RET;
typedef struct
{
    unsigned int keyStatus[KEY_NUM];
    KEY_RET buf[MAX_KEY_BUF];
    unsigned int head,tail;
    wait_queue_head_t wq;
    struct cdev key_cdev;
}KEY_DEV;

KEY_DEV *key_dev;
static struct timer_list key_timer[KEY_NUM];

static int isKey_down(int key)
{
    int key_status;
    key_status=!(s3c2410_gpio_getpin(button_irqs[key].pin));
    return key_status;
}

static irqreturn_t buttons_interrupt(int irq,void *dev_id)
{
   unsigned int key1;
   //key=(volatile int *)dev_id;
   key1=*key;
   printk(KERN_NOTICE "interrupt-wawayu Error key_button_interrupt_handle adding");
  
    disable_irq(button_irqs[2].irq);
    printk(KERN_NOTICE "interrupt-wawayu Error key_button_interrupt_timer_add_before adding");
    key_dev->keyStatus[2]=KEYSTATUS_DOWNX;
    
    key_timer[2].expires=jiffies+KEY_TIMER_DELAY1;
    
    add_timer(&key_timer[2]);
     printk(KERN_NOTICE "interrupt-wawayu Error key_button_interrupt_timer_add_after adding");
    return IRQ_RETVAL(IRQ_HANDLED);
}

static void keyEvent_raw(int key)
{
    if(key_dev->keyStatus[key]==KEYSTATUS_DOWN)
        {
            BUF_HEAD=key+1;
        }
    key_dev->head=INCBUF(key_dev->head,MAX_KEY_BUF);
    wake_up_interruptible(&(key_dev->wq));
}

static void keyEventnull(int key)
{
}

static void key_timer_handle(unsigned long data)
{
    unsigned int key1;
    key1=*key;
    if(isKey_down(2))
        {
            printk(KERN_NOTICE "interrupt-wawayu Error key_timer_handle adding");
            if(key_dev->keyStatus[2]==KEYSTATUS_DOWNX)
                {
                    key_dev->keyStatus[2]=KEYSTATUS_DOWN;
                    key_timer[2].expires=jiffies+KEY_TIMER_DELAY;
                    (*keyEvent)(2);
                    add_timer(&key_timer[2]);
                }
            else
                {
                    key_timer[2].expires=jiffies+KEY_TIMER_DELAY;
                    add_timer(&key_timer[2]);
                }
        }
    else
        {
            key_dev->keyStatus[2]=KEYSTATUS_UP;
            enable_irq(button_irqs[2].irq);
        }
}




/* 应用程序对设备文件/dev/buttons执行open(...)时,
* 就会调用s3c24xx_buttons_open函数
*/
static int s3c24xx_buttons_open(struct inode *inode, struct file *file)
{
    key_dev->head=key_dev->tail=0;
    keyEvent=keyEvent_raw;
    printk(KERN_NOTICE "interrupt-wawayu Error open_function_adding");
    return 0;
}



/* 应用程序对设备文件/dev/buttons执行close(...)时,
* 就会调用s3c24xx_buttons_close函数
*/
static int s3c24xx_buttons_close(struct inode *inode, struct file *file)
{
    keyEvent=keyEventnull;
    return 0;
}


/* 应用程序对设备文件/dev/buttons执行read(...)时,
* 就会调用s3c24xx_buttons_read函数
*/

static KEY_RET read_key()
{
    KEY_RET key_ret;
    key_ret=BUF_TAIL;
    key_dev->tail=INCBUF(key_dev->tail,MAX_KEY_BUF);
    return key_ret;
}
static int s3c24xx_buttons_read(struct file *filp, char __user *buff,
                                         size_t count, loff_t *offp)
{
    KEY_RET key_ret;
    unsigned long error;
    
retry:
    if(key_dev->head !=key_dev->tail)
           {
               key_ret=read_key();
            error=copy_to_user(buff,(char *)&key_ret,sizeof(key_ret));
           }
    else
        {
            if(filp->f_flags & O_NONBLOCK)
                return -EAGAIN;

            interruptible_sleep_on(&(key_dev->wq));
            goto retry;
        }
    return 0;
}

/* 这个结构是字符设备驱动程序的核心
* 当应用程序操作设备文件时所调用的open、read、write等函数,
* 最终会调用这个结构中的对应函数
*/
static struct file_operations s3c24xx_buttons_fops = {
    .owner   =   THIS_MODULE,    /* 这是一个宏,指向编译模块时自动创建的__this_module变量 */
    .open    =   s3c24xx_buttons_open,
    .release =   s3c24xx_buttons_close,
    .read    =   s3c24xx_buttons_read,
};


static int request_irqs(void)
{
    int i;
    for(i=0;i<KEY_NUM;i++)
        {
            if(request_irq(button_irqs.irq, buttons_interrupt,button_irqs.flags,button_irqs.name,(void *)&i))
                {
                printk(KERN_NOTICE "interrupt-wawayu Error %d adding",i);
                return -1;
                }
        }
    return 0;
}

static int free_irqs(void)
{
    int i;
    for(i=0;i<KEY_NUM;i++)
        {
            free_irq(button_irqs.irq,buttons_interrupt);
        }
    return 0;
}




static void buttons_setup_cdev(KEY_DEV *dev, int index)
{
  int err, devno = MKDEV(BUTTON_MAJOR, index);

  cdev_init(&dev->key_cdev, &s3c24xx_buttons_fops);
  dev->key_cdev.owner = THIS_MODULE;
  dev->key_cdev.ops = &s3c24xx_buttons_fops;
  err = cdev_add(&dev->key_cdev, devno, 1);
  if (err)
    printk(KERN_NOTICE "Error %d adding LED%d", err, index);
}

/*
* 执行“insmod s3c24xx_buttons.ko”命令时就会调用这个函数
*/
static int __init s3c24xx_buttons_init(void)
{
    int ret,i;
    dev_t devno=MKDEV(BUTTON_MAJOR,0);
    if(BUTTON_MAJOR)
        ret=register_chrdev_region(devno,1,DEVICE_NAME);
    else
        {
            ret=alloc_chrdev_region(&devno,0,1,DEVICE_NAME);
            //BUTTON_MAJOR=MAJOR(devno);
        }
    if(ret<0)
        return ret;
    key_dev=kmalloc(sizeof(KEY_DEV),GFP_KERNEL);
    if(!key_dev)
        {
            ret=- ENOMEM;
            goto fail_malloc;
        }
    memset(key_dev, 0, sizeof(KEY_DEV));

    buttons_setup_cdev(key_dev,0);    //申请设备号,注册设备
    
    request_irqs();
    key_dev->head=key_dev->tail=0;
    for(i=0;i<KEY_NUM;i++)
        key_dev->keyStatus=KEYSTATUS_UP;
    init_waitqueue_head(&key_dev->wq);

    for(i=0;i<KEY_NUM;i++)
        setup_timer(&key_timer,key_timer_handle,i);
    return 0;
    fail_malloc:unregister_chrdev_region(devno,1);
    return 0;
}

/*
* 执行”rmmod s3c24xx_buttons.ko”命令时就会调用这个函数
*/
static void __exit s3c24xx_buttons_exit(void)
{
    /* 卸载驱动程序 */
    free_irqs();
    cdev_del(&key_dev->key_cdev);   /*注销cdev*/
    kfree(key_dev);     /*释放设备结构体内存*/  
    unregister_chrdev_region(MKDEV(BUTTON_MAJOR, 0), 1); /*释放设备号*/
}

/* 这两行指定驱动程序的初始化函数和卸载函数 */
module_init(s3c24xx_buttons_init);
module_exit(s3c24xx_buttons_exit);

/* 描述驱动程序的一些信息,不是必须的 */
MODULE_AUTHOR("http://www.100ask.net");             // 驱动程序的作者
MODULE_DESCRIPTION("S3C2410/S3C2440 BUTTON Driver");   // 一些描述信息
MODULE_LICENSE("GPL");                              // 遵循的协议



这是oops信息:interrupt-wawayu Error open_function_adding<5>interrupt-wawayu Error key_button_interrupt_handle adding<1>Unable to handle kernel paging request at virtual address 7effbd78
pgd = c0004000
[7effbd78] *pgd=00000000
Internal error: Oops: 5 [#1]
Modules linked in: s3c24xx_buttons1
CPU: 0    Not tainted  (2.6.22.6 #3)
PC is at buttons_interrupt+0x24/0xb4 [s3c24xx_buttons1]
LR is at release_console_sem+0x1e8/0x204
pc : [<bf0000a0>]    lr : [<c0035c38>]    psr: 60000013
sp : c0305ec0  ip : 00000000  fp : c0305ed4
r10: 3001e554  r9 : 41129200  r8 : 3001e5bc
r7 : 00000037  r6 : 00000000  r5 : bf001640  r4 : ebfffb9b
r3 : bf0003c8  r2 : c030c594  r1 : 60000093  r0 : 0000003c
Flags: nZCv  IRQs on  FIQs on  Mode SVC_32  Segment kernel
Control: c000717f  Table: 33c28000  DAC: 00000017
Process swapper (pid: 0, stack limit = 0xc0304260)
Stack: (0xc0305ec0 to 0xc0306000)
5ec0: c07ceb00 00000000 c0305ef4 c0305ed8 c005cc24 bf00008c c030ecf0 00000037
5ee0: c07ceb00 c030ed1c c0305f14 c0305ef8 c005de08 c005cbf0 00000000 00000015
5f00: 00000000 c036e674 c0305f2c c0305f18 c002f2ac c005dcf4 c030e3e8 00000015
5f20: c0305f4c c0305f30 c0024044 c002f22c ffffffff f0000000 00000020 c036e674
5f40: c0305fa4 c0305f50 c0024a24 c0024010 c0021c80 00000032 f0200000 60000013
5f60: c0025e34 c0304000 c0307e24 c036e674 3001e5bc 41129200 3001e554 c0305fa4
5f80: c0305f98 c0305f98 c0025e94 c0025ea0 60000013 ffffffff c0305fbc c0305fa8
5fa0: c00265b0 c0025e44 c0349b40 c0323bec c0305fcc c0305fc0 c0265b1c c002657c
5fc0: c0305ff4 c0305fd0 c0008b74 c0265ae4 c0008674 00000000 00000000 c002132c
5fe0: c0007175 c0324134 00000000 c0305ff8 30008030 c000891c 00000000 00000000
Backtrace:
[<bf00007c>] (buttons_interrupt+0x0/0xb4 [s3c24xx_buttons1]) from [<c005cc24>] (handle_IRQ_event+0x44/0x80)
r5:00000000 r4:c07ceb00
[<c005cbe0>] (handle_IRQ_event+0x0/0x80) from [<c005de08>] (handle_edge_irq+0x124/0x174)
r7:c030ed1c r6:c07ceb00 r5:00000037 r4:c030ecf0
[<c005dce4>] (handle_edge_irq+0x0/0x174) from [<c002f2ac>] (s3c_irq_demux_extint8+0x90/0xa4)
r7:c036e674 r6:00000000 r5:00000015 r4:00000000
[<c002f21c>] (s3c_irq_demux_extint8+0x0/0xa4) from [<c0024044>] (__exception_text_start+0x44/0x60)
r5:00000015 r4:c030e3e8
[<c0024000>] (__exception_text_start+0x0/0x60) from [<c0024a24>] (__irq_svc+0x24/0xa0)
Exception stack(0xc0305f50 to 0xc0305f98)
5f40:                                     c0021c80 00000032 f0200000 60000013
5f60: c0025e34 c0304000 c0307e24 c036e674 3001e5bc 41129200 3001e554 c0305fa4
5f80: c0305f98 c0305f98 c0025e94 c0025ea0 60000013 ffffffff                  
r7:c036e674 r6:00000020 r5:f0000000 r4:ffffffff
[<c0025e34>] (default_idle+0x0/0x74) from [<c00265b0>] (cpu_idle+0x44/0x60)
[<c002656c>] (cpu_idle+0x0/0x60) from [<c0265b1c>] (rest_init+0x48/0x58)
r5:c0323bec r4:c0349b40
[<c0265ad4>] (rest_init+0x0/0x58) from [<c0008b74>] (start_kernel+0x268/0x2c0)
[<c000890c>] (start_kernel+0x0/0x2c0) from [<30008030>] (0x30008030)
Code: e5851008 e5914000 eb40d883 e59f3078 (e7930204)
Kernel panic - not syncing: Fatal exception in interrupt



请问错在哪里?????
哪位大大帮帮

*無鈳取玳
级别: 论坛版主
UID: 27
精华: 12
发帖: 5398
金钱: 40120 两
威望: 17929 点
综合积分: 11036 分
注册时间: 2008-01-16
最后登录: 2014-11-22
1楼  发表于: 2009-10-14 20:03
C语言编程的基本原则:
1. 尽量不要用毫无意义的全局变量,特别是当这个全局变量是指针;
2. 不要使用未初始化的指针。
"If you have an apple and I have an apple and we exchange apples, then you and I will
still each have one apple. But if you have an idea and I have an idea and we exchange
these ideas, then each of us will have two ideas."
级别: 新手上路
UID: 8921
精华: 0
发帖: 3
金钱: 30 两
威望: 15 点
综合积分: 6 分
注册时间: 2009-09-11
最后登录: 2009-10-19
2楼  发表于: 2009-10-14 22:20