第一次调用驱动,interruptible_sleep_on过不去怎么办?

kobeyuan   2007-8-6 16:28 楼主
我在调试一个语音驱动,语音codec是cp1306

在open函数中我申请了DMA通道,在read/write函数中等待interruptible_sleep_on(&ssi_rwait);

在DMA完成中,wake_up_interruptible(&ssi_rwait);

结果我第一次调用read/write函数时候,程序就停在interruptible_sleep_on(&ssi_rwait);

我ctrl+C后,再调用驱动时候,就OK了,不知道这个是什么原因?

具体代码如下:
static devfs_handle_t devfs_handle;
int init_module()
{
        int result;
        printk("ssi649 driver version 1.0  "__DATE__" / "__TIME__"\n");

        result = devfs_register_chrdev(0, "SSI649", &ssi649_fops);
        if ( result < 0 )
        {
                printk("ssi649 error: Unable to register driver\n");               
                return -ENODEV;
        }
        devfs_handle =devfs_register(NULL, "SSI649", DEVFS_FL_DEFAULT,
                              result, 0,
                              S_IFCHR | S_IRUSR | S_IWUSR,
                              &ssi649_fops, NULL);


        gMajor = result;
        if(malloc_buffer()<0)
                printk("ERROR: can't malloc buffer\n");

        //set mode
        _reg_CRM_CSCR &= ~0x180000;   /* ssi1 ssi2 SEL */
        _reg_CRM_PCCR0 |= 0x320d0;    /* 3 ssi1,2 baud En; 2 dma En;
                                        5 cspi1 ssi1 ssi2 En */
        _reg_CRM_PCCR1 |= 0x800000;    /*  cspi3 En *///add: cspi3 en
       
        //_reg_CRM_CCSR = 0xf;          /* ssi1 baud output */
        _reg_CRM_CCSR = 0xf;          /* ssi2 baud output */
                                                                               
            return 0;
}



static int ssi649_open(struct inode *inode, struct file *filp)
{
        MOD_INC_USE_COUNT;
          
        dma_request_t ssi_dma_req ;
       
        memset(&ssi_dma_req, 0, sizeof(dma_request_t));
       
        if ((mx_request_dma(&channel_mem2ssi, "SSISTX"))>=0)
        {
               
                /* Configure the dma request members that do not change */
                ssi_dma_req.burstLength = 8;
                ssi_dma_req.callback = (dma_callback_t)ssiTX_complete_handler;
                /* dma source config */
                ssi_dma_req.sourceType = DMA_TYPE_LINEAR;
                ssi_dma_req.sourcePort = DMA_MEM_SIZE_32;
                /* dma dest config */
                ssi_dma_req.destType = DMA_TYPE_FIFO;
                ssi_dma_req.destAddr = (uint32_t *)0x10011000;        //SSI1 Tx data register 0
                ssi_dma_req.destPort = DMA_MEM_SIZE_8;
                // request config
                ssi_dma_req.request = 9;               /* request source: SSI2 TX0 FIFO */
                _reg_DMA_CCR(channel_mem2ssi) |= 1<<3;
                _reg_DMA_RTOR(channel_mem2ssi) = 0x0;

                mx_dma_set_config(channel_mem2ssi, &ssi_dma_req);
       }
          else
             {   
                   printk(" Failed to acquire TX DMA\n");
        }
       
       
        memset(&ssi_dma_req,0,sizeof(dma_request_t));
        if (( mx_request_dma(&channel_ssi2mem,"SSISRX")) >=0 )
        {
               
                // Configure the dma request members that do not change
                ssi_dma_req.burstLength = 8;
                // DMA interrupt config
                ssi_dma_req.callback = (dma_callback_t)ssiRX_complete_handler;
                // source config
                ssi_dma_req.sourceType = DMA_TYPE_FIFO;
                ssi_dma_req.sourceAddr = (uint32_t *)0x10011008;        //SSI1 Rx data register 0
                ssi_dma_req.sourcePort = DMA_MEM_SIZE_8;
                // dest config
                ssi_dma_req.destType = DMA_TYPE_LINEAR;
                ssi_dma_req.destPort = DMA_MEM_SIZE_32;
                // request config
                ssi_dma_req.request = 8;        /* request source: SSI2 RX0 FIFO */
                _reg_DMA_CCR(channel_ssi2mem) |= 1<<3;
                _reg_DMA_RTOR(channel_ssi2mem) = 0x0;

                mx_dma_set_config(channel_ssi2mem, &ssi_dma_req);
         }
          else
             {
                printk(" Failed to acquire RX DMA");
        }
       return 1;
}


