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.

CCS/TMS320F2812: SPI ENABLE pin does not toggle

Part Number: TMS320F2812

Tool/software: Code Composer Studio

Hi,

I am trying to establish communication between the TI DSP and the ET1100 (EtherCAT slave controller). The SPI ENABLE pin does not toggle when I run the code continuously. It does toggle when I set breakpoints. Which is a very strange behavior. I don't know where I am going wrong with this code. Please help me understand what could be the reason behind the ENABLE pin NOT TOGGLING (because of which the ET1100 does not reply) when the code runs continuously.

The GPIO and SPI Initialization code is as below

void InitGpio(void)
{

	EALLOW;
	IER = 0x0000;
	IFR = 0x0000;

	// Enable the four I/O pins for the SPI interface
	GpioMuxRegs.GPFMUX.bit.SPISIMOA_GPIOF0 = 1;                                // Slave In, Master Out
	GpioMuxRegs.GPFMUX.bit.SPISOMIA_GPIOF1 = 1;                                // Slave Out, Master In
	GpioMuxRegs.GPFMUX.bit.SPICLKA_GPIOF2 = 1;                                 // Serial Clock
	GpioMuxRegs.GPFMUX.bit.SPISTEA_GPIOF3 = 1;                                 // Slave Transmit Enable (SYNC)

	EDIS;
}


void InitSPI(void)
{

	EALLOW;
	// Initialize SPI FIFO registers
	SpiaRegs.SPICCR.bit.SPISWRESET=0; // Reset SPI

	SpiaRegs.SPICCR.bit.SPICHAR = 0x7; // Character Length  = 8

	SpiaRegs.SPICCR.bit.CLKPOLARITY = 1; // Rising edge

	SpiaRegs.SPICTL.bit.SPIINTENA = 1;		// Enabled
	SpiaRegs.SPICTL.bit.TALK = 1;			//
	SpiaRegs.SPICTL.bit.MASTER_SLAVE = 1;	// Master mode
	SpiaRegs.SPICTL.bit.CLK_PHASE = 0;		// Add 1/2-cycle delay of Clk wrt SPISTEA
	SpiaRegs.SPICTL.bit.OVERRUNINTENA = 1;	// Overrun Interrupt enabled

	//ClkCfgRegs.LOSPCP.all = 0x1; // 0 = sysclk/1 = 200M; 1 = sysclk/2 = 100M

	SpiaRegs.SPISTS.all=0x0000;		// Clear Status bits (TxBufFull,INT, Overrun)
	SpiaRegs.SPIBRR=0x0004;		// Baud Rate = LSPCLK / (SPIBRR+1) [LSPCLK=SysClk/4 by default=50M]
	//---------------------------------------------------------------------------------------------

	SpiaRegs.SPIFFTX.all=0xC022;      	// Enable FIFO's, reset them, set TX FIFO IntLevl = 2,TXINT disabled
	SpiaRegs.SPIFFTX.bit.TXFFIENA = 0;	// Disable TXFF INT

	SpiaRegs.SPIFFRX.all=0x006A;      	// Enable FIFO's, reset them, set RXFFIL= 10(dec)
	SpiaRegs.SPIFFRX.bit.RXFFIL = 0x02;
	SpiaRegs.SPIFFRX.bit.RXFFIENA = 0;	// disable RXFF INT

	//----------------------------------------------------------------------------------------------
	SpiaRegs.SPIFFCT.all=0x00;			// FFTXDLY = 0 (delay btw Tx transfers)
	SpiaRegs.SPIPRI.all=0x0020;			// Stop after transaction complete on EmuStop

	SpiaRegs.SPICCR.bit.SPISWRESET=1;  // Enable SPI

	SpiaRegs.SPIFFTX.bit.TXFIFO=1;		// Reset Tx FIFO
	SpiaRegs.SPIFFRX.bit.RXFIFORESET=1;

	EDIS;
}

The SPI_Read code (similarly is the SPI_write function )

