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.

tms470 spi transfer problem

Other Parts Discussed in Thread: HALCOGEN, TMS470MF06607

Hello,

I'm facing a problem with SPI, the tms470 is a master and is connected with a maxim 3420E spi-usb device.

With an oscilloscope I see the data on MOSI (or SIMO), but I had to modify the autogenerate source code from codegen to make it works, since after a completed transfer, I got the bit at 1 when calling the next spiTransfer.

while(spi->TGCTRL[group] & 0x80000000U){;}

spiTransfer(spi, group);

After this modification, I got all the data I'm expecting from the external chip (I see them on oscilloscope). 

My problem is that when I'm reading 

BYTE rreg(BYTE reg)
{
BYTE data;
WORD regTmp,dataTmp;

regTmp = reg << 8;

//select register to read
spiSetData(spiREG1,0,&regTmp);
mySpiTransfer(spiREG1,0);

while(!spiIsTransferComplete(spiREG1,0));
//read value
spiGetData(spiREG1,0,&dataTmp);

data = dataTmp &0xFF;

return data;
}

I have always the data received 1 step before.

For example the chip answers 0x2, 0x4, 0x8, 0x10, 0x20, 0x40, 0x80 (from oscilloscope)

but the readings I got are 0x4,0x8,0x10, ecc ecc

does anyone has any suggestions? Since the documentation on datasheet are not very clear when it comes to SPI (not on legacy mode)

