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.

Trouble getting ADC data via DMA on CC3200

Other Parts Discussed in Thread: CC3200, ENERGIA

I am having a problem of getting ADC data using DMA pingpong mode on CC3200.

Looks like there is a non-stop DMA interrupt. 

Did anyone try getting ADC data using DMA mode?

This is how I setup the ADC and the DMA interrupt handler.

Appreciated if anyone can tell me what I missed. 

 

#define DMA_ITEM_SIZE 800

unsigned long g_ulDMABuf0[DMA_ITEM_SIZE];
unsigned long g_ulDMABuf1[DMA_ITEM_SIZE];

int g_DMABufferIndex = 0;

void InitDMA(void)
{
g_DMABufferIndex = 0;
MAP_PinTypeADC(PIN_59, PIN_MODE_255);
ADCIntRegister(ADC_BASE, ADC_CH_2, DMAInterruptHandler);

ADCIntClear(ADC_BASE, ADC_CH_2, ADC_DMA_DONE);
ADCIntEnable(ADC_BASE, ADC_CH_2, ADC_DMA_DONE);
ADCChannelEnable(ADC_BASE, ADC_CH_2);
ADCDMAEnable(ADC_BASE, ADC_CH_2);

ADCChannelEnable(ADC_BASE, ADC_CH2_2);

ADCTimerConfig(ADC_BASE,2^17);
ADCTimerEnable(ADC_BASE);
ADCEnable(ADC_BASE);

SetupTransfer(UDMA_CH16_ADC_CH2 | UDMA_PRI_SELECT,
UDMA_MODE_PINGPONG,
DMA_ITEM_SIZE-1, UDMA_SIZE_32, UDMA_ARB_4,
(void *)(ADC_BASE + ADC_O_channel4FIFODATA),
UDMA_SRC_INC_NONE,
&g_ulDMABuf0,
UDMA_DST_INC_32);

SetupTransfer(UDMA_CH16_ADC_CH2 | UDMA_ALT_SELECT,
UDMA_MODE_PINGPONG,
DMA_ITEM_SIZE-1, UDMA_SIZE_32, UDMA_ARB_4,
(void *)(ADC_BASE + ADC_O_channel4FIFODATA),
UDMA_SRC_INC_NONE,
&g_ulDMABuf1,
UDMA_DST_INC_32);
}


void DMAInterruptHandler(void)
{
   unsigned long ulStatus;
   unsigned long ulMode;

   if ((g_DMABufferIndex & 1) == 0)
   {
     ulMode = MAP_uDMAChannelModeGet(UDMA_CH16_ADC_CH2 | UDMA_PRI_SELECT);
     if (ulMode == UDMA_MODE_STOP)
     {
        SetupTransfer(UDMA_CH16_ADC_CH2 | UDMA_PRI_SELECT,
                      UDMA_MODE_PINGPONG,
                      DMA_ITEM_SIZE-1, UDMA_SIZE_32, UDMA_ARB_4,
                      (void *)(ADC_BASE + ADC_O_channel4FIFODATA),
                      UDMA_SRC_INC_NONE,
                      &g_ulDMABuf0,
                      UDMA_DST_INC_32);

        g_DMABufferIndex = 1;
      }
   }
   else
   {
      ulMode = MAP_uDMAChannelModeGet(UDMA_CH16_ADC_CH2 | UDMA_ALT_SELECT);
      if (ulMode == UDMA_MODE_STOP)
      {
        SetupTransfer(UDMA_CH16_ADC_CH2 | UDMA_ALT_SELECT,
                      UDMA_MODE_PINGPONG,
                      DMA_ITEM_SIZE-1, UDMA_SIZE_32, UDMA_ARB_4,
                      (void *)(ADC_BASE + ADC_O_channel4FIFODATA),
                      UDMA_SRC_INC_NONE,
                      &g_ulDMABuf1,
                      UDMA_DST_INC_32);
        g_DMABufferIndex = 0;
      }
   }
   ADCIntClear(ADC_BASE, ADC_CH_2, ADC_DMA_DONE);
}

 