static ssize_t ssi649_read(struct file *filp, char *buf, size_t count, loff_t *f_pos)
{
        if(mm>300)
        {
                mm=0;
                rdata_buf=rdata_buf3;
        }
        rdata_buf=rdata_buf+count/4;
        dma_phyraddr = virt_to_bus((void *)rdata_buf);
        mm++;
        _reg_DMA_DAR(channel_ssi2mem) = dma_phyraddr;
        _reg_DMA_CNTR(channel_ssi2mem) =count;
        _reg_DMA_CCR(channel_ssi2mem) = 0x818;
        enable_dma(channel_ssi2mem);
        interruptible_sleep_on(&ssi_rwait);
        copy_to_user(buf,rdata_buf,count);
        return 1;

}


static void ssiTX_complete_handler(void* arg)
{
        uint32_t status = *(uint32_t *)arg;
        if(status & DMA_DONE)
        {
                if (_reg_SSI_SISR(SSI2) & (1<<10))
                {
                        pr_debug("!!!!! RX FIFO Overrun!\n");
                }
                //DMAbuf_inputintr(dbmx_audiodev);
                _reg_DMA_DISR=(1<                 _reg_DMA_CCR(channel_mem2ssi) &= ~0x1;
        }
        else
        {
                if (status & DMA_BURST_TIMEOUT)
                        printk("%s: DMA_BURST_TIMEOUT\n", __FUNCTION__);
                if (status & DMA_TRANSFER_ERROR)
                        printk("%s: DMA_TRANSFER_ERROR\n", __FUNCTION__);
                if (status & DMA_BUFFER_OVERFLOW)
                        printk("%s: DMA_BUFFER_OVERFLOW\n", __FUNCTION__);
                if (status & DMA_REQUEST_TIMEOUT)
                        printk("%s: DMA_REQUEST_TIMEOUT\n", __FUNCTION__);
                       
                mx_dump_dma_register(channel_mem2ssi);
        }
        
        _reg_DMA_DISR=(1<         _reg_DMA_CCR(channel_mem2ssi) &= ~0x1;
        wake_up_interruptible(&ssi_twait);
}


程序第一次调用的时候就停在interruptible_sleep_on(&ssi_rwait);
第二次和以后就过去了,一点事也没有,这个是什么原因,请高手们指教!

回复评论 (6)

是不是第一次调用的时候有些步骤没有成功,比如enable_dma(channel_ssi2mem);

建议检查返回值,判断是否成功,也可以调用两次测试一下
点赞  2007-8-7 09:53
extern void enable_dma(dmach_t channel); 这个没有返回值的
点赞  2007-8-8 09:46
没有返回值也应该有办法测试一下是否调用成功吧
点赞  2007-8-8 12:27
不过我在ssi1306_write加上这个,就能解决一下这个问题,不过感觉治标不治本
         if(gFlag_First!=1)
        {
                interruptible_sleep_on(&ssi_twait);
        }
        gFlag_First = 2;
点赞  2007-8-13 20:37
很显然,你没把ssi1306_write贴出来
点赞  2007-8-14 10:55
ssi1306_write和ssi1306_read其实没有什么区别的

static ssize_t ssi1306_write(struct file *filp, const char *buf, size_t count, loff_t *f_pos)
{
        copy_from_user(rdata_buf1,buf,count);

        _reg_DMA_SAR(channel_mem2ssi) = dma_phyraddr1;
        _reg_DMA_CNTR(channel_mem2ssi) =count;
        enable_dma(channel_mem2ssi);
        if(gFlag_First!=1)
        {
                interruptible_sleep_on(&ssi_twait);
        }
        gFlag_First = 2;
        return 1;
}
点赞  2007-8-27 09:13
电子工程世界版权所有 京B2-20211791 京ICP备10001474号-1 京公网安备 11010802033920号
    写回复