Other Parts Discussed in Thread: TM4C1294NCPDT, TM4C1290NCPDT
Hi,
My application needed SPI Slave lagacy mode with interrupt based Rx and DMA based Tx.I used demo code UART DMA and modified as per my application needs and checked it on TI launch pad.When a Master(TM4C1294NCPDT lauch pad 1) sends a data to slave(TM4C1294NCPDT lauch pad 2) then the interrupt is getting triggered and able to receive the data from Master.But It is not able to sent(Transmit) data using DMA.It is always going to uDMAErrorHandler(ie there is a bus error)
Summary:
Interrupt based Receive is working but DMA based Transmit is not working
Master is sending a data in every 1sec
Any help here would be greatly appreciated.
Please find the code below
uint32_t g_ui32DataRxSSI0[];
uint32_t g_ui32IndexSSI0;
uint32_t g_ui32SPI0intflag;
static uint32_t g_ui32uDMAErrCount = 0;
uint8_t g_ui8TxBuf[]={'S','L','A','V','E',' ','O','N',' ','S','S','I','O'};
#ifdef DEBUG
void
__error__(char *pcFilename, uint32_t ui32Line)
{
}
#endif
//*****************************************************************************
//
// 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
//-------------------------------------------------------------------------------------------------------------------
void InitSPI0(void)
{
// The SSI0 peripheral must be enabled for use.
MAP_SysCtlPeripheralEnable(SYSCTL_PERIPH_SSI0);
MAP_SysCtlPeripheralEnable(SYSCTL_PERIPH_GPIOA);
// Configure the pin muxing for SSI0 functions on port A2, A3, A4, and A5.
MAP_GPIOPinConfigure(GPIO_PA2_SSI0CLK);
MAP_GPIOPinConfigure(GPIO_PA3_SSI0FSS);
MAP_GPIOPinConfigure(GPIO_PA4_SSI0XDAT0);
MAP_GPIOPinConfigure(GPIO_PA5_SSI0XDAT1);
//
// Configure the GPIO settings for the SSI pins. This function also gives
// control of these pins to the SSI hardware.
// The pins are assigned as follows:
// PA5 - SSI0Tx
// PA4 - SSI0Rx
// PA3 - SSI0Fss
// PA2 - SSI0CLK
MAP_GPIOPinTypeSSI(GPIO_PORTA_BASE, GPIO_PIN_5 | GPIO_PIN_4 | GPIO_PIN_3 | GPIO_PIN_2);
// Configure and enable the SSI port for SPI slave mode. Use SSI0,
// system clock supply, idle clock level low and active low clock in
// freescale SPI mode, slave mode, MHz SSI frequency, and 16-bit data.
MAP_SSIConfigSetExpClk(SSI0_BASE, DEF_SYSCLK, SSI_FRF_MOTO_MODE_1,SSI_MODE_SLAVE, DEF_SPI_RATE,DEF_BYTE);
MAP_SSIEnable(SSI0_BASE);
}
//-------------------------------------------------------------------------------------------------------------------
void InitSSI0DMATransfer(void)
{
ROM_SSIDMAEnable(SSI0_BASE,SSI_DMA_TX);
ROM_uDMAChannelAttributeEnable(UDMA_CHANNEL_SSI0TX, UDMA_ATTR_USEBURST);
ROM_uDMAChannelControlSet(UDMA_CHANNEL_SSI0TX | UDMA_PRI_SELECT,
UDMA_SIZE_8 | UDMA_SRC_INC_8 |
UDMA_DST_INC_NONE |
UDMA_ARB_4);
ROM_uDMAChannelTransferSet(UDMA_CHANNEL_SSI0TX | UDMA_PRI_SELECT,
UDMA_MODE_BASIC, g_ui8TxBuf,
HWREG(SSI0_BASE + SSI_O_DR),
13);//size of g_ui8TxBuf[]=13
// SSIIntEnable(SSI0_BASE,SSI_RXFF);//Interrupt enable for Rx
SSIIntEnable(SSI0_BASE,SSI_RXFF|SSI_DMATX);//Interrupt enable for Rx and DMA based Tx
IntEnable(INT_SSI0);
// ROM_uDMAChannelEnable(UDMA_CHANNEL_SSI0TX);
SSIDMAEnable(SSI0_BASE,SSI_DMA_TX);
}
//-------------------------------------------------------------------------------------------------------------------
void InitConsole(void)
{
MAP_SysCtlPeripheralEnable(SYSCTL_PERIPH_GPIOA);
MAP_GPIOPinConfigure(GPIO_PA0_U0RX);
MAP_GPIOPinConfigure(GPIO_PA1_U0TX);
MAP_SysCtlPeripheralEnable(SYSCTL_PERIPH_UART0);
MAP_UARTClockSourceSet(UART0_BASE, UART_CLOCK_PIOSC);
MAP_GPIOPinTypeUART(GPIO_PORTA_BASE, GPIO_PIN_0 | GPIO_PIN_1);
UARTStdioConfig(0, 115200, 16000000);
}
//-------------------------------------------------------------------------------------------------------------------
void uDMAErrorHandler(void)
{
uint32_t ui32Status;
//
// Check for uDMA error bit
//
ui32Status = ROM_uDMAErrorStatusGet();
//
// If there is a uDMA error, then clear the error and increment
// the error counter.
//
if(ui32Status)
{
ROM_uDMAErrorStatusClear();
g_ui32uDMAErrCount++;
}
}
//-------------------------------------------------------------------------------------------------------------------
void SSI0IntHandler(void)
{
uint32_t ui32tempIndex=0,ui32tempIndex2=0;
//SSI0_BASE=0x4000.8000,SSI_O_SR(offset)=0x00C,SSI_SR_RNE=4
g_ui32SPI0intflag=1;//semaphore
while((HWREG(SSI0_BASE + SSI_O_SR) & SSI_SR_RNE)==4)
{
SSIDataGetNonBlocking(SSI0_BASE, &g_ui32DataRxSSI0[ui32tempIndex++]);
}
g_ui32IndexSSI0=ui32tempIndex;
//DMA interrupt handler
//--------------------------------------------------------------------------------------
if(!ROM_uDMAChannelIsEnabled(UDMA_CHANNEL_SSI0TX))
{
//
// Start another DMA transfer to SSI0 TX.
//
ROM_uDMAChannelTransferSet(UDMA_CHANNEL_SSI0TX | UDMA_PRI_SELECT,
UDMA_MODE_BASIC, g_ui8TxBuf,
HWREG(SSI0_BASE + SSI_O_DR),
13);
ROM_uDMAChannelEnable(UDMA_CHANNEL_SSI0TX);
}
//------------------------------------------------------------------------------------------
}
//-------------------------------------------------------------------------------------------------------------------
int main(void) {
uint32_t ui32status,ui32count,ui32count1,ui32tempIndex1,ui32tempIndex2;
const uint32_t ui32SysClock = MAP_SysCtlClockFreqSet((SYSCTL_XTAL_25MHZ |SYSCTL_OSC_MAIN | SYSCTL_USE_PLL |SYSCTL_CFG_VCO_480), 120000000);//for TM4C129
InitSPI0();
IntMasterEnable();//put it in some other function in systemInit.c file
// DMA configuration
// Enable the uDMA controller at the system level.
MAP_SysCtlPeripheralEnable(SYSCTL_PERIPH_UDMA);
// Enable the uDMA controller.
MAP_uDMAEnable();
// Enable the uDMA controller error interrupt. This interrupt will occur if there is a bus error during a transfer.
MAP_IntEnable(INT_UDMAERR);
//
// Point at the control table to use for channel control structures.
//
MAP_uDMAControlBaseSet(pui8ControlTable);
InitConsole();
InitSSI0DMATransfer();
while(1)
{
if(g_ui32SPI0intflag)
{
g_ui32SPI0intflag=0;
UARTprintf("\n Received on SSI0:\n ");
for(ui32tempIndex2=0;ui32tempIndex2<g_ui32IndexSSI0;ui32tempIndex2++)
{
UARTprintf("'%c' ", g_ui32DataRxSSI0[ui32tempIndex2]);
}
}
else{;}
}
return 0;
}