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.

TM4C123GH6PM: SSI Interrupts

Part Number: TM4C123GH6PM

I am trying to implement an SSI EOT interrupt and I'm not having much success.    I started with some sample code that did not have interrupts enabled and had a SysCtlDelay() after the write to hold the *CS gpio line low until the last bit was clocked out.  This works ok, but now I'm trying to make the code more efficient and faster.  So, I'd like to instead wait on the interrupt to come in and then drop the chip select.  Interrupts do occur, but I'm expecting just the SSI_TXFF interrupt and I get everything but that one.  Per the datasheet, I set the EOT bit in the SSI1_CR1R register.  What I'm not sure about is the correct placement of this call?  Should it be made prior to the Interrupts being enabled? (where I do it now.)

Here is my SSI initialization code:

void SpiInit_SSI1(void) {

// The SSI1 peripheral must be enabled for use.
ROM_SysCtlPeripheralEnable(SYSCTL_PERIPH_SSI1);

// For the TM4C123G, SSI0 is used with PortA[5:2].
ROM_SysCtlPeripheralEnable(SYSCTL_PERIPH_GPIOD);

// Configure the pin muxing for SSI0 functions on port A2, A3, A4, and A5.
ROM_GPIOPinConfigure(GPIO_PD0_SSI1CLK); // Configure PA2 for the clock
ROM_GPIOPinConfigure(GPIO_PD2_SSI1RX);
ROM_GPIOPinConfigure(GPIO_PD3_SSI1TX); // Configure PA5 for the Master Transmit


// 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 - Not Used
// PA2 - SSI0CLK
ROM_GPIOPinTypeSSI(GPIO_PORTD_BASE, GPIO_PIN_0 | GPIO_PIN_2 | GPIO_PIN_3);

// Configure and enable the SSI port for SPI master mode. Use SSI1,
// system clock supply, idle clock level low and active low clock in
// freescale SPI mode, master mode, 1MHz SSI frequency, and 8-bit data.
// For SPI mode, you can set the polarity of the SSI clock when the SSI
// unit is idle. You can also configure what clock edge you want to
// capture data on. Please reference the datasheet for more information on
// the different SPI modes.
ROM_SSIConfigSetExpClk(SSI1_BASE, 80000000, SSI_FRF_MOTO_MODE_0,
SSI_MODE_MASTER, 2000000, 16);

SSIIntDisable(SSI1_BASE, 0x0F);

SSI1_CR1_R |= 0x00000010;

SSIIntEnable(SSI1_BASE, SSI_TXFF);

SSIIntRegister(SSI1_BASE, &Ssi1IntHandler);

// Enable the SSI0 module.
ROM_SSIEnable(SSI1_BASE);

uint32_t pui32DataRx[2];

// 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(ROM_SSIDataGetNonBlocking(SSI1_BASE, &pui32DataRx[0])){ }

}

  • I just found the errata spmz849f.pdf indicating that the TX EOT interrupt is not latched. I'm not sure if this is what I'm encountering? I moved setting the EOT bit in CR1 register to after the Interrupt Enabling and now I get multiple interrupts for SSI_TXFF but I'm not seeing any data on the o-scope.
  • Hello Brian,

    Yeah, that would be what you are encountering. Saying that you are getting multiple interrupts of SSI_TXFF makes me think that you aren't actually setting the EOT bit correctly anymore, as that sounds like condition 1 - but in this case that's okay since in the end that's actually what you will want to do ultimately.

    As documented in the errata, the workaround is actually to keep the EOT bit clear anyways, which will activate this behavior: "The TXRIS interrupt indicates that the transmit FIFO is half full or less".

    Then what you should do is have the Interrupt Handler upon each time you get receive the TXRIS interrupt check if you are done transferring data into SSIDR, and if so then clear the SSIIM TXIM bit to halt the case of the interrupt being asserted all the time (as described as "Condition 1" of the Errata item SSI#07).

    With that logic in place, you can then re-enable the SSIIM TXIM bit when you need to receive the next transmit buffer interrupts such as for the next transmission.

    This all said, you would still need some form of delay to allow the remaining data in the FIFO to transmit before you can release the CS line...