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.

SSI(SPI) Slave mode on TM4C1294NCPDT

Other Parts Discussed in Thread: TM4C1294NCPDT

Hi,

I am using TM4C1294NCPDT plays the role of SPI slave. The protocol between master and slave is using 5 bytes.

Three instruction bytes and two data bytes. Now, I face two problems.

1. Always outputs nothing at first transmit after boot-up. The second transmit outputs signal. Below is the first run screenshot.

(Yellow: CS, Blue: Clock, Green: Master request, Pink: Slave response)

tek00000.tif

Below is the second run screen shot.

(Yellow: CS, Blue: Clock, Green: Master request, Pink: Slave response)

tek00003.tif

2. Slave response data  always appear on next transmit

Example: Slave should send data 0x08 at this time, but 0x08 appears at the next transmit

                Run             0              1            2             3             4

                Should       0x08       0x09       0x0A        0x0B       0x0C

                Actual        0x00        0x08      0x09        0x0A        0x0B

Below is the SSI setting

void ssi0Init(void)
{
	UINT32 g_ulDataRx[5];
    //
    // The SSI0 peripheral must be enabled for use.
    //
    SysCtlPeripheralEnable(SYSCTL_PERIPH_SSI0);

    //
    // For this example SSI0 is used with PortA[5:2].  GPIO port A needs to be
    // enabled so these pins can be used.
    //
    SysCtlPeripheralEnable(SYSCTL_PERIPH_GPIOA);

    //
    // Configure the pin muxing for SSI0 functions on port A2, A3, A4, and A5.
    // This step is not necessary if your part does not support pin muxing.
    //
    GPIOPinConfigure(GPIO_PA2_SSI0CLK);
    GPIOPinConfigure(GPIO_PA3_SSI0FSS);
	GPIOPinConfigure(GPIO_PA4_SSI0XDAT0);
	GPIOPinConfigure(GPIO_PA5_SSI0XDAT1);

    //
    // Configure the GPIO settings for the SSI pins.  This function also gives
    // control of these pins to the SSI hardware.  Consult the data sheet to
    // see which functions are allocated per pin.
    // The pins are assigned as follows:
    //      PA5 - SSI0Tx
    //      PA4 - SSI0Rx
    //      PA3 - SSI0Fss
    //      PA2 - SSI0CLK
    //
    GPIOPinTypeSSI(GPIO_PORTA_BASE, GPIO_PIN_5 | GPIO_PIN_4 | GPIO_PIN_3 |
                   GPIO_PIN_2);

    //
    // Configure and enable the SSI0 port for SPI master mode.
    //
    SSIConfigSetExpClk(SSI0_BASE, g_ui32SysClock, SSI_FRF_MOTO_MODE_0,
    				   SSI_MODE_SLAVE, 1000000, 8);

	//SSIAdvModeSet(SSI0_BASE, SSI_ADV_MODE_LEGACY);

    //
    // Enable the SSI0 module.
    //
    SSIEnable(SSI0_BASE);

	//
    // Enable RX timeout interrupt.
    //
    SSIIntEnable(SSI0_BASE, SSI_RXTO);

    //
    // Read any residual data from the SSI port.  This makes sure the receive
    // FIFOs are empty, so we don't read any unwanted junk.  This is done here
    // because the SPI SSI mode is full-duplex, which allows you to send and
    // receive at the same time.  The SSIDataGetNonBlocking function returns
    // "true" when data was returned, and "false" when no data was returned.
    // The "non-blocking" function checks if there is any data in the receive
    // FIFO and does not "hang" if there isn't.
    //
    while(SSIDataGetNonBlocking(SSI0_BASE, &g_ulDataRx[0]))
    {
    }

    //
    // Clear any pending interrupt
    //
    SSIIntClear(SSI0_BASE, SSI_RXTO);

	//
    // Enable the SSI2 interrupts to ARM core.  This has to be done here,
    // otherwise the RX timeout interrupt will fire before all the data has
    // been transferred.  This is specific to this example as both the SSI
    // master and slave are on the same microcontroller.
    //
    IntEnable(INT_SSI0);
}

Below is the Interrupt Handler

void SSI0IntHandler(void)
{
        uint32_t i;
	uint32_t int_status;


	//Get the interrrupt status.
	int_status = SSIIntStatus(SSI0_BASE, true);

	// Clear the asserted interrupts.
	if(int_status&SSI_RXTO)
	{
		ssi0INT = 1;//semaphore
		
		for(i=0;i<5;i++)
		{
			SSIDataGet(SSI0_BASE, &ssi0RxBUFF[i]);
		}
	}
	SSIIntClear(SSI0_BASE, int_status);
}

Below is the main task

uint8_t ssi0RxBUFF[5];
uint8_t ssi0TxBUFF[5];
uint32_t ssi0INT;
uint32_t ssi0XmitCnt = 5;

INT32 ATU_Service(void)
{
	uint32_t idx;
	UINT8 vswr_value_h, vswr_value_l;
	CALI_FREQ_INFO_ENTRY_S pData;
	UINT16 data;

	if(ssi0INT)
	{
		ssi0INT = 0;

		memcpy(ssi0TxBUFF, ssi0RxBUFF, 5);
		ssi0TxBUFF[4] = ssi0XmitCnt++;
		
	
		for(idx=0;idx<5;idx++)
		{
			SSIDataPutNonBlocking(SSI0_BASE, ssi0TxBUFF[idx]);
		}

		IoPrintf("\r\n Input = ");
		for(idx=0;idx<5;idx++)
		{
			IoPrintf("0x%02x ",ssi0RxBUFF[idx]);
		}
		IoPrintf("\r\n Output = ");
		for(idx=0;idx<5;idx++)
		{
			IoPrintf("0x%02x ",ssi0TxBUFF[idx]);
		}
         }
}



main(void)
{
    ssi0Init();
    
    while(1)
    {
         ATU_Service();
    }
}

I appreciate any help or guidance that is provided!

Regards,

Collin

  • Hello Collin,

    The issue arises from the use of RX TimeOut interrupt. The first time when you run the application, the master sends data to the slave. However it takes time for the slave to generate a RXTO. As a result the ssi0INT flag which is not set causes the device not to send any data to the master. By the next run the flag is set. As a result the flag which is now set after the first byte is received and hence the pattern shifts by a byte position,

    I would suggest using the priming method: where the SSI Slave puts the data in the TXFIFO unconditionally and then waits for a RXTO before putting the next set of bytes.

    Regards
    Amit
  • Hello Amit,

    Thanks for your reply. Since the master will send request for acquiring information which located on the slave. I cannot predict which information the master desired. The posted code above is the test code for this issue. Currently the master must request twice to get the correct data.

    Based on the information about the slave needs time to generate a RXTO. If the master wait long enough then the first transaction will be correct? If so, how long should the master wait?

    I have check the slave TX FIFO status and found the TX FIFO is not empty after the first transaction. I think this means the first response data not send out on wire. But I cannot find the way to reset FIFO after the first transaction. Is there any other way to solve this issue?

    Regards,
    Collin
  • Hello Collin,

    The master wait can be achieved by knowing the SSI Clock Rate on the SCLK pin and then multiplying it by 32 (as given in the data sheet) after the last transmission is completed

    The Slave FIFO can be only be reset by resetting the SSI Instance at the start of the program.

    Regards
    Amit