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.

Setting up the TM4C123GXL as an SPI slave?

Part Number: EK-TM4C123GXL

Hi all,

I'm an engineering student who has some experience programming arduinos. I've had a project involving an EK-TM4C123GXL thrown on me. My goal is to set up the EK-TM4C123GXL as an SPI slave and an Arduino Mega 2560 as an SPI master. I've read through the user manual and a lot of other E2E posts, but I'm having no luck sending anything from the Arduino to the EK-TM4C123GXL. I've attached my code I have for both the Arduino and the EK-TM4C123GXL below. If someone could point out what I'm doing wrong, I would appreciate it. Just from using print statements, it looks like the EK-TM4C123GXL code doesn't execute past initiating SSI2.

//*****************************************************************************
//
// project0.c - Example to demonstrate minimal TivaWare setup
//
// Copyright (c) 2012-2020 Texas Instruments Incorporated.  All rights reserved.
// Software License Agreement
//
// Texas Instruments (TI) is supplying this software for use solely and
// exclusively on TI's microcontroller products. The software is owned by
// TI and/or its suppliers, and is protected under applicable copyright
// laws. You may not combine this software with "viral" open-source
// software in order to form a larger program.
//
// THIS SOFTWARE IS PROVIDED "AS IS" AND WITH ALL FAULTS.
// NO WARRANTIES, WHETHER EXPRESS, IMPLIED OR STATUTORY, INCLUDING, BUT
// NOT LIMITED TO, IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
// A PARTICULAR PURPOSE APPLY TO THIS SOFTWARE. TI SHALL NOT, UNDER ANY
// CIRCUMSTANCES, BE LIABLE FOR SPECIAL, INCIDENTAL, OR CONSEQUENTIAL
// DAMAGES, FOR ANY REASON WHATSOEVER.
//
// This is part of revision 2.2.0.295 of the EK-TM4C123GXL Firmware Package.
//
//*****************************************************************************

#include <stdbool.h>
#include <stdint.h>
#include "inc/hw_ints.h"
#include "inc/hw_memmap.h"
#include "driverlib/debug.h"
#include "driverlib/gpio.h"
#include "driverlib/interrupt.h"
#include "driverlib/pin_map.h"
#include "driverlib/pwm.h"
#include "driverlib/rom.h"
#include "driverlib/rom_map.h"
#include "driverlib/hw_memmap.h"
#include "driverlib/qei.h"
#include "driverlib/sysctl.h"
#include "driverlib/uart.h"
#include "utils/uartstdio.h"
#include "driverlib/fpu.h"
#include "inc/hw_types.h"
#include "inc/hw_memmap.h"
// The error routine that is called if the driver library encounters an error.
#include "inc/hw_types.h"                   // Defines common types and macros
#include "inc/hw_gpio.h"                    // Defines Macros for GPIO hardware
#include "inc/hw_qei.h"
#include "driverlib/ssi.h"

#include "driverlib/uartstdio.h"


