Hi TI community,
I'm beginner with the interest in transfer array of 1024 bits of data continuously from tm4c129EXL board to 1.3" OLED display using DMA BASIC mode. Before that i tried below code.
Which transfer data from buffer g_ui8TxBuf to the (void *)(SSI1_BASE) using UDMA_CHANNEL_SSI1TX channel. The data is not transferred.
- Do i need to trigger using uDMAChannelRequest(UDMA_TRANSFER_CHANNEL); to transfer or uDMAChannelEnable(UDMA_TRANSFER_CHANNEL); is enough
- i'm not sure that to receive data at destination i used SSIDataGetNonBlocking is this proper way to receive data from SSI1 base.
Please find the code below :
#include <stdint.h>
#include <stdbool.h>
#include <stdio.h>
#include <string.h>
#include "inc/hw_memmap.h"
#include "driverlib/sysctl.h"
#include "driverlib/udma.h"
#include "driverlib/pin_map.h"
#include "driverlib/gpio.h"
#include "driverlib/ssi.h"
#define CLK_FREQ 80000000
#define CLK_RATE 1000000
#define DATA_WIDTH 8
#define SSI_RXBUF_SIZE 256
#define UDMA_TRANSFER_CHANNEL UDMA_CHANNEL_SSI1TX
#define SSIDATA_FRAME_SIZE UDMA_SIZE_8
#define TIMES_DMA_TRANSFER UDMA_ARB_8
#define UDMA_TRANSFER_MODE UDMA_MODE_BASIC
#define SSI_TXBUF_SIZE 256
unsigned char g_ui8TxBuf[SSI_TXBUF_SIZE];
unsigned char pui8ControlTable[1024];
static unsigned char u32Rxdata[SSI_TXBUF_SIZE];
void init_uDMA();
void config_DMA_transfer();
void spi1_init()
{
unsigned int ui32SysClock;
ui32SysClock = SysCtlClockFreqSet((SYSCTL_XTAL_25MHZ |SYSCTL_OSC_MAIN |SYSCTL_USE_OSC), CLK_FREQ);
SysCtlPeripheralEnable(SYSCTL_PERIPH_SSI1);
SysCtlPeripheralEnable(SYSCTL_PERIPH_GPIOB);
SysCtlPeripheralEnable(SYSCTL_PERIPH_GPIOE);
SysCtlPeripheralEnable(SYSCTL_PERIPH_GPIOP);
GPIOPinTypeGPIOOutput(GPIO_PORTP_BASE, GPIO_PIN_0);
GPIOPinTypeGPIOOutput(GPIO_PORTP_BASE, GPIO_PIN_1);
GPIOPinConfigure(GPIO_PB4_SSI1FSS);
GPIOPinConfigure(GPIO_PB5_SSI1CLK);
GPIOPinConfigure(GPIO_PE4_SSI1XDAT0);
GPIOPinTypeSSI(GPIO_PORTB_BASE, GPIO_PIN_5 | GPIO_PIN_4);
GPIOPinTypeSSI(GPIO_PORTE_BASE, GPIO_PIN_4);
SSIConfigSetExpClk(SSI1_BASE, ui32SysClock, SSI_FRF_MOTO_MODE_0, SSI_MODE_MASTER, CLK_RATE, DATA_WIDTH);
SSIEnable(SSI1_BASE);
printf("SPI Iniitiated sh1106 driver\n");
}
int main()
{
spi1_init();
//initialize uDMA module with transfer size of 16 bits
init_uDMA();
config_DMA_transfer();
uint_fast32_t i;
for(i = 0; i < SSI_TXBUF_SIZE; i++)
{
// Wait for data to be available in the receive buffer
while(SSIDataGetNonBlocking(SSI1_BASE, &u32Rxdata[i])) {}
}
//print on console
for(i = 0; i< SSI_TXBUF_SIZE; i++)
{
printf("u32Rxdata[%d] = %d\n", i, u32Rxdata[i]);
}
uDMADisable();
}
//*****************************************************************************
// initiate uDMA module and configure SSI for uDMA transfer
//*****************************************************************************
void init_uDMA()
{
printf("uDMA module initiating\n");
//called once to configure or initiate uDMA
//
// Enable the UDMA peripheral
//
printf("---- Enabling UDMA Peripheral----\n");
SysCtlPeripheralEnable(SYSCTL_PERIPH_UDMA);
//
// Wait for the UDMA module to be ready.
//
printf("---- Waiting for UDMA Peripheral to ready----\n");
while(!SysCtlPeripheralReady(SYSCTL_PERIPH_UDMA))
{
}
uDMAControlBaseSet(&pui8ControlTable[0]);
printf("uDMA channel control base set done\n");
//
// Put the attributes in a known state for the uDMA SSI1TX channel. These
// should already be disabled by default.
//
uDMAChannelAttributeDisable(UDMA_TRANSFER_CHANNEL,UDMA_ATTR_ALTSELECT |
UDMA_ATTR_HIGH_PRIORITY | UDMA_ATTR_REQMASK);
//
// Set the USEBURST attribute for the uDMA SSI TX channel. This will
// force the controller to always use a burst when transferring data from
// the TX buffer to the UART. This is somewhat more efficient bus usage
// than the default which allows single or burst transfers.
//
uDMAChannelAttributeEnable(UDMA_TRANSFER_CHANNEL, UDMA_ATTR_USEBURST);
printf("uDMA channel attributes set done\n");
uDMAChannelControlSet(UDMA_TRANSFER_CHANNEL | UDMA_PRI_SELECT,
SSIDATA_FRAME_SIZE | UDMA_SRC_INC_8 |
UDMA_DST_INC_NONE | TIMES_DMA_TRANSFER);
printf("uDMA channel control set is done\n");
//enabling the uDMA module
uDMAEnable();
//
// Enable the uDMA interface for TX channel.
//
//
SSIDMAEnable(SSI1_BASE, SSI_DMA_TX); // transfer the control to uDMA controller
}
void config_DMA_transfer()
{
printf("SSI1 Transfering\n");
static uint_fast16_t ui16Idx;
//
// Fill the TX buffer with a simple data 0 to 255.
//
for(ui16Idx = 0; ui16Idx < SSI_TXBUF_SIZE; ui16Idx++)
{
g_ui8TxBuf[ui16Idx] = ui16Idx;
printf("g_ui8TxBuf %d\n", g_ui8TxBuf[ui16Idx]);
}
printf("DMA Transfer enabled\n");
//
// Set up the transfer parameters for the uDMA SSI TX channel. This will
// configure the transfer source and destination and the transfer size.
// Basic mode is used because the peripheral is making the uDMA transfer
// request. The source is the TX buffer and the destination is the SSI
// data register.
//
// Not transfering data from tx to SSI Base
uDMAChannelTransferSet(UDMA_TRANSFER_CHANNEL | UDMA_PRI_SELECT,
UDMA_TRANSFER_MODE, g_ui8TxBuf,
(void *)(SSI1_BASE),
sizeof(g_ui8TxBuf));
uDMAChannelEnable(UDMA_TRANSFER_CHANNEL);
printf("uDMA transfer channel enabled\n");
printf("--- Waiting to complete data transfer ---\n");
//wait for DMA transfer to complete
while(uDMAChannelIsEnabled(UDMA_TRANSFER_CHANNEL)) {}
printf("\n--- Transfer completed ---\n");
}
Thank you in Advance