Tool/software:
Hi, i am working on a project that requires communicating in quad spi in dma mode.I had referred few example codes udma_demo and ssi_quad_mode from Tiva Series board examples.I am using EK TM4C129EXL board,SSI0 to send and SSI1 to receive, the data is not being received.If anyone could suggest what am i missing it would be helpful.Thankyou in advance.
//*****************************************************************************
//
// ssi_quad_mode.c - Demonstrates configuring SSI0 and SSI1 in Quad-SSI mode.
//
// Copyright (c) 2019-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-TM4C129EXL Firmware Package.
//
//*****************************************************************************
#include <stdbool.h>
#include <stdint.h>
#include "inc/hw_memmap.h"
#include "inc/hw_ints.h"
#include "inc/hw_ssi.h"
#include "inc/hw_udma.h"
#include "inc/hw_types.h"
#include "driverlib/fpu.h"
#include "driverlib/debug.h"
#include "driverlib/gpio.h"
#include "driverlib/interrupt.h"
#include "driverlib/pin_map.h"
#include "driverlib/rom.h"
#include "driverlib/rom_map.h"
#include "driverlib/ssi.h"
#include "driverlib/sysctl.h"
#include "driverlib/systick.h"
#include "driverlib/uart.h"
#include "driverlib/udma.h"
#include "utils/uartstdio.h"
//*****************************************************************************
//
//! \addtogroup example_list
//! <h1>Quad-SSI Master (ssi_quad_mode)</h1>
//!
//! This example shows how to configure SSI0 as a Quad-SSI Master and SSI1 as a
//! Quad-SSI slave. The master device will send four characters to the slave
//! device using the advanced Quad mode. In Quad-SSI mode, four bits are sent
//! on each SSI Clock pulse. Once the Quad-SSI slave receives the four
//! characters in its receive FIFO it will generate an interrupt.
//!
//! This example uses the following peripherals and I/O signals. You must
//! review these and change as needed for your own board:
//! - SSI0 peripheral
//! - GPIO Port A peripheral (for SSI0 pins)
//! - SSI0Clk - PA2
//! - SSI0Fss - PA3
//! - SSI0XDAT0 - PA4
//! - SSI0XDAT1 - PA5
//! - SSI0XDAT2 - PA6
//! - SSI0XDAT3 - PA7
//!
//! - SSI1 peripheral
//! - GPIO Port B, D, E peripheral (for SSI1 pins)
//! - SSI1Clk - PB5
//! - SSI1Fss - PB4
//! - SSI1XDAT0 - PE4
//! - SSI1XDAT1 - PE5
//! - SSI1XDAT2 - PD4
//! - SSI1XDAT3 - PD5
//!
//! This example requires board level connection between SSI0 and SSI1.
//!
//! UART0, connected to the Virtual Serial Port and running at 115,200, 8-N-1,
//! is used to display messages from this application.
//
//*****************************************************************************
//****************************************************************************
//
// The variable g_ui32SysClock contains the system clock frequency in Hz.
//
//****************************************************************************
uint32_t g_ui32SysClock;
//*****************************************************************************
//
// Global flag to indicate data was received
//
//*****************************************************************************
volatile uint32_t g_bReceiveFlag = 0;
//*****************************************************************************
//
// Number of bytes to send and receive.
//
//*****************************************************************************
#define NUM_SSI_DATA 4
//
// The size of the memory transfer source and destination buffers (in words).
//
//*****************************************************************************
#define MEM_BUFFER_SIZE 1024
//*****************************************************************************
//
// The size of the UART transmit and receive buffers. They do not need to be
// the same size.
//
//*****************************************************************************
#define UART_TXBUF_SIZE 4
#define UART_RXBUF_SIZE 4
//*****************************************************************************
//
// The count of times the uDMA interrupt occurred but the uDMA transfer was not
// complete. This should remain 0.
//
//*****************************************************************************
static uint32_t g_ui32BadISR = 0;
//*****************************************************************************
//
// The source and destination buffers used for memory transfers.
//
//*****************************************************************************
static uint32_t g_ui32SrcBuf[MEM_BUFFER_SIZE];
static uint32_t g_ui32DstBuf[MEM_BUFFER_SIZE];
//*****************************************************************************
//
// The count of SSI buffers filled, one for each ping-pong buffer.
//
//*****************************************************************************
static uint32_t g_ui32RxBufACount = 0;
static uint32_t g_ui32RxBufBCount = 0;
//*****************************************************************************
//
// The transmit and receive buffers used for the UART transfers. There is one
// transmit buffer and a pair of recieve ping-pong buffers.
//
//*****************************************************************************
static uint8_t g_ui8TxBuf[UART_TXBUF_SIZE];
static uint8_t g_ui8SSIRxBufA[UART_RXBUF_SIZE];
static uint8_t g_ui8SSIRxBufB[UART_RXBUF_SIZE];
//*****************************************************************************
//
// The count of memory uDMA transfer blocks. This value is incremented by the
// uDMA interrupt handler whenever a memory block transfer is completed.
//
//*****************************************************************************
static uint32_t g_ui32MemXferCount = 0;
//*****************************************************************************
//
// The count of uDMA errors. This value is incremented by the uDMA error
// handler.
//
//*****************************************************************************
static uint32_t g_ui32uDMAErrCount = 0;
//*****************************************************************************
//
// The control table used by the uDMA controller. This table must be aligned
// to a 1024 byte boundary.
//
//*****************************************************************************
#if defined(ewarm)
#pragma data_alignment=1024
uint8_t pui8ControlTable[1024];
#elif defined(ccs)
#pragma DATA_ALIGN(pui8ControlTable, 1024)
uint8_t pui8ControlTable[1024];
#else
uint8_t pui8ControlTable[1024] __attribute__ ((aligned(1024)));
#endif
//*****************************************************************************
//
// The error routine that is called if the driver library encounters an error.
//
//*****************************************************************************
#ifdef DEBUG
void
__error__(char *pcFilename, uint32_t ui32Line)
{
}
#endif
void TransmitDataSSI0(uint32_t *data, uint32_t numBytes);
void ReceiveDataSSI1(uint32_t *data, uint32_t numBytes);
void ConfigureSSI(void);
void ConfigureUART(void);
uint32_t pui32DataTx[NUM_SSI_DATA];
uint32_t pui32DataRx[NUM_SSI_DATA];
//*****************************************************************************
//
// The interrupt handler for uDMA errors. This interrupt will occur if the
// uDMA encounters a bus error while trying to perform a transfer. This
// handler just increments a counter if an error occurs.
//
//*****************************************************************************
void uDMAErrorHandler(void)
{
uint32_t ui32Status;
//
// Check for uDMA error bit
//
ui32Status = uDMAErrorStatusGet();
//
// If there is a uDMA error, then clear the error and increment
// the error counter.
//
if (ui32Status)
{
uDMAErrorStatusClear();
g_ui32uDMAErrCount++;
}
}
//*****************************************************************************
//
// The interrupt handler for uDMA interrupts from the memory channel. This
// interrupt will increment a counter, and then restart another memory
// transfer.
//
//*****************************************************************************
void uDMAIntHandler(void)
{
uint32_t ui32Mode;
//
// Check for the primary control structure to indicate complete.
//
ui32Mode = uDMAChannelModeGet(UDMA_CHANNEL_SW);
if (ui32Mode == UDMA_MODE_STOP)
{
//
// Increment the count of completed transfers.
//
g_ui32MemXferCount++;
//
// Configure it for another transfer.
//
uDMAChannelTransferSet(UDMA_CHANNEL_SW, UDMA_MODE_AUTO, g_ui32SrcBuf,
g_ui32DstBuf,
MEM_BUFFER_SIZE);
//
// Initiate another transfer.
//
uDMAChannelEnable(UDMA_CHANNEL_SW);
uDMAChannelRequest(UDMA_CHANNEL_SW);
}
//
// If the channel is not stopped, then something is wrong.
//
else
{
g_ui32BadISR++;
}
}
//*****************************************************************************
//
// SSI0 Interrupt Handler
//
//*****************************************************************************
void SSI0IntHandler(void)
{
uint32_t ui32Status;
uint32_t ui32Mode;
//READ INTERRUPT STATUS OF SSI
ui32Status = SSIIntStatus(SSI1_BASE, 1);
// Clear any pending status
SSIIntClear(SSI1_BASE, ui32Status);
//
// Check the DMA control table to see if the ping-pong "A" transfer is
// complete. The "A" transfer uses receive buffer "A", and the primary
// control structure.
//
ui32Mode = uDMAChannelModeGet(UDMA_CHANNEL_SSI1RX | UDMA_PRI_SELECT);
//
// If the primary control structure indicates stop, that means the "A"
// receive buffer is done. The uDMA controller should still be receiving
// data into the "B" buffer.
//
if (ui32Mode == UDMA_MODE_STOP)
{
//
// Increment a counter to indicate data was received into buffer A. In
// a real application this would be used to signal the main thread that
// data was received so the main thread can process the data.
//
g_ui32RxBufACount++;
//
// Set up the next transfer for the "A" buffer, using the primary
// control structure. When the ongoing receive into the "B" buffer is
// done, the uDMA controller will switch back to this one. This
// example re-uses buffer A, but a more sophisticated application could
// use a rotating set of buffers to increase the amount of time that
// the main thread has to process the data in the buffer before it is
// reused.
//
uDMAChannelTransferSet(UDMA_CHANNEL_SSI0RX | UDMA_PRI_SELECT,
UDMA_MODE_PINGPONG,
(void*) (SSI1_BASE + SSI_O_DR), g_ui8SSIRxBufA,
sizeof(g_ui8SSIRxBufA));
}
//
// Check the DMA control table to see if the ping-pong "B" transfer is
// complete. The "B" transfer uses receive buffer "B", and the alternate
// control structure.
//
ui32Mode = uDMAChannelModeGet(UDMA_CHANNEL_SSI0RX | UDMA_ALT_SELECT);
//
// If the alternate control structure indicates stop, that means the "B"
// receive buffer is done. The uDMA controller should still be receiving
// data into the "A" buffer.
//
if (ui32Mode == UDMA_MODE_STOP)
{
//
// Increment a counter to indicate data was received into buffer A. In
// a real application this would be used to signal the main thread that
// data was received so the main thread can process the data.
//
g_ui32RxBufBCount++;
//
// Set up the next transfer for the "B" buffer, using the alternate
// control structure. When the ongoing receive into the "A" buffer is
// done, the uDMA controller will switch back to this one. This
// example re-uses buffer B, but a more sophisticated application could
// use a rotating set of buffers to increase the amount of time that
// the main thread has to process the data in the buffer before it is
// reused.
//
uDMAChannelTransferSet(UDMA_CHANNEL_SSI1RX | UDMA_ALT_SELECT,
UDMA_MODE_PINGPONG,
(void*) (SSI1_BASE + SSI_O_DR), g_ui8SSIRxBufB,
sizeof(g_ui8SSIRxBufB));
}
//
// If the UART1 DMA TX channel is disabled, that means the TX DMA transfer
// is done.
//
if (!uDMAChannelIsEnabled(UDMA_CHANNEL_SSI1RX))
{
//
// Start another DMA transfer to UART1 TX.
//
uDMAChannelTransferSet(UDMA_CHANNEL_SSI0TX | UDMA_PRI_SELECT,
UDMA_MODE_BASIC,
g_ui8TxBuf, (void*) (SSI1_BASE + SSI_O_DR),
sizeof(g_ui8TxBuf));
//
// The uDMA TX channel must be re-enabled.
//
uDMAChannelEnable(UDMA_CHANNEL_SSI0TX);
}
}
//*****************************************************************************
//
// Configure the SSI and its pins. This must be called before UARTprintf().
//
//*****************************************************************************
void ConfigureSSI(void)
{
//
// Run from the PLL at 120 MHz.
// Note: SYSCTL_CFG_VCO_240 is a new setting provided in TivaWare 2.2.x and
// later to better reflect the actual VCO speed due to SYSCTL#22.
//
g_ui32SysClock = SysCtlClockFreqSet((SYSCTL_XTAL_25MHZ |
SYSCTL_OSC_MAIN |
SYSCTL_USE_PLL |
SYSCTL_CFG_VCO_240),
120000000);
//
// The SSI0 and SSI1 peripheral must be enabled for use.
//
SysCtlPeripheralEnable(SYSCTL_PERIPH_SSI0);
SysCtlPeripheralEnable(SYSCTL_PERIPH_SSI1);
//
// For this example SSI0 is used with PortA[7:2]. The SSI1 uses
// PortB, PortD and PortE for the SSICLK, SSIFss and the 4 data pins.
// GPIO ports need to be enabled so those pins can be used.
//
SysCtlPeripheralEnable(SYSCTL_PERIPH_GPIOA);
SysCtlPeripheralEnable(SYSCTL_PERIPH_GPIOB);
SysCtlPeripheralEnable(SYSCTL_PERIPH_GPIOD);
SysCtlPeripheralEnable(SYSCTL_PERIPH_GPIOE);
//
// Configure the pin muxing for SSI0 functions on PA[7:2].
// Configure the pin muxing for SSI1 functions on PB, PD and PE.
//
GPIOPinConfigure(GPIO_PA2_SSI0CLK);
GPIOPinConfigure(GPIO_PA3_SSI0FSS);
GPIOPinConfigure(GPIO_PA4_SSI0XDAT0);
GPIOPinConfigure(GPIO_PA5_SSI0XDAT1);
GPIOPinConfigure(GPIO_PA6_SSI0XDAT2);
GPIOPinConfigure(GPIO_PA7_SSI0XDAT3);
GPIOPinConfigure(GPIO_PB5_SSI1CLK);
GPIOPinConfigure(GPIO_PB4_SSI1FSS);
GPIOPinConfigure(GPIO_PE4_SSI1XDAT0);
GPIOPinConfigure(GPIO_PE5_SSI1XDAT1);
GPIOPinConfigure(GPIO_PD4_SSI1XDAT2);
GPIOPinConfigure(GPIO_PD5_SSI1XDAT3);
//
// 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:
// SSI0
// PA7 - SSI0XDAT3
// PA6 - SSI0XDAT2
// PA5 - SSI0XDAT1
// PA4 - SSI0XDAT0
// PA3 - SSI0Fss
// PA2 - SSI0CLK
// SSI1
// PD5 - SSI1XDAT3
// PD4 - SSI1XDAT2
// PE5 - SSI1XDAT1
// PE4 - SSI1XDAT0
// PB4 - SSI1Fss
// PB5 - SSI1CLK
//
GPIOPinTypeSSI(GPIO_PORTA_BASE, GPIO_PIN_7 | GPIO_PIN_6 | GPIO_PIN_5 |
GPIO_PIN_4 | GPIO_PIN_3 | GPIO_PIN_2);
GPIOPinTypeSSI(GPIO_PORTB_BASE, GPIO_PIN_5 | GPIO_PIN_4);
GPIOPinTypeSSI(GPIO_PORTD_BASE, GPIO_PIN_5 | GPIO_PIN_4);
GPIOPinTypeSSI(GPIO_PORTE_BASE, GPIO_PIN_5 | GPIO_PIN_4);
//
// Configure and enable the SSI0 port for SPI master mode. Use SSI0,
// system clock supply, idle clock level low and active low clock in
// freescale SPI mode, master mode, 2MHz 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 device datasheet for more
// information on the different SPI modes.
//
SSIConfigSetExpClk(SSI0_BASE, g_ui32SysClock, SSI_FRF_MOTO_MODE_0,
SSI_MODE_MASTER,
2000000, 8);
//
// Configure and enable the SSI1 port for SPI slave mode.
//
SSIConfigSetExpClk(SSI1_BASE, g_ui32SysClock, SSI_FRF_MOTO_MODE_0,
SSI_MODE_SLAVE,
2000000, 8);
//
// Enable Quad-SSI mode for both SSI0 and SSI1.
//
SSIAdvModeSet(SSI0_BASE, SSI_ADV_MODE_QUAD_WRITE);
SSIAdvModeSet(SSI1_BASE, SSI_ADV_MODE_QUAD_READ);
//
// Hold the Fss pin low during transfers. The Fss will be controlled
// directly by the SSIAdvDataPutFrameEnd(). If calling
// SSIAdvDataPutFrameEnd to write data to the FIFO, the Fss is de-asserted
// for the corresponding data.
//
SSIAdvFrameHoldEnable(SSI0_BASE);
//
// Enable processor interrupts.
//
IntMasterEnable();
//
// Enable SSI1 interrupt on RX FIFO full.
//
SSIIntEnable(SSI1_BASE, SSI_RXFF);
//
// Enable the SSI1 interrupts on the processor (NVIC).
//
IntEnable(INT_SSI1);
//
// Enable the SSI0 and SSI1 modules.
//
SSIEnable(SSI0_BASE);
SSIEnable(SSI1_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, &pui32DataRx[0]))
{
}
while (SSIDataGetNonBlocking(SSI1_BASE, &pui32DataRx[0]))
{
}
}
//*****************************************************************************
//
// Configure the UART and its pins. This must be called before UARTprintf().
//
//*****************************************************************************
void ConfigureUART(void)
{
//
// Enable the GPIO Peripheral used by the UART.
//
SysCtlPeripheralEnable(SYSCTL_PERIPH_GPIOA);
//
// Enable UART0.
//
SysCtlPeripheralEnable(SYSCTL_PERIPH_UART0);
//
// Configure GPIO Pins for UART mode.
//
GPIOPinConfigure(GPIO_PA0_U0RX);
GPIOPinConfigure(GPIO_PA1_U0TX);
GPIOPinTypeUART(GPIO_PORTA_BASE, GPIO_PIN_0 | GPIO_PIN_1);
//
// Initialize the UART for console I/O.
//
UARTStdioConfig(0, 115200, g_ui32SysClock);
}
//*****************************************************************************
//
// When the received FIFO is half-full, an interrupt will be generated.
//
//*****************************************************************************
void SSI1IntHandler(void)
{
uint32_t ui32Status;
//
// Read the SSI Masked Interrupt Status.
//
ui32Status = SSIIntStatus(SSI1_BASE, true);
//
// Clear the SSI interrupt.
//
SSIIntClear(SSI1_BASE, ui32Status);
//
// Turn off the RX FIFO interrupt.
//
SSIIntDisable(SSI1_BASE, SSI_RXFF);
//
// Toggle flag to indicate that data has been received.
//
g_bReceiveFlag = 1;
}
void InitSSI0Transfer(void)
{
uint_fast16_t ui16Idx;
//
// Fill the TX buffer with a simple data pattern.
//
for (ui16Idx = 0; ui16Idx < UART_TXBUF_SIZE; ui16Idx++)
{
g_ui8TxBuf[ui16Idx] = ui16Idx;
}
SysCtlPeripheralEnable(SYSCTL_PERIPH_UDMA);
SysCtlPeripheralEnable(SYSCTL_PERIPH_SSI0);
SysCtlPeripheralEnable(SYSCTL_PERIPH_SSI1);
// SSIDisable(SSI0_BASE);
SSIConfigSetExpClk(SSI0_BASE, g_ui32SysClock, SSI_FRF_MOTO_MODE_0,
SSI_MODE_MASTER,2000000, 8);
SSIConfigSetExpClk(SSI1_BASE, g_ui32SysClock, SSI_FRF_MOTO_MODE_0,
SSI_MODE_MASTER,2000000, 8);
SSIEnable(SSI0_BASE);
SSIDMAEnable(SSI0_BASE,SSI_DMA_TX);
SSIDMAEnable(SSI1_BASE, SSI_DMA_RX);
ROM_uDMAChannelAssign(UDMA_CH11_SSI0TX);
ROM_uDMAChannelAssign(UDMA_CH24_SSI1RX);
//
// Put the attributes in a known state for the uDMA UART1RX channel. These
// should already be disabled by default.
//
ROM_uDMAChannelAttributeDisable(UDMA_CHANNEL_SSI1RX,
UDMA_ATTR_ALTSELECT | UDMA_ATTR_USEBURST |
UDMA_ATTR_HIGH_PRIORITY |
UDMA_ATTR_REQMASK);
ROM_uDMAChannelAttributeDisable(UDMA_CHANNEL_SSI0TX,
UDMA_ATTR_ALTSELECT | UDMA_ATTR_USEBURST |
UDMA_ATTR_HIGH_PRIORITY |
UDMA_ATTR_REQMASK);
// HWREG(SSI0_BASE + SSI_O_CR1) |= SSI_CR1_LBM;//Loopback mode to/from the QSSI*
ROM_uDMAChannelControlSet(UDMA_CHANNEL_SSI0TX | UDMA_PRI_SELECT,
UDMA_SIZE_8 | UDMA_SRC_INC_NONE | UDMA_DST_INC_8 |
UDMA_ARB_4);
ROM_uDMAChannelControlSet(UDMA_CHANNEL_SSI1RX | UDMA_ALT_SELECT,
UDMA_SIZE_8 | UDMA_SRC_INC_NONE | UDMA_DST_INC_8 |
UDMA_ARB_4);
ROM_uDMAChannelTransferSet(UDMA_CHANNEL_SSI1RX | UDMA_PRI_SELECT,
UDMA_MODE_PINGPONG,
(void*) (SSI0_BASE + SSI_O_DR), g_ui8SSIRxBufA,
sizeof(g_ui8SSIRxBufA));
ROM_uDMAChannelTransferSet(UDMA_CHANNEL_SSI1RX | UDMA_ALT_SELECT,
UDMA_MODE_PINGPONG,
(void*) (SSI0_BASE + SSI_O_DR), g_ui8SSIRxBufB,
sizeof(g_ui8SSIRxBufB));
// uDMAChannelAttributeEnable(UDMA_CHANNEL_SSI1RX, UDMA_ATTR_USEBURST);
ROM_uDMAChannelEnable(UDMA_CHANNEL_SSI1RX);
ROM_uDMAChannelEnable(UDMA_CHANNEL_SSI0TX);
//
// Enable the SSI DMA TX/RX interrupts.
//
ROM_SSIIntEnable(SSI0_BASE, SSI_DMA_TX);
ROM_SSIIntEnable(SSI0_BASE, SSI_DMA_RX);
ROM_IntEnable(INT_SSI0);
ROM_IntEnable(INT_SSI1);
}
//*****************************************************************************
//
// Configure SSI0 in Quad-SSI master Freescale (SPI) mode and SSI1 in Quad-SSI
// slave mode. The SSI0 will send out 4 bytes of data in advanced Quad mode
// and the SSI1 slave will receive the 4 bytes of data also in Quad mode. The
// slave will generate interrupt upon receiving the 4 bytes of data.
//
//*****************************************************************************
int main(void)
{
uint32_t ui32Index;
g_ui32SysClock = SysCtlClockFreqSet((SYSCTL_XTAL_25MHZ |
SYSCTL_OSC_MAIN |
SYSCTL_USE_PLL |
SYSCTL_CFG_VCO_480), 120000000);
ConfigureUART();
ConfigureSSI();
uDMAEnable();
SysCtlDelay(g_ui32SysClock / 20 / 3);
uDMAControlBaseSet(pui8ControlTable);
InitSSI0Transfer();
pui32DataTx[0]='Q';
pui32DataTx[1]='S';
pui32DataTx[2]='S';
pui32DataTx[3]='I';
TransmitDataSSI0(pui32DataTx, NUM_SSI_DATA);
ReceiveDataSSI1(pui32DataRx, NUM_SSI_DATA);
while (1)
{
}
return 0;
}
void TransmitDataSSI0(uint32_t *data, uint32_t numBytes)
{
uint32_t ui32Index;
SSIDMAEnable(SSI0_BASE,SSI_DMA_TX);
for (ui32Index = 0; ui32Index < NUM_SSI_DATA; ui32Index++)
{
//
// Dummy write to start slave which is required for Quad-SSI
// mode operation.
//
MAP_SSIDataPut(SSI1_BASE, 0);
//
// Check if the last data byte is queued up to be sent.
//
if (ui32Index == (NUM_SSI_DATA - 1))
{
//
// Calling SSIAdvDataPutFrameEnd on the last data will put out the
// data and de-assert the the Fss pin.
//
MAP_SSIAdvDataPutFrameEnd(SSI0_BASE, pui32DataTx[ui32Index]);
}
else
{
//
// 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.
//
MAP_SSIDataPut(SSI0_BASE, pui32DataTx[ui32Index]);
}
}
}
void ReceiveDataSSI1(uint32_t *data, uint32_t numBytes)
{
uint32_t ui32Index;
SSIDMAEnable(SSI1_BASE,SSI_DMA_RX);
for (ui32Index = 0; ui32Index < 4; ui32Index++)
{
// while (!(MAP_SSIBusy(SSI1_BASE)))
// {
// }; // Wait until SSI1 is not busy
//
// Receive the data using the "blocking" Get function. This function
// will wait until there is data in the receive FIFO before returning.
//
SSIDataGetNonBlocking(SSI1_BASE, &pui32DataRx[ui32Index]);
//
// Since we are using 8-bit data, mask off the MSB.
//
pui32DataRx[ui32Index] &= 0x00FF;
UARTprintf("'%c' ", data[ui32Index]);
}
g_bReceiveFlag = 0; // Clear the receive flag after receiving all data
}