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.

Tiva C uDMA and ADC

I am currently working on uDMA with ADC sampling. The following code is an attempt at adapting and simplifying an example I have followed for use on the Tiva C TM1294XL. 
The goal is to simply retrieve the ADC samples so I can collect a few before sending them through Ethernet. This example is to be attached to a larger project where I've already created an Ethernet module. I am using uDMA so I can achieve 1M samples per second.
I would like the ADC input to be on GPIO PE0 and the output to be either a printout or an obvious buffer containing these samples.
The current state of this program is that it gets to the for(;;) loop once, then crashes (entering loader_exit() ). My prediction is that I have not set the uDMA up correctly. Any assistance or useful advice to what might be missing or incorrect would be highly appreciated. 

#include <stdbool.h> #include <stdint.h> #include <string.h> #include <stdio.h> #include "inc/hw_ints.h" #include "inc/hw_memmap.h" #include "inc/hw_adc.h" #include "inc/hw_types.h" #include "inc/hw_udma.h" #include "inc/hw_emac.h" #include "utils/uartstdio.h" #include "utils/ustdlib.h" #include <xdc/runtime/System.h> #include "driverlib/debug.h" #include "driverlib/gpio.h" #include "driverlib/interrupt.h" #include "driverlib/pin_map.h" #include "driverlib/rom.h" #include "driverlib/sysctl.h" #include "driverlib/uart.h" #include "driverlib/adc.h" #include "driverlib/udma.h" #include "driverlib/emac.h" //***************************************************************************** // // The error routine that is called if the driver library encounters an error. // //***************************************************************************** #ifdef DEBUG void __error__(char *pcFilename, uint32_t ui32Line) { } #endif #define TXDESC_SIZE (4) #define EMAC_BUF_SIZE (1536) typedef uint16_t adc_sample_t; #define ADC_SAMPLE_BUF_SIZE (1024/sizeof(adc_sample_t)) uint8_t emacBufTx[EMAC_BUF_SIZE * TXDESC_SIZE] __attribute__(( aligned(4) )); // <-- Stores ADC samples here uint32_t tx_adc_index = 0; // feed buffer pointers to the ADC uDMA descriptors in order // // the ADC data is transferred by DMA directly into the EMAC buffers // when the ADC interrupt fires, it calls tx_EMAC() to have the EMAC immediately send the data out // // get_ADC_buf() uses tx_adc_index which stores the position of the ADC uDMA descriptor uint8_t * get_ADC_buf() { uint32_t i = tx_adc_index; tx_adc_index = (i + 1) & (TXDESC_SIZE - 1); return &emacBufTx[i * EMAC_BUF_SIZE]; } // feed ethernet frames to the EMAC // // tx_EMAC() uses txdesc_index which stores the position of the EMAC DMA descriptor void tx_EMAC() { /* Will expand this to send values through ethernet in packets, right now I just want to values are arriving */ /* Try to print out ADC values */ System_printf("ADC value: %d/n", emacBufTx[tx_adc_index * EMAC_BUF_SIZE]); System_flush(); } uint32_t adc_complete_count = 0; // uDMA descriptors used by the hardware are stored in this table // uDMAChannel* functions write to this table uint32_t udmaCtrlTable[1024/sizeof(uint32_t)] __attribute__(( aligned(1024) )); void uDMAErrorHandler() { System_printf("uDMAErrorHandler\n"); System_flush(); } void ADCprocess(uint32_t ch) { if ((((tDMAControlTable *) udmaCtrlTable)[ch].ui32Control & UDMA_CHCTL_XFERMODE_M) != UDMA_MODE_STOP) return; // store the next buffer in the uDMA transfer descriptor // the ADC is read directly into the correct emacBufTx to be transmitted uDMAChannelTransferSet(ch, UDMA_MODE_PINGPONG, (void *)(ADC0_BASE + ADC_O_SSFIFO0), get_ADC_buf(), ADC_SAMPLE_BUF_SIZE); adc_complete_count++; tx_EMAC(); } void ADCseq0Handler() { // this interrupt handler is optimized to use as few CPU cycles as possible // it must handle ADC_SAMPLE_BUF_SIZE samples in 1/125000 seconds // // optimizations include: // 1. choosing ADC_SAMPLE_BUF_SIZE to minimize overhead // 2. replacing calls to * functions with raw memory accesses (less portable) *(uint32_t *) (ADC0_BASE + ADC_O_ISC) = ADC_INT_DMA_SS0; // optimized form of ADCIntClearEx(ADC0_BASE, ADC_INT_DMA_SS0); ADCprocess(UDMA_CHANNEL_ADC0 | UDMA_PRI_SELECT); // <-- Use primary control structure, why both? ADCprocess(UDMA_CHANNEL_ADC0 | UDMA_ALT_SELECT); // <-- Use alternate control structure } /* * @brief Initialise uDMA for ADC * @params sysclock : System Clcok * @retval None */ void main() { #define ADC_TARGET (8*1000*1000) // 120 MHz/7 = about 17 MHz = 1.07143 MSps // Set System clock to 120MHz ui32SysClkFreq = SysCtlClockFreqSet((SYSCTL_XTAL_25MHZ | SYSCTL_OSC_MAIN | SYSCTL_USE_PLL | SYSCTL_CFG_VCO_480), 120000000); /* Added from original main */ SysCtlPeripheralEnable(SYSCTL_PERIPH_ADC0); SysCtlPeripheralEnable(SYSCTL_PERIPH_UDMA); SysCtlPeripheralEnable(SYSCTL_PERIPH_GPIOE); // Enable GPIO Port E GPIOPinTypeADC(GPIO_PORTE_BASE, GPIO_PIN_0 ); // Set Pin type to Analog IN SysCtlDelay(1); IntMasterEnable(); /* Added from adc_init() */ uint32_t div; if (sysclock < 2*ADC_TARGET) { div = ADC_CLOCK_SRC_PLL; } else { div = ADC_CLOCK_SRC_PLL | (((sysclock + ADC_TARGET - 1) / ADC_TARGET - 1) << 4); } #undef ADC_TARGET *(uint32_t *) (ADC0_BASE + ADC_O_CC) = div; ADCSequenceConfigure(ADC0_BASE, 0 /*SS0*/, ADC_TRIGGER_PROCESSOR, 3 /*priority*/); // SS0-SS3 priorities must always be different ADCSequenceConfigure(ADC0_BASE, 3 /*SS3*/, ADC_TRIGGER_PROCESSOR, 0 /*priority*/); // so change SS3 to prio0 when SS0 gets set to prio3 ADCSequenceStepConfigure(ADC0_BASE, 0 /*SS0*/, 0, ADC_CTL_TS); // ADC_CTL_TS = read temp sensor ADCSequenceStepConfigure(ADC0_BASE, 0 /*SS0*/, 1, ADC_CTL_TS); ADCSequenceStepConfigure(ADC0_BASE, 0 /*SS0*/, 2, ADC_CTL_TS); ADCSequenceStepConfigure(ADC0_BASE, 0 /*SS0*/, 3, ADC_CTL_TS); ADCSequenceStepConfigure(ADC0_BASE, 0 /*SS0*/, 4, ADC_CTL_TS); ADCSequenceStepConfigure(ADC0_BASE, 0 /*SS0*/, 5, ADC_CTL_TS); ADCSequenceStepConfigure(ADC0_BASE, 0 /*SS0*/, 6, ADC_CTL_TS); ADCSequenceStepConfigure(ADC0_BASE, 0 /*SS0*/, 7, ADC_CTL_TS | ADC_CTL_END | ADC_CTL_IE); // ADC_CTL_IE fires every 8 samples ADCSequenceEnable(ADC0_BASE, 0); uDMAEnable(); uDMAControlBaseSet(udmaCtrlTable); ADCSequenceDMAEnable(ADC0_BASE, 0); // disable some bits uDMAChannelAttributeDisable(UDMA_CHANNEL_ADC0, UDMA_ATTR_ALTSELECT /*start with ping-pong PRI side*/ | UDMA_ATTR_HIGH_PRIORITY /*low priority*/ | UDMA_ATTR_REQMASK /*unmask*/); // enable some bits uDMAChannelAttributeEnable(UDMA_CHANNEL_ADC0, UDMA_ATTR_USEBURST /*only allow burst transfers*/); // set dma params on PRI_ and ALT_SELECT uDMAChannelControlSet(UDMA_CHANNEL_ADC0 | UDMA_PRI_SELECT, UDMA_SIZE_16 | UDMA_SRC_INC_NONE | UDMA_DST_INC_16 | UDMA_ARB_128); uDMAChannelControlSet(UDMA_CHANNEL_ADC0 | UDMA_ALT_SELECT, UDMA_SIZE_16 | UDMA_SRC_INC_NONE | UDMA_DST_INC_16 | UDMA_ARB_128); uDMAChannelTransferSet(UDMA_CHANNEL_ADC0 | UDMA_PRI_SELECT, UDMA_MODE_PINGPONG, (void *)(ADC0_BASE + ADC_O_SSFIFO0), get_ADC_buf(), ADC_SAMPLE_BUF_SIZE); uDMAChannelTransferSet(UDMA_CHANNEL_ADC0 | UDMA_ALT_SELECT, UDMA_MODE_PINGPONG, (void *)(ADC0_BASE + ADC_O_SSFIFO0), get_ADC_buf(), ADC_SAMPLE_BUF_SIZE); IntEnable(INT_ADC0SS0); ADCIntEnableEx(ADC0_BASE, ADC_INT_DMA_SS0); uDMAChannelEnable(UDMA_CHANNEL_ADC0); /* Added from original main */ ADCSequenceConfigure(ADC0_BASE, 0 /*SS0*/, ADC_TRIGGER_ALWAYS, 3 /*priority*/); // <-- Assume Link Up uint32_t count = 0; for (;;) { count++; /* Loops here every cycle that the link is up */ if (count < 0x7fff) continue; // Check if count is up to 32767 = 15bits all 1s count = 0; adc_complete_count = 0; } }

  • Hello Kristan,

    Not a wise idea to use Always Trigger when developing uDMA code. Instead use Processor Trigger which is under CPU control.

    Also get_ADC_buf() is allocating the same address to the DMA ping and pong buffer. Again, the data may being overwritten.

    Finally when a crash occur what does the CPU end up doing/executing?

    Regards
    Amit
  • Okay so I have found a simpler example. Here I have two separate buffers for ping and pong. I have also switched to ADC Processor Trigger (will this ensure I receive 1M samples/second?) . When I execute the code with the debugger it appears to terminate after it's triggered. The debugger stops in loader_exit() located in ti\ccsv6\tools\compiler\ti-cgt-arm_5.2.5\lib\src\exit.c

    #include <stdbool.h>
    #include <stdint.h>
    #include <string.h>
    
    #include "inc/hw_ints.h"
    #include "inc/hw_memmap.h"
    #include "inc/hw_adc.h"
    #include "inc/hw_types.h"
    #include "inc/hw_udma.h"
    #include "inc/hw_emac.h"
    #include "inc/hw_uart.h"
    #include "driverlib/debug.h"
    #include "driverlib/gpio.h"
    #include "driverlib/interrupt.h"
    #include "driverlib/pin_map.h"
    #include "driverlib/rom.h"
    #include "driverlib/sysctl.h"
    #include "driverlib/uart.h"
    #include "driverlib/adc.h"
    #include "driverlib/udma.h"
    #include "driverlib/emac.h"
    #include "utils/uartstdio.h"
    #include <xdc/runtime/System.h>
    #include "os_udma.h"
    
    
    uint32_t count = 0;
    
    //*****************************************************************************
    //
    // The control table used by the uDMA controller.  This table must be aligned
    // to a 1024 byte boundary.
    //
    //*****************************************************************************
    
    uint8_t pui8ControlTable[1024] __attribute__ ((aligned(1024)));
    
    
    //DMA bus error count
    uint32_t g_ui32uDMAErrCount = 0;
    
    #define ADC_DMA_SIZE 1024
    static uint16_t adcbuffer_ping[ADC_DMA_SIZE+1];
    static uint16_t adcbuffer_pong[ADC_DMA_SIZE+1];
    
    //*****************************************************************************
    //
    // The error routine that is called if the driver library encounters an error.
    //
    //*****************************************************************************
    #ifdef DEBUG
    void __error__(char *pcFilename, uint32_t ui32Line)
    {
    	while (1);
    }
    #endif
    
    
    void ConfigureADC(void)
    {
    
        SysCtlPeripheralEnable(SYSCTL_PERIPH_ADC0);
        SysCtlPeripheralEnable(SYSCTL_PERIPH_UDMA);
    
        SysCtlPeripheralEnable(SYSCTL_PERIPH_GPIOE);
        GPIOPinTypeADC(GPIO_PORTE_BASE, GPIO_PIN_0);
        SysCtlDelay(10);
    
        ADCClockConfigSet(ADC0_BASE, ADC_CLOCK_SRC_PLL | ADC_CLOCK_RATE_FULL, 30);
    
        ADCHardwareOversampleConfigure(ADC0_BASE,5); 
        //ADCSequenceConfigure(ADC0_BASE, 0, ADC_TRIGGER_ALWAYS, 0);
        ADCSequenceConfigure(ADC0_BASE, 0, ADC_TRIGGER_PROCESSOR, 0);
        ADCSequenceStepConfigure(ADC0_BASE, 0, 0, ADC_CTL_TS );
        ADCSequenceStepConfigure(ADC0_BASE, 0, 1, ADC_CTL_TS );
        ADCSequenceStepConfigure(ADC0_BASE, 0, 2, ADC_CTL_TS );
        ADCSequenceStepConfigure(ADC0_BASE, 0, 3, ADC_CTL_TS );
        ADCSequenceStepConfigure(ADC0_BASE, 0, 4, ADC_CTL_TS );
        ADCSequenceStepConfigure(ADC0_BASE, 0, 5, ADC_CTL_TS );
        ADCSequenceStepConfigure(ADC0_BASE, 0, 6, ADC_CTL_TS );
        ADCSequenceStepConfigure(ADC0_BASE, 0, 7, ADC_CTL_TS | ADC_CTL_IE | ADC_CTL_END);
        ADCSequenceEnable(ADC0_BASE, 0);
    
        //
        // Enable the uDMA controller.
        //
        uDMAEnable();
        uDMAChannelAssign(UDMA_CH14_ADC0_0);
        //
        // Point at the control table to use for channel control structures.
        //
        uDMAControlBaseSet(pui8ControlTable);
    
    	ADCSequenceDMAEnable(ADC0_BASE, 0);
    
    	// disable some bits
    	uDMAChannelAttributeDisable(UDMA_CH14_ADC0_0, UDMA_ATTR_ALTSELECT /*start with ping-pong PRI side*/ |
    		UDMA_ATTR_HIGH_PRIORITY /*low priority*/ | UDMA_ATTR_REQMASK /*unmask*/);
    	// enable some bits
    	uDMAChannelAttributeEnable(UDMA_CH14_ADC0_0, UDMA_ATTR_USEBURST /*only allow burst transfers*/);
    
    
        // set dma params on PRI_ and ALT_SELECT
        uDMAChannelControlSet(UDMA_CH14_ADC0_0 | UDMA_PRI_SELECT, UDMA_SIZE_16 | UDMA_SRC_INC_NONE | UDMA_DST_INC_16 | UDMA_ARB_1024);
        uDMAChannelControlSet(UDMA_CH14_ADC0_0 | UDMA_ALT_SELECT, UDMA_SIZE_16 | UDMA_SRC_INC_NONE | UDMA_DST_INC_16 | UDMA_ARB_1024);
        uDMAChannelTransferSet(UDMA_CH14_ADC0_0 | UDMA_PRI_SELECT, UDMA_MODE_PINGPONG, (void *)(ADC0_BASE + ADC_O_SSFIFO0), &adcbuffer_ping[0], 1024);
        uDMAChannelTransferSet(UDMA_CH14_ADC0_0 | UDMA_ALT_SELECT, UDMA_MODE_PINGPONG, (void *)(ADC0_BASE + ADC_O_SSFIFO0), &adcbuffer_pong[0], 1024);
    
        uDMAChannelEnable(UDMA_CH14_ADC0_0);
    
        uDMAChannelEnable(UDMA_CHANNEL_ADC0);
    
        IntEnable(INT_UDMAERR);
        IntEnable(INT_ADC0SS0);
    
        ADCIntEnableEx(ADC0_BASE, ADC_INT_DMA_SS0);
    
    }
    
    //*****************************************************************************
    //
    // 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++;
        }
        while(1);
    }
    
    void ADCseq0Handler()
    {
    
        uint32_t ui32Status = ADCIntStatus(ADC0_BASE, 0, false);
    
        //ADCIntClear(ADC0_BASE, 0);
        ADCIntClearEx(ADC0_BASE, ui32Status);
    
    	if (uDMAChannelModeGet(UDMA_CH14_ADC0_0 | UDMA_PRI_SELECT) == UDMA_MODE_STOP) {
    		// Set up DMA transfer to the buffer
    		uDMAChannelTransferSet(UDMA_CH14_ADC0_0 | UDMA_PRI_SELECT, UDMA_MODE_PINGPONG, (void *)(ADC0_BASE + ADC_O_SSFIFO0), &adcbuffer_ping[0], 1024);
    		System_printf("P:%d ",adcbuffer_ping[0]);
    		System_flush();
    		return;
    	}
    
    	if (uDMAChannelModeGet(UDMA_CH14_ADC0_0 | UDMA_ALT_SELECT) == UDMA_MODE_STOP) {
    		uDMAChannelTransferSet(UDMA_CH14_ADC0_0 | UDMA_ALT_SELECT, UDMA_MODE_PINGPONG, (void *)(ADC0_BASE + ADC_O_SSFIFO0), &adcbuffer_pong[0], 1024);
    		System_printf("p:%d \n",adcbuffer_pong[0]);
    		System_flush();
    		return;
    	}
    
    }
    
    void main(void)
    {
    
    
    	sysclock = SysCtlClockFreqSet((SYSCTL_XTAL_25MHZ | SYSCTL_OSC_MAIN | SYSCTL_USE_PLL | SYSCTL_CFG_VCO_480), 120000000);
    
        SysCtlDelay(5);
    
        ConfigureADC();
    
    
    	while(1)
    	{
    		//ADCSequenceConfigure(ADC0_BASE, 0, ADC_TRIGGER_ALWAYS, 0);
    		ADCProcessorTrigger(ADC0_BASE,0);
    		count++;
    	}
    }
    

  • Hello Kristan,

    When using Processor trigger make sure that the last conversion is complete before requesting for the next conversion. There is a ADC Active Status bit. If the bit is 1 then it means that the conversion is ongoing. The application must wait for the bit to be 0 before requesting the next conversion/

    Regards
    Amit
  • Hello Amit,

    Thanks for the response so far. Unfortunately I am still experiencing the same problem. I have tried checking both ADCIntStatus() and ADCBusy() as reflected in my code, but both seem to indicate it is fine to continue. I have also tried only triggering once using ADCProcessorTrigger() but on this very first call it appears to crash. Any advice on how to proceed here is much appreciated.

    #include <stdbool.h>
    #include <stdint.h>
    #include <string.h>
    
    #include "inc/hw_ints.h"
    #include "inc/hw_memmap.h"
    #include "inc/hw_adc.h"
    #include "inc/hw_types.h"
    #include "inc/hw_udma.h"
    #include "inc/hw_emac.h"
    #include "inc/hw_uart.h"
    #include "driverlib/debug.h"
    #include "driverlib/gpio.h"
    #include "driverlib/interrupt.h"
    #include "driverlib/pin_map.h"
    #include "driverlib/rom.h"
    #include "driverlib/sysctl.h"
    #include "driverlib/uart.h"
    #include "driverlib/adc.h"
    #include "driverlib/udma.h"
    #include "driverlib/emac.h"
    #include "utils/uartstdio.h"
    #include <xdc/runtime/System.h>
    #include "os_udma.h"
    
    
    uint32_t count = 0;
    
    //*****************************************************************************
    //
    // The control table used by the uDMA controller.  This table must be aligned
    // to a 1024 byte boundary.
    //
    //*****************************************************************************
    
    uint8_t pui8ControlTable[1024] __attribute__ ((aligned(1024)));
    
    
    //DMA bus error count
    uint32_t g_ui32uDMAErrCount = 0;
    
    #define ADC_DMA_SIZE 1024
    static uint16_t adcbuffer_ping[ADC_DMA_SIZE+1];
    static uint16_t adcbuffer_pong[ADC_DMA_SIZE+1];
    
    //*****************************************************************************
    //
    // The error routine that is called if the driver library encounters an error.
    //
    //*****************************************************************************
    #ifdef DEBUG
    void __error__(char *pcFilename, uint32_t ui32Line)
    {
    	while (1);
    }
    #endif
    
    
    void ConfigureADC(void)
    {
    
        SysCtlPeripheralEnable(SYSCTL_PERIPH_ADC0);
        SysCtlPeripheralEnable(SYSCTL_PERIPH_UDMA);
    
        SysCtlPeripheralEnable(SYSCTL_PERIPH_GPIOE);
        GPIOPinTypeADC(GPIO_PORTE_BASE, GPIO_PIN_0);
        SysCtlDelay(10);
    
        ADCClockConfigSet(ADC0_BASE, ADC_CLOCK_SRC_PLL | ADC_CLOCK_RATE_FULL, 30);
    
        ADCHardwareOversampleConfigure(ADC0_BASE,5);
        //ADCSequenceConfigure(ADC0_BASE, 0, ADC_TRIGGER_ALWAYS, 0);
        ADCSequenceConfigure(ADC0_BASE, 0, ADC_TRIGGER_PROCESSOR, 0);
        ADCSequenceStepConfigure(ADC0_BASE, 0, 0, ADC_CTL_TS );
        ADCSequenceStepConfigure(ADC0_BASE, 0, 1, ADC_CTL_TS );
        ADCSequenceStepConfigure(ADC0_BASE, 0, 2, ADC_CTL_TS );
        ADCSequenceStepConfigure(ADC0_BASE, 0, 3, ADC_CTL_TS );
        ADCSequenceStepConfigure(ADC0_BASE, 0, 4, ADC_CTL_TS );
        ADCSequenceStepConfigure(ADC0_BASE, 0, 5, ADC_CTL_TS );
        ADCSequenceStepConfigure(ADC0_BASE, 0, 6, ADC_CTL_TS );
        ADCSequenceStepConfigure(ADC0_BASE, 0, 7, ADC_CTL_TS | ADC_CTL_IE | ADC_CTL_END);
        ADCSequenceEnable(ADC0_BASE, 0);
    
        //
        // Enable the uDMA controller.
        //
        uDMAEnable();
        uDMAChannelAssign(UDMA_CH14_ADC0_0);
        //
        // Point at the control table to use for channel control structures.
        //
        uDMAControlBaseSet(pui8ControlTable);
    
    	ADCSequenceDMAEnable(ADC0_BASE, 0);
    
    	// disable some bits
    	uDMAChannelAttributeDisable(UDMA_CH14_ADC0_0, UDMA_ATTR_ALTSELECT /*start with ping-pong PRI side*/ |
    		UDMA_ATTR_HIGH_PRIORITY /*low priority*/ | UDMA_ATTR_REQMASK /*unmask*/);
    	// enable some bits
    	uDMAChannelAttributeEnable(UDMA_CH14_ADC0_0, UDMA_ATTR_USEBURST /*only allow burst transfers*/);
    
    
        // set dma params on PRI_ and ALT_SELECT
        uDMAChannelControlSet(UDMA_CH14_ADC0_0 | UDMA_PRI_SELECT, UDMA_SIZE_16 | UDMA_SRC_INC_NONE | UDMA_DST_INC_16 | UDMA_ARB_1024);
        uDMAChannelControlSet(UDMA_CH14_ADC0_0 | UDMA_ALT_SELECT, UDMA_SIZE_16 | UDMA_SRC_INC_NONE | UDMA_DST_INC_16 | UDMA_ARB_1024);
        uDMAChannelTransferSet(UDMA_CH14_ADC0_0 | UDMA_PRI_SELECT, UDMA_MODE_PINGPONG, (void *)(ADC0_BASE + ADC_O_SSFIFO0), &adcbuffer_ping[0], 1024);
        uDMAChannelTransferSet(UDMA_CH14_ADC0_0 | UDMA_ALT_SELECT, UDMA_MODE_PINGPONG, (void *)(ADC0_BASE + ADC_O_SSFIFO0), &adcbuffer_pong[0], 1024);
    
        uDMAChannelEnable(UDMA_CH14_ADC0_0);
    
        uDMAChannelEnable(UDMA_CHANNEL_ADC0);
    
        IntEnable(INT_UDMAERR);
        IntEnable(INT_ADC0SS0);
    
        ADCIntEnableEx(ADC0_BASE, ADC_INT_DMA_SS0);
    
    }
    
    //*****************************************************************************
    //
    // 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++;
        }
        while(1);
    }
    
    void ADCseq0Handler()
    {
    
        uint32_t ui32Status = ADCIntStatus(ADC0_BASE, 0, false);
    
        //ADCIntClear(ADC0_BASE, 0);
        ADCIntClearEx(ADC0_BASE, ui32Status);
    
    	if (uDMAChannelModeGet(UDMA_CH14_ADC0_0 | UDMA_PRI_SELECT) == UDMA_MODE_STOP) {
    		// Set up DMA transfer to the buffer
    		uDMAChannelTransferSet(UDMA_CH14_ADC0_0 | UDMA_PRI_SELECT, UDMA_MODE_PINGPONG, (void *)(ADC0_BASE + ADC_O_SSFIFO0), &adcbuffer_ping[0], 1024);
    		System_printf("P:%d ",adcbuffer_ping[0]);
    		System_flush();
    		return;
    	}
    
    	if (uDMAChannelModeGet(UDMA_CH14_ADC0_0 | UDMA_ALT_SELECT) == UDMA_MODE_STOP) {
    		uDMAChannelTransferSet(UDMA_CH14_ADC0_0 | UDMA_ALT_SELECT, UDMA_MODE_PINGPONG, (void *)(ADC0_BASE + ADC_O_SSFIFO0), &adcbuffer_pong[0], 1024);
    		System_printf("p:%d \n",adcbuffer_pong[0]);
    		System_flush();
    		return;
    	}
    
    }
    
    void main(void)
    {
    
    
    	sysclock = SysCtlClockFreqSet((SYSCTL_XTAL_25MHZ | SYSCTL_OSC_MAIN | SYSCTL_USE_PLL | SYSCTL_CFG_VCO_480), 120000000);
    
        SysCtlDelay(5);
    
        ConfigureADC();
    
        ADCProcessorTrigger(ADC0_BASE,0); // <- Tried with just a single trigger and program stopped at this point
    
    
    	while(1)
    	{
        // Also tried ADCBusy(ADC0_BASE)
    		while (!ADCIntStatus(ADC0_BASE, 0 , false)) {
          ;
        }
    
    		ADCProcessorTrigger(ADC0_BASE,0);
    		count++;
    	}
    }