void ESC_read(uint16_t offset_addr, void *buf, uint16_t len, void *tALevent)
{

	uint16_t i,cmd, readval, numwords = 0, j;
	uint16_t *ptr = (uint16_t *)0;
	uint16_t readphase[16];  // FIFO=16,Up to 13 words can be read (Addrphase takes 2Addr+1WS)

	ptr = (uint16_t *)tALevent;

	if(len > 0 && len <= 26) //It is only possible to read 26 bytes of payload (+4 bytes of address) at a time from the TI SPI's FIFO
	{
	// Construct Address cmd bytes into 16-bit words for SPI xmission,
	//    SPI xmits MSBit 1st, so must swap bytes in this 16b word for transmission
	// Byte order of READ cmd sequence:
	// Byte 0: A[12:5]
	// Byte 1: A[4:0], 110b   			(110b is 3-byte cmd extension)
	// Byte 2: A[15:13], CMD[2:0], 00b	(011b is READ w/ WS)
	// Byte 3: FFh						(Wait State)
	//cmd = offset_addr & 0x1f

	cmd =(offset_addr & 0x1FE0)<<3; // offset_addr[12:5] is 1st address phase byte, shift to upper byte
	cmd |= (((offset_addr & 0x1F) << 3) | ESC_ETHERCAT_3BYTEADDR);
	readphase[0] = cmd;
	numwords++;
	readphase[1] = (offset_addr & 0xE000) | (ESC_ETHERCAT_READ_WAIT <<10) | ESC_ETHERCAT_WAIT;
	numwords++;

	for(i=2, j = 0; j<len ; i++)   //numwords is in no. of bytes;
	{
		readphase[i] = (uint16_t) ESC_ETHERCAT_CONTINUE;
		numwords++;
		j++;
		j++;
	}
	readphase[--i] |= (ESC_ETHERCAT_RDTERMINATE); // set last byte as 0xFF

	/*Disable Interrupts*/
	DINT;

	for(i = 0; i < numwords; i++)
	{
		while(SpiaRegs.SPISTS.bit.BUFFULL_FLAG == 1);
		SpiaRegs.SPITXBUF = readphase[i] & (0xFF00);
		while(SpiaRegs.SPISTS.bit.BUFFULL_FLAG == 1);
		SpiaRegs.SPITXBUF = ((readphase[i] & (0xFF)) << 8);
	}

	CPU_DELAY_US(5);
	j = len;


	while(SpiaRegs.SPIFFRX.bit.RXFFST < j);
	readval = (SpiaRegs.SPIRXBUF) & 0xFF; // Read to tALevent
	*(ptr) = (readval & 0xFF);
	CPU_DELAY_US(2);	//delay before reading next byte
	readval = (SpiaRegs.SPIRXBUF) & 0xFF; // Read to tALevent
	*(ptr) |= ((readval & 0xFF) << 8);
	CPU_DELAY_US(2);	//delay before reading next byte

	readval = SpiaRegs.SPIRXBUF; // ignore
	CPU_DELAY_US(2);	//delay before reading next byte
	readval = SpiaRegs.SPIRXBUF; // ignore
	CPU_DELAY_US(2);	//delay before reading next byte


	ptr = (uint16_t *)buf;
		for(i=0;((SpiaRegs.SPIFFRX.bit.RXFFST != 0));i++)
	    {

			readval = (SpiaRegs.SPIRXBUF) & 0xFF;
			ptr[i]= (readval & 0xFF);

			CPU_DELAY_US(2);	//delay before reading next byte

			readval = (SpiaRegs.SPIRXBUF) & 0xFF;
			ptr[i] |= ((readval & 0xFF) << 8);

	    }


	SpiaRegs.SPIFFRX.bit.RXFIFORESET = 0; //reset the FIFO pointer
	SpiaRegs.SPIFFRX.bit.RXFIFORESET = 1; //reenable the FIFO operation

	/*Enable Interrupts*/
	EINT;


	}
}


 

  • Raghu,

    Generally, if you are using the FIFO, the SPISTE will not toggle between words. SPISTE will toggle only when the last transmission has completed and there are no longer any words left in the FIFO. If you require SPISTE to toggle between words, you have a few choices:
    1.Do not use FIFO and wait for the full word to be transmitted by monitoring the SPI_INT signal. Waiting on SPI_INT will guarantee that the word has been fully transmitted, allowing SPISTE to return high.
    2. Still using a non-FIFO mode, and waiting on SPI_INT flag. Instead of relying on the SPI to toggle the STE, you use a GPIO as the Enable signal. These will be explicit writes to the state of Enable, allowing you full control.

    Thanks,
    Mark
  • Maybe I should have made it more clear. I meant SPISTE doesn't toggle at all! Not after every word. I meant it doesn't toggle ever. The code looks perfectly fine to me. I am not sure if there is some timing related issues. 

  • Raghu,

    Can you verify your GPIO mux settings?

  • Raghu,

    Have you been able to resolve the issue that you are seeing? If you have, please post your solution so that others may learn from your experience. If you have not, please post additional questions.
  • Hi,
    I have been able to resolve the issue. But it's something very unexpected. I had to increase the delay between consecutive byte reads. At the moment I have been using a CPU_Delay for 2us but I changed that to 5us THROUGHOUT the code. The least possible delay with which the system stably works for me is 5us. I also think the reason for this is I use physical wiring as a connection between the SPI of the DSP and the SPI of the ET1100. The physical wiring also generates some amount of delay. But if someone is aware of the theoretical way of calculating this delay between wires, please update here. I would like to confirm if this is the case.

    Also another issue I have noticed is when I lower the SPI speeds (baudrate) to less than approx. 2Megabit per second, the system will fail again. This issue has not been solved. But I choose to ignore it because I currently intend higher speeds of SPI and not the lower speeds.
    I am still exploring the reasons for this to happen. But theoretically I think the reason is that the SPI clock generated by the DSP as the master does not have a consistent duty cycle. There are cycles when the duty-cycle is 50% and then there cycle where it is not 50% (technically called duty-cycle distortion or duty cycle jitter or simply timing jitter). I would like to hear what the others' opinion on this too.