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.

TMS570LC4357: SPI in slave mode and DMA

Part Number: TMS570LC4357

Hello all, 

We need to have slave SPI in compatibility  mode  and DMA transfer. 

We have a master one emitting at 1.25MHz. Without DMA, the code is working fine.

You will find our code included. 

#include "HL_spi.h"
#include "HL_sys_dma.h"
#include "sys_common.h"

g_dmaCTRL g_dmaCTRLPKT;    /* DMA control packet configuration stack */
void dmaConfigCtrlPacket(uint32 sadd,uint32 dadd,uint32 dsize, uint32 fsize);

void main(void)
{
	uint32_t Count=0;
	uint16_t RX_Data_Slave[52]  = { 0 };
	dmaBASE_t *DMA_REG =  dmaREG;
	spiBASE_t * SPI_REG3 = spiREG3;

	spiDAT1_t dataconfig1_t;

	dataconfig1_t.CS_HOLD = FALSE;
	dataconfig1_t.WDEL    = TRUE;
	dataconfig1_t.DFSEL   = SPI_FMT_0;
	dataconfig1_t.CSNR    = 0xFD;


	spiInit();	// Initialize SPI3 (SLAVE)
    gioInit();
	spiREG3->DAT1 = ((uint32)SPI_FMT_0 << 24U) |(0XFD << 16U) |(0x04000000U);

// - enabling dma module : this brings DMA out of reset
	 dmaEnable();
// - assigning dma request: channel-0 with request line - 14 (SPI3 Receive DMA Request)
	 dmaReqAssign(0,14);
// - configuring DMA control packets
	 dmaConfigCtrlPacket((uint32)(&spiREG3->BUF) ,(uint32)(&RX_Data_Slave),26,1);
// - setting DMA control packets
	 dmaSetCtrlPacket(DMA_CH0,g_dmaCTRLPKT);
// - setting the DMA channel to trigger on h/w request */
	 dmaSetChEnable(DMA_CH0, DMA_HW);

	 spiREG3->INT0 = 0x00010000;// DMA_REQ_Enable
	 	 	 	 	 	 	 	// On first received data, a DMA_Req will be
	 	 	 	 	 	 	 	// send to DMA

	 while(1)
	 {
	     while(DMA_REG->BTCFLAG!=0x00000001)						// Wait for Block Transfer Complete
		{															
			Count++;												
		}
		Count=0; // Reset Count
		DMA_REG->BTCFLAG=0x00000001;	// Clear BTC Flag
										// Because Channel 0 is configured with AutoInit
										// DMA is ready to receive the next Block.
		spiREG3->DAT1 = ((uint32)SPI_FMT_0 << 24U) | (0XFD << 16U) | (0x04000000U);
	  }
}

void dmaConfigCtrlPacket(uint32 sadd,uint32 dadd,uint32 dsize, uint32 fsize)
{
  g_dmaCTRLPKT.SADD      = sadd+2;			  /* source address             */
  g_dmaCTRLPKT.DADD      = dadd;			  /* destination  address       */
  g_dmaCTRLPKT.CHCTRL    = 0;                 /* channel control            */
  g_dmaCTRLPKT.FRCNT	 = fsize;                 /* frame count                */
  g_dmaCTRLPKT.ELCNT     = dsize;             /* element count              */
  g_dmaCTRLPKT.ELDOFFSET = 0;                 /* element destination offset */
  g_dmaCTRLPKT.ELSOFFSET = 0;		          /* element source offset      */
  g_dmaCTRLPKT.FRDOFFSET = 0;		          /* frame destination offset   */
  g_dmaCTRLPKT.FRSOFFSET = 0;                 /* frame destination offset   */
  g_dmaCTRLPKT.PORTASGN  = 4;                 /* port b                     */
  g_dmaCTRLPKT.RDSIZE    = ACCESS_16_BIT;	  /* read size                  */
  g_dmaCTRLPKT.WRSIZE    = ACCESS_16_BIT; 	  /* write size                 */
  g_dmaCTRLPKT.TTYPE     = FRAME_TRANSFER ;   /* transfer type              */
  g_dmaCTRLPKT.ADDMODERD = ADDR_FIXED;        /* address mode read          */
  g_dmaCTRLPKT.ADDMODEWR = ADDR_INC1;         /* address mode write         */
  g_dmaCTRLPKT.AUTOINIT  = AUTOINIT_ON;       /* autoinit                   */
}

We have made some tests:

1) With element count equal to 26  and frame count equal to 1, we got 26 time the same value in the reception buffer

2) With element count equal to 1  and frame count equal to 26, the DMA doesn't finish (BTCFLAG never equal to zero).

We cannot understand this behavior. 

Is someone can explain this strange phenomena? 

Thanks a lot 

Alain 

  • In the first case, element count equal to 26 and frame count equal to 1, you are telling the DMA to read the same location26 times when you get one DMA request, that is, one SPI word received. This is typically not what you want.

    In the second case, you read one SPI word. The DMA is likely waiting for the SPI to receive another word. Since the SPI is configured as a slave, have you verified that the master (whatever it is) is sending more than one word?
  • Hi Bob,

    For the first case, you are right, this is not what's we want.


    For the second one, we are sure that the master send data continuously. The master send one different word (1, 2, 3, ...) each 1ms, a classical (non DMA slave) receive it OK. That's why we cannot understand the behavior.


    alain
  • I think the issue is that the slave SPI wants to work in full duplex mode. It will not receive a new character unless there is a new character in the transmit buffer. I see in your example that you have one write to spiREG3->DAT1. That put dummy data (looks like 0s) into the transmit buffer. That allowed the slave SPI to receive one character.

    To use the SPI in slave mode with DMA you need to use two DMA channels. The second channel is triggered off of the SPI TX buffer empty and can just be writing some constant dummy data to spiREG3->DAT0.
  • Hi Bob, 

    You are right, the SPI is full duplex and we need to write a dummy data in DAT1.  But three additional questions:

    1) Is there a way to avoid this situation, receive data without writing something before in the case of a slave SPI?

    2) Have you a DMA transmit sample code?

    3) We have cache enabled. When DMA is storing data in memory, this memory is not updated in the cache. Is there a way to solve this issue with cache enable?

    Alain 

     

  • 1) No, on these devices you must load the TX buffer to receive as a slave.
    2) Not exactly. Here is an example doing SCI transmit with DMA which might help;
    www.ti.com/.../spna213.pdf
    Here is an example using parallel MibSPI with DMA, but this is more complicated than you need.
    www.ti.com/.../spna231.pdf
    3) Use the MPU and map the section of RAM used for the SPI buffers as non-cacheable.
  • Hello,

    1) OK
    2) We will try and come back soon.
    3) It works fine.

    Best regards

    Alain