microcreat 发表于 2010-10-28 15:39:25

请大家帮我看下,为什么我会出现这个错误!关于linux驱动的中断的问题!

struct ep3cxx_device_info {
    unsigned char                  flag;
        struct            device           *dev;
        struct            resource   *men;
        void                __iomem    *base;
        //spinlock_t                     lock;
        //struct            semaphoresem;
        int                            irq;
        //wait_queue_head_t            wait_read;
        //wait_queue_head_t            wait_write;
        unsigned char                  rev_flag;
        unsigned char                  wr_flag;
        unsigned char                  rev_skb;
        unsigned char                  wr_skb;
};

// 定义中断底半部函数并关联
static void ep3cxx_interrupt_bottom(unsigned long arg);
DECLARE_TASKLET(ep3cxx_tasklet, ep3cxx_interrupt_bottom, 0);


// ep3cxx所需要的资源情况,根据硬件的不同这个需要修改
struct resource ep3cxx_resource[] = {      
        ={                                                   
                .start =S3C6410_SROMC_BASE,            
                .end   =S3C6410_SROMC_BASE + S3C6410_SRMOC_LEN,            
                .flags =IORESOURCE_MEM,            
                },

        ={                           
          .start =S3C6410_GPO_BASE,                           
                .end   =S3C6410_GPO_BASE + S3C6410_GPO_LEN,                           
                .flags =IORESOURCE_MEM,                           
                },

        ={            
                .start =S3C6410_SROM_CS5,            
                .end   =S3C6410_SROM_CS5 + S3C6410_SROM_CS5_LEN,            
                .flags =IORESOURCE_MEM,            
                },

        ={            
                .start =S3C6410_GPN_BASE,            
                .end   =S3C6410_GPN_BASE + S3C6410_GPN_LEN,            
                .flags =IORESOURCE_MEM,            
                },

        ={            
                .start =S3C6410_EXINT_CON_BASE,            
                .end   =S3C6410_EXINT_CON_BASE + S3C6410_EXINT_CON_LEN,            
                .flags =IORESOURCE_MEM,            
                },

        ={            
                .start =S3C6410_VIC1_BASE,            
                .end   =S3C6410_VIC1_BASE + S3C6410_VIC1_LEN,
                .flags =IORESOURCE_MEM,            
                },

        ={            
                .start =FPGG_IRQ_EXINT,            
                .end   =FPGG_IRQ_EXINT,
                .flags =IORESOURCE_IRQ | IRQF_TRIGGER_LOW,            
                }
        };

/*******************************************************************************************
Function:   static irqreturn_t ep3cxx_interrupt_handle( int irq, void* dev_id )
Description:外部中断时的顶部处理函数
Input:      int irq
            void* dev_id
Return:      
Others:      
*******************************************************************************************/
static irqreturn_t ep3cxx_interrupt_handle( int irq, void* dev_id )
{
        printk(KERN_ALERT "%s:%s,%s\r\n", __FUNCTION__,__DATE__,__TIME__);
               
        return IRQ_HANDLED;       
}

/*******************************************************************************************
Function:   static void ep3cxx_release(struct device * dev)
Description:当执行驱动卸载的时候调用此函数
Input:      struct device * dev
Return:      
Others:      
*******************************************************************************************/
static void ep3cxx_release(struct device * dev)
{
                printk(KERN_ALERT "%s:%s,%s\r\n", __FUNCTION__,__DATE__,__TIME__);
}

// ep3cxx_device为一个平台设备
struct platform_device ep3cxx_device= {      
          .name            =DEV_NAME,      
                .id                =-1,      
                .num_resources   =ARRAY_SIZE(ep3cxx_resource),      
                .resource          =ep3cxx_resource,      
                .dev               =
                {            
                .release         =ep3cxx_release,
                }      
        };

