AnsweredAssumed Answered

edma dspi0 slave on linux

Question asked by David Chou on Jan 15, 2015
Latest reply on Jan 19, 2015 by Timesys Support

We use the spi0 slave to connect to ad73360 to read AD sample data,but it can not work correctly on emcraft vf6 iot-kit board,
but it works fine on the PHYTEC VF6 SBC(http://phytec.com/products/single-board-computers/cosmic-vybrid/).

we use the EDMA and dspi module to read AD73360 sample data in linux.

the buffers print as follows:

0661 0601 0599 0699 0849 0671 -001 -001 -001 -001 -001 -001 -001 -001 -001 -001 0661 0603 0601 0699 0847

0671 -001 -001 -001 -001 -001 -001 -001 0667 0623 0609 0715 0867 0681 -001 -001 -001 -001 -001 -001 -001 -001 -001 -001

-001 -001 -001 0661 0605 0601 0699 0851 0671 -001 -001 -001 -001 -001 -001 -001 0669 0623 0607 0715 0865 0681 -001 -001

-001 -001 -001 -001 -001 -001 -001 -001

but the correct buffers print as:
0661 0601 0599 0699 0849 0671 -001 -001 -001 -001 -001 -001 -001 -001 -001 -001 0661 0603 0601 0699 0847

0671 -001 -001 -001 -001 -001 -001 -001 -001 -001 -001 0667 0623 0609 0715 0867 0681 -001 -001 -001 -001 -001 -001 -001 -001 -001 -001  0661 0605 0601 0699 0851 0671 -001 -001 -001 -001 -001 -001 -001 -001 -001 -001 0669 0623 0607 0715 0865 0681 -001 -001 -001 -001 -001 -001 -001 -001 -001 -001

the data that ad73360 sending is combined by six data words and ten free data words(-1).

 

I have found the problem occurred when stop and then restart the spi0 dma channel.but it worked correctly

on PHYTEC VF6 SBC. and the mvf_edma.c are the same.the ioctl source code is as follows:

    case SAMPLE_IOC_WR_BUFFER_SIZE:

        printk("ioctl!\r\n");

        retval = __get_user(tmp, (__u32 __user *)arg);

        if (retval == 0) {

            gpio_set_value(23, 0);//AD73360 SE pulled down

            mcf_edma_stop_transfer(dspi_drv_data.rx_chan);//

            mcf_edma_stop_transfer(ftm0_ch0);

            __raw_writel(0x00, PIT_BASE + 0x178);//pit 7控制寄存器

            writel(0x00000c01, dspi_drv_data.base+SPI_MCR);//将dspi0设置为从机、清空收发FIFO计数器、停止dspi传输

            writel(0x01010001 | readl(dspi_drv_data.base+SPI_MCR), dspi_drv_data.base+SPI_MCR);//ROOE=1

            //从机使能dspi模块、片选低电平有效、停止传输、禁能收发fifo

            //writel(0,dspi_drv_data.base+SPI_RSER);

            reg=readl(dspi_drv_data.base+SPI_SR);

            reg=reg|readl(dspi_drv_data.base+SPI_SR);

            writel(reg,dspi_drv_data.base+SPI_SR);//清空状态寄存器

            //msleep(10);

 

            citer=4096*7;   

            nr_list=tmp / citer;

            nr_mod_num=tmp % citer;

            if(nr_mod_num>0) nr_list++;

            for(i=0;i<nr_list;i++){

                  (TCD_LIST+i)->SADDR=0x4002c038;

                (TCD_LIST+i)->ATTR=0x01010000;//s0ff=0,ssize=dsize=001,16位

                (TCD_LIST+i)->NBYTES=2;//每次dma请求传送2个字节

                (TCD_LIST+i)->SLAST=0;

                (TCD_LIST+i)->DADDR=DMA_START_ADDR + i*citer*2;//

                if((nr_mod_num>0)&&(i==(nr_list-1)))

                 citer=nr_mod_num;   

                (TCD_LIST+i)->CITER_DOFF=(citer<<16)|0x02;

                //if(i<(nr_list-1))

                   (TCD_LIST+i)->DLAST_SGA=DMA_START_ADDR+DMA_LL_OFF+(i+1)*32;

                (TCD_LIST+i)->BITER_STAT=(citer<<16)|((i+1)<<8)|0x12;//MAJOR.LINKCH为TCD标识符,E_SG=1,INT_MAJ=1;

            }

            TCD_LIST=TCD_LIST+nr_list;

            dest=DMA_START_ADDR+tmp*2;

            citer=4096*7;

            for(i=0;i<nr_list;i++){

                  (TCD_LIST+i)->SADDR=0x4002c038;

                (TCD_LIST+i)->ATTR=0x01010000;//s0ff=0,ssize=dsize=001,16位

                (TCD_LIST+i)->NBYTES=2;//每次dma请求传送2个字节

                (TCD_LIST+i)->SLAST=0;

                (TCD_LIST+i)->DADDR=dest + i*citer*2;//

                if((nr_mod_num>0)&&(i==(nr_list-1)))

                 citer=nr_mod_num;

                (TCD_LIST+i)->CITER_DOFF=(citer<<16)|0x02;

                if(i<(nr_list-1))

                   (TCD_LIST+i)->DLAST_SGA=DMA_START_ADDR+DMA_LL_OFF+(nr_list+i+1)*32;

                else

                   (TCD_LIST+i)->DLAST_SGA=DMA_START_ADDR+DMA_LL_OFF;

                (TCD_LIST+i)->BITER_STAT=(citer<<16)|((i+1)<<8)|0x12;//MAJOR.LINKCH为TCD标识符,E_SG=1,INT_MAJ=1;

            }

 

            mcf_edma_set_tcd_params(dspi_drv_data.rx_chan,

            0x4002c038,

            DMA_START_ADDR,

            MCF_EDMA_TCD_ATTR_SSIZE_16BIT

            | MCF_EDMA_TCD_ATTR_DSIZE_16BIT,

            0,        /* soff */

            2,    /* nbytes */

            0,        /* slast */

            4096*7,        /* citer */

            4096*7,        /* biter */

            2,        /* doff */

            DMA_START_ADDR+DMA_LL_OFF+0x20,        /*dlastsga 指向链表的第二项*/

            1,        /* major_int */

            0,        /* disable_req */

            1);        /* enable sg */

 

            cnt=0;

            cnt_halfint=nr_list;

            sampleover=0;

            fn=0;//重新计算频率

            //gpio_set_value(23, 0);//ad73360 se引脚拉低,关闭串口.

            //writel(0x7a000000, dspi_drv_data.base+SPI_CTAR0_SLAVE);//16位数据传输、cpol=0、cpha=1,下降沿接收

            writel(0x72000000, dspi_drv_data.base+SPI_CTAR0_SLAVE);//15位数据传输、cpol=0、cpha=1,下降沿接收

            printk("spi dw=15\r\n");

            reg=readl(dspi_drv_data.base+SPI_SR);

            reg=reg|readl(dspi_drv_data.base+SPI_SR);

            writel(reg,dspi_drv_data.base+SPI_SR);//清空状态寄存器

            spin_lock_irqsave(&lock, flags);

            //gpio_set_value(23, 1);

            writel((1<<16)|(1<<17)/*|(1<<24)|(1<<25)*/,dspi_drv_data.base+SPI_RSER);//允许接收中断产生DMA请求

            mcf_edma_enable_transfer(dspi_drv_data.rx_chan);//开始DMA接收数据

            //msleep(10);

            writel(readl(dspi_drv_data.base+SPI_MCR)&0xfffffffe,dspi_drv_data.base+SPI_MCR);//从机开始传输

            __raw_writel(0xffffffff, PIT_BASE + 0x170);//pit 7加载值寄存器

            __raw_writel(1, PIT_BASE + 0x178);

            mcf_edma_enable_transfer(ftm0_ch0);

            gpio_set_value(23, 1);

            spin_unlock_irqrestore(&lock, flags);

        }

        break;

Outcomes