打印

求助:oops异常分析

[复制链接]
2391|1
手机看帖
扫描二维码
随时随地手机跟帖
跳转到指定楼层
楼主
widpj|  楼主 | 2011-11-3 17:30 | 只看该作者 |只看大图 回帖奖励 |倒序浏览 |阅读模式
本帖最后由 widpj 于 2011-11-4 11:15 编辑

下面是我的oops信息,希望大侠帮帮忙,给点提示也行!菜鸟,刚学习驱动,有许多不懂之处,望各位大侠指点迷津!
下面是我的驱动程序,(是一个mini2440的按键驱动程序)采用的是平台总线platform编写的,希望各位帮忙!

#include<linux/module.h>
#include<linux/types.h>
#include<linux/miscdevice.h>
#include<linux/fs.h>
#include<linux/init.h>
#include<linux/platform_device.h>
#include<linux/interrupt.h>
#include<linux/clk.h>
#include<linux/uaccess.h>
#include<linux/io.h>
#include<mach/map.h>
#include<mach/regs-gpio.h>
#include<mach/gpio-fns.h>
#include<linux/sched.h>
#include<linux/poll.h>
#include<linux/irq.h>
#include<asm/unistd.h>
#include<linux/device.h>
#include<linux/kernel.h>


static DECLARE_WAIT_QUEUE_HEAD(button_waitq);
#define KEY_TIMER_DELAY1    (HZ/50)             //按键按下去抖延时20毫秒        
#define KEY_TIMER_DELAY2    (HZ/10)             //按键抬起去抖延时100毫秒

static volatile int press=0;

static int key_value;
static struct resource *button_mem;
static struct resource *button_irq;
static void __iomem *button_base;  //基地址
static struct timer_list key_timers[6];  //定义6个按键去抖动定时器
static int pin[]={S3C2410_GPG(0),S3C2410_GPG(3),S3C2410_GPG(5),S3C2410_GPG(6),S3C2410_GPG(11)};   //定义引脚

static int button_irqs[6];

static irqreturn_t buttons_interrupt(int irq, void *dev_id)
{
        int i;
        for(i=0; i<6; i++){
                if(irq == button_irqs){
               
                //设置当前按键按下去抖定时器的延时并启动定时器
        key_timers.expires = jiffies + KEY_TIMER_DELAY1;
        add_timer(&key_timers);
                }
        }
    return IRQ_RETVAL(IRQ_HANDLED);
       
}
static void buttons_timer(unsigned long arg)
{
    //获取当前按键资源的索引
    int key = arg;

    //获取当前按键引脚上的电平值来判断按键是按下还是抬起
   int up = s3c2410_gpio_getpin(pin[key]);


                if(!up)//低电平,按键按下
    {
        
            
            //标识当前按键已按下并唤醒等待队列
            press = 1;
            key_value=key;
            wake_up_interruptible(&button_waitq);

        //设置当前按键抬起去抖定时器的延时并启动定时器
        key_timers[key].expires = jiffies + KEY_TIMER_DELAY2;
        add_timer(&key_timers[key]);   //由于定时器超时后系统会自动将定时器删除,故应重新开启定时器
    }
    else//高电平,按键抬起
    {
        //标识当前按键状态为抬起
          press = 1;
    }
}

static int s3c24xx_button_open(struct inode *inode, struct file *file)
{
          int i;
        int err = 0;
        /*注册中断*/
        for(i=0; i<6; i++){
                if (button_irqs < 0)
                        continue;
                                                    
                                /*中断触发方式:上升沿触发*/
        err = request_irq(button_irqs,buttons_interrupt,IRQ_TYPE_EDGE_RISING,NULL,NULL);
                if(err)
                  break;
                  
                  //初始化并设置6个去抖定时器
        setup_timer(&key_timers, buttons_timer, i);
        }

        if (err) {
                i--;
                for (; i >= 0; i--) {
                        if (button_irqs < 0) {
                                continue;
                        }
                        disable_irq(button_irqs);
                        free_irq(button_irqs, NULL);
                }
                return -EBUSY;
        }

    press = 0;   
    return 0;
         
          }
static int s3c24xx_button_close(struct inode *inode,struct file *file)
{
        int i;

    //释放6个定时器和中断
    for(i = 0; i < 6; i++)
    {
        del_timer(&key_timers);

        disable_irq(button_irqs);
        free_irq(button_irqs, (void *)i);
    }

    return 0;
       
       
        }
