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.

LM4F232 SSI setup/verification



I am going to be using the LM4F232H5QD as the microcontroller to control a stepper motor.  I used the example code on how to set up the serial ports PA2-PA5 as SSI master modules but i am having trouble verifying that they are working.  I have tried connecting the pins to an oscilloscope to make sure that the clock is working and the data is being transmitted but I am not seeing anything that would lead me to believe that it is working.  I worked through most of the errors that I saw everyone else having in this area but I was wondering if there was any way to figure this issue out. In addition to this I was curious about the functionality of the UARTprint functions i.e. where they print to and how i would view these print outs.  The code below is what I am currently using.  The while loop that loops 10 times turns an LED on and off and is being used for debugging purposes. The while loop at the bottom before the return(0) was intended to bypass an error that kept occurring at the end of the running of the program: No source available for "C$$EXIT() at C:\Users\owner\workspace_v5_2\hello\Debug\hello.out:{3} 0xe40{4}". 


#include "inc/lm4f232h5qd.h"
#include "inc/hw_types.h"
#include "inc/hw_memmap.h"
#include "driverlib/fpu.h"
#include "driverlib/sysctl.h"
#include "driverlib/rom.h"
#include "driverlib/pin_map.h"
#include "grlib/grlib.h"
#include "drivers/cfal96x64x16.h"
#include "utils/uartstdio.h"
#include "driverlib/gpio.h"
#include "driverlib/ssi.h"

//*****************************************************************************
//
//! \addtogroup example_list
//! <h1>Hello World (hello)</h1>
//!
//! A very simple ``hello world'' example.  It simply displays ``Hello World!''
//! on the display and is a starting point for more complicated applications.
//! This example uses calls to the Stellaris Graphics Library graphics
//! primitives functions to update the display.  For a similar example using
//! widgets, please see ``hello_widget''.
//
//*****************************************************************************

//*****************************************************************************
//
// The error routine that is called if the driver library encounters an error.
//
//*****************************************************************************
#ifdef PART_IS_LM4F232H5QD
   GPIOPinConfigure(GPIO_PA2_SSI0CLK);
   GPIOPinConfigure(GPIO_PA3_SSI0FSS);
   GPIOPinConfigure(GPIO_PA4_SSI0RX);
   GPIOPinConfigure(GPIO_PA5_SSI0TX);
#endif

#define NUM_SSI_DATA 3

//*****************************************************************************
//
// 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.
    // TODO: change this to whichever GPIO port you are using.
    //
    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.
    // TODO: change this to select the port/pin you are using.
    //
    GPIOPinConfigure(GPIO_PA0_U0RX);
    GPIOPinConfigure(GPIO_PA1_U0TX);

    //
    // Select the alternate (UART) function for these pins.
    // TODO: change this to select the port/pin you are using.
    //
    GPIOPinTypeUART(GPIO_PORTA_BASE, GPIO_PIN_0 | GPIO_PIN_1);

    //
    // Initialize the UART for console I/O.
    //
    UARTStdioInit(0);
}