/*******************************************************************************************
Function:   static int fpga_ep3cxx_open(struct inode *inode,struct file *filp)
Description:fpga ep3cxx open函数,提供给实现应用程序中open函数的功能
Input:      struct inode *inode
            struct file *filp
Return:       0为成功,非0为失败
Others:       这个是linux实现标准函数
*******************************************************************************************/
static int fpga_ep3cxx_open(struct inode *inode,struct file *filp)
{
    struct ep3cxx_device_info *info = platform_get_drvdata(&ep3cxx_device);

        DEBUG(KERN_ALERT "%s:%s,%s\r\n", __FUNCTION__,__DATE__,__TIME__);
       
        if(request_irq(info->irq, ep3cxx_interrupt_handle, IRQF_DISABLED | IRQF_TRIGGER_RISING, DEV_NAME, info ))
                {               
                printk("fail to install irq\n");               
                return -EAGAIN;       
                }

        filp->private_data = info;
               
        return 0;
}

/*******************************************************************************************
Function:   static ssize_t fpga_ep3cxx_read(struct file *filp,char __user *buffer,size_t size,loff_t *offset)
Description:fpga ep3cxx open函数,提供给实现应用程序中open函数的功能
Input:      struct file *filp
            char __user *buffer
            size_t size
            loff_t *offset
Return:       0为成功,非0为失败
Others:       这个是linux实现标准函数
*******************************************************************************************/
static ssize_t fpga_ep3cxx_read(struct file *filp,char __user *buffer,size_t size,loff_t *offset)
{
}

/*******************************************************************************************
Function:   static ssize_t fpga_ep3cxx_write(struct file *filp,const char __user *buffer,size_t size,loff_t *offset)
Description:这个函数是上层write函数的实现,当上层函数调用write的时候,就会直接调用此函数
Input:      struct inode *inode
            const char __user *buffer
            size_t size
            loff_t *offset
Output:       无
Return:       0为成功,非0为失败
Others:      
*******************************************************************************************/
static ssize_t fpga_ep3cxx_write(struct file *filp,const char __user *buffer,size_t size,loff_t *offset)
{      
}

/*******************************************************************************************
Function:   static int fpga_ep3cxx_ioctl(struct inode *inode,struct file *filp,unsigned int cmd,unsigned long arg)
Description:这个函数是上层write函数的实现,当上层函数调用write的时候,就会直接调用此函数
Input:      struct inode *inode
            struct file *filp
            unsigned int cmd
            unsigned long arg
Return:       0为成功,非0为失败
Others:      
*******************************************************************************************/
static int fpga_ep3cxx_ioctl(struct inode *inode,struct file *filp,unsigned int cmd,unsigned long arg)
{
}

/*******************************************************************************************
Function:   static void ep3cxx_interrupt_bottom(unsigned long arg)
Description:外部中断时的底部处理函数
Input:      unsigned long arg
Return:       void
Others:      
*******************************************************************************************/
static void ep3cxx_interrupt_bottom(unsigned long arg)
{
}

/*******************************************************************************************
Function:   static unsigned int fpga_ep3xx_poll(struct file *filp, poll_table *wait)
Description:
Input:      struct file *filp
            poll_table *wait
Return:      
Others:      
*******************************************************************************************/
static unsigned int fpga_ep3xx_poll(struct file *filp, poll_table *wait)
{
}

/*******************************************************************************************
Function:   static int fpga_ep3cxx_release(struct inode *inode,struct file *filp)
Description:当执行close的时候执行此函数
Input:      struct inode *inode
            struct file *filp
Return:      
Others:      
*******************************************************************************************/
static int fpga_ep3cxx_release(struct inode *inode,struct file *filp)
{
    struct ep3cxx_device_info *release_info = filp->private_data;

        printk(KERN_ALERT "%s:%s,%s\r\n", __FUNCTION__,__DATE__,__TIME__);

    free_irq(release_info->irq, release_info);

    release_info = NULL;
       
    return 0;
}

struct file_operations fpga_ep3cxx_opt ={
      .owner   =THIS_MODULE,
      .ioctl   =fpga_ep3cxx_ioctl,
      .open      =fpga_ep3cxx_open,
      .read      =fpga_ep3cxx_read,
      .write   =fpga_ep3cxx_write,
      .release   =fpga_ep3cxx_release,
      .poll      =fpga_ep3xx_poll,
};