Thanks.

  • Hi Yau,

    At a high level i reviewed the initial setting, It seems OK. However i could not look at the settings in the interrupt routine.
    I suggest we approach this debug in a step by step manner.
    1. Just enable DMA without the PING_PONG mode, See if this wroks fine
    2. Now enable the ping-pong mode and setting up of both primary and alternate.

    Also note that there is a udma example for ping-pong mode, Use that to cross check if your settings are same as that. but for the channel no's the flow should be similar.

    Thanks and Regards,
    Siddaram
  • Hi, Siddaram,

    I have tried to use BASIC mode but I got the same results. Random data and unexpected DMA interrupts.

    As you can see, my logic is based on the udma example.

    I wonder if you have any example code that shows getting ADC data using DMA ping-pong mode.

    Thanks,

    YK 

  • Hi Yau,

    I have setup the ADC in ping pong mode using the code below and it works fine. Note that after you have collected the number of samples needed you should call ADCDMADisable so that you don't continuously get interrupts. Also note that i have removed the comments from code below just to make it compact.This code is based on adc example in SDK.
    main()
    {
    BoardInit();
    PinMuxConfig();
    InitTerm();
    DisplayBanner(APP_NAME);
    InitAdcDma();
    }

    unsigned long DmaDataDumpPing[640];
    unsigned long DmaDataDumpPong[640];
    void ADCIntHandler(void)
    {
    unsigned long ulChannelStructIndex, ulMode, ulControl;
    tDMAControlTable *pControlTable;
    unsigned long *pDataDumpBuff = NULL;
    unsigned short Status;
    unsigned short uiIndex;

    Status = ADCIntStatus(ADC_BASE, ADC_CH_2);
    ADCIntClear(ADC_BASE, ADC_CH_2,Status|ADC_DMA_DONE);
    ulMode = MAP_uDMAChannelModeGet(UDMA_CH16_ADC_CH2 | UDMA_PRI_SELECT);
    if(ulMode == UDMA_MODE_STOP)
    {
    ulChannelStructIndex = UDMA_CH16_ADC_CH2 | UDMA_PRI_SELECT;
    pDataDumpBuff = &(DmaDataDumpPing[0]);
    }
    else
    {
    ulMode = MAP_uDMAChannelModeGet(UDMA_CH16_ADC_CH2 | UDMA_ALT_SELECT);
    if(ulMode == UDMA_MODE_STOP)
    {
    ulChannelStructIndex = UDMA_CH16_ADC_CH2 | UDMA_ALT_SELECT;
    pDataDumpBuff = &(DmaDataDumpPong[0]);
    }
    }

    if(pDataDumpBuff != NULL)
    {
    ulChannelStructIndex &= 0x3f;
    pControlTable = uDMAControlBaseGet();
    ulControl = (pControlTable[ulChannelStructIndex].ulControl &
    ~(UDMA_CHCTL_XFERSIZE_M | UDMA_CHCTL_XFERMODE_M));
    ulControl |= UDMA_MODE_PINGPONG | ((640 - 1) << 4);
    uDMAChannelControlSet(ulChannelStructIndex,ulControl);
    #if 1
    UART_PRINT("\n\rVoltage is %f\n\r",(((float)((pDataDumpBuff[0] >> 2 ) & 0x0FFF))*1.4)/4096);
    #endif
    }
    }

    void InitAdcDma( void )
    {
    unsigned short Status;

    UDMAInit();
    PinTypeADC(PIN_59,0xFF);
    MAP_uDMAChannelAssign(UDMA_CH16_ADC_CH2);
    UDMASetupTransfer(UDMA_CH16_ADC_CH2|UDMA_PRI_SELECT, UDMA_MODE_PINGPONG,
    640,
    UDMA_SIZE_32, UDMA_ARB_1,
    (void *)(0x4402E874+ADC_CH_2), UDMA_SRC_INC_NONE,
    (void *)&(DmaDataDumpPing[0]), UDMA_DST_INC_32);

    UDMASetupTransfer(UDMA_CH16_ADC_CH2|UDMA_ALT_SELECT, UDMA_MODE_PINGPONG,
    640,
    UDMA_SIZE_32, UDMA_ARB_1,
    (void *)(0x4402E874+ADC_CH_2), UDMA_SRC_INC_NONE,
    (void *)&(DmaDataDumpPong[0]), UDMA_DST_INC_32);

    ADCDMAEnable(ADC_BASE, ADC_CH_2);
    ADCIntRegister(ADC_BASE, ADC_CH_2,ADCIntHandler);
    Status = ADCIntStatus(ADC_BASE, ADC_CH_2);
    ADCIntClear(ADC_BASE, ADC_CH_2,Status|ADC_DMA_DONE);
    ADCIntEnable(ADC_BASE, ADC_CH_2,ADC_DMA_DONE);
    ADCChannelEnable(ADC_BASE, ADC_CH_2);
    ADCEnable(ADC_BASE);
    while(1);
    }

  • Siddaram, I have the DMA running. Thanks.

  • Hi Yau,

    Thanks for confirming that ADC with DMA PING-PONG mode is working fine.
    I am closing this thread, if the issue still exists please open a new thread and add a link to this one for reference

    Thanks and Regards,
    Siddaram
  • Hi

    How I can run this code in Energia MT ?

  • Hi Siddaram,

    I am trying to compile your code. Could you share us with the libraries and defines you used in this code?

    Thanks.
    Yin
  • Yin,

    This code is based on the adc example from the CC3200 SDK, which includes the libraries that you need to compile this code.

    Regards,
    Seong
  • Hi Seong,

    Thanks. I already made it run.