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.

CCS/EK-TM4C1294XL: ADC with DMA Ping-Pong, MEM_BUFFER_SIZE limited to 8

Part Number: EK-TM4C1294XL

Tool/software: Code Composer Studio

**EDIT** See working example at the bottom of the page

Hi,

I'm trying to learn DMA with ADC, using a modified udma_demo. But I'm a bit confused on how the readings are done and having some problems setting the ADC buffer size to 2.

#include "config/config.h"

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

#define MEM_BUFFER_SIZE         8

static uint16_t g_adcBufA[MEM_BUFFER_SIZE];
static uint16_t g_adcBufB[MEM_BUFFER_SIZE];

static uint32_t g_uDMAErrCount;

void config_ADC0DMA(void)
{
    ROM_GPIOPinTypeADC(GPIO_PORTK_BASE, GPIO_PIN_0 | GPIO_PIN_1);

    ROM_ADCSequenceConfigure(ADC0_BASE, 1, ADC_TRIGGER_ALWAYS, 0);
    ROM_ADCSequenceStepConfigure(ADC0_BASE, 1, 0, ADC_CTL_CH16);
    ROM_ADCSequenceStepConfigure(ADC0_BASE, 1, 1, ADC_CTL_CH17 | ADC_CTL_IE | ADC_CTL_END);

    //(320MHz PLL/2) / 5 = 32MHz = 2MSPS
    ADCClockConfigSet(ADC0_BASE, ADC_CLOCK_SRC_PLL | ADC_CLOCK_RATE_FULL, 5);

    //ROM_ADCHardwareOversampleConfigure(ADC0_BASE, 64);

    ROM_ADCSequenceEnable(ADC0_BASE, 1);
    ROM_ADCSequenceDMAEnable(ADC0_BASE, 1);

    ROM_uDMAChannelAttributeDisable(UDMA_CHANNEL_ADC1,
                                    UDMA_ATTR_ALTSELECT | UDMA_ATTR_USEBURST |
                                    UDMA_ATTR_HIGH_PRIORITY |
                                    UDMA_ATTR_REQMASK);

    ROM_uDMAChannelAttributeEnable(UDMA_CHANNEL_ADC1, UDMA_ATTR_USEBURST);

    ROM_uDMAChannelControlSet(UDMA_CHANNEL_ADC1 | UDMA_PRI_SELECT,
                              UDMA_SIZE_16 | UDMA_SRC_INC_NONE | UDMA_DST_INC_16 |
                              UDMA_ARB_1);

    ROM_uDMAChannelControlSet(UDMA_CHANNEL_ADC1 | UDMA_ALT_SELECT,
                              UDMA_SIZE_16 | UDMA_SRC_INC_NONE | UDMA_DST_INC_16 |
                              UDMA_ARB_1);

    ROM_uDMAChannelTransferSet(UDMA_CHANNEL_ADC1 | UDMA_PRI_SELECT,
                               UDMA_MODE_PINGPONG,
                               (void *)(ADC0_BASE + ADC_O_SSFIFO1),
                               g_adcBufA, MEM_BUFFER_SIZE);

    ROM_uDMAChannelTransferSet(UDMA_CHANNEL_ADC1 | UDMA_ALT_SELECT,
                               UDMA_MODE_PINGPONG,
                               (void *)(ADC0_BASE + ADC_O_SSFIFO1),
                               g_adcBufB, MEM_BUFFER_SIZE);

    ROM_uDMAChannelEnable(UDMA_CHANNEL_ADC1);

    ROM_ADCIntEnableEx(ADC0_BASE, ADC_INT_DMA_SS1);
    ROM_IntEnable(INT_ADC0SS1);;
}