static struct miscdevice ep3cxx_dev_misc ={
      .minor   =MISC_DYNAMIC_MINOR,
      .name      =   MISC_DEV_NAME,
                .fops      =&fpga_ep3cxx_opt,
};

/*******************************************************************************************
Function:   static int ep3cxx_probe ( struct platform_device *dev )
Description:这个是驱动探测函数,当驱动加载到内核的时候调用此函数,实现设备,资源等的注_册
Input:      struct platform_device *dev
Return:       0为成功,非0为失败
Others:       这个是驱动里面最重要的函数,驱动靠这个函数注_册进入内核里
            函数主要实现下面的功能:
            1,申请虚拟的内存,然后把需要访问的物理内存映射到虚拟内存空间
            2,使用虚拟内存后,设置各个寄存器,设置SROMC控制器来控制bank5,
            设置GPIO的控制器,来配置GPIO_O3为CS5,然后配置中断INIT15引脚的
            配置
*******************************************************************************************/
static int __devinit ep3cxx_probe ( struct platform_device *dev )
{
    struct ep3cxx_device_info *priv_info = NULL;
        struct resource *res = NULL;
        int ret = 0;
        int size = 0;
        unsigned int resource_num = 0;
    unsigned int cnt = 0;
       
        printk(KERN_ALERT "%s:%s,%s\r\n", __FUNCTION__,__DATE__,__TIME__);

        priv_info = kzalloc(sizeof(struct ep3cxx_device_info), GFP_KERNEL);
        if (!priv_info) {
                printk("kzalloc is fail!\n\n");
                ret = -ENOMEM;
                goto err_out;
        }

        /* get the num of not initerrupt of resource */
        resource_num = RESOURCE_NUM;

        for(cnt = 0; cnt < resource_num; cnt++)
                {
                res = platform_get_resource( dev, IORESOURCE_MEM, cnt );
          if (NULL == res)
                  {
                  printk("no memory resource %d\n", cnt);
                  ret = -ENOENT;
                  goto err_out_kfree;
                  }

                size = (res->end-res->start)+1;
          priv_info->men = request_mem_region(res->start, size, dev->name);
          if (NULL == priv_info->men)
                  {               
                  printk("failed to get memory %d\n", cnt);               
                  ret = -ENOENT;               
                  goto err_release;       
                  }

                priv_info->base = ioremap(res->start, size);
          if (NULL == priv_info->base)
                  {               
                  printk("failed to ioremap %d\n", cnt);               
                  ret = -EINVAL;               
                  goto err_iounmap;       
                  }
                }

    ep3cxx_dev_misc.parent = &dev->dev;
        ret=misc_register(&ep3cxx_dev_misc);
    if(ret)
      {
      printk("cannot register ep3cxx_dev_misc miscdev!\n");
                goto err_misc;
      }

        priv_info->dev = &dev->dev;
        // 申请中断资源       
        priv_info->irq = platform_get_irq(dev, 0);
        printk("priv_info->irq = %d\n", priv_info->irq);
        if(priv_info->irq < 0)               
                {               
                printk("get irq resource fail\n");
                ret = -ENXIO;
                goto err_irq;               
                }

    // 初始化读等待队列        
        //init_waitqueue_head(&priv_info->wait_read);
        //init_waitqueue_head(&priv_info->wait_write);
        // 初始化自旋锁       
        //spin_lock_init(&priv_info->lock);   
        // 初始化信号量       
        //init_MUTEX(&priv_info->sem);

        // 设置SROMC控制器,片选区域为bank5 写S3C6410_SROM_BC5寄存器,主要是设置时序
        // S3C_SROM_BW31~24      23~20          19~16         15~12          11~8          7~4            3~0
    //            reservedMemory bank5   Memory bank4Memory bank3Memory bank2   Memory bank1Memory bank0
        iowrite32((ioread32(priv_info->base+S3C6410_SROM_BW) & ~(0xF<<20))| (0x3<<22), priv_info->base+S3C6410_SROM_BW);
        iowrite32((0x0<<28)|(0x4<<24)|(0xd<<16)|(0x1<<12)|(0x4<<8)|(0x6<<4)|(0x0<<0), priv_info->base+S3C6410_SROM_BC5);

        // 配置GPIO_O5为MEM0_nCS bit 7:6 = 10 O5为上拉 GPN15为中断 GPN15为上拉
        iowrite32((ioread32(priv_info->base+S3C6410_GPNCON) & ~(0x3<<6)) | (0x2<<6), priv_info->base+S3C6410_GPNCON);
        iowrite32((ioread32(priv_info->base+S3C6410_GPNPUD) & ~(0x3<<6)) | (0x2<<6), priv_info->base+S3C6410_GPNPUD);
        iowrite32((ioread32(priv_info->base+S3C6410_GPNCON) & ~(0x3<<30)) | (0x2<<30), priv_info->base+S3C6410_GPNCON);
        iowrite32((ioread32(priv_info->base+S3C6410_GPNPUD) & ~(0x3<<30)) | (0x2<<30), priv_info->base+S3C6410_GPNPUD);

        // 设置中断的模式: 000 = Low level 001 = High level01x = Falling edge triggered
        //               11x = Both edge triggered               10x = Rising edge triggered
        iowrite32((ioread32(priv_info->base+S3C6410_EINT0CON0) & ~(0x7 <<28)) | (0x2 << 28), priv_info->base+S3C6410_EINT0CON0);
        iowrite32((ioread32(priv_info->base+S3C6410_EINT0FLTCON1) & ~(0x3 <<30)) | (0x1 << 31), priv_info->base+S3C6410_EINT0FLTCON1);
        iowrite32((ioread32(priv_info->base+S3C6410_EINT0PEND) & ~(0x1<<15)), priv_info->base+S3C6410_EINT0PEND);
        iowrite32((ioread32(priv_info->base+S3C6410_EINT0MASK) & ~(0x1<<15)), priv_info->base+S3C6410_EINT0MASK);
        iowrite32((ioread32(priv_info->base+S3C6410_VIC1INTENABLE) & ~(0x1<<1)) | (0x1 << 0), priv_info->base+S3C6410_VIC1INTENABLE);

    /* set the platform_drvdata */
    platform_set_drvdata(dev, priv_info);
   
        return ret;
       
        err_iounmap:
          switch(cnt)
                  {
                  case SROMC: goto err_iounmap0;
                        case GPO:   goto err_iounmap1;
                        case CS5:   goto err_iounmap2;
                        case GPN:   goto err_iounmap3;
                        case EXINT: goto err_iounmap4;
                        case VIC1:goto err_iounmap5;
                        default:    goto err_out;
                  }   
        err_release:
          switch(cnt)
                  {
                  case SROMC: goto err_release0;
                        case GPO:   goto err_release1;
                        case CS5:   goto err_release2;
                        case GPN:   goto err_release3;
                        case EXINT: goto err_release4;
                        case VIC1:goto err_release5;
                        default:    goto err_out;
                  }
               
        err_irq:
                misc_deregister(&ep3cxx_dev_misc);
        err_misc:       
        err_iounmap5:
                iounmap(priv_info->base);
    err_release5:
      release_resource(priv_info->men);
    err_iounmap4:
                iounmap(priv_info->base);
    err_release4:
      release_resource(priv_info->men);
        err_iounmap3:
                iounmap(priv_info->base);
    err_release3:
      release_resource(priv_info->men);
    err_iounmap2:
                iounmap(priv_info->base);
    err_release2:
      release_resource(priv_info->men);
    err_iounmap1:
                iounmap(priv_info->base);
    err_release1:
      release_resource(priv_info->men);
    err_iounmap0:
                iounmap(priv_info->base);
    err_release0:
      release_resource(priv_info->men);
        err_out_kfree:
                kfree(priv_info);
    err_out:
                printk("ep3cxx probe is fail!\n");
          return ret;
}

