3712|6

73

帖子

0

TA的资源

一粒金砂(初级)

楼主
 

第一次调用驱动,interruptible_sleep_on过不去怎么办? [复制链接]

我在调试一个语音驱动,语音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);
第二次和以后就过去了,一点事也没有,这个是什么原因,请高手们指教!

最新回复

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
点赞 关注

回复
举报

58

帖子

0

TA的资源

一粒金砂(初级)

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

建议检查返回值,判断是否成功,也可以调用两次测试一下
 
 

回复

77

帖子

0

TA的资源

一粒金砂(初级)

板凳
 
extern void enable_dma(dmach_t channel); 这个没有返回值的
 
 
 

回复

60

帖子

0

TA的资源

一粒金砂(初级)

4
 
没有返回值也应该有办法测试一下是否调用成功吧
 
 
 

回复

72

帖子

0

TA的资源

一粒金砂(初级)

5
 
不过我在ssi1306_write加上这个,就能解决一下这个问题,不过感觉治标不治本
         if(gFlag_First!=1)
        {
                interruptible_sleep_on(&ssi_twait);
        }
        gFlag_First = 2;
 
 
 

回复

76

帖子

0

TA的资源

一粒金砂(初级)

6
 
很显然,你没把ssi1306_write贴出来
 
 
 

回复

98

帖子

0

TA的资源

一粒金砂(初级)

7
 
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;
}
 
 
 

回复
您需要登录后才可以回帖 登录 | 注册

随便看看
查找数据手册?

EEWorld Datasheet 技术支持

相关文章 更多>>
关闭
站长推荐上一条 1/10 下一条

 
EEWorld订阅号

 
EEWorld服务号

 
汽车开发圈

About Us 关于我们 客户服务 联系方式 器件索引 网站地图 最新更新 手机版

站点相关: 国产芯 安防电子 汽车电子 手机便携 工业控制 家用电子 医疗电子 测试测量 网络通信 物联网

北京市海淀区中关村大街18号B座15层1530室 电话:(010)82350740 邮编:100190

电子工程世界版权所有 京B2-20211791 京ICP备10001474号-1 电信业务审批[2006]字第258号函 京公网安备 11010802033920号 Copyright © 2005-2024 EEWORLD.com.cn, Inc. All rights reserved
快速回复 返回顶部 返回列表