This thread has been locked.

If you have a related question, please click the "Ask a related question" button in the top right corner. The newly created question will be automatically linked to this question.

16-bit transfer via SPI with DMA TMS320C6745 yields overlapping output

Other Parts Discussed in Thread: ADS7953, TMS320C6745

I have a custom board with a TMS320C6745 connected to a ADS7953 ADC. I would like to utilize the full capability of the ADC so I am using DMA.

The problem I am having is that the DMA controller isn't correctly incrementing its pointer in memory. Though it should be incremented by 2, it is only incremented by 1 and thus the data written to the SPI port overlaps.

I have looked at these related threads to no avail:

http://e2e.ti.com/support/dsp/omap_applications_processors/f/42/t/168604.aspx (Copied this code into Spi_edma, recompiled driver, recompiled test program, still broken)

http://e2e.ti.com/support/embedded/bios/f/355/t/89303.aspx (Tried this, still no)

http://e2e.ti.com/support/embedded/bios/f/355/t/170382.aspx (This too, no)

http://e2e.ti.com/support/embedded/bios/f/355/t/130781.aspx (This neither)

I'm out of ideas. Perhaps someone can attach a working copy of the source code and the compiled libraries. I'm not sure where the problem is at this point.

TMS320C6745
CCS 5.2.1.00018
BIOS 5.41.13.42
PSP 01.30.01
EDMA3 01.11.03.01

void SpiUserInit()
{
spiParams = Spi_PARAMS;

spiParams.hwiNumber = 8;
spiParams.spiHWCfgData.intrLevel = FALSE;
spiParams.opMode = Spi_OpMode_DMAINTERRUPT;
//spiParams.opMode = Spi_OpMode_INTERRUPT;
//spiParams.opMode = Spi_OpMode_POLLED;

spiParams.outputClkFreq = 15000000; 
spiParams.loopbackEnabled = FALSE;
spiParams.edmaHandle = NULL;

spiParams.spiHWCfgData.configDatafmt[0].charLength = 16u;
spiParams.spiHWCfgData.configDatafmt[0].clkHigh = TRUE;
spiParams.spiHWCfgData.configDatafmt[0].lsbFirst = FALSE;
spiParams.spiHWCfgData.configDatafmt[0].oddParity = FALSE;
spiParams.spiHWCfgData.configDatafmt[0].parityEnable = FALSE;
spiParams.spiHWCfgData.configDatafmt[0].phaseIn = FALSE;
spiParams.spiHWCfgData.configDatafmt[0].waitEnable = FALSE;
spiParams.spiHWCfgData.configDatafmt[0].wDelay = 10;
spiParams.spiHWCfgData.intrLevel = TRUE;

spiParams.spiHWCfgData.waitDelay = TRUE;/**< True - enable format delay between 2 consecutive transfers ; */
spiParams.spiHWCfgData.pinOpModes = Spi_PinOpMode_SPISCS_4PIN;
spiParams.spiHWCfgData.delay.c2TDelay = 5; // < [IN] Chip-select-active-to-transmit-start-delay
spiParams.spiHWCfgData.delay.t2CDelay = 0; /**< [IN] Transmit-end-to-chip-select-inactive-delay */
//spiParams.spiHWCfgData.delay.t2EDelay = 0;/**< [IN] Transmit-data-finished-to-ENA-pin-inactive-time-out */
//spiParams.spiHWCfgData.delay.c2EDelay = 0;/**< [IN] Chip-select-active-to-ENA-signal-active-time-out */

Spi_init();
}

/* Buffer alignment is required when working in DMA Mode */
#pragma DATA_ALIGN(loopWrite, 128);
Uint8 loopWrite[ADC_BUF_SIZE];
/* Buffer alignment is required when working in DMA Mode */
#pragma DATA_ALIGN(loopRead, 128);
Uint8 loopRead[ADC_BUF_SIZE];


void init_adc()
{
GIO_Attrs gioAttrs = GIO_ATTRS;

Spi_ChanParams chanParams;


//if the edma support is required then we need to configure edma
EDMA3_DRV_Result edmaResult = 0;

if (NULL == hEdma)
{
edmaResult = edma3init();
if (EDMA3_DRV_SOK != edmaResult)
{
//Error in configuring the edma driver
LOG_printf(&trace,"\r\nEDMA3 : edma3init() failed\r\n");
}
else
{
LOG_printf(&trace,"\r\nEDMA3 : edma3init() passed\r\n");
}
}
chanParams.hEdma = hEdma;


//create SPI channel for transmission

spiHandle = GIO_create("/Spi1",IOM_INOUT,NULL,&chanParams,&gioAttrs);

if (spiHandle == NULL)
{
LOG_printf(&trace,"\r\n SPI Driver Handle creation Failed ");
}

}

void adc_read(int channel, Uint16 *buf, int count)
{

Spi_DataParam dataparam;
size_t size = 0;

/* clear the input and output buffers */
memset(loopWrite, 0x00, sizeof(loopWrite));
memset(loopRead , 0x00, sizeof(loopRead));

/* clear the spi params data structure */
memset(&dataparam,0x00, sizeof(Spi_DataParam));

//MANUAL MODE COMMAND for NEXT channel
int cmd = MODE_MANUAL | (channel << 7);

//Set data to be written
int i;
for(i = 0; i < count*2; i++)
{
loopWrite[i++] = (Uint8)cmd;
loopWrite[i] = (Uint8)(cmd >> 8);

}

dataparam.bufLen = 2*count;
dataparam.inBuffer = &loopRead[0];
dataparam.outBuffer = &loopWrite[0];
//CS needs to be toggled after every 16-bit word. The input is sampled at the CS signal's falling edge.
//dataparam.flags = Spi_CSHOLD; 
dataparam.dataFormat = Spi_DataFormat_0;
dataparam.chipSelect = 0x01;
size = dataparam.bufLen;

// write command
GIO_write(spiHandle, &dataparam, &size);

//... do something with the data

}

  • Hi Ben,

    After making the change that Norman has suggested  did you rebuild the SPI BIOS driver and make sure you are linking the newly built library. As Sandeep has said the source code change suggested by Norman in the last forum thread that you had referred, should be sufficient for 16 bit transfers but it would need you to rebuild the driver library and link it to your application.

    If this doesn`t work, please open a register view in Code composer studio and check the ACNT value and bcnt values in the EDMA param registers. Acnt should 2 and bcnt = buffer length/ 2.

    Regards,

    Rahul

  • Hi Rahul,

    Turns out that I was linking to the wrong library. When I built the driver it generated another lib directory and put the library there. It's working properly now. I should have checked that before I posted.

    I used the source code that Norman Wong posted here: http://e2e.ti.com/support/embedded/bios/f/355/t/130781.aspx

    Thanks