/*******************************************************************************************
Function:   static int ep3cxx_remove ( struct platform_device *dev )
Description:驱动移除函数,与probe函数进行相反的工作
Input:      struct platform_device *dev      
Return:      
Others:      
*******************************************************************************************/
static int __devexit ep3cxx_remove ( struct platform_device *dev )
{
    unsigned int remove_num = RESOURCE_NUM;
       
        struct ep3cxx_device_info *priv = platform_get_drvdata(dev);

        printk(KERN_ALERT "%s:%s,%s\r\n", __FUNCTION__,__DATE__,__TIME__);

        platform_set_drvdata(dev, NULL);

        misc_deregister(&ep3cxx_dev_misc);

        while(remove_num--)
                {
                iounmap(priv->base);
          release_resource(priv->men);
                }
       
        kfree(priv);
       
        return 0;
}

static struct platform_driver ep3cxx_driver = {
      .probe   =    ep3cxx_probe,
                .remove    =    __devexit_p(ep3cxx_remove),
                .driver    =    {
                        .owner    =    THIS_MODULE,
                                                .name   =    DEV_NAME,
                },
};

/*******************************************************************************************
Function:   static int __init ep3cxx_init ( void )
Description:
Input:            
Return:      
Others:      
*******************************************************************************************/
static int __init ep3cxx_init ( void )
{
    int ret = 0;

        printk(KERN_ALERT "%s:%s,%s\r\n", __FUNCTION__,__DATE__,__TIME__);

        ret = platform_device_register ( &ep3cxx_device );
        if ( ret )
                {
                platform_device_unregister ( &ep3cxx_device );
      printk ( "platform_device_register is fail!\n" );
                return ret;
                }
        printk ( "platform_device_register is ok!\n" );
       
        ret = platform_driver_register ( &ep3cxx_driver );
        if ( ret )
                {
                printk ( "platform_driver_register is fail!\n" );
                platform_driver_unregister ( &ep3cxx_driver );
                return ret;
                }
        printk ( "platform_driver_register is ok!\n" );
       
        return ret;
}