//*****************************************************************************
//
//! \addtogroup ssi_examples_list
//! <h1>SPI Slave (spi_slave)</h1>
//!
//! This example configures the SSI0 as SPI Master, SSI2 as SPI Slave on an
//! EK-LM4F232 evaluation board.  RX timeout interrupt is configured for SSI2.
//! Three characters are sent on the master TX, then SSI2 RX timeout interrupt
//! is enabled. The code then waits for the interrupt to fire.  Once the
//! interrupt is fired the data from slave RX FIFO is read and compared to the
//! transmitted packet and the appropriate status is displayed.  If everything
//! goes well you should see a "Test Passed." message on the terminal window.
//! The status messages are transmitted over UART0 at 115200 baud and 8-n-1
//! mode.
//!
//! This example uses the following peripherals and I/O signals on EK-LM4F232.
//! You must review these and change as needed for your own board:
//! - SSI0 peripheral
//! - GPIO Port A peripheral (for SSI0 pins) (available near the SD card slot)
//! - SSI0CLK - PA2
//! - SSI0Fss - PA3
//! - SSI0Rx  - PA4
//! - SSI0Tx  - PA5
//!
//! - SSI2 peripheral
//! - GPIO Port M peripheral (for SSI2 pins) (available right below the OLED)
//! - SSI2CLK - PH4
//! - SSI2Fss - PH5
//! - SSI2Rx  - PH6
//! - SSI2Tx  - PH7
//!
//! For this example to work, the following connections are needed on the
//! EK-LM4F232 evaluation board.
//! - SSI0CLK(PA2) - SSI2CLK(PH4)
//! - SSI0Fss(PA3) - SSI0Fss(PH5)
//! - SSI0Rx(PA4)  - SSI2Tx(PH7)
//! - SSI0Tx(PA5)  - SSI2Rx(PH6)
//!
//! The following UART signals are configured only for displaying console
//! messages for this example.  These are not required for operation of SSI0.
//! - UART0 peripheral
//! - GPIO Port A peripheral (for UART0 pins)
//! - UART0RX - PA0
//! - UART0TX - PA1
//!
//! This example uses the following interrupt handlers.  To use this example
//! in your own application you must add these interrupt handlers to your
//! vector table.
//! - SSI2IntHandler.
//!
//
//*****************************************************************************

//*****************************************************************************
//
// Number of bytes to send and receive.
//
//*****************************************************************************
#define NUM_SSI_DATA 1

//*****************************************************************************
//
// Global variables used in interrupt handler and the main loop.
//
//*****************************************************************************
volatile unsigned long g_ulSSI2RXTO = 0;
unsigned long g_ulDataRx2[NUM_SSI_DATA];

//*****************************************************************************
//
// Interrupt handler for SSI2 peripheral in slave mode.  It reads the interrupt
// status and if the interrupt is fired by a RX time out interrupt it reads the
// SSI2 RX FIFO and increments a counter to tell the main loop that RX timeout
// interrupt was fired.
//
//*****************************************************************************
void
SSI2IntHandler(void)
{
    unsigned long ulStatus, ulIndex;

    //
    // Read interrupt status.
    //
    ulStatus = SSIIntStatus(SSI2_BASE, 1);

    //
    // Check the reason for the interrupt.
    //
    if(ulStatus)
    {
        //
        // Interrupt is because of RX time out.  So increment counter to tell
        // main loop that RX timeout interrupt occurred.
        //
        g_ulSSI2RXTO++;

        //
        // Read NUM_SSI_DATA bytes of data from SSI2 RX FIFO.
        //
        for(ulIndex = 0; ulIndex < NUM_SSI_DATA; ulIndex++)
        {
            SSIDataGet(SSI2_BASE, &g_ulDataRx2[ulIndex]);
        }
    }

    //
    // Clear interrupts.
    //
    SSIIntClear(SSI2_BASE, ulStatus);
}

//*****************************************************************************
//
// This function sets up UART0 to be used for a console to display information
// as the example is running.
//
//*****************************************************************************
void
InitConsole(void)
{
    //
    // Enable GPIO port A which is used for UART0 pins.
    //
    SysCtlPeripheralEnable(SYSCTL_PERIPH_GPIOA);

    //
    // Configure the pin muxing for UART0 functions on port A0 and A1.
    // This step is not necessary if your part does not support pin muxing.
    //
    GPIOPinConfigure(GPIO_PA0_U0RX);
    GPIOPinConfigure(GPIO_PA1_U0TX);

    //
    // Select the alternate (UART) function for these pins.
    //
    GPIOPinTypeUART(GPIO_PORTA_BASE, GPIO_PIN_0 | GPIO_PIN_1);

    //
    // Initialize the UART for console I/O.
    //
    UARTStdioConfig(0, 115200, 16000000);
}