int main(void)
{
    uint32_t g_cpuFrequency = SysCtlClockFreqSet((SYSCTL_XTAL_25MHZ | SYSCTL_OSC_MAIN |
            SYSCTL_USE_PLL | SYSCTL_CFG_VCO_320), 120000000);
    ROM_FPUEnable();
    ROM_FPULazyStackingEnable();

    ROM_IntMasterDisable();

    initPeripherals();

    config_UART2(921600, g_cpuFrequency);

    UARTprintf("\033[2J\033[H");

    ROM_IntEnable(INT_UDMAERR);

    ROM_uDMAEnable();

    ROM_uDMAControlBaseSet(dmaControlTable);

    config_ADC0DMA();

    ROM_IntMasterEnable();

    for(;;)
    {
        UARTprintf("ADC ReadingA: %u %u %u %u %u %u %u %u Error Count: %u\n", g_adcBufA[0], g_adcBufA[1],
                   g_adcBufA[2], g_adcBufA[3], g_adcBufA[4], g_adcBufA[5], g_adcBufA[6], g_adcBufA[7], g_uDMAErrCount);
        UARTprintf("ADC ReadingB: %u %u %u %u %u %u %u %u Error Count: %u\n", g_adcBufB[0], g_adcBufB[1],
                           g_adcBufB[2], g_adcBufB[3], g_adcBufB[4], g_adcBufB[5], g_adcBufB[6], g_adcBufB[7], g_uDMAErrCount);

        //UARTprintf("ADC ReadingA: %u %u Error Count: %u\n", g_adcBufA[0], g_adcBufA[1], g_uDMAErrCount);
        //UARTprintf("ADC ReadingB: %u %u Error Count: %u\n", g_adcBufB[0], g_adcBufB[1], g_uDMAErrCount);

        ROM_SysCtlDelay((g_cpuFrequency/3)*0.1);
    }
}

void ADC0SS1IntHandler(void)
{
    uint32_t ui32Mode;

    //limpa interrupção causada pelo DMA
    ADCIntClearEx(ADC0_BASE, ADC_INT_DMA_SS1);

    ui32Mode = ROM_uDMAChannelModeGet(UDMA_CHANNEL_ADC1 | UDMA_PRI_SELECT);

    if(ui32Mode == UDMA_MODE_STOP)
        ROM_uDMAChannelTransferSet(UDMA_CHANNEL_ADC1 | UDMA_PRI_SELECT,
                                   UDMA_MODE_PINGPONG,
                                   (void *)(ADC0_BASE + ADC_O_SSFIFO1),
                                   g_adcBufA, MEM_BUFFER_SIZE);

    ui32Mode = ROM_uDMAChannelModeGet(UDMA_CHANNEL_ADC1 | UDMA_ALT_SELECT);

    if(ui32Mode == UDMA_MODE_STOP)
        ROM_uDMAChannelTransferSet(UDMA_CHANNEL_ADC1 | UDMA_ALT_SELECT,
                                   UDMA_MODE_PINGPONG,
                                   (void *)(ADC0_BASE + ADC_O_SSFIFO1),
                                   g_adcBufB, MEM_BUFFER_SIZE);
}

void uDMAErrorHandler(void)
{
    uint32_t ui32Status;

    ui32Status = ROM_uDMAErrorStatusGet();

    if(ui32Status)
    {
        ROM_uDMAErrorStatusClear();
        g_uDMAErrCount++;
    }
}

I'm trying to read from pins PK0 (GND) and PK1 (3V3). I'm setting the g_adcBufA and g_adcBufB size to 8 and getting [4095 0 4095 0 4095 0 4095 0] on each. Seems like it's reading [PK1 PK0 PK1 PK0 PK1 PK0 PK1 PK0].

The SS1 has a FIFO depth of 4 and can hold 4 readings. But I'm using a buffer of 8 positions and these are filled with PK1 and PK0 readings alternately. 

Questions:

Shouldn't g_adcBufA hold the first two values and print something else in the rest?

Why can't I use a buffer of two values? It only works with 8 minimum. I need the results immediately, not waiting a buffer to be filled 8 times before I can process data.

