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) FIFO Operation -- Only able to receive the first 8 words.

Hello all.

I'm working with SPI and the TM4C is in a slave configuration. I need to send up to (120) 16-bit words to the TM4C in one data stream from the master device. Essentially this is a command buffer from which the TM4C will perform certain operations.

The master has software timed SPI, so there is variation in the transfer rate. Each transfer looks slightly different. A capture from the logic analyzer shows this (each "blip" is a 16-bit word). Chip select (FSS) is toggled between each word.

When I send the 120 test words, the TM4C interrupt triggers correctly, but I am only able to read out at most the first 8 words (a full FIFO worth). The rest of the data is "lost" in the ether.

Based on what I am seeing, the first interrupt triggered is RXTO, which does not seem to make sense. I would have thought RXFF would have been the flag. Regardless, I always see RXTO followed, often but not always, by RXOR.

My configuration of the peripheral is:

ROM_SysCtlClockSet(SYSCTL_SYSDIV_5|SYSCTL_USE_PLL|SYSCTL_XTAL_16MHZ|SYSCTL_OSC_MAIN);
ROM_SysCtlPeripheralReset(SYSCTL_PERIPH_SSI1);
ROM_SysCtlPeripheralEnable(SYSCTL_PERIPH_GPIOF);
ROM_SysCtlPeripheralEnable(SYSCTL_PERIPH_SSI1);

GPIOPinUnlockGPIO(GPIO_PORTF_BASE, GPIO_PIN_0);     // Unlock protected PF0 GPIO
GPIOPinConfigure(GPIO_PF0_SSI1RX);
GPIOPinConfigure(GPIO_PF1_SSI1TX);
GPIOPinConfigure(GPIO_PF2_SSI1CLK);
GPIOPinConfigure(GPIO_PF3_SSI1FSS);
GPIOPinTypeSSI(GPIO_PORTF_BASE,GPIO_PIN_3|GPIO_PIN_2|GPIO_PIN_1|GPIO_PIN_0);

SSIDisable(SSI1_BASE);
ROM_SSIConfigSetExpClk(SSI1_BASE,ROM_SysCtlClockGet(), SSI_FRF_MOTO_MODE_0,SSI_MODE_SLAVE,385000,16);
SSIEnable(SSI1_BASE);

// ENABLE INTERRUPT ON THE SPI1 Rx FIFO
IntRegister(INT_SSI1, SPI_ISR_Handler);
IntEnable(INT_SSI1);
// Clear out any potential stale data from the Rx FIFO
while(SSIDataGetNonBlocking(SSI1_BASE, &cmd_buffer[0])){}
cmd_buffer[0] = 0;
SSIIntClear(SSI1_BASE, SSI_RXFF | SSI_RXTO | SSI_RXOR);
SSIIntEnable(SSI1_BASE, SSI_RXFF | SSI_RXTO | SSI_RXOR);
IntMasterEnable();

My interrupt contains the following read code:

void SPI_ISR_Handler (void) {
volatile uint32_t ui32Index = 0;
uint16_t isr_source = SSIIntStatus(SSI1_BASE, 1);
if (isr_source & SSI_RXTO) { while (SSI1_SR_R & SSI_SR_RNE) { SSIDataGet(SSI1_BASE, &cmd_buffer[ui32Index]); ui32Index++; } SSIIntClear(SSI1_BASE, SSI_RXTO); } if (isr_source & SSI_RXFF) { while (SSI1_SR_R & SSI_SR_RNE) { SSIDataGet(SSI1_BASE, &cmd_buffer[ui32Index]); ui32Index++; } SSIIntClear(SSI1_BASE, SSI_RXFF); } if (isr_source & SSI_RXOR) { while (SSI1_SR_R & SSI_SR_RNE) { SSIDataGet(SSI1_BASE, &cmd_buffer[ui32Index]); ui32Index++; } SSIIntClear(SSI1_BASE, SSI_RXOR); }
}

Can anyone suggest a better method to ensure that I capture all 120 words (or fewer, depending upon the command length)?

Also, for understanding, with the Rx FIFO ignore everything beyond the first 8 words until a read is performed? This is how it appears, but I want to make sure that this is correct.

Thank you!

  • Hi Ryan,

    The FIFO can only contain 8 words so until you give it some room it will not save any more. You "give it some room" by reading the content. Each time you read 1 word a room for another word is made (in practical sense) .

    So basically you have to at least read the FIFO once, to give room for 1 word, before receiving another one.
    With so many transfer either create a handshake between the master and slave or try using the DMA to continuously empty the FIFO into the RAM for those 120 words (probably best option)
  • Hello Ryan,

    If the transaction time between two transfers is greater than the Timeout interval, then RXTO would be the first interrupt to fire. Having said that the interrupt routine is very clean and it should not be losing any data. The only thing I find suspicious is the ui32Index which is 0 at every interrupt. Hence the command buffer will be overwritten every time the interrupt is inovked.

    Regards
    Amit