Thanks!

  • You did not mention which TMS470 device you are using, so I might be making some assumptions. There are four modes the TMS470 SPI can be in based on two control bits, PHASE and POLARITY. These bits are in the appropriate SPIFMTx register. Looking at the maxim 3420E datasheet (page 11), it looks like you need to have PHASE=1 and POLARITY=0. Is this the setting you are using?

  • Hello, thanks for the reply (and also thanks too much to have look inside the maxim's datasheet). I've already noticed that the phase and polarity needs to be adjusted, so right now they are what you've suggested ( PHASE=1 and POLARITY=0).

    To test the device I'm using the code suggested by maxim here <<www.maximintegrated.com/.../3663>>

    just modified a little

    void test_SPI(void)
    {
    	BYTE j,wr,rd;
    	spiInit();                // Configure and initialize the uP's SPI port
    
    	wreg(rPINCTL,bmFDUPSPI);    // MAX3420: SPI=full-duplex
    	wreg(rUSBCTL,bmCHIPRES);    // reset the MAX3420E
    	wreg(rUSBCTL,0);            // remove the reset
    
    	do{
    
    	wr=0x01;                    // initial register write value
    	serialprint(" result= ");
    	for(j=0; j<8; j++)
    	{
    		wreg(rUSBIEN,wr);
    		rd = rreg(rUSBIEN);
    		serialprint(" %d ",rd);
    		wr <<= 1;       // Put a breakpoint here. Values of 'rd' should be 01,02,04,08,10,20,40,80
    	}
    	serialprint("\n\r end of cycle \r\n");
    	wait(1000000);
    	}while(1);
    }

    with 

    void wreg(BYTE reg, BYTE dat)
    {
    	WORD xferTmp,xferTmp1;
    
    	xferTmp = ((reg+2) << 8) | dat;
    	//select register
    	spiSetData(spiREG1,0,&xferTmp);
    	
    	//transfer
    	mySpiTransfer(spiREG1,0);
    	
    	while(!spiIsTransferComplete(spiREG1,0));
    
    	//check data received
    	spiGetData(spiREG1,0,&xferTmp); //HERE I READ THE ANSWER 1 STEP BEFORE
    	spiGetData(spiREG1,0,&xferTmp1);//HERE I READ THE SAME ANSWER OF xferTmp
    
    	//serialprint("\n\r");
    }
    
    BYTE rreg(BYTE reg)
    {
    	BYTE data;
    	WORD regTmp,dataTmp;
    
    	regTmp = reg << 8;
    
    	//select register
    	spiSetData(spiREG1,0,&regTmp);
    	//transfer
    	mySpiTransfer(spiREG1,0);
    	
    	while(!spiIsTransferComplete(spiREG1,0));
    	//read data
    	spiGetData(spiREG1,0,&dataTmp);
    
    	data = dataTmp &0xFF; //HERE I GOT ALWAYS SAME VALUE OF 2
    
    	return data;
    }
    
    void mySpiTransfer(spiBASE_t *spi, uint32 group)
    {
            //must wait here because found bit already 1 from previous transfer
    	while(spi->TGCTRL[group] & 0x80000000U){;}
    
    	spiTransfer(spi, group);
    }
    

    But the results are not what I expected, even if at oscilloscope (LeCroy with serial decode ability to see hex symbol) I see the data as they are meant to be.

    When I send data, they are ok

    but when I'm trying to read the answer, I got the problem.

    I hope I'm more clear now and you still have the will to help me.

    Thanks

    I'm using SPI1, with 16 bit data transfer, no delay, transfer group 0 with

    length = 1

    TRG_ALWAYS

    TRG_DISABLED

    CS_0

    0 data format

    4 buffer mode

    oneshot transfer

    all other checkbox on halcogen are disabled

    Update:

    after a day of trials I have it working. To do that I had to

    put another while after spiTransfer to be sure that the transfer is really completed (otherwise I could call a SetData too soon)

    void mySpiTransfer(spiBASE_t *spi, uint32 group)
    {
    
    	while(spi->TGCTRL[group] & 0x80000000U){;}
    
    	spiTransfer(spi, group);
    
    	while(spi->TGCTRL[group] & 0x80000000U){;}
    }

    and insert a spiGetData(spiREG1,0,&xferTmp); after the write

    void wreg(BYTE reg, BYTE dat)
    {
    	WORD xferTmp,xferTmp1;
    
    	xferTmp = ((reg+2) << 8) | dat;
    	serialprint("\nwrite %x: ",xferTmp);
    	
    	spiSetData(spiREG1,0,&xferTmp);
    	
    	mySpiTransfer(spiREG1,0);
    	
    	while(!spiIsTransferComplete(spiREG1,0));
    
    	serialprint("wreg done ");
    
    #if 1
    	uint32 ret;
    	ret = spiGetData(spiREG1,0,&xferTmp);
    	serialprint(" get %x [%X]", xferTmp,ret);
    #endif
    }

    If I remove the spiGetData the system hangs inside one of the while(spi->TGCTRL[group] & 0x80000000U){;} If I remove one of the while written above, the reading made by rreg return always a flags (ram->rx[start].flags) with value 0x20FE. where the 20 means an error.

    So for me there are a problem or a misunderstanding about:

    1) the function IsTransferComplete: it is not assured that after that function, I can call a spiSetData

    2) the use of spi: like it is now, is blocking (can I use DMA to set data to be transferred and use the cpu to do other jobs? if yes, HOW?)

    Please help me to understand what I am doing wrong (or if the management of SPI with TMS470 is afflicted by bugs on the hardware, or is the code from codegen that needs some improvements)

    Thanks

  • You can use interrupts to make the SPI non-blocking. Please tell me which TMS470 device you are using. Not all of them have DMA.
  • Hi,

    I'm using this one <<http:/www.ti.com/tool/tmdx470mf066hdk>>

    so it should be a TMS470MF06607 microcontroller.

    Any comments about the behaviour of spiIsTransferComplete(spiREG1,0)? after it has succeeded it is not assured that I can begin a new transfer.

    is there any way to avoid spiGetData(spiREG1,0,&xferTmp) (that means clear or set a register to avoid unecessary reading of data I don't care)?

    If I have to transfer more data without touching chip select, I understand that I can check the Chip Select Hold on codegen. But it is not clear for me how to manually bring it up/down.

    The length of my transfer group is 1 and data format is 16bit wide.

    I see that there is a CSHOLD bit on SPIDAT1 but how can I access it?

    If I'm making no mistake, I have to set it to 1 before the last data to transfer, and set it to 0 before the forst data to transfer , am I right?

    does it work with the 

    spiSetData(spiREG1,0,&xferTmp);
    
    mySpiTransfer(spiREG1,0);
    
    while(!spiIsTransferComplete(spiREG1,0));

    instructions to transfer data through SPI?

    Thanks

    Thanks

  • enrico dalla via said:
    If I have to transfer more data without touching chip select, I understand that I can check the Chip Select Hold on codegen. But it is not clear for me how to manually bring it up/down.

    When you select the "Chip Select Hold" box in HALCoGen for a transfer group, the initialization code sets the CSHOLD bit in all of the Transmit Data register control fields of that frame except the last one. So after the last data item is shifted out, the CS goes inactive.

  • Thank you very much, for the explanation.

    Now comes the last question I hope someone can answer, if I have to transfer (on reading and writing) different word's length with CS active, do I have to setup a number of transfer group, each one with different lenght, or can I change the parameters of transfer group at runtime?

    I see from spi_init that the lenght of transfer group is present inside a lot of register's settings..

    Do I have to switch to the other functions

    uint32 spiTransmitData(spiBASE_t *spi, spiDAT1_t *dataconfig_t, uint32 blocksize, uint16 * srcbuff)
    uint32 spiReceiveData(spiBASE_t *spi, spiDAT1_t *dataconfig_t, uint32 blocksize, uint16 * destbuff)
    

    If yes, I'll really appreciate any help about how to configure the dataconfig_t param.

    Thanks

  • I'm sorry, but before and after selecting CS_HOLD on codegen for a transfer group of 33 elements, the code is like this:

    with CS_HOLD
    if (33U > 0U)
    {
    while (i < ((1U+3U+5U+18U+28U+33U)-1U))
    {
    spiRAM1->tx[i++].control = (4U << 13U) /* buffer mode */
    | (1U << 12U) /* chip select hold */
    | (0U << 11U) /* lock transmission */
    | (0U << 8U) /* data format */
    | CS_0; /* chip select */
    }
    spiRAM1->tx[i++].control = (4U << 13U) /* buffer mode */
    | (1U << 12U) /* chip select hold must be zero for last buffer */
    | (0U << 10U) /* enable WDELAY */
    | (0U << 8U) /* data format */
    | CS_0; /* chip select */
    }

    without CS_HOLD
    if (33U > 0U)
    {
    while (i < ((1U+3U+5U+18U+28U+33U)-1U))
    {
    spiRAM1->tx[i++].control = (4U << 13U) /* buffer mode */
    | (1U << 12U) /* chip select hold */
    | (0U << 11U) /* lock transmission */
    | (0U << 8U) /* data format */
    | CS_0; /* chip select */
    }
    spiRAM1->tx[i++].control = (4U << 13U) /* buffer mode */
    | (0U << 12U) /* chip select hold must be zero for last buffer */
    | (0U << 10U) /* enable WDELAY */
    | (0U << 8U) /* data format */
    | CS_0; /* chip select */
    }

    So it is not true that the CS will go inactive after the last one (with CS_HOLD selected) it seems it is the opposite? Am I wrong?

    Thanks
  • You are correct (my apologies), when you select "Chip Select Hold" for a transfer group, the chip select stays low at the end of the transfer group. You would then not select "Chip Select Hold" for the last transfer group. So then the simple way to change the character length is to have a separate transfer group with a different character length.