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 }