//*****************************************************************************
//
// Configure SSI0 in master Freescale (SPI) mode.  This example will send out
// 3 bytes of data, then wait for 3 bytes of data to come in.  This will all be
// done using the polling method.
//
//*****************************************************************************
int
main(void)
{
    volatile unsigned long kloop;
      volatile unsigned long ulLoop;
      int k = 0;

        //
        // Enable the GPIO port that is used for the on-board LED.
        //
        SYSCTL_RCGC2_R = SYSCTL_RCGC2_GPIOG;

        //
        // Do a dummy read to insert a few cycles after enabling the peripheral.
        //
        ulLoop = SYSCTL_RCGC2_R;
        kloop = SYSCTL_RCGC2_R;

        //
        // Enable the GPIO pin for the LED (PG2).  Set the direction as output, and
        // enable the GPIO pin for digital function.
        //
        GPIO_PORTG_DIR_R = 0x04;
        GPIO_PORTG_DEN_R = 0x04;

        //
        // Loop forever.
        //


    unsigned long ulDataTx[NUM_SSI_DATA];
    unsigned long ulDataRx[NUM_SSI_DATA];
    unsigned long ulindex;

    //
    // Set the clocking to run directly from the external crystal/oscillator.
    // TODO: The SYSCTL_XTAL_ value must be changed to match the value of the
    // crystal on your board.
    //
    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: 8-bit\n\n");

    //
    // The SSI0 peripheral must be enabled for use.
    //
    SysCtlPeripheralEnable(SYSCTL_PERIPH_SSI0);

    //
    // For this example SSI0 is used with PortA[5:2].  The actual port and pins
    // used may be different on your part, consult the data sheet for more
    // information.  GPIO port A needs to be enabled so these pins can be used.
    // TODO: change this to whichever GPIO port you are using.
    //
    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.
    // TODO: change this to select the port/pin you are using.
    //
    GPIOPinConfigure(GPIO_PA2_SSI0CLK);
    GPIOPinConfigure(GPIO_PA3_SSI0FSS);
    GPIOPinConfigure(GPIO_PA4_SSI0RX);
    GPIOPinConfigure(GPIO_PA5_SSI0TX);

    //
    // 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
    // TODO: change this to select the port/pin you are using.
    //
    GPIOPinTypeSSI(GPIO_PORTA_BASE, GPIO_PIN_5 | GPIO_PIN_4 | GPIO_PIN_3 |
                   GPIO_PIN_2);

    //
    // Configure and enable the SSI port for SPI master mode.  Use SSI0,
    // 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.
    //
    SSIConfigSetExpClk(SSI0_BASE, SysCtlClockGet(), SSI_FRF_MOTO_MODE_0, SSI_MODE_MASTER, 1000, 8);

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

    //
    // 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, &ulDataRx[0]))
    {
    }

    //
    // Initialize the data to send.
    //
    ulDataTx[0] = 's';
    ulDataTx[1] = 'p';
    ulDataTx[2] = 'i';

    //
    // Display indication that the SSI is transmitting data.
    //
    UARTprintf("Sent:\n  ");

    //
    // Send 3 bytes of data.
    //
    for(ulindex = 0; ulindex < NUM_SSI_DATA; ulindex++)
    {
        //
        // Display the data that SSI is transferring.
        //
        UARTprintf("'%c' ", ulDataTx[ulindex]);

        //
        // Send the data using the "blocking" put function.  This function
        // will wait until there is room in the send FIFO before returning.
        // This allows you to assure that all the data you send makes it into
        // the send FIFO.
        //
        SSIDataPut(SSI0_BASE, ulDataTx[ulindex]);
    }

    //
    // Wait until SSI0 is done transferring all the data in the transmit FIFO.
    //
    while(SSIBusy(SSI0_BASE))
    {
    }

    while(k<10)
    {
    GPIO_PORTG_DATA_R |= 0x04;

                //
                // Delay for a bit.
                //
                for(ulLoop = 0; ulLoop < 500000; ulLoop++)
                {
                }

                //
                // Turn off the LED.
                //
                GPIO_PORTG_DATA_R &= ~(0x04);

                //
                // Delay for a bit.
                //
                for(ulLoop = 0; ulLoop < 500000; ulLoop++)
                {
                }
                k++;
    }
    //
    // Display indication that the SSI is receiving data.
    //
 /*   UARTprintf("\nReceived:\n  ");

    //
    // Receive 3 bytes of data.
    //
    for(ulindex = 0; ulindex < NUM_SSI_DATA; ulindex++)
    {
        //
        // Receive the data using the "blocking" Get function. This function
        // will wait until there is data in the receive FIFO before returning.
        //
        SSIDataGet(SSI0_BASE, &ulDataRx[ulindex]);

        //
        // Since we are using 8-bit data, mask off the MSB.
        //
        ulDataRx[ulindex] &= 0x00FF;

        //
        // Display the data that SSI0 received.
        //
        UARTprintf("'%c' ", ulDataRx[ulindex]);
    }
*/
    //
    // Return no errors
    //
    while(1)
    {

    }
    return(0);
}

Thank you,

Vaughn Gooding

CPE Student @ URI

  • This code that you have here should send some data out the SSI pins, but it will do so only once for the three bytes that you send and then will not transfer any more data or provide any more clocks after the data has been sent.

    The UARTprintf() function will print out UART0 at a baud rate of 115200, N,8,1 stop bit

    Your EXIT problem is that this program has no where to exit to so you must have a while(1) at some point.