Part Number: TM4C123GH6PM
Hi, I'm using a pair of TM4C123G evaluation boards trying to get an SSI channel to work. These boards have TM4C123GH6PM microcontrollers. I'm using a recent version of Code Composer Studio and TivaWare 2.2.0.295.
Between the boards we have SSI1 clock connected, and SSI1 RX/TX crosswired - RX on board 1 connects to TX on board 2 and vice versa. I have two CCS projects, a SPI master and a SPI slave. I'm simply trying to transmit "1234" from master to slave twice a second. We've looked at the lines on a scope, we see a 1 MHz clock and 2 Hz data. From that it seems the master side is working as expected. This issue I have is on the slave. After setup I'm in a loop trying to read data, and the first call to SSIDataGet never returns. Code for both sides below. What am I doing wrong ?!
// SPI master
#include <stdint.h>
#include "inc/hw_memmap.h"
#include "driverlib/gpio.h"
#include "driverlib/pin_map.h"
#include "driverlib/ssi.h"
#include "driverlib/sysctl.h"
#include "driverlib/uart.h"
/////////////////////////////////////////////////////////////////////////////
void InitializeSystem()
{
// Set the clocking to run directly from the crystal.
SysCtlClockSet(SYSCTL_SYSDIV_1 | SYSCTL_USE_OSC | SYSCTL_OSC_MAIN | SYSCTL_XTAL_16MHZ);
// Initialize UART1 to 115200 baud, N-8-1
// UART1 : GPIO Port B : UART1RX = PB0 : UART1TX = PB1
SysCtlPeripheralEnable(SYSCTL_PERIPH_UART1);
SysCtlPeripheralEnable(SYSCTL_PERIPH_GPIOB);
GPIOPinConfigure(GPIO_PB0_U1RX);
GPIOPinConfigure(GPIO_PB1_U1TX);
GPIOPinTypeUART(GPIO_PORTB_BASE, GPIO_PIN_0 | GPIO_PIN_1);
UARTConfigSetExpClk(UART1_BASE, SysCtlClockGet(), 115200,
UART_CONFIG_WLEN_8 | UART_CONFIG_STOP_ONE | UART_CONFIG_PAR_NONE);
}
/////////////////////////////////////////////////////////////////////////////
void InitializeSSI1()
{
// Enable the SSI1 peripheral for use.
SysCtlPeripheralEnable(SYSCTL_PERIPH_SSI1);
// We have PD0 (SSI1 Clk), PD2 (SSI1 Rx), and PD3 (SSI1 Tx) connected.
// (Odd thing, pins/ports for SSI1 are the same as SSI3 ?!)
SysCtlPeripheralEnable(SYSCTL_PERIPH_GPIOD);
// Configure the pin muxing for SSI functions
GPIOPinConfigure(GPIO_PD0_SSI1CLK);
GPIOPinConfigure(GPIO_PD1_SSI1FSS);
GPIOPinConfigure(GPIO_PD2_SSI1RX);
GPIOPinConfigure(GPIO_PD3_SSI1TX);
// Configure the GPIO settings for the SSI pins. This function also gives
// control of these pins to the SSI hardware.
GPIOPinTypeSSI(GPIO_PORTD_BASE, GPIO_PIN_0 | GPIO_PIN_1 | GPIO_PIN_2 | GPIO_PIN_3);
// Configure and enable the SSI port for SPI master mode.
SSIDisable(SSI1_BASE);
SSIConfigSetExpClk(SSI1_BASE, SysCtlClockGet(), SSI_FRF_MOTO_MODE_0, SSI_MODE_MASTER, 1000000, 8);
// Advance mode settings. Legacy is default. I've seen several mentions
// in technical forum discussions that when writing as SSI master, you
// need "dummy" reads (in legacy mode)?
//SSIAdvModeSet(SSI1_BASE, SSI_ADV_MODE_WRITE);
// Enable the SSI module.
SSIEnable(SSI1_BASE);
// Read residual data from the SSI port so we don't read any junk.
uint32_t RxData;
while (SSIDataGetNonBlocking(SSI1_BASE, &RxData))
{
}
}
/////////////////////////////////////////////////////////////////////////////
int main(void)
{
InitializeSystem();
InitializeSSI1();
// A call to SysCtlDelay with a delay count of 1 takes 3 clock cycles
unsigned int nDelayOneMillisecond = (SysCtlClockGet() / 3) / 1000;
const unsigned int nDelayCount = 500 /* milliseconds */ * nDelayOneMillisecond;
const unsigned int Message[4] = { '1', '2', '3', '4' };
uint32_t RxData = 0;
while (true)
{
// Transmit on SPI and UART every <n> milliseconds.
SysCtlDelay(nDelayCount);
for (unsigned int nByte = 0 ; nByte < 4 ; nByte++)
{
while (SSIDataGetNonBlocking(SSI1_BASE, &RxData)) {}
SSIDataPut(SSI1_BASE, Message[nByte]);
// SSIDataGetNonBlocking(SSI1_BASE, &RxData);
UARTCharPut(UART1_BASE, (unsigned char)Message[nByte]);
}
}
}
// SPI slave
#include <stdint.h>
#include "inc/hw_memmap.h"
#include "driverlib/gpio.h"
#include "driverlib/pin_map.h"
#include "driverlib/ssi.h"
#include "driverlib/sysctl.h"
#include "driverlib/uart.h"
/////////////////////////////////////////////////////////////////////////////
void InitializeSystem()
{
// Set the clocking to run directly from the crystal.
SysCtlClockSet(SYSCTL_SYSDIV_1 | SYSCTL_USE_OSC | SYSCTL_OSC_MAIN | SYSCTL_XTAL_16MHZ);
// Initialize UART1 to 115200 baud, N-8-1
// UART1 : GPIO Port B : UART1RX = PB0 : UART1TX = PB1
SysCtlPeripheralEnable(SYSCTL_PERIPH_UART1);
SysCtlPeripheralEnable(SYSCTL_PERIPH_GPIOB);
GPIOPinConfigure(GPIO_PB0_U1RX);
GPIOPinConfigure(GPIO_PB1_U1TX);
GPIOPinTypeUART(GPIO_PORTB_BASE, GPIO_PIN_0 | GPIO_PIN_1);
UARTConfigSetExpClk(UART1_BASE, SysCtlClockGet(), 115200,
UART_CONFIG_WLEN_8 | UART_CONFIG_STOP_ONE | UART_CONFIG_PAR_NONE);
}
/////////////////////////////////////////////////////////////////////////////
void InitializeSSI1()
{
// Enable the SSI1 peripheral for use.
SysCtlPeripheralEnable(SYSCTL_PERIPH_SSI1);
// We have PD0 (SSI1 Clk), PD2 (SSI1 Rx), and PD3 (SSI1 Tx) connected.
// (Odd thing, pins/ports for SSI1 are the same as SSI3 ?!)
SysCtlPeripheralEnable(SYSCTL_PERIPH_GPIOD);
// Configure the pin muxing for SSI functions
GPIOPinConfigure(GPIO_PD0_SSI1CLK);
GPIOPinConfigure(GPIO_PD1_SSI1FSS);
GPIOPinConfigure(GPIO_PD2_SSI1RX);
GPIOPinConfigure(GPIO_PD3_SSI1TX);
// Configure the GPIO settings for the SSI pins. This function also gives
// control of these pins to the SSI hardware.
GPIOPinTypeSSI(GPIO_PORTD_BASE, GPIO_PIN_0 | GPIO_PIN_1 | GPIO_PIN_2 | GPIO_PIN_3);
// Configure and enable the SSI port for SPI slave mode.
SSIDisable(SSI1_BASE);
SSIConfigSetExpClk(SSI1_BASE, SysCtlClockGet(), SSI_FRF_MOTO_MODE_0, SSI_MODE_SLAVE, 1000000, 8);
//SSIConfigSetExpClk(SSI1_BASE, SysCtlClockGet(), SSI_FRF_MOTO_MODE_0, SSI_MODE_SLAVE_OD, 1000000, 8);
// Advance mode settings. Legacy is default.
//SSIAdvModeSet(SSI1_BASE, SSI_ADV_MODE_LEGACY);
// Enable the SSI module.
SSIEnable(SSI1_BASE);
// Read residual data from the SSI port so we don't read any junk.
uint32_t RxData;
while (SSIDataGetNonBlocking(SSI1_BASE, &RxData))
{
}
}
/////////////////////////////////////////////////////////////////////////////
int main(void)
{
// Initialize the system
InitializeSystem();
InitializeSSI1();
unsigned int nByte = 0;
while (true)
{
// Get next charater on SPI and forward to UART
SSIDataPut(SSI1_BASE, 0); // dummy write?
SSIDataGet(SSI1_BASE, &nByte);
UARTCharPut(UART1_BASE, (unsigned char)nByte);
}
}