/*******************************************************************************************
Function:   static void __exit ep3cxx_exit ( void )
Description:
Input:            
Return:      
Others:      
*******************************************************************************************/
static void __exit ep3cxx_exit ( void )
{
    printk(KERN_ALERT "%s:%s,%s\r\n", __FUNCTION__,__DATE__,__TIME__);

    platform_driver_unregister ( &ep3cxx_driver );
        platform_device_unregister ( &ep3cxx_device );
}

module_init ( ep3cxx_init );
module_exit ( ep3cxx_exit );

以上是我的代码,有部分没有实现的:
# insmod ep3cxx_new.ko
ep3cxx_init:Oct 28 2010,15:17:19
platform_device_register is ok!
ep3cxx_probe:Oct 28 2010,15:17:19
priv_info->irq = 79
platform_driver_register is ok!
# ./ep3cxx
<1>fpga_ep3cxx_open:Oct 28 2010,15:17:19

##################################################
ep3cxx_interrupt_handle:Oct 28 2010,15:17:19
ep3cxx_interrupt_handle:Oct 28 2010,15:17:19
ep3cxx_interrupt_handle:Oct 28 2010,15:17:19
ep3cxx_interrupt_handle:Oct 28 2010,15:17:19
ep3cxx_interrupt_handle:Oct 28 2010,15:17:19
ep3cxx_interrupt_handle:Oct 28 2010,15:17:19
ep3cxx_interrupt_handle:Oct 28 2010,15:17:19
ep3cxx_interrupt_handle:Oct 28 2010,15:17:19
fpga_ep3cxx_release:Oct 28 2010,15:17:19

#

这里我用ctrl+c推出了,上面是我用按键模拟的一个外部中断,按下按键会有上面的打印信息。

现在我推出程序后,就是close后,释放中断后,我在按下按键来模拟外部中断,就会出现下面的错误,这个现象在执行rmmod xx.ko也会出现!
(只要申请中断后就会出现这个现象)
BUG: soft lockup - CPU#0 stuck for 11s!

