This thread has been locked.

If you have a related question, please click the "Ask a related question" button in the top right corner. The newly created question will be automatically linked to this question.

Basic SPI (SSI0) Data Transfer Through uDMA Issues



Hello TI community. I'm developing on the Tiva C for my senior design project and am currently having some issues transmitting multiple bytes of data over SPI through the DMA controller. 

My end goal is to send 3 bytes of data to an external DAC that is controlled by 24 bit messages. I've red over the various tutorials and examples, but have had no luck viewing the SPI transmit data on a logic analyzer when the dma request is asserted. 

Below is my code I am using for testing features (sorry for the mess, still early on in the development cycle), any help would be much appreciated!!!

//*****************************************************************************
//
// Testing the peripherals and stuff.
//
//*****************************************************************************

// c includes
#include <stdint.h>
#include <stdbool.h>
// part include
#include "inc/tm4c123gh6pm.h"
// hardware includes
#include "inc/hw_memmap.h"
#include "inc/hw_ssi.h"
#include "inc/hw_types.h"
// driver library includes
#include "driverlib/gpio.h"
#include "driverlib/interrupt.h"
#include "driverlib/pin_map.h"
#include "driverlib/ssi.h"
#include "driverlib/sysctl.h"
#include "driverlib/timer.h"
#include "driverlib/udma.h"
// custom includes
#include "dac.h"
#include "dsp.h"

#pragma DATA_ALIGN(pui8ControlTable, 1024)
uint8_t pui8ControlTable[1024];


//*****************************************************************************
//
// Timer0 Interrupt
//
//*****************************************************************************

// TODO: CHANGE SETUP SUCH THAT DMA TRANSFERS ARE UTILIZED

uint8_t pui16SSITransmitBuffer[DAC_BYTE_SIZE] = {0xFF, 0x00, 0xFF};
uint8_t pui16SSIRecieveBuffer[DAC_BYTE_SIZE] = {0x00, 0x00, 0x00};
void Timer0IntHandler(void)
{
	// clear the interrupt
	TimerIntClear(TIMER0_BASE, TIMER_TIMA_TIMEOUT);

	/*
	if (ui16Count++ >= 20)
	{
		ui16Out = ui16Out == 0x7FFF ? 0x7000 : 0x7FFF;
		ui16Count = 0;
	}
	// send sample out
	SSIDataPutNonBlocking(SSI0_BASE, ui16Out);

	if (GPIOPinRead(GPIO_PORTF_BASE, GPIO_PIN_2))
	{
		GPIOPinWrite(GPIO_PORTF_BASE, GPIO_PIN_2, 0);
	}
	else
	{
		GPIOPinWrite(GPIO_PORTF_BASE, GPIO_PIN_2, 4);
	}
	*/

	uDMAChannelRequest(UDMA_CHANNEL_SSI0TX);

	//GPIOPinWrite(GPIO_PORTF_BASE, GPIO_PIN_3, 0);
}


//*****************************************************************************
//
// Blink the on-board LED, interrupt style.
//
//*****************************************************************************
int
main(void)
{
	uint32_t ui32Period;

	// configure operating frequency
	SysCtlClockSet(SYSCTL_SYSDIV_1|SYSCTL_USE_PLL|SYSCTL_XTAL_16MHZ|SYSCTL_OSC_MAIN);

	// enable needed peripherals
	SysCtlPeripheralEnable(SYSCTL_PERIPH_GPIOF);
	// configure general purpose input and output
	GPIOPinTypeGPIOOutput(GPIO_PORTF_BASE, GPIO_PIN_2 | GPIO_PIN_3);


	// configure ssi module
	SysCtlPeripheralEnable(SYSCTL_PERIPH_SSI0);
	SysCtlPeripheralEnable(SYSCTL_PERIPH_GPIOA);
	GPIOPinConfigure(GPIO_PA2_SSI0CLK);
	GPIOPinConfigure(GPIO_PA3_SSI0FSS);
	GPIOPinConfigure(GPIO_PA5_SSI0TX);
	GPIOPinTypeSSI(GPIO_PORTA_BASE, GPIO_PIN_5 | GPIO_PIN_4 | GPIO_PIN_3 |
				   GPIO_PIN_2);
	SSIConfigSetExpClk(SSI0_BASE, SysCtlClockGet(), SSI_FRF_MOTO_MODE_0,
					   SSI_MODE_MASTER, 5000000, 16);
	SSIDMAEnable(SSI0_BASE, SSI_DMA_TX);
	SSIEnable(SSI0_BASE);

	//  configure udma
	uDMAEnable();
	SysCtlPeripheralEnable(SYSCTL_PERIPH_UDMA);
	uDMAControlBaseSet(pui8ControlTable);
	uDMAChannelSelectDefault(UDMA_DEF_SSI0TX_SEC_SSI1TX | UDMA_DEF_SSI0RX_SEC_SSI1RX);
	uDMAChannelControlSet(UDMA_CHANNEL_SSI0TX | UDMA_PRI_SELECT,
            			  UDMA_SIZE_8 | UDMA_SRC_INC_8 | UDMA_DST_INC_NONE | UDMA_ARB_4);
	uDMAChannelTransferSet(UDMA_CHANNEL_SSI0TX | UDMA_PRI_SELECT,
						   UDMA_MODE_AUTO,
						   pui16SSITransmitBuffer,
						   (void*) (SSI0_BASE + SSI_O_DR),
						   sizeof(pui16SSITransmitBuffer));
	uDMAChannelAttributeDisable(UDMA_CHANNEL_SSI0TX, UDMA_ATTR_ALTSELECT |UDMA_ATTR_HIGH_PRIORITY| UDMA_ATTR_REQMASK );
	uDMAChannelAttributeEnable(UDMA_CHANNEL_SSI0TX, UDMA_ATTR_USEBURST);
	uDMAChannelEnable(UDMA_CHANNEL_SSI0TX);


	// configure timer module
	SysCtlPeripheralEnable(SYSCTL_PERIPH_TIMER0);
	TimerConfigure(TIMER0_BASE, TIMER_CFG_PERIODIC);
	ui32Period = SysCtlClockGet() / 44100;
	TimerLoadSet(TIMER0_BASE, TIMER_A, ui32Period-1);
	IntEnable(INT_TIMER0A);
	TimerIntEnable(TIMER0_BASE, TIMER_TIMA_TIMEOUT);
	IntMasterEnable();

	// start the timer module
	TimerEnable(TIMER0_BASE, TIMER_A);

	//GPIOPinWrite(GPIO_PORTF_BASE, GPIO_PIN_3, 8);

	while(1)
	{
		// raise your dongers
	}

}

P.S. Custom header files have little to nothing in them at all except for a few numeric defines, should be easy to spot and ignore.

  • Hello Michael,

    The UDMA is configured for AUTO mode. This mode is only for SW request and not for HW request, which in this case is by SSI0.

    Also you need to configure UDMA first and then configure SSI.

    Lastly, the uDMATransferRequest is not needed if the mode is other than AUTO,

    Regards

    Amit