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 Slave Receive FIFO time-out never triggers

Hi,

We are going through some frustrating debugging time with the LM4F SSI module and it looks like we need your help!

The SSI2 module is used as a slave using Freescale SPI mode 2 and a bitrate of around 660 kHz. We need to process frames as fast as possible without polling the module with nonblocking functions. We think that the receive FIFO timeout interrupt should do the job.

The datasheet states that the timeout interrupt asserts after 32 bit clock periods. This is roughly equal to 48 us, and frames arrive periodically with an interval of 400 us. The problem is that it never triggers! Other interrupts, such as the receive FIFO half full work just fine.

Please see initialization code below. Kind Regards, Per

EDIT: For clarification, I can also say that by watching the status register when using the half full interrupt, it is possible to see that the SSI Receive FIFO Not Empty (RNE) bit indeed does go low and then high. Thus the initial condition for the timeout counter should be OK.


   // Enable GPIO port H (PH7:PH4 are mapped to SSI2 peripheral)
   SysCtlPeripheralEnable(SYSCTL_PERIPH_GPIOH);
   
   // Enable SSI2 peripheral
   SysCtlPeripheralEnable(SYSCTL_PERIPH_SSI2);
   
   // Configure the pin muxing for SSI2 functions on port H4, H5, H6 and H7.
   GPIOPinConfigure(GPIO_PH4_SSI2CLK);
   GPIOPinConfigure(GPIO_PH5_SSI2FSS);
   GPIOPinConfigure(GPIO_PH6_SSI2RX);
   GPIOPinConfigure(GPIO_PH7_SSI2TX);
   
   // Configure the GPIO settings for the SSI pins.  This function also gives
   // control of these pins to the SSI hardware.
   // The pins are assigned as follows:
   //    PH7 - SSI2Tx
   //    PH6 - SSI2Rx
   //    PH5 - SSI2Fss
   //    PH4 - SSI2CLK
   GPIOPinTypeSSI(GPIO_PORTH_BASE,
                  GPIO_PIN_7 | GPIO_PIN_6 | GPIO_PIN_5 | GPIO_PIN_4);
                  
   // Configure and enable the SSI2 port for Freescale SPI slave (PO=1, PH=0).
   SSIConfigSetExpClk(SSI2_BASE, 50000000, SSI_FRF_MOTO_MODE_2,
                      SSI_MODE_SLAVE, 660000, 16);
                      
   // Enable the SSI2 module.
   SSIEnable(SSI2_BASE);
   
   // Enable RX timeout interrupt (asserted 32 bit clocks after a word is
   // written to the empty RX FIFO
   SSIIntEnable(SSI2_BASE, SSI_RXTO);
   
   while (0 != ROM_SSIDataGetNonBlocking(SSI2_BASE, &rx_data))
   {
      // Read any residual frames
   }
   
   // Clear any pending interrupt
   SSIIntClear(SSI2_BASE, SSI_RXTO);
   
   // Gate SSI2 interrupts to mcu core
   ROM_IntEnable(INT_SSI2);
  • Hi,

    Two small comments about this problem:

    1. You do not specify how long is your frame - how many words do you expect to receive. This is important - if your master uses back-to-back transmissions, then for your chosen mode, SSI_FRF_MOTO_MODE_2 the master should rise the FSS pin for every word - this is documented in the user manual.
    2. Take into account that the received word ready is at the same time when Tx FIFO is empty - so you can shorten the processing time based on this interrupt rather than Rx timeout - this timeout is 32 bit clock periods but is started when RxFIFO goes from EMPTY to non-EMPTY!

    Petrei

  • Hi Petrei,

    1. Each frame (or word, if you prefer the term) is 16 bits wide, and FSS does toggle ahead of each frame. The serial protocol matches the SSI_FRF_MOTO_MODE_2 setting perfectly, which is why we chose it in the first place. The frames are repeated indefinitely with a pause in-between that is far greater than 32 SSI clocks.

    2. The TX FIFO must never be emptied, since this is a full-duplex protocol. We don't need to shorten the processing time further. We just want the Receive FIFO time-out interrupt to work as documented!

    Kind Regards, Per

    Additional information:

    The MCU model is LX4F232H5QC and the behavior is consistent with different silicon revisions. I cannot find any errata information related to this behavior - hopefully we have missed something simple!

  • Feel your pain - our group has bit smaller package LX4F - we've not (yet) noted your issue.

    You seem thorough/studied - (forgive) should this repeat: (these are our findings - again different LX4F MCU - results upon RX timeout)

    a) SSIMIS Reg - RTMIS bit should be set (1)

    b) SSIRIS Reg - RTRIS bit should be set (1)

    c) SSIIM Reg -   RTIM bit should be clear (0)

    That last register has "flipped" bit setting - perhaps worth quick check.

  • The raw interrupt status bit (SSI_RIS_RTRIS) is never set, and thus the masked interrupt status bit will never be set either. On a further note, the SSIM bits should actually be set to allow an interrupt source to be gated to the interrupt controller. The datasheet is a bit unclear on this point, but real-life testing shows that this is the case.

    Have you got the Receive FIFO time-out interrupt working?

  • Per E said:
    datasheet is a bit unclear on this point

    Kind (diplomatic) of you to state in this manner - must plead "temporary insanity" for false advice - pardon.

    My recall is that we did observe both 1/2 Full and time-out interrupts - but w/a different SSI mode than you're using.  (Will search for past notes - may be awhile)

    As a plausible "work-around" - might you be able to use the "RXRIS" bit (w/in Reg: SSIRIS) to trigger a fixed length Timer - and have the expiration of that Timer "announce" the RX Time-Out?  Indeed extra code/effort - but may satisfy your "read to schedule" requirement.

  • Hi,

    This microcontroller is a new beast - it has some new introduced features, not explained in the data sheet: it is about a new configuration bit, SLBY6 (page 976 of the user manual) and this is not managed by StellarisWare v.9453. The data sheet says, if this bit is set to 1: " SSI module functions such that the slave operates at a 6:1 ratio of system clock to SSInCLK." 

    Maybe setting this bit will solve the problem? This assertion only is not clear.

    Petrei

  • Hi Petrei,

    Thanks for your suggestion. Unfortunately it did not change anything, which is quite logical considering that our SSI clock is about 1/75 of the system clock.

    Kind Regards, Per

  • The receive timeout by itself is not useful on the SSI or UART for the purposes of determining that there's a gap in communication.  The timeout will clear if you empty the RX FIFO for instance.  What it's useful for is for getting the last few bytes of a transmission that didn't quite trigger the RX FIFO level interrupt.

    If gaps in communication are critical to your protocol, you really need another way of detecting them, I would suggest a timer that you reset whenever you enter your receive interrupt handler.

  • I understand the function perfectly (at least if the manual description is accurate). This is exactly what we want to do. I know that the timeout clears when the RX FIFO is emptied, that is how it's supposed to work! Of course we will not read from the FIFO outside the ISR.

    As stated above, we need to process the most recent word as fast as possible. When looking at our options, it seems that the Receive FIFO timeout is the best way. If instead we were to use the half full interrupt, we would effectively wait for 4 words to be received prior to processing the first one.

  • Hi all,

    I apologize that this thread has gone unresolved for so long without much TI attention.

    Based on what I've read so far, I'd like to try to reproduce the "missing interrupt Rx timeout" to see if this is really a device issue. If it's a problem at the silicon level, I'll make sure it gets documented properly in the next errata update. If not, and I can get it working, maybe we can compare systems to see why you're not getting the interrupt you expect.

    I'll post again here once I've been able to do a little investigation.

    Regards,

    Christian

  • Hello Per,

    I was able to get the RX timeout interrupt to work in Freescale SPI mode at a bit rate of 660KHz on the EK-LM4F232 evaluation board. Please find the attached files for reference. The test sets up SPI0 as master and SPI2 as slave on a single EK-LM4F232 board. The GPIOs used by these peripherals are readily available on this board with the necessary connections explained in the attached "spi_slave.c" file. The status messages are transmitted over UART0 at 115200 baud and 8-n-1 mode. 

    The following are the sequence of events that are performed by this test.
    - The master transfers 3 bytes of data.
    - The salve RX timeout interrupt is gated to the ARM core.
    - The RX timeout interrupt is fired and the slave RX FIFO data is read.
    - The sent and received data is compared.

    I hope this addresses your issue!

    Regards,
    Sainandan Reddy
  • Hi Sai,

    Thank you. I will not have time to test this for some days, and I am noting two differences between our applications

    1) The transfer is not continuous in your example
    2) The word width is 8 bits as opposed to 16 bits in our case

    But this is easy for me to test once I get the chance! Will report back then.

    Kind Regards,
    Per

  • Others have watched w/interest too - in addition to the two differences highlighted by requesting poster - does not the "all in one" (MCU loopback test) cause some discomfort? 

    Recognize that loopback is "quick/easy" - but would not a more "pure" test result from "board to board" transaction (2 separate devices) which more closely approximates poster's implementation - and is "free" from any possible "unwanted coupling" - which such "all in one" test may introduce?  This reporter would prefer to see 2 eval boards exchange - to better mirror "reality."

    In past life - designing 32 bit MCU for #1 selling "set top box" - such testing "short-cuts" often fell short of "real-world" operational demands - and thus provided "sub-optimal" verifications...