//*****************************************************************************
//
// This function sets up SPI2 to be used as slave in freescale mode.
//
//*****************************************************************************
void
InitSPI2(void)
{
    //
    // The SSI0 peripheral must be enabled for use.
    //
    SysCtlPeripheralEnable(SYSCTL_PERIPH_SSI2);

    //
    // For this example SSI2 is used with PortH[7:4].  GPIO port H needs to be
    // enabled so these pins can be used.
    //
    SysCtlPeripheralEnable(SYSCTL_PERIPH_GPIOH);

    //
    // Configure the pin muxing for SSI2 functions on port H4, H5, H6 and H7.
    // This step is not necessary if your part does not support pin muxing.
    //
    GPIOPinConfigure(GPIO_PB4_SSI2CLK);
    GPIOPinConfigure(GPIO_PB5_SSI2FSS);
    GPIOPinConfigure(GPIO_PB6_SSI2RX);
    GPIOPinConfigure(GPIO_PB7_SSI2TX);

    //
    // 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:
    //      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 SPI slave mode.
    //
    SSIConfigSetExpClk(SSI2_BASE, SysCtlClockGet(), SSI_FRF_MOTO_MODE_2,
                       SSI_MODE_SLAVE, 660000, 8);

    //
    // Enable the SSI2 module.
    //
    SSIEnable(SSI2_BASE);
}

//*****************************************************************************
//
// This example will send out 3 bytes of data from master, then waits for slave
// RX timeout interrupt to fire (where these 3 bytes are read).  Then the sent
// and returned data are compared to give out appropriate status messages on
// UART0.
//
//*****************************************************************************
int
main(void)
{
    unsigned long ulDataTx0[NUM_SSI_DATA];
    unsigned long ulDataRx0[NUM_SSI_DATA];
    unsigned long ulindex;

    //
    // Set the clocking to run directly from the external crystal/oscillator.
    //
    SysCtlClockSet(SYSCTL_SYSDIV_1 | SYSCTL_USE_OSC | SYSCTL_OSC_MAIN |
                   SYSCTL_XTAL_16MHZ);

    //
    // Set up the serial console to use for displaying messages.  This is
    // just for this example program and is not needed for SSI operation.
    //
    InitConsole();

    //
    // Display the setup on the console.
    //
    UARTprintf("SSI ->\n");
    UARTprintf("  Mode: SPI\n");
    UARTprintf("  Data: 16-bit\n\n");


    //
    // Init SPI2 as slave.
    //
    UARTprintf("290\n\n");
    InitSPI2();
    UARTprintf("292\n\n");
    //
    // Enable RX timeout interrupt.
    //
    SSIIntEnable(SSI2_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(SSI2_BASE, &g_ulDataRx2[0]))
    {
    }

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

    //

    //
    IntEnable(INT_SSI2);

    //
    // Wait for the SSI2 RXTO interrupt to fire and data read from RXFIFO.
    //
    while(g_ulSSI2RXTO == 0)
    {
        UARTprintf("\waiting...\n  ");
    }

    //
    // Display indication that salve has receiving data.
    //
    UARTprintf("\nReceived:\n  ");

    //
    // Display the 3 bytes of data that were read from RX FIFO.
    //
    for(ulindex = 0; ulindex < NUM_SSI_DATA; ulindex++)
    {
        UARTprintf("'%c' ", g_ulDataRx2[ulindex]);
    }



    if(g_ulSSI2RXTO > 1)
    {
        //
        // Tell the user that the test failed and the reason.
        //
        UARTprintf("\n\nError: %d interrupt(s) fired when expecting only one."
                   "\n", g_ulSSI2RXTO);
    }
    else
    {
        //
        // Tell the user that the test passed.
        //
        UARTprintf("\n\nTest Passed.\n\n");
    }

    while(1)
    {
    }
}

For whatever reason, TI's website will not let me place another code object, so for the arduino:

#include<SPI.h>

void setup() {
  // put your setup code here, to run once:
  Serial.begin(115200);

  SPI.begin();
  //SPI.setClockDivider(SPI_CLOCK_DIV8);
  digitalWrite(SS,HIGH);
 
}