Is the Ping-Pong the best way to use the DMA with ADC? I heard I could use Scatter-Gather, but seems rather complex, not sure if the complexity makes up for the performance gain (and I'm totally newbie with DMA, only worked once with a STM32 board, which has a rather nice software called STM32CubeMX that does all the stuff in the background).

  • Helder Sales said:
    Shouldn't g_adcBufA hold the first two values and print something else in the rest?

    You configured the uDMA to do 8 sixteen bit transfers. All 8 locations will have A to D results.

    Helder Sales said:
    Why can't I use a buffer of two values? It only works with 8 minimum. I need the results immediately, not waiting a buffer to be filled 8 times before I can process data.

    It does not make sense to have a uDMA buffer size smaller than the A to D FIFO size. If you need the results immediately, use sequence 3 and straight A to D interrupts.

    Helder Sales said:
    Is the Ping-Pong the best way to use the DMA with ADC?

    It depends on what you are trying to do. If you continuously sample a signal and process that signal in blocks, then Ping-Pong works well.

  • Bob Crosby said:

    It does not make sense to have a uDMA buffer size smaller than the A to D FIFO size. If you need the results immediately, use sequence 3 and straight A to D interrupts.

    It's possible to do that with at least 3 pins to read? I plan to read from these using DMA and two ADCs with phase control to achieve 4MSPS (then oversample to get better results). For now, I'm using only two pins for the sake of simplicity.

    Tried to modify to something similar to this, but didn't work

    ROM_ADCSequenceStepConfigure(ADC0_BASE, 3, 0, ADC_CTL_CH16 | ADC_CTL_IE);
    ROM_ADCSequenceStepConfigure(ADC0_BASE, 3, 0, ADC_CTL_CH17 | ADC_CTL_IE | ADC_CTL_END);

    Even with only one channel (CH17), uDMA never gets to STOP mode. And I believe that it never leaves the ISR also.

    Another problem is that I change the MEM_BUFFER_SIZE to anything below 8 (MEM_BUFFER_SIZE  = 4 for example), even with SS1 it hangs in the ISR and uDMA never gets to STOP.

    Bob Crosby said:

    You configured the uDMA to do 8 sixteen bit transfers. All 8 locations will have A to D results.

    Assuming I have a funtional buffer with size 4 (using SS1), if I only use two channels, the FIFO will store

    adcBuf[0] = Channel 0;

    adcBuf[1] = Channel 1;

    adcBuf[2] = Channel 0;

    adcBuf[3] = Channel 1;

    like this?

    And the 8 sixteen bit transfers will be like A to D + A to D totalling 8 results?

  • I found the problem regarding setting the ADC buffer size below 8. I don't know why, but at very high speeds the µDMA doesn't seems to function properly with small buffers. When I enabled the 64x oversampling, the problem was gone. Measured in the logic analyser to confirm the ADC was working at full speed oversampled.

    I'll help the community by sharing a working code that I've developed.

    Basically, it configures both ADCs to work simultaneously with phase shift, in order to double the sampling frequency. The combined speed is 4MSPS divided by a oversampling of 64, resulting in ~30KSPS. The number of sampled channels is two (PK0 and PK1), and it utilizes Sample Sequencer 1. Also, it utilizes the µDMA in Ping-Pong mode.

    #include <stdint.h>
    #include <stdbool.h>
    #include "inc/hw_memmap.h"
    #include "inc/hw_types.h"
    #include "inc/hw_ints.h"
    #include "inc/hw_adc.h"
    #include "inc/hw_timer.h"
    #include "inc/hw_gpio.h"
    #include "inc/hw_udma.h"
    #include "driverlib/pin_map.h"
    #include "driverlib/rom.h"
    #include "driverlib/sysctl.h"
    #include "driverlib/interrupt.h"
    #include "driverlib/gpio.h"
    #include "driverlib/adc.h"
    #include "driverlib/pwm.h"
    #include "driverlib/fpu.h"
    #include "driverlib/uart.h"
    #include "driverlib/timer.h"
    #include "driverlib/udma.h"
    #include "utils/uartstdio.h"
    
    #pragma DATA_ALIGN(dmaControlTable, 1024)
    uint8_t dmaControlTable[1024];
    
    #define ADC_BUFFER_SIZE 2
    
    static uint16_t g_adcBuf[ADC_BUFFER_SIZE];
    static uint32_t g_uDMAErrCount;
    
    bool g_flagAdc0;
    bool g_flagAdc1;
    
    void initPeripherals(void)
    {
        ROM_SysCtlPeripheralDisable(SYSCTL_PERIPH_GPIOA);
        ROM_SysCtlPeripheralReset(SYSCTL_PERIPH_GPIOA);
        ROM_SysCtlPeripheralEnable(SYSCTL_PERIPH_GPIOA);
        while(!ROM_SysCtlPeripheralReady(SYSCTL_PERIPH_GPIOA));
    
        ROM_SysCtlPeripheralDisable(SYSCTL_PERIPH_GPIOD);
        ROM_SysCtlPeripheralReset(SYSCTL_PERIPH_GPIOD);
        ROM_SysCtlPeripheralEnable(SYSCTL_PERIPH_GPIOD);
        while(!ROM_SysCtlPeripheralReady(SYSCTL_PERIPH_GPIOD));
    
        ROM_SysCtlPeripheralDisable(SYSCTL_PERIPH_GPIOK);
        ROM_SysCtlPeripheralReset(SYSCTL_PERIPH_GPIOK);
        ROM_SysCtlPeripheralEnable(SYSCTL_PERIPH_GPIOK);
        while(!ROM_SysCtlPeripheralReady(SYSCTL_PERIPH_GPIOK));
    
        ROM_SysCtlPeripheralDisable(SYSCTL_PERIPH_ADC0);
        ROM_SysCtlPeripheralReset(SYSCTL_PERIPH_ADC0);
        ROM_SysCtlPeripheralEnable(SYSCTL_PERIPH_ADC0);
        while(!ROM_SysCtlPeripheralReady(SYSCTL_PERIPH_ADC0));
    
        ROM_SysCtlPeripheralDisable(SYSCTL_PERIPH_ADC1);
        ROM_SysCtlPeripheralReset(SYSCTL_PERIPH_ADC1);
        ROM_SysCtlPeripheralEnable(SYSCTL_PERIPH_ADC1);
        while(!ROM_SysCtlPeripheralReady(SYSCTL_PERIPH_ADC1));
    
        ROM_SysCtlPeripheralDisable(SYSCTL_PERIPH_UART2);
        ROM_SysCtlPeripheralReset(SYSCTL_PERIPH_UART2);
        ROM_SysCtlPeripheralEnable(SYSCTL_PERIPH_UART2);
        while(!ROM_SysCtlPeripheralReady(SYSCTL_PERIPH_UART2));
    
        ROM_SysCtlPeripheralDisable(SYSCTL_PERIPH_UDMA);
        ROM_SysCtlPeripheralReset(SYSCTL_PERIPH_UDMA);
        ROM_SysCtlPeripheralEnable(SYSCTL_PERIPH_UDMA);
        while(!ROM_SysCtlPeripheralReady(SYSCTL_PERIPH_UDMA));
    }
    
    void config_UART2(uint32_t baudrate, uint32_t cpuClock)
    {
        ROM_GPIOPinConfigure(GPIO_PD4_U2RX);
        ROM_GPIOPinConfigure(GPIO_PD5_U2TX);
        ROM_GPIOPinTypeUART(GPIO_PORTD_BASE, GPIO_PIN_4 | GPIO_PIN_5);
    
        ROM_UARTClockSourceSet(UART2_BASE, UART_CLOCK_SYSTEM);
    
        UARTStdioConfig(2, baudrate, cpuClock);
    }
    
    void config_ADC0DMA(void)
    {
        ROM_GPIOPinTypeADC(GPIO_PORTK_BASE, GPIO_PIN_0 | GPIO_PIN_1);
    
        ROM_ADCReferenceSet(ADC0_BASE, ADC_REF_INT);
    
        ROM_ADCSequenceConfigure(ADC0_BASE, 1, ADC_TRIGGER_ALWAYS, 0);
    
        ROM_ADCSequenceStepConfigure(ADC0_BASE, 1, 0, ADC_CTL_CH16);
        ROM_ADCSequenceStepConfigure(ADC0_BASE, 1, 1, ADC_CTL_CH17 | ADC_CTL_IE | ADC_CTL_END);
    
        //(320MHz PLL/2) / 5 = 32MHz = 2MSPS (there's an issue with the documentation, the PLL is divided by 2, hence 320MHz/2)
        ADCClockConfigSet(ADC0_BASE, ADC_CLOCK_SRC_PLL | ADC_CLOCK_RATE_FULL, 10);
    
        //enable oversampling
        ROM_ADCHardwareOversampleConfigure(ADC0_BASE, 64);
    
        //set the phase delay, so the two ADCs can sample the same signal alternately, the value is experimental
        //and you should check with an logic analyser or oscilloscope to see if they're separated by ~180°
        //this case is 0 for being the reference
        ROM_ADCPhaseDelaySet(ADC0_BASE, ADC_PHASE_0);
    
        //enable ADC and ADC DMA  
        ROM_ADCSequenceEnable(ADC0_BASE, 1);
        ROM_ADCSequenceDMAEnable(ADC0_BASE, 1);
    
        //configures the uDMA 
        ROM_uDMAChannelAttributeDisable(UDMA_CHANNEL_ADC1, UDMA_ATTR_ALL);
        ROM_uDMAChannelAttributeEnable(UDMA_CHANNEL_ADC1, UDMA_ATTR_USEBURST);
    
        ROM_uDMAChannelControlSet(UDMA_CHANNEL_ADC1 | UDMA_PRI_SELECT,
                                  UDMA_SIZE_16 | UDMA_SRC_INC_NONE | UDMA_DST_INC_16 |
                                  UDMA_ARB_1);
        ROM_uDMAChannelControlSet(UDMA_CHANNEL_ADC1 | UDMA_ALT_SELECT,
                                  UDMA_SIZE_16 | UDMA_SRC_INC_NONE | UDMA_DST_INC_16 |
                                  UDMA_ARB_1);
    
        ROM_uDMAChannelTransferSet(UDMA_CHANNEL_ADC1 | UDMA_PRI_SELECT,
                                   UDMA_MODE_PINGPONG,
                                   (void *)(ADC0_BASE + ADC_O_SSFIFO1),
                                   g_adcBuf, ADC_BUFFER_SIZE);
        ROM_uDMAChannelTransferSet(UDMA_CHANNEL_ADC1 | UDMA_ALT_SELECT,
                                   UDMA_MODE_PINGPONG,
                                   (void *)(ADC0_BASE + ADC_O_SSFIFO1),
                                   g_adcBuf, ADC_BUFFER_SIZE);
    
        ROM_uDMAChannelEnable(UDMA_CHANNEL_ADC1);
    
        //enable the interrupts (for this case is ADCIntEnableEx instead of ADCIntEnable)
        ROM_ADCIntEnableEx(ADC0_BASE, ADC_INT_DMA_SS1);
        ROM_IntEnable(INT_ADC0SS1);
    }
    
    void config_ADC1DMA(void)
    {
        ROM_GPIOPinTypeADC(GPIO_PORTK_BASE, GPIO_PIN_0 | GPIO_PIN_1);
    
        ROM_ADCReferenceSet(ADC1_BASE, ADC_REF_INT);
    
        ROM_ADCSequenceConfigure(ADC1_BASE, 1, ADC_TRIGGER_ALWAYS, 0);
    
        ROM_ADCSequenceStepConfigure(ADC1_BASE, 1, 0, ADC_CTL_CH16);
        ROM_ADCSequenceStepConfigure(ADC1_BASE, 1, 1, ADC_CTL_CH17 | ADC_CTL_IE | ADC_CTL_END);
    
        //(320MHz PLL/2) / 5 = 32MHz = 2MSPS (there's an issue with the documentation, the PLL is divided by 2, hence 320MHz/2)
        ADCClockConfigSet(ADC1_BASE, ADC_CLOCK_SRC_PLL | ADC_CLOCK_RATE_FULL, 10);
    
        //enable oversampling
        ROM_ADCHardwareOversampleConfigure(ADC1_BASE, 64);
    
        //set the phase delay, so the two ADCs can sample the same signal alternately, the value is experimental
        //and you should check with an logic analyser or oscilloscope to see if they're separated by ~180°
        ROM_ADCPhaseDelaySet(ADC1_BASE, ADC_PHASE_270);
    
        //enable ADC and DMA
        ROM_ADCSequenceEnable(ADC1_BASE, 1);
        ROM_ADCSequenceDMAEnable(ADC1_BASE, 1);
    
        //assign channel 25 to ADC1 (since the channel defaults to SSI1TX)
        ROM_uDMAChannelAssign(UDMA_CH25_ADC1_1);
    
        //configures the uDMA (secondary peripheral assignments)
        ROM_uDMAChannelAttributeDisable(UDMA_SEC_CHANNEL_ADC11, UDMA_ATTR_ALL);
        ROM_uDMAChannelAttributeEnable(UDMA_SEC_CHANNEL_ADC11, UDMA_ATTR_USEBURST);
    
        ROM_uDMAChannelControlSet(UDMA_SEC_CHANNEL_ADC11 | UDMA_PRI_SELECT,
                                  UDMA_SIZE_16 | UDMA_SRC_INC_NONE | UDMA_DST_INC_16 |
                                  UDMA_ARB_1);
        ROM_uDMAChannelControlSet(UDMA_SEC_CHANNEL_ADC11 | UDMA_ALT_SELECT,
                                  UDMA_SIZE_16 | UDMA_SRC_INC_NONE | UDMA_DST_INC_16 |
                                  UDMA_ARB_1);
    
        ROM_uDMAChannelTransferSet(UDMA_SEC_CHANNEL_ADC11 | UDMA_PRI_SELECT,
                                   UDMA_MODE_PINGPONG,
                                   (void *)(ADC1_BASE + ADC_O_SSFIFO1),
                                   g_adcBuf, ADC_BUFFER_SIZE);
        ROM_uDMAChannelTransferSet(UDMA_SEC_CHANNEL_ADC11 | UDMA_ALT_SELECT,
                                   UDMA_MODE_PINGPONG,
                                   (void *)(ADC1_BASE + ADC_O_SSFIFO1),
                                   g_adcBuf, ADC_BUFFER_SIZE);
    
        ROM_uDMAChannelEnable(UDMA_SEC_CHANNEL_ADC11);
    
        //enable the interrupts (for this case is ADCIntEnableEx instead of ADCIntEnable)
        ROM_ADCIntEnableEx(ADC1_BASE, ADC_INT_DMA_SS1);
        ROM_IntEnable(INT_ADC1SS1);
    }
    
    int main(void)
    {
        //config CPU to run at 120MHz with 320MHz VCO
        uint32_t g_cpuFrequency = SysCtlClockFreqSet((SYSCTL_XTAL_25MHZ | SYSCTL_OSC_MAIN |
                SYSCTL_USE_PLL | SYSCTL_CFG_VCO_320), 120000000);
        ROM_FPUEnable();
        ROM_FPULazyStackingEnable();
    
        //disable interrupts to safely configure peripherals
        ROM_IntMasterDisable();
    
        //enable peripherals
        initPeripherals();
    
        //configs UART 2 (Launchpad jumpers must be in CAN position, otherwhise you'll need to rewrite this function to UART0)
        config_UART2(921600, g_cpuFrequency);
    
        //set PA output pins to change state after every interrupt from the ADC
        ROM_GPIOPinTypeGPIOOutput(GPIO_PORTA_BASE, GPIO_PIN_4 | GPIO_PIN_5);
    
        //clears screen and reset the cursor
        UARTprintf("\033[2J\033[H");
    
        //enable udma error interrupt
        ROM_IntEnable(INT_UDMAERR);
    
        //enable udma
        ROM_uDMAEnable();
    
        ROM_uDMAControlBaseSet(dmaControlTable);
    
        //configs ADC
        config_ADC0DMA();
        config_ADC1DMA();
    
        //now that every periph is safely configured, we can enable interrupts
        ROM_IntMasterEnable();
    
        for(;;)
        {
            UARTprintf("ADC Reading: %u %u Error Count: %u\n", g_adcBuf[0], g_adcBuf[1], g_uDMAErrCount);
    
            ROM_SysCtlDelay((g_cpuFrequency/3)*0.1);
        }
    }
    
    void ADC0SS1IntHandler(void)
    {
        uint32_t ui32Mode;
    
        //clear ADC interrupt caused by DMA
        ADCIntClearEx(ADC0_BASE, ADC_INT_DMA_SS1);
    
        //checks udma primary control structure current mode
        ui32Mode = ROM_uDMAChannelModeGet(UDMA_CHANNEL_ADC1 | UDMA_PRI_SELECT);
    
        //if udma primary control structure is done transfering data, re-enable it
        if(ui32Mode == UDMA_MODE_STOP)
            ROM_uDMAChannelTransferSet(UDMA_CHANNEL_ADC1 | UDMA_PRI_SELECT,
                                       UDMA_MODE_PINGPONG,
                                       (void *)(ADC0_BASE + ADC_O_SSFIFO1),
                                       g_adcBuf, ADC_BUFFER_SIZE);
    
        //checks udma secondary control structure current mode
        ui32Mode = ROM_uDMAChannelModeGet(UDMA_CHANNEL_ADC1 | UDMA_ALT_SELECT);
    
        //if udma secondary control structure is done transfering data, re-enable it
        if(ui32Mode == UDMA_MODE_STOP)
            ROM_uDMAChannelTransferSet(UDMA_CHANNEL_ADC1 | UDMA_ALT_SELECT,
                                       UDMA_MODE_PINGPONG,
                                       (void *)(ADC0_BASE + ADC_O_SSFIFO1),
                                       g_adcBuf, ADC_BUFFER_SIZE);
    
        //toggle pin PA5 to analyse it with an oscilloscope or logic analyser the ADC current speed
        ROM_GPIOPinWrite(GPIO_PORTA_BASE, GPIO_PIN_4, g_flagAdc0 ? GPIO_PIN_4 : 0x00);
        g_flagAdc0 = !g_flagAdc0;
    }
    
    void ADC1SS1IntHandler(void)
    {
        uint32_t ui32Mode;
    
        //clear ADC interrupt caused by DMA
        ADCIntClearEx(ADC1_BASE, ADC_INT_DMA_SS1);
    
        //checks udma primary control structure current mode
        ui32Mode = ROM_uDMAChannelModeGet(UDMA_SEC_CHANNEL_ADC11 | UDMA_PRI_SELECT);
    
        //if udma primary control structure is done transfering data, re-enable it
        if(ui32Mode == UDMA_MODE_STOP)
            ROM_uDMAChannelTransferSet(UDMA_SEC_CHANNEL_ADC11 | UDMA_PRI_SELECT,
                                       UDMA_MODE_PINGPONG,
                                       (void *)(ADC1_BASE + ADC_O_SSFIFO1),
                                       g_adcBuf, ADC_BUFFER_SIZE);
    
        //checks udma secondary control structure current mode
        ui32Mode = ROM_uDMAChannelModeGet(UDMA_SEC_CHANNEL_ADC11 | UDMA_ALT_SELECT);
    
        //if udma secondary control structure is done transfering data, re-enable it
        if(ui32Mode == UDMA_MODE_STOP)
            ROM_uDMAChannelTransferSet(UDMA_SEC_CHANNEL_ADC11 | UDMA_ALT_SELECT,
                                       UDMA_MODE_PINGPONG,
                                       (void *)(ADC1_BASE + ADC_O_SSFIFO1),
                                       g_adcBuf, ADC_BUFFER_SIZE);
    
        //toggle pin PA5 to analyse it with an oscilloscope or logic analyser the ADC current speed
        ROM_GPIOPinWrite(GPIO_PORTA_BASE, GPIO_PIN_5, g_flagAdc1 ? GPIO_PIN_5 : 0x00);
        g_flagAdc1 = !g_flagAdc1;
    }
    
    void uDMAErrorHandler(void)
    {
        uint32_t ui32Status;
    
        ui32Status = ROM_uDMAErrorStatusGet();
    
        if(ui32Status)
        {
            ROM_uDMAErrorStatusClear();
            g_uDMAErrCount++;
        }
    }
    

    Also I've attached the projet file. Hope it helps, I'm not sure why there isn't a "official" example of that, only the UART one.

    0333.ADC_DMA.zip

    P.S. in this case I used only one buffer for ping and pong, but is also possible to use adcBufA to ping and adcBufB to pong. Separating may come in handy for processing large blocks of data.