Pid: 0, comm:            swapper
CPU: 0    Not tainted(2.6.24.2 #460)
PC is at __do_softirq+0x48/0xc0
LR is at irq_exit+0x44/0x4c
pc : [<c00a4d60>]    lr : [<c00a5108>]    psr: 20000113
sp : c03efee0ip : c03eff10fp : c03eff0c
r10: 00000000r9 : c0426ad8r8 : 00000001
r7 : c04257e0r6 : 0000000ar5 : 00000002r4 : 0000001c
r3 : c03ee000r2 : 00000100r1 : c04257e0r0 : 0000001c
Flags: nzCvIRQs onFIQs onMode SVC_32ISA ARMSegment kernel
Control: 00c5387fTable: 550a0008DAC: 00000017
[<c0088444>] (show_regs+0x0/0x50) from [<c00c0b5c>] (softlockup_tick+0xec/0x11c)
r4:0000002a
[<c00c0a70>] (softlockup_tick+0x0/0x11c) from [<c00a8f20>] (run_local_timers+0x18/0x1c)
[<c00a8f08>] (run_local_timers+0x0/0x1c) from [<c00a8fa0>] (update_process_times+0x2c/0x58)
[<c00a8f74>] (update_process_times+0x0/0x58) from [<c008ade0>] (timer_tick+0xcc/0xec)
r5:00000000 r4:c0426e10
[<c008ad14>] (timer_tick+0x0/0xec) from [<c0097a1c>] (s3c_timer_interrupt+0x24/0x54)
r5:00000000 r4:c0426e10
[<c00979f8>] (s3c_timer_interrupt+0x0/0x54) from [<c00c0e80>] (handle_IRQ_event+0x3c/0x74)
r4:c03f6568
[<c00c0e44>] (handle_IRQ_event+0x0/0x74) from [<c00c2738>] (handle_level_irq+0xd4/0xf0)
r7:c04257e0 r6:c03eff40 r5:0000001c r4:c03fbc0c
[<c00c2664>] (handle_level_irq+0x0/0xf0) from [<c0086048>] (__exception_text_start+0x48/0x64)
r5:c03fbc0c r4:0000001c
[<c0086000>] (__exception_text_start+0x0/0x64) from [<c0086a70>] (__irq_svc+0x30/0x80)
Exception stack(0xc03efe98 to 0xc03efee0)
fe80:                                                       0000001c c04257e0
fea0: 00000100 c03ee000 0000001c 00000002 0000000a c04257e0 00000001 c0426ad8
fec0: 00000000 c03eff0c c03eff10 c03efee0 c00a5108 c00a4d60 20000113 ffffffff
r6:10000000 r5:f4600000 r4:ffffffff
[<c00a4d18>] (__do_softirq+0x0/0xc0) from [<c00a5108>] (irq_exit+0x44/0x4c)
[<c00a50c4>] (irq_exit+0x0/0x4c) from [<c008604c>] (__exception_text_start+0x4c/0x64)
[<c0086000>] (__exception_text_start+0x0/0x64) from [<c0086a70>] (__irq_svc+0x30/0x80)
Exception stack(0xc03eff40 to 0xc03eff88)
ff40: 00000002 c622b5e0 f6800000 00000021 c00885cc c03ee000 c00885cc c0412f68
ff60: 50022088 410fb766 50022054 c03eff94 c03eff88 c03eff88 c00905d0 c0088624
ff80: a0000013 ffffffff
r6:10000000 r5:f4600000 r4:ffffffff
[<c00885cc>] (default_idle+0x0/0x64) from [<c0088398>] (cpu_idle+0x34/0x50)
[<c0088364>] (cpu_idle+0x0/0x50) from [<c03254e4>] (rest_init+0x50/0x60)
r7:c03f1db8 r6:c0023f28 r5:c0412b28 r4:c042815c
[<c0325494>] (rest_init+0x0/0x60) from [<c0008d5c>] (start_kernel+0x250/0x2bc)
[<c0008b0c>] (start_kernel+0x0/0x2bc) from [<50008034>] (0x50008034)

microcreat 发表于 2010-10-28 15:54:57

沉的真快!。。。顶!

microcreat 发表于 2010-10-28 16:11:13

希望高手能帮我看下,给点提示也好啊!谢谢了!

microcreat 发表于 2010-10-29 08:23:12

...
再次请教!

microcreat 发表于 2010-10-29 13:58:37

沉了!
页: [1]
查看完整版本: 请大家帮我看下,为什么我会出现这个错误!关于linux驱动的中断的问题!