void loop() {
  // put your main code here, to run repeatedly:
  Serial.println("Sending over SPI");
  byte master_send, master_receive;

  digitalWrite(SS, LOW);
 
  master_send = 1;

  master_receive = SPI.transfer(master_send);

  if(master_receive == 1)                   //Logic for setting the LED output depending upon value received from slave
  {
    Serial.println("SPI working");
  }  

  delay(1000);
}

  • Hello Ben,

    You are enabling the wrong GPIO port for the SSI connection:

    SysCtlPeripheralEnable(SYSCTL_PERIPH_GPIOH);

    Try

    SysCtlPeripheralEnable(SYSCTL_PERIPH_GPIOB);

    That might be all that is wrong.

    Best Regards,

    Ralph Jacobi

  • Hi Ralph,

    Thanks for pointing that out. I corrected this, but I'm still having issues. I was able to find using print statements that my InitSPI2 function does not run. I don't have any errors, so I'm not sure why it doesn't run.

  • Hello Ben,

    That usually would indicate a System Fault happened due to improper initialization of a peripheral.

    Looking at your code again, this line is also wrong:

     GPIOPinTypeSSI(GPIO_PORTH_BASE, GPIO_PIN_7 | GPIO_PIN_6 | GPIO_PIN_5 |
                       GPIO_PIN_4);

    It should be GPIO_PORTB_BASE, not PORTH.

    From what I can see the only mismatches configuration was were for the GPIO port and SSI2 seems to be setup correctly across the whole code block.

    Best Regards,

    Ralph Jacobi

  • Ralph,

    I've changed that and made a few more modifications to my code. I've connected my arduino master to an oscilloscope and confirmed that it is generating an output, but I am still having trouble receiving anything on the TI microcontroller.

    If you look at my code below, I have a few print statements for testing. I believe that the arduino is triggering the TI microcontroller because the UARTprintf("Interrupt Enabled\n"); print statement does execute, but the section of code that prints my data just displays ' ' as shown in the output below:

    Could this be due to the clock for the SSI not being set to match the Arduino?

    I've read the documentation and found this:

    on page 955 of https://www.ti.com/lit/ds/symlink/tm4c123gh6pm.pdf

    I can't figure out how to set CPSDVSR or SCR though.

    My current code for the TI microcontroller is:

    #include <stdbool.h>
    #include <stdint.h>
    #include "inc/hw_ints.h"
    #include "inc/hw_memmap.h"
    #include "driverlib/debug.h"
    #include "driverlib/gpio.h"
    #include "driverlib/interrupt.h"
    #include "driverlib/pin_map.h"
    #include "driverlib/pwm.h"
    #include "driverlib/rom.h"
    #include "driverlib/rom_map.h"
    #include "driverlib/hw_memmap.h"
    #include "driverlib/qei.h"
    #include "driverlib/sysctl.h"
    #include "driverlib/uart.h"
    #include "utils/uartstdio.h"
    #include "driverlib/fpu.h"
    #include "inc/hw_types.h"
    #include "inc/hw_memmap.h"
    // The error routine that is called if the driver library encounters an error.
    #include "inc/hw_types.h"                   // Defines common types and macros
    #include "inc/hw_gpio.h"                    // Defines Macros for GPIO hardware
    #include "inc/hw_qei.h"
    #include "driverlib/ssi.h"
    
    #include "driverlib/uartstdio.h"
    
    
    //*****************************************************************************
    //
    //! \addtogroup ssi_examples_list
    //! <h1>SPI Slave (spi_slave)</h1>
    //!
    //! This example configures the SSI0 as SPI Master, SSI2 as SPI Slave on an
    //! EK-LM4F232 evaluation board.  RX timeout interrupt is configured for SSI2.
    //! Three characters are sent on the master TX, then SSI2 RX timeout interrupt
    //! is enabled. The code then waits for the interrupt to fire.  Once the
    //! interrupt is fired the data from slave RX FIFO is read and compared to the
    //! transmitted packet and the appropriate status is displayed.  If everything
    //! goes well you should see a "Test Passed." message on the terminal window.
    //! The status messages are transmitted over UART0 at 115200 baud and 8-n-1
    //! mode.
    //!
    //! This example uses the following peripherals and I/O signals on EK-LM4F232.
    //! You must review these and change as needed for your own board:
    //! - SSI0 peripheral
    //! - GPIO Port A peripheral (for SSI0 pins) (available near the SD card slot)
    //! - SSI0CLK - PA2
    //! - SSI0Fss - PA3
    //! - SSI0Rx  - PA4
    //! - SSI0Tx  - PA5
    //!
    //! - SSI2 peripheral
    //! - GPIO Port M peripheral (for SSI2 pins) (available right below the OLED)
    //! - SSI2CLK - PH4
    //! - SSI2Fss - PH5
    //! - SSI2Rx  - PH6
    //! - SSI2Tx  - PH7
    //!
    //! For this example to work, the following connections are needed on the
    //! EK-LM4F232 evaluation board.
    //! - SSI0CLK(PA2) - SSI2CLK(PH4)
    //! - SSI0Fss(PA3) - SSI0Fss(PH5)
    //! - SSI0Rx(PA4)  - SSI2Tx(PH7)
    //! - SSI0Tx(PA5)  - SSI2Rx(PH6)
    //!
    //! The following UART signals are configured only for displaying console
    //! messages for this example.  These are not required for operation of SSI0.
    //! - UART0 peripheral
    //! - GPIO Port A peripheral (for UART0 pins)
    //! - UART0RX - PA0
    //! - UART0TX - PA1
    //!
    //! This example uses the following interrupt handlers.  To use this example
    //! in your own application you must add these interrupt handlers to your
    //! vector table.
    //! - SSI2IntHandler.
    //!
    //
    //*****************************************************************************
    
    //*****************************************************************************
    //
    // Number of bytes to send and receive.
    //
    //*****************************************************************************
    #define NUM_SSI_DATA 1
    
    //*****************************************************************************
    //
    // Global variables used in interrupt handler and the main loop.
    //
    //*****************************************************************************
    volatile uint32_t g_ulSSI2RXTO = 0;
    uint32_t g_ulDataRx2[NUM_SSI_DATA];
    
    //*****************************************************************************
    //
    // Interrupt handler for SSI2 peripheral in slave mode.  It reads the interrupt
    // status and if the interrupt is fired by a RX time out interrupt it reads the
    // SSI2 RX FIFO and increments a counter to tell the main loop that RX timeout
    // interrupt was fired.
    //
    //*****************************************************************************
    void
    SSI2IntHandler(void)
    {
        unsigned long ulStatus, ulIndex;
    
        //
        // Read interrupt status.
        //
        ulStatus = SSIIntStatus(SSI2_BASE, 1);
    
        //
        // Check the reason for the interrupt.
        //
        if(ulStatus)
        {
            //
            // Interrupt is because of RX time out.  So increment counter to tell
            // main loop that RX timeout interrupt occurred.
            //
            g_ulSSI2RXTO++;
    
            //
            // Read NUM_SSI_DATA bytes of data from SSI2 RX FIFO.
            //
            for(ulIndex = 0; ulIndex < NUM_SSI_DATA; ulIndex++)
            {
                SSIDataGet(SSI2_BASE, &g_ulDataRx2[ulIndex]);
            }
        }
    
        //
        // Clear interrupts.
        //
        SSIIntClear(SSI2_BASE, ulStatus);
    }
    
    //*****************************************************************************
    //
    // This function sets up UART0 to be used for a console to display information
    // as the example is running.
    //
    //*****************************************************************************
    void
    InitConsole(void)
    {
        //
        // Enable GPIO port A which is used for UART0 pins.
        //
        SysCtlPeripheralEnable(SYSCTL_PERIPH_GPIOA);
    
        //
        // Configure the pin muxing for UART0 functions on port A0 and A1.
        // This step is not necessary if your part does not support pin muxing.
        //
        GPIOPinConfigure(GPIO_PA0_U0RX);
        GPIOPinConfigure(GPIO_PA1_U0TX);
    
        //
        // Select the alternate (UART) function for these pins.
        //
        GPIOPinTypeUART(GPIO_PORTA_BASE, GPIO_PIN_0 | GPIO_PIN_1);
    
        //
        // Initialize the UART for console I/O.
        //
        UARTStdioConfig(0, 115200, 16000000);
    }
    
    
    
    //*****************************************************************************
    //
    // This function sets up SPI2 to be used as slave in freescale mode.
    //
    //*****************************************************************************
    void
    InitSPI2(void)
    {
        //
        // The SSI0 peripheral must be enabled for use.
        //
        SysCtlPeripheralEnable(SYSCTL_PERIPH_SSI2);
    
        //
        // For this example SSI2 is used with PortH[7:4].  GPIO port H needs to be
        // enabled so these pins can be used.
        //
        SysCtlPeripheralEnable(SYSCTL_PERIPH_GPIOB);
    
        //
        // Configure the pin muxing for SSI2 functions on port H4, H5, H6 and H7.
        // This step is not necessary if your part does not support pin muxing.
        //
        GPIOPinConfigure(GPIO_PB4_SSI2CLK);
        GPIOPinConfigure(GPIO_PB5_SSI2FSS);
        GPIOPinConfigure(GPIO_PB6_SSI2RX);
        GPIOPinConfigure(GPIO_PB7_SSI2TX);
    
        //
        // 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:
        //      PH7 - SSI2Tx
        //      PH6 - SSI2Rx
        //      PH5 - SSI2Fss
        //      PH4 - SSI2CLK
        //
        GPIOPinTypeSSI(GPIO_PORTB_BASE, GPIO_PIN_7 | GPIO_PIN_6 | GPIO_PIN_5 |
                       GPIO_PIN_4);
    
        //
        // Configure and enable the SSI2 port for SPI slave mode.
        //
    
    
    
        SSIConfigSetExpClk(SSI2_BASE, SysCtlClockGet(), SSI_FRF_MOTO_MODE_0, SSI_MODE_SLAVE, 1000000, 8);
    
        //
        // Enable the SSI2 module.
        //
        SSIEnable(SSI2_BASE);
        UARTprintf("SSI Enabled\n");
    }
    
    //*****************************************************************************
    //
    // This example will send out 3 bytes of data from master, then waits for slave
    // RX timeout interrupt to fire (where these 3 bytes are read).  Then the sent
    // and returned data are compared to give out appropriate status messages on
    // UART0.
    //
    //*****************************************************************************
    int
    main(void)
    {
        //unsigned long ulDataTx0[NUM_SSI_DATA];
        //unsigned long ulDataRx0[NUM_SSI_DATA];
        uint32_t ulindex;
    
        //
        // Set the clocking to run directly from the external crystal/oscillator.
        //
        SysCtlClockSet(SYSCTL_SYSDIV_1 | SYSCTL_USE_OSC | SYSCTL_OSC_MAIN | SYSCTL_XTAL_16MHZ);
    
        //
        // Set up the serial console to use for displaying messages.  This is
        // just for this example program and is not needed for SSI operation.
        //
    
    
    
        InitConsole();
    
    
    
    
    
    
    
        //
        // Display the setup on the console.
        //
        UARTprintf("SSI ->\n");
        UARTprintf("  Mode: SPI\n");
        UARTprintf("  Data: 16-bit\n\n");
    
    
        //
        // Init SPI2 as slave.
        //
    
        InitSPI2();
    
        //
        // Enable RX timeout interrupt.
        //
        IntRegister(INT_SSI2,SSI2IntHandler);
    
        SSIIntEnable(SSI2_BASE,SSI_RXTO);
        UARTprintf("Test 1\n");
        //
        // 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(SSI2_BASE, &g_ulDataRx2[0]))
        {
        }
        UARTprintf("test 2\n");
        //
        // Clear any pending interrupt
        //
        SSIIntClear(SSI2_BASE, SSI_RXOR);
        SSIIntClear(SSI2_BASE, SSI_RXTO);
    
        UARTprintf("test 3\n");
        //
    
        //
    
        IntEnable(INT_SSI2);
        if(IntIsEnabled(INT_SSI2))
        {
            UARTprintf("Interrupt Enabled\n");
        }
    
    
        //
        // Wait for the SSI2 RXTO interrupt to fire and data read from RXFIFO.
        //
        while(g_ulSSI2RXTO == 0)
        {
    
        }
    
        //
        // Display indication that salve has receiving data.
        //
        UARTprintf("\nReceived:\n  ");
    
        //
        // Display the 3 bytes of data that were read from RX FIFO.
        //
        for(ulindex = 0; ulindex < NUM_SSI_DATA; ulindex++)
        {
            UARTprintf("'%c' ", g_ulDataRx2[ulindex]);
        }
    
        while(1)
        {
        }
    }
    

    My current code for the Arduino is:

    #include<SPI.h>

    byte x = 0b01100001;

    SPISettings ti_settings(SPI_CLOCK_DIV16,MSBFIRST,SPI_MODE0);

    void setup() {
      pinMode(SS, OUTPUT);
      // put your setup code here, to run once:
      Serial.begin(115200);

      SPI.begin();
      //SPI.setClockDivider(SPI_CLOCK_DIV32);
      digitalWrite(SS,HIGH);
      delay(100);
    }

    void loop() {
      // put your main code here, to run repeatedly:

     
      Serial.println("Sending over SPI");

      digitalWrite(SS, LOW);
     
      SPI.beginTransaction(ti_settings);
     
     
      SPI.transfer(x);

      digitalWrite(53, HIGH);

      SPI.endTransaction();

    }

  • Hello Ben,

    Could this be due to the clock for the SSI not being set to match the Arduino?

    That could be a reason, yes.

    I can't figure out how to set CPSDVSR or SCR though.

    That is handled by SSIConfigSetExpClk.

    I am not sure what your Arduino is doing in terms of clock speed. What is the Arduino running at natively? Or maybe even better, what do you see the clock speed being output as on your scope captures?

    Another reason could be if the SPI modes are not matching, but it looks like that is done correctly on both the Arduino and TM4C.

    If you have a second LaunchPad, maybe you could test that you are receiving data when using two LaunchPads that are configured for the same SSI rate & frame format mode? This would help indicate if your code is working beyond a mismatch of SSI settings between the Arduino and the TM4C.

    Best Regards,

    Ralph Jacobi

  • I've played around with the ISR frequency of both the Arduino and the TI microcontroller. the Arduino has a system clock frequency of 16Mhz, but I've had the ISR frequency at 1Mhz using the SPI_CLOCK_DIV16 divider in my code above. I unfortunately don't have access to a second TM4C.

  • Hello Ben,

    The clock frequencies sound like they would line up then.

    Reviewing your code further and the outputs you reported, you are at least getting an interrupt firing then? Perhaps you can save the flag information or use a breakpoint inside to see what flag has been set?

    Also have you tried using a breakpoint to see the contents of the g_ulDataRx2 buffer after you have received data?

    Best Regards,

    Ralph Jacobi

  • I am getting an interrupt firing, but the contents of g_ulDataRx2 are blank after examining with a breakpoint

  • Hello Ben,

    Can you look at the register for the SSI2 peripheral or the ulStatus variable to see what interrupt specifically is firing then?

    You can also try and look at the SSI_DR while in the ISR as well.

    Best Regards,

    Ralph Jacobi