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.

Problem with MSP432 ADC DMA Ping-Pong mode, only filling first buffer and then stopping.

Other Parts Discussed in Thread: BOOSTXL-K350QVG-S1

I have a problem similar to others: https://e2e.ti.com/support/microcontrollers/msp430/f/166/p/425881/1750461

while using the MSP432 launchpad ADC DMA in Ping-Pong mode. In my code (see below) the dma will only successfully fill the first buffer and then stops.

I have attempted to add most of the suggestions that i could find in other posts, but to no avail.

This program is a modified version of the MSP-EXP432P401R + Educational Boosterpack MkII - Microphone FFT example.

I suspect my problem is caused by the :   while(1) { MAP_PCM_gotoLPM0();  not looping forever, or possibly by lack of understanding of how to setup interrupt service routines.

Please see the code below, any suggestions greatly appreciated

Jack

-------------------------------------------------------------
//****************************************************************************
//extracted from MSP-EXP432P401R + Educational Boosterpack MkII - Microphone FFT

#include "msp.h"
#include "driverlib.h"
#include "rom_map.h"

#include "arm_const_structs.h"

/* Standard Includes */
#include <stdio.h>
#include <stdint.h>

#define SAMPLE_LENGTH 512

/* ------------------------------------------------------------------
* Global variables for FFT Bin Example
* ------------------------------------------------------------------- */
volatile arm_status status;


#define SMCLK_FREQUENCY     48000000
// sample frequency is nyquist
#define SAMPLE_FREQUENCY    8000
//#define SAMPLE_FREQUENCY    200000

/* FFT data/processing buffers*/
int16_t data_array0[SAMPLE_LENGTH];
int16_t data_array1[SAMPLE_LENGTH];
int16_t data_array2[SAMPLE_LENGTH];
int16_t value;

/* DMA Control Table */
#ifdef ewarm
#pragma data_alignment=256
#else
#pragma DATA_ALIGN(controlTable, 256)
#endif
uint8_t controlTable[256];

volatile int switch_data = 0;

/* Timer_A PWM Configuration Parameter */
Timer_A_PWMConfig pwmConfig =
{
        TIMER_A_CLOCKSOURCE_SMCLK,
        TIMER_A_CLOCKSOURCE_DIVIDER_1,
        (SMCLK_FREQUENCY/SAMPLE_FREQUENCY),
        TIMER_A_CAPTURECOMPARE_REGISTER_1,
        TIMER_A_OUTPUTMODE_SET_RESET,
        (SMCLK_FREQUENCY/SAMPLE_FREQUENCY)/2
};


void main(void)
{
    /* Halting WDT and disabling master interrupts */
    MAP_WDT_A_holdTimer();
    MAP_Interrupt_disableMaster();

    /* Initialize the launchpad fpu. */
    MAP_FPU_enableModule();
    MAP_FPU_enableLazyStacking();

//    boardInit();
    /* Initializes Clock System */
    MAP_CS_setDCOCenteredFrequency(CS_DCO_FREQUENCY_48);
    MAP_CS_initClockSignal(CS_MCLK, CS_DCOCLK_SELECT, CS_CLOCK_DIVIDER_1 );
    MAP_CS_initClockSignal(CS_HSMCLK, CS_DCOCLK_SELECT, CS_CLOCK_DIVIDER_1 );
    MAP_CS_initClockSignal(CS_SMCLK, CS_DCOCLK_SELECT, CS_CLOCK_DIVIDER_1 );
    MAP_CS_initClockSignal(CS_ACLK, CS_REFOCLK_SELECT, CS_CLOCK_DIVIDER_1);

    /* Configuring Timer_A to have a period of approximately 500ms and
     * an initial duty cycle of 10% of that (3200 ticks)  */
    Timer_A_generatePWM(TIMER_A0_BASE, &pwmConfig);

    /* Initializing ADC (MCLK/1/1) */
    ADC14_enableModule();
    ADC14_initModule(ADC_CLOCKSOURCE_MCLK, ADC_PREDIVIDER_1, ADC_DIVIDER_1, 0);
    MAP_ADC14_setResolution(ADC_14BIT);

    ADC14_setSampleHoldTrigger(ADC_TRIGGER_SOURCE1, false);

    /* Configuring GPIOs (4.3 A10) */
//    GPIO_setAsPeripheralModuleFunctionInputPin(GPIO_PORT_P4, GPIO_PIN3,
//    GPIO_TERTIARY_MODULE_FUNCTION);

    /* Setting up GPIO pins p5.5 and p5.4 as analog inputs */
//    MAP_GPIO_setAsPeripheralModuleFunctionInputPin(GPIO_PORT_P5,
//            GPIO_PIN5 | GPIO_PIN4, GPIO_TERTIARY_MODULE_FUNCTION);

    /* Configuring GPIOs (5.5 A0) */
    MAP_GPIO_setAsPeripheralModuleFunctionInputPin(GPIO_PORT_P5, GPIO_PIN5,
    GPIO_TERTIARY_MODULE_FUNCTION);

    /* Configuring ADC Memory */
    ADC14_configureSingleSampleMode(ADC_MEM0, true);

//    ADC14_configureConversionMemory(ADC_MEM0, ADC_VREFPOS_AVCC_VREFNEG_VSS,
//    ADC_INPUT_A10, false);

//    MAP_ADC14_configureConversionMemory(ADC_MEM0, ADC_VREFPOS_AVCC_VREFNEG_VSS,
//            ADC_INPUT_A0, true);

    MAP_ADC14_configureConversionMemory(ADC_MEM0, ADC_VREFPOS_AVCC_VREFNEG_VSS,
            ADC_INPUT_A0, false);

    /* Set ADC result format to signed binary */
//    ADC14_setResultFormat(ADC_SIGNED_BINARY);
    ADC14_setResultFormat(ADC_UNSIGNED_BINARY);

    /* Configuring DMA module */
    DMA_enableModule();
    DMA_setControlBase(controlTable);

    DMA_disableChannelAttribute(DMA_CH7_ADC12C,
                                 UDMA_ATTR_ALTSELECT | UDMA_ATTR_USEBURST |
                                 UDMA_ATTR_HIGH_PRIORITY |
                                 UDMA_ATTR_REQMASK);


    /* Setting Control Indexes. In this case we will set the source of the
     * DMA transfer to ADC14 Memory 0
     *  and the destination to the
     * destination data array. */
    MAP_DMA_setChannelControl(UDMA_PRI_SELECT | DMA_CH7_ADC12C,
        UDMA_SIZE_16 | UDMA_SRC_INC_NONE | UDMA_DST_INC_16 | UDMA_ARB_1);
    MAP_DMA_setChannelTransfer(UDMA_PRI_SELECT | DMA_CH7_ADC12C,
        UDMA_MODE_PINGPONG, (void*) (ADC14_BASE + OFS_ADC14MEM0),
        data_array1, SAMPLE_LENGTH);

    MAP_DMA_setChannelControl(UDMA_ALT_SELECT | DMA_CH7_ADC12C,
        UDMA_SIZE_16 | UDMA_SRC_INC_NONE | UDMA_DST_INC_16 | UDMA_ARB_1);
    MAP_DMA_setChannelTransfer(UDMA_ALT_SELECT | DMA_CH7_ADC12C,
        UDMA_MODE_PINGPONG, (void*) (ADC14_BASE + OFS_ADC14MEM0),
        data_array2, SAMPLE_LENGTH);

    /* Assigning/Enabling Interrupts */
    MAP_DMA_assignInterrupt(DMA_INT1, 7);
    MAP_Interrupt_enableInterrupt(INT_DMA_INT1);
    MAP_DMA_assignChannel(DMA_CH7_ADC12C);
    MAP_DMA_clearInterruptFlag(7);
    MAP_Interrupt_enableMaster();

    /* Making it so that we go back to sleep when interrupts end */
     MAP_Interrupt_enableSleepOnIsrExit();

    /* Now that the DMA is primed and setup, enabling the channels. The ADC14
     * hardware should take over and transfer/receive all bytes */
    MAP_DMA_enableChannel(7);
    /* FROM TIM-TI, We need to enable interrupts after enabling the DMA channel
     * to ensure that we don't get stuck in a "deadlock" situation */
    MAP_ADC14_enableConversion();

    while(1)
    {
        MAP_PCM_gotoLPM0();

        int i = 0;

        /* Computer real FFT using the completed data buffer */
        if (switch_data & 1)
        {
            value = data_array1[1];
            for (i=0; i<SAMPLE_LENGTH; i++)
            {
                data_array0[i] = data_array1[i];
            }
            printf(" switch buf 1 %i\r\n ", switch_data);
        }
        else
        {
            value = data_array2[1];
            for (i=0; i<SAMPLE_LENGTH; i++)
            {
                data_array0[i] = data_array2[i];
            }
            printf(" switch buf 2 %i\r\n ", switch_data);
        }

    }
}

/* Completion interrupt for ADC14 MEM0 */
void DMA_INT1_IRQHandler(void)
{
    MAP_DMA_clearInterruptFlag(7);
    /* Switch between primary and alternate bufferes with DMA's PingPong mode */
    if (DMA_getChannelAttribute(7) & UDMA_ATTR_ALTSELECT)
    {
        DMA_setChannelControl(UDMA_PRI_SELECT | DMA_CH7_ADC12C,
            UDMA_SIZE_16 | UDMA_SRC_INC_NONE | UDMA_DST_INC_16 | UDMA_ARB_1);
        DMA_setChannelTransfer(UDMA_PRI_SELECT | DMA_CH7_ADC12C,
            UDMA_MODE_PINGPONG, (void*) (ADC14_BASE + OFS_ADC14MEM0),
            data_array1, SAMPLE_LENGTH);
        switch_data = 1;
    }
    else
    {
        DMA_setChannelControl(UDMA_ALT_SELECT | DMA_CH7_ADC12C,
            UDMA_SIZE_16 | UDMA_SRC_INC_NONE | UDMA_DST_INC_16 | UDMA_ARB_1);
        DMA_setChannelTransfer(UDMA_ALT_SELECT | DMA_CH7_ADC12C,
            UDMA_MODE_PINGPONG, (void*) (ADC14_BASE + OFS_ADC14MEM0),
            data_array2, SAMPLE_LENGTH);
        switch_data = 0;
    }
}
---------------------------------------------------------------------------------

Jack

  • Jack,

    It seems that you might be running into a known errata using the DMA interrupts on the MSP432. Please look through the MSP432P401R Device Erratasheet, linked below, and search for DMA12. Apply the workaround and let me know if this solves your issue!

    www.ti.com/.../slaz610c.pdf

    Best regards,
    Michael Arriete
  • Thank you for your prompt response, however, i had already reviewed the errata sheet, specifically the DMA12 and specifically Timothy Logan's response in these forums, hence the arrangement referenced near the comment:
    /* FROM TIM-TI, We need to enable interrupts after enabling the DMA channel to ensure that we don't get stuck in a "deadlock" situation */
    yet the DMA only functions for the first ping-pong, but not beyond that.
    Jack
  • Jack,

    I don't believe that statement from Tim's thread is what DMA12 is referring to. The issue you will see without the DMA12 workaround is what you are experiencing.. An initial interrupt trigger but then nothing beyond that point. I've linked a different thread below that is probably the exact same issue you are experiencing. Go through the code provided and compare to see where the issue may lie. The fixes are also provided within the messages.

    e2e.ti.com/.../485002

    Good luck!
    Michael Arriete
  • Michael, I am aware of that post, having found it a few days ago. I attempted to implement those suggestions/fixes earlier this week, and again just now, with the same lack of success. - Jack
  • Jack,

    I understand that adding the workaround may not have fixed the immediate problem you are having with the DMA interrupts but I suggest that you leave those workarounds within your code, as this is a known error within the silicon and is required for correct operation. Without it, the interrupt function will definitely not work and we will be no closer to solving the issue.

    I am still looking into what else could be causing the problem and will get back to you as soon as I can.

    Best regards,
    Michael Arriete
  • Hi Michael,
    The problem appears to be caused by the debugger, rather than any coding errors.
    I went back to square one, and started the project from scratch, using the original "MSP-EXP432P401R + Educational Boosterpack MkII - Microphone FFT" example, re-working the display to use a K350QVG-S1 LCD instead of EDUMKII board. See the code below.
    The example works flawlessly, with the DMA ping-pong mode reading the ADC and updating the FFT spectrum display as expected.
    However, as soon as i attempt to debug by adding any watch expressions, the interrupt sequence is disturbed, the ping-pong halts, and will not restart. I don't know why, or how to avoid this other than not using any debug options during execution.
    thanks for the help so far - Jack
    ------------------------------------------
    /* --COPYRIGHT--,BSD
    * Copyright (c) 2015, Texas Instruments Incorporated
    * --/COPYRIGHT--*/
    //****************************************************************************
    //
    // ScopeFFTmain.c - adapted from:
    // MSP-EXP432P401R + Educational Boosterpack MkII - Microphone FFT
    //
    // CMSIS DSP Software Library is used to perform 512-point FFT on
    // the audio samples collected with MSP432's ADC14 from the Education
    // Boosterpack's onboard microhpone. Code modified to display the resulting
    // frequency bin data on a K350QVG-S1 LCD instead of EDUMKII board.
    // Note: LcdDriver lib must be replaced with lib from:
    // BOOSTXL-K350QVG-S1_GrlibExample_MSP432P401R
    //
    // MSP432p401rpz
    // ----------------- 3.3v
    // /|\| | /
    // | | | \ 1u cap
    // --|RST (4.3 A10)|<--->/---||---<
    // | | \
    // | | /25kohm pot
    // gnd
    //****************************************************************************

    #include "msp.h"
    #include <driverlib.h>
    #include <grlib.h>
    #include "LcdDriver/kitronix320x240x16_ssd2119_spi.h"
    #include <stdio.h>
    #include <arm_math.h>
    #include "arm_const_structs.h"

    #define SAMPLE_LENGTH 512

    /* ------------------------------------------------------------------
    * Global variables for FFT Bin Example
    * ------------------------------------------------------------------- */
    uint32_t fftSize = SAMPLE_LENGTH;
    uint32_t ifftFlag = 0;
    uint32_t doBitReverse = 1;
    volatile arm_status status;

    /* Graphic library context */
    Graphics_Context g_sContext;

    #define SMCLK_FREQUENCY 48000000
    #define SAMPLE_FREQUENCY 8000


    /* DMA Control Table */
    #ifdef ewarm
    #pragma data_alignment=256
    #else
    #pragma DATA_ALIGN(controlTable, 256)
    #endif
    uint8_t controlTable[256];


    /* FFT data/processing buffers*/
    float hann[SAMPLE_LENGTH];
    int16_t data_array1[SAMPLE_LENGTH];
    int16_t data_array2[SAMPLE_LENGTH];
    int16_t data_input[SAMPLE_LENGTH*2];
    int16_t data_output[SAMPLE_LENGTH];

    volatile int switch_data = 0;

    uint32_t color = 0;

    /* Timer_A PWM Configuration Parameter */
    Timer_A_PWMConfig pwmConfig =
    {
    TIMER_A_CLOCKSOURCE_SMCLK,
    TIMER_A_CLOCKSOURCE_DIVIDER_1,
    (SMCLK_FREQUENCY/SAMPLE_FREQUENCY),
    TIMER_A_CAPTURECOMPARE_REGISTER_1,
    TIMER_A_OUTPUTMODE_SET_RESET,
    (SMCLK_FREQUENCY/SAMPLE_FREQUENCY)/2
    };
    uint32_t ix1,iy1,ix2,iy2, imx,imy;
    uint32_t ifreq, itime;


    void main(void)
    {
    /* Halting WDT and disabling master interrupts */
    MAP_WDT_A_holdTimer();
    MAP_Interrupt_disableMaster();

    /* Initializes Clock System */
    MAP_CS_setDCOCenteredFrequency(CS_DCO_FREQUENCY_48);
    MAP_CS_initClockSignal(CS_MCLK, CS_DCOCLK_SELECT, CS_CLOCK_DIVIDER_1 );
    MAP_CS_initClockSignal(CS_HSMCLK, CS_DCOCLK_SELECT, CS_CLOCK_DIVIDER_1 );
    MAP_CS_initClockSignal(CS_SMCLK, CS_DCOCLK_SELECT, CS_CLOCK_DIVIDER_1 );
    MAP_CS_initClockSignal(CS_ACLK, CS_REFOCLK_SELECT, CS_CLOCK_DIVIDER_1);

    /* Initializes display */
    // Crystalfontz128x128_Init();
    // LCD setup using Graphics Library API calls
    Kitronix320x240x16_SSD2119Init();


    /* Set default screen orientation */
    // Crystalfontz128x128_SetOrientation(LCD_ORIENTATION_UP);

    /* Initializes graphics context */
    // Graphics_initContext(&g_sContext, &g_sCrystalfontz128x128);
    Graphics_initContext(&g_sContext, &g_sKitronix320x240x16_SSD2119);

    /* Get Screen extents */
    imx = Graphics_getDisplayWidth(&g_sContext) - 1;
    imy = Graphics_getDisplayHeight(&g_sContext) -1;

    /* Draw Title, x-axis, gradation & labels */
    Graphics_setForegroundColor(&g_sContext, GRAPHICS_COLOR_BLACK);
    Graphics_setBackgroundColor(&g_sContext, GRAPHICS_COLOR_WHITE);
    GrContextFontSet(&g_sContext, &g_sFontFixed6x8);
    Graphics_clearDisplay(&g_sContext);

    Graphics_drawLineH(&g_sContext, 2, imx, imy-13);
    Graphics_drawLineV(&g_sContext, 2, imy-15, imy-11);
    Graphics_drawLineV(&g_sContext, 16*2.5, imy-15, imy-12);
    Graphics_drawLineV(&g_sContext, (32*2.5)-1, imy-15, imy-11);
    Graphics_drawLineV(&g_sContext, 32*2.5, imy-15, imy-11);
    Graphics_drawLineV(&g_sContext, 48*2.5, imy-15, imy-12);
    Graphics_drawLineV(&g_sContext, (64*2.5)-1, imy-15, imy-11);
    Graphics_drawLineV(&g_sContext, 64*2.5, imy-15, imy-11);
    Graphics_drawLineV(&g_sContext, 80*2.5, imy-15, imy-12);
    Graphics_drawLineV(&g_sContext, (96*2.5)-1, imy-15, imy-11);
    Graphics_drawLineV(&g_sContext, 96*2.5, imy-15, imy-11);
    Graphics_drawLineV(&g_sContext, 112*2.5, imy-15, imy-12);
    Graphics_drawLineV(&g_sContext, 127*2.5, imy-15, imy-11);


    Graphics_drawStringCentered(&g_sContext,
    "512-Point FFT",
    AUTO_STRING_LENGTH,
    64,
    6,
    OPAQUE_TEXT);
    Graphics_drawStringCentered(&g_sContext,
    "0",
    AUTO_STRING_LENGTH,
    2.5*4,
    imy-6,
    OPAQUE_TEXT);
    Graphics_drawStringCentered(&g_sContext,
    "1",
    AUTO_STRING_LENGTH,
    2.5*32,
    imy-6,
    OPAQUE_TEXT);
    Graphics_drawStringCentered(&g_sContext,
    "2",
    AUTO_STRING_LENGTH,
    2.5*64,
    imy-6,
    OPAQUE_TEXT);
    Graphics_drawStringCentered(&g_sContext,
    "3",
    AUTO_STRING_LENGTH,
    2.5*96,
    imy-6,
    OPAQUE_TEXT);
    Graphics_drawStringCentered(&g_sContext,
    "4",
    AUTO_STRING_LENGTH,
    2.5*125,
    imy-6,
    OPAQUE_TEXT);
    Graphics_setForegroundColor(&g_sContext, GRAPHICS_COLOR_RED);
    Graphics_drawStringCentered(&g_sContext,
    "kHz",
    AUTO_STRING_LENGTH,
    2.5*112,
    imy-6,
    OPAQUE_TEXT);

    // Initialize Hann Window
    int n;
    for (n = 0; n < SAMPLE_LENGTH; n++)
    {
    hann[n] = 0.5 - 0.5 * cosf((2*PI*n)/(SAMPLE_LENGTH-1));
    }

    /* Configuring Timer_A to have a period of approximately 500ms and
    * an initial duty cycle of 10% of that (3200 ticks) */
    Timer_A_generatePWM(TIMER_A0_BASE, &pwmConfig);

    /* Initializing ADC (MCLK/1/1) */
    ADC14_enableModule();
    ADC14_initModule(ADC_CLOCKSOURCE_MCLK, ADC_PREDIVIDER_1, ADC_DIVIDER_1, 0);

    ADC14_setSampleHoldTrigger(ADC_TRIGGER_SOURCE1, false);

    /* Configuring GPIOs (4.3 A10) */
    GPIO_setAsPeripheralModuleFunctionInputPin(GPIO_PORT_P4, GPIO_PIN3,
    GPIO_TERTIARY_MODULE_FUNCTION);

    /* Configuring ADC Memory */
    ADC14_configureSingleSampleMode(ADC_MEM0, true);
    ADC14_configureConversionMemory(ADC_MEM0, ADC_VREFPOS_AVCC_VREFNEG_VSS,
    ADC_INPUT_A10, false);

    /* Set ADC result format to signed binary */
    ADC14_setResultFormat(ADC_SIGNED_BINARY);

    /* Configuring DMA module */
    DMA_enableModule();
    DMA_setControlBase(controlTable);


    DMA_disableChannelAttribute(DMA_CH7_ADC12C,
    UDMA_ATTR_ALTSELECT | UDMA_ATTR_USEBURST |
    UDMA_ATTR_HIGH_PRIORITY |
    UDMA_ATTR_REQMASK);


    /* Setting Control Indexes. In this case we will set the source of the
    * DMA transfer to ADC14 Memory 0
    * and the destination to the
    * destination data array. */
    MAP_DMA_setChannelControl(UDMA_PRI_SELECT | DMA_CH7_ADC12C,
    UDMA_SIZE_16 | UDMA_SRC_INC_NONE | UDMA_DST_INC_16 | UDMA_ARB_1);
    MAP_DMA_setChannelTransfer(UDMA_PRI_SELECT | DMA_CH7_ADC12C,
    UDMA_MODE_PINGPONG, (void*) (ADC14_BASE + OFS_ADC14MEM0),
    data_array1, SAMPLE_LENGTH);

    MAP_DMA_setChannelControl(UDMA_ALT_SELECT | DMA_CH7_ADC12C,
    UDMA_SIZE_16 | UDMA_SRC_INC_NONE | UDMA_DST_INC_16 | UDMA_ARB_1);
    MAP_DMA_setChannelTransfer(UDMA_ALT_SELECT | DMA_CH7_ADC12C,
    UDMA_MODE_PINGPONG, (void*) (ADC14_BASE + OFS_ADC14MEM0),
    data_array2, SAMPLE_LENGTH);

    /* Assigning/Enabling Interrupts */
    MAP_DMA_assignInterrupt(DMA_INT1, 7);
    MAP_Interrupt_enableInterrupt(INT_DMA_INT1);
    MAP_DMA_assignChannel(DMA_CH7_ADC12C);
    MAP_DMA_clearInterruptFlag(7);
    MAP_Interrupt_enableMaster();

    /* Now that the DMA is primed and setup, enabling the channels. The ADC14
    * hardware should take over and transfer/receive all bytes */
    MAP_DMA_enableChannel(7);
    MAP_ADC14_enableConversion();

    while(1)
    {
    MAP_PCM_gotoLPM0();

    int i = 0;

    /* Computer real FFT using the completed data buffer */
    if (switch_data & 1)
    {
    for (i=0; i<512; i++)
    {
    data_array1[i] = (int16_t)(hann[i]*data_array1[i]);
    }
    arm_rfft_instance_q15 instance;
    status = arm_rfft_init_q15(&instance, fftSize, ifftFlag, doBitReverse);

    arm_rfft_q15(&instance, data_array1, data_input);
    }
    else
    {
    for (i=0; i<512; i++)
    {
    data_array2[i] = (int16_t)(hann[i]*data_array2[i]);
    }
    arm_rfft_instance_q15 instance;
    status = arm_rfft_init_q15(&instance, fftSize, ifftFlag, doBitReverse);

    arm_rfft_q15(&instance, data_array2, data_input);
    }

    /* Calculate magnitude of FFT complex output */
    for (i = 0; i < 1024; i+=2)
    {
    data_output[i/2] = (int32_t)(sqrtf((data_input[i] * data_input[i]) + (data_input[i+1] * data_input[i+1])));
    }

    q15_t maxValue;
    uint32_t maxIndex = 0;

    arm_max_q15(data_output, fftSize, &maxValue, &maxIndex);

    if (maxIndex <= 64)
    color = ((uint32_t)(0xFF * (maxIndex / 64.0f)) << 8) + 0xFF;
    else if (maxIndex <= 128)
    color = (0xFF - (uint32_t)(0xFF * ((maxIndex-64) / 64.0f))) + 0xFF00;
    else if (maxIndex <= 192)
    color = ((uint32_t)(0xFF * ((maxIndex-128) / 64.0f)) << 16) + 0xFF00;
    else
    color = ((0xFF - (uint32_t)(0xFF * ((maxIndex-192) / 64.0f))) << 8) + 0xFF0000;

    /* Draw frequency bin graph */
    for (i = 0; i < 256; i+=1)
    {
    int x = min(200, (int)((data_output[i]+data_output[i+1])/8));
    // uint32_t ifreq = 1 + (i/2)*2.5;
    ifreq = 1 + (i*1.25);
    Graphics_setForegroundColor(&g_sContext, GRAPHICS_COLOR_WHITE);
    /*
    Graphics_drawLineV(&g_sContext, i/2, 114-x, 14);
    Graphics_setForegroundColor(&g_sContext, color);
    Graphics_drawLineV(&g_sContext, i/2, 114, 114 - x); */

    Graphics_drawLineV(&g_sContext, ifreq, imy-13-x, 14);
    Graphics_setForegroundColor(&g_sContext, color);
    Graphics_drawLineV(&g_sContext, ifreq, imy-13, imy-13 - x);

    }
    }
    }


    /* Completion interrupt for ADC14 MEM0 */
    void DMA_INT1_IRQHandler(void)
    {
    /* Switch between primary and alternate bufferes with DMA's PingPong mode */
    if (DMA_getChannelAttribute(7) & UDMA_ATTR_ALTSELECT)
    {
    DMA_setChannelControl(UDMA_PRI_SELECT | DMA_CH7_ADC12C,
    UDMA_SIZE_16 | UDMA_SRC_INC_NONE | UDMA_DST_INC_16 | UDMA_ARB_1);
    DMA_setChannelTransfer(UDMA_PRI_SELECT | DMA_CH7_ADC12C,
    UDMA_MODE_PINGPONG, (void*) (ADC14_BASE + OFS_ADC14MEM0),
    data_array1, SAMPLE_LENGTH);
    switch_data = 1;
    }
    else
    {
    DMA_setChannelControl(UDMA_ALT_SELECT | DMA_CH7_ADC12C,
    UDMA_SIZE_16 | UDMA_SRC_INC_NONE | UDMA_DST_INC_16 | UDMA_ARB_1);
    DMA_setChannelTransfer(UDMA_ALT_SELECT | DMA_CH7_ADC12C,
    UDMA_MODE_PINGPONG, (void*) (ADC14_BASE + OFS_ADC14MEM0),
    data_array2, SAMPLE_LENGTH);
    switch_data = 0;
    }
    }
    ------------------------------------------------------------
  • Jack,

    There are two things you could try to do:

    1) Instead of halting the system using breakpoints, try changing the break point properties to Update View for Expressions. Then when running the system with the debugger, enable the Continuous Refresh in the Expressions window. This will update the expressions window without halting the system and may work as an alternative.

    2) There is an option in CCS that allows you to disable interrupts when halted with the debugger under Project Properties -> Debug. Under Disable Interrupts make sure "When assembly stepping" and "When source stepping" are checked.

    My assumption is that when using the debugger you are halting the system to see the expressions update, but when doing so you are missing a triggering of the DMA interrupt. When this happens, you cannot clear the interrupt and allow for another trigger to occur, effectively freezing the DMA.

    - Michael Arriete
  • Michael - thank you for the suggestions. I looked into 2) and it turns out that the checkboxes for "When assembly stepping" and "When source stepping" were already checked, so it seems the ping-pong interrupts are more fragile than normal interrupts.

    for suggestion 1) i tried setting a hardware breakpoint and editing the properties to update view, and i also tried update all windows, but neither attempt was successful. Ping-pong always halts if a hardware breakpoint is set.

    without breakpoints, I was able to add the array as a watch expression, then graphed it, and turned on continuous refresh. This did display updated values in the graph window with each pingpong switch. however the watch expression window remains static (i could not find how to set to continuous refresh?

    at least now i have something i can use for debugging.
    Jack
  • Jack,

    I apologize for the inconvenience this issue may have caused. I'm glad you were able to find a workaround for the time being. I'll see if there's anything else that I can dig up on our side as to why this is happening.

    Best regards,
    Michael Arriete
  • Thanks to this thread I have gotten my ADC to work with the DMA. 

    To get it running, I had to implement the workaround for DMA12 and change the breakpoint properties so the program isn't halted. 

    I want to contribute to this thread with my working code so future readers can see how such a fix can look like.

    Again, thank you so much for saving me lots of effort and frustration,

    ~ Andy

     * Author: Andrew Delay
     ******************************************************************************/
    /* DriverLib Includes */
    #include "driverlib.h"
    
    /* Standard Includes */
    #include <stdint.h>
    #include <string.h>
    #include <stdbool.h>
    
    /* FFT data/processing buffers*/
    #define SAMPLE_LENGTH 512
    int16_t data_array0[SAMPLE_LENGTH];
    int16_t data_array1[SAMPLE_LENGTH];
    int16_t data_array2[SAMPLE_LENGTH];
    int16_t value;
    
    /* DMA Control Table */
    #ifdef ewarm
    #pragma data_alignment=1024
    #else
    #pragma DATA_ALIGN(controlTable, 1024)
    #endif
    uint8_t controlTable[1024];
    
    uint16_t * destination;
    uint16_t * ADC_result = (uint16_t *)0x40012098; //ADCMEM0 register
    
    int main(void)
    {
        /* Halting the Watchdog, disable interrupts */
        MAP_WDT_A_holdTimer();
        MAP_Interrupt_disableMaster();
    
    
        /* Setting Flash wait state */
        MAP_FlashCtl_setWaitState(FLASH_BANK0, 2);
        MAP_FlashCtl_setWaitState(FLASH_BANK1, 2);
        
        /* Setting DCO to 48MHz  */
        MAP_PCM_setPowerState(PCM_AM_LDO_VCORE1);
        MAP_CS_setDCOCenteredFrequency(CS_DCO_FREQUENCY_48);
    
    /*  ADC   ***********************************************************/
    
        /* Initializing ADC (MCLK/1/1) */
        MAP_ADC14_enableModule();
        MAP_ADC14_initModule(ADC_CLOCKSOURCE_MCLK, ADC_PREDIVIDER_1, ADC_DIVIDER_1,
                0);
        MAP_ADC14_setResolution(ADC_14BIT);
    
        /* Configuring GPIOs (5.5 A0) */
        MAP_GPIO_setAsPeripheralModuleFunctionInputPin(GPIO_PORT_P5, GPIO_PIN5,
        GPIO_TERTIARY_MODULE_FUNCTION);
    
        /* Configuring ADC Memory */
        MAP_ADC14_configureSingleSampleMode(ADC_MEM0, true);
        MAP_ADC14_configureConversionMemory(ADC_MEM0, ADC_VREFPOS_AVCC_VREFNEG_VSS,
        ADC_INPUT_A0, false);
    
        /* Configuring Sample Timer */
        MAP_ADC14_enableSampleTimer(ADC_AUTOMATIC_ITERATION);
    
    /*  DMA   ***********************************************************/
    
        /* Configuring DMA module */
        MAP_DMA_enableModule();
        MAP_DMA_setControlBase(controlTable);
    
        /* Disabling channel attributes */
        MAP_DMA_disableChannelAttribute(DMA_CH7_ADC14,
    									 UDMA_ATTR_ALTSELECT | UDMA_ATTR_USEBURST |
    									 UDMA_ATTR_HIGH_PRIORITY |
    									 UDMA_ATTR_REQMASK);
    
        /* Setting Control Indexes */
        MAP_DMA_setChannelControl(UDMA_PRI_SELECT | DMA_CH7_ADC14,
    		   UDMA_SIZE_16 | UDMA_SRC_INC_NONE | UDMA_DST_INC_16 | UDMA_ARB_1);
        MAP_DMA_setChannelTransfer(UDMA_PRI_SELECT | DMA_CH7_ADC14,
        			UDMA_MODE_PINGPONG, (void *)ADC_result,
    			data_array1, SAMPLE_LENGTH);
    
        MAP_DMA_setChannelControl(UDMA_ALT_SELECT | DMA_CH7_ADC14,
        		   UDMA_SIZE_16 | UDMA_SRC_INC_NONE | UDMA_DST_INC_16 | UDMA_ARB_1);
    	MAP_DMA_setChannelTransfer(UDMA_ALT_SELECT | DMA_CH7_ADC14,
    			UDMA_MODE_PINGPONG, (void *)ADC_result,
    			data_array2, SAMPLE_LENGTH);
    
    	/* Assigning/Enabling Interrupts */
    	MAP_DMA_assignInterrupt(DMA_INT1, 7);
    	MAP_Interrupt_enableInterrupt(INT_DMA_INT1);
    	//MAP_DMA_assignChannel(DMA_CH7_ADC14); moved further down - DMA12 error
    	MAP_DMA_clearInterruptFlag(7);
    
    	/* Making it so that we go back to sleep when interrupts end */
    	 MAP_Interrupt_enableSleepOnIsrExit();
    
    	/* DMA12 error workaround: Set DMA trigger source as last step in DMA init routine */
    	MAP_DMA_assignChannel(DMA_CH7_ADC14);
    
    	/* Now that the DMA is primed and setup, enabling the channels. The ADC14
    	 * hardware should take over and transfer/receive all bytes */
    	MAP_DMA_enableChannel(7);
    
    	/* Enabling/Toggling Conversion */
    	MAP_ADC14_enableConversion();
    	MAP_ADC14_toggleConversionTrigger();
    
    	MAP_Interrupt_enableMaster();
    
        while (1)
        {
            MAP_PCM_gotoLPM0();
        		__no_operation();
        }
        
    }
    
    
    /* Completion interrupt for ADC14 MEM0 */
    void DMA_INT1_IRQHandler(void)
    {
    	/* DMA12 error workaround */
    	MAP_ADC14_disableConversion();
    	MAP_ADC14_disableModule();
    
    	__no_operation(); //Put breakpoint here
    	/* WARNING: Do not use regular breakpoint, change breakpoint property to 'update view' for 'expressions'
    	 * In the expressions view, select 'continous refresh'
    	 * Normal breakpoint in this code will freeze DMA unless changing CCS Debug properties */
    
        MAP_DMA_clearInterruptFlag(7);
        /* Switch between primary and alternate bufferes with DMA's PingPong mode */
        if (MAP_DMA_getChannelAttribute(7) & UDMA_ATTR_ALTSELECT)
        {
            MAP_DMA_setChannelControl(UDMA_PRI_SELECT | DMA_CH7_ADC14,
                UDMA_SIZE_16 | UDMA_SRC_INC_NONE | UDMA_DST_INC_16 | UDMA_ARB_1);
            MAP_DMA_setChannelTransfer(UDMA_PRI_SELECT | DMA_CH7_ADC14,
                UDMA_MODE_PINGPONG, (void*)ADC_result,
                data_array1, SAMPLE_LENGTH);
        }
        else
        {
            MAP_DMA_setChannelControl(UDMA_ALT_SELECT | DMA_CH7_ADC14,
                UDMA_SIZE_16 | UDMA_SRC_INC_NONE | UDMA_DST_INC_16 | UDMA_ARB_1);
            MAP_DMA_setChannelTransfer(UDMA_ALT_SELECT | DMA_CH7_ADC14,
                UDMA_MODE_PINGPONG, (void*)ADC_result,
                data_array2, SAMPLE_LENGTH);
        }
    
        /* DMA12 error workaround */
        MAP_ADC14_enableModule();
        MAP_ADC14_enableConversion();
        MAP_ADC14_toggleConversionTrigger();
    }

**Attention** This is a public forum