static int s3c24xx_button_read(struct file *file,char __user *buff,size_t count,loff_t *offp)       
                  {
                          unsigned long ret;

    if(!press)//判断按键按下产生标识,0没有产生
  {
        if(file->f_flags & O_NONBLOCK)
        {
            //应用程序若采用非阻塞方式读取则返回错误
            return -EAGAIN;
        }
        else
        {
            //以阻塞方式读取且按键按下没有产生,让等待队列进入睡眠
            wait_event_interruptible(button_waitq, press);
        }
    }

    //1为按键按下产生,并清除标识为0,准备给下一次判断用
    press = 0;

    //将内核中的按键状态数据拷贝到用户空间给应用程序使用
    ret = copy_to_user(buff, &key_value, sizeof(key_value));

    return ret;
                         
                          }
static unsigned int s3c24xx_button_poll(struct file *file,struct poll_table_struct *wait)                         
                          {
                                  unsigned int mask = 0;

    //添加等待队列到等待队列表中(poll_table)
poll_wait(file, &button_waitq, wait);

    if(press)
    {
        //标识数据可以获得
        mask |= POLLIN | POLLRDNORM;
    }

    return mask;
                                 
                                 
}
static struct file_operations mini2440button_fops={
                                                .owner = THIS_MODULE,
                                                .open  = s3c24xx_button_open,
                                                .release = s3c24xx_button_close,
                                                .read  = s3c24xx_button_read,
                                                .poll  = s3c24xx_button_poll,
                                                                     };


static struct miscdevice mini2440_miscdev=
                                {
                                  .minor = MISC_DYNAMIC_MINOR,
                                  .name  = "button"
//                                  .fops  = mini2440button_fops,
                                       
                                };

static int mini2440_button_probe(struct platform_device *pdev)
{
        struct resource *res;
        struct device *dev;
        int size;
        int ret;
        int i;

        dev=&(pdev->dev);
       
        /*获取内存资源*/
        res=platform_get_resource(pdev,IORESOURCE_MEM,0);
        if(res==NULL)       
          {
                          dev_err(dev,"no memory resource specified\n");
                          return -ENOENT;
          }
         size=(res->start-res->end)+1;
          button_mem = request_mem_region(res->start,size,pdev->name);
          if(button_mem==NULL)
          {
                  dev_err(dev,"Faild to get memory region\n");
                   ret= -ENOENT;
                   goto err_req;
                  }
          button_base = ioremap(res->start,size);
                        if(button_base==NULL)          
             {
                          dev_err(dev,"failed to ioremap() region\n");               
                          ret = -EINVAL;
                    goto err_req;
                     }
          printk(KERN_DEBUG "probe: mapped button_base=%p\n",button_base);
       
                /*获取中断号*/
                for(i=0;i<6;i++)
                        {
                                button_irq = platform_get_resource(pdev,IORESOURCE_IRQ,i);
                                        if(button_irq==NULL)
                                                {
                                                        dev_err(dev,"no irq resource specified\n");
                                                        ret= -ENONET;
                                                        goto err_map;
                                                        }
                                        button_irqs= button_irq->start;               
                                }
                               
                                ret=misc_register(&mini2440_miscdev);
                                mini2440_miscdev.fops=&mini2440button_fops;       
                                return 0;
                               
                                err_map:
                                                iounmap(button_base);
                                err_req:
                                                release_resource(button_mem);
                                    kfree(button_mem);

                                return ret;
}
       
int mini2440_button_remove(struct platform_device *dev)
{
       
        release_resource(button_mem);
        kfree(button_mem);
        button_mem = NULL;

        iounmap(button_base);
        misc_deregister(&mini2440_miscdev);
        return 0;
}
struct platform_driver button_driver=
{
                .probe  =  mini2440_button_probe,
                .remove        =  mini2440_button_remove,
                .driver =
                                {
                                        .owner        = THIS_MODULE,
                                        .name        = "mini2440_buttons",
                                        },
};

static int __init init_driver(void)
{
        return platform_driver_register(&button_driver);
               
}
       
        static void __exit driver_exit(void)
        {
                        platform_driver_unregister(&button_driver);
        }
module_init(init_driver);
module_exit(driver_exit);

MODULE_AUTHOR("Linux-wu");
MODULE_LICENSE("GPL");
MODULE_DESCRIPTION("Mini2440_button_driver");

QQ截图20111103174123.png (19.39 KB )

QQ截图20111103174123.png

QQ截图20111103174143.png (19.51 KB )

QQ截图20111103174143.png

相关帖子

沙发
sjl2006| | 2011-11-4 17:16 | 只看该作者
本帖最后由 sjl2006 于 2011-11-4 17:20 编辑

如果你在mini2440_button_probe()中进入这个条件:   if(button_mem==NULL),会发生什么??
异常信息首先告诉你:unable to handle kernel NULL pointer,
然后告诉你LR在mini2440_button_probe()里,PC在release_resource()里,这就差不多出来了。你在mini2440_button_probe()里给内核函数release_resource()传递了一个空指针。

使用特权

评论回复
发新帖 我要提问
您需要登录后才可以回帖 登录 | 注册

本版积分规则

0

主题

40

帖子

0

粉丝