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.

RTOS/CC3220SF-LAUNCHXL: ADC with DMA transfer

Part Number: CC3220SF-LAUNCHXL
Other Parts Discussed in Thread: CC3220SF

Tool/software: TI-RTOS

Hello. I am trying to setup a configuration where the dma transfers 64 samples in a buffer. As it is my first time working with a RTOS and TI Products, i have little experience programming the device. Below is the main thread. Please note that i have used driverlib and TI-drivers together where possible, and while debugging , the buffer doesn't fill with any samples, although the ADC is working(i have tested that)

 *  ======== empty.c ========
 */

/* For usleep() */
#include <unistd.h>
#include <stdint.h>
#include <stddef.h>

#include <ti/devices/cc32xx/inc/hw_memmap.h>
#include <ti/devices/cc32xx/inc/hw_ocp_shared.h>
#include <ti/devices/cc32xx/inc/hw_ints.h>
#include <ti/devices/cc32xx/inc/hw_types.h>
#include <ti/devices/cc32xx/inc/hw_adc.h>

/* Driverlib Header Files */
#include <ti/devices/cc32xx/driverlib/rom.h>
#include <ti/devices/cc32xx/driverlib/rom_map.h>
#include <ti/devices/cc32xx/driverlib/udma.h>
#include <ti/devices/cc32xx/driverlib/adc.h>



/* Driver Header files */
#include <ti/drivers/GPIO.h>
#include <ti/drivers/dma/UDMACC32XX.h>
#include <ti/drivers/ADC.h>
#include <ti/drivers/adc/ADCCC32XX.h>
// #include <ti/drivers/I2C.h>
// #include <ti/drivers/SDSPI.h>
// #include <ti/drivers/SPI.h>
// #include <ti/drivers/UART.h>
// #include <ti/drivers/Watchdog.h>



/* Board Header file */
#include "Board.h"

/*
 *  ======== mainThread ========
 */
void *mainThread(void *arg0)
{
    unsigned int buffer[65]={1024};
    UDMACC32XX_Handle udma;
    ADC_Handle adcch2;
    ADC_Params param;
    ADC_Params_init(&param);

    /* set up the dma channel transfer */
    UDMACC32XX_init();
    udma=UDMACC32XX_open();
    uDMAChannelAssign(UDMA_CH16_ADC_CH2);
    uDMAChannelControlSet(UDMA_CH16_ADC_CH2|UDMA_PRI_SELECT, UDMA_SIZE_32|UDMA_SRC_INC_NONE|UDMA_DST_INC_32|UDMA_ARB_1);
    uDMAChannelAttributeEnable(UDMA_CH16_ADC_CH2,UDMA_ATTR_USEBURST);
    uDMAChannelTransferSet(UDMA_CH16_ADC_CH2|UDMA_PRI_SELECT,UDMA_MODE_BASIC,(void*)(ADC_BASE+ADC_O_channel2FIFODATA),(void*)0x20000678,63);
    uDMAChannelAttributeEnable(UDMA_CH16_ADC_CH2,UDMA_ATTR_REQMASK);
    uDMAChannelEnable(UDMA_CH16_ADC_CH2);

    /* set up the ADC channel */

    ADC_init();
    adcch2=ADC_open(CC3220SF_LAUNCHXL_ADC0,&param);
    ADCChannelDisable(ADC_BASE, ADCCC32XX_PIN_59_CH_2);
    ADCDMAEnable(ADC_BASE, ADCCC32XX_PIN_59_CH_2);
    ADCChannelEnable(ADC_BASE, ADCCC32XX_PIN_59_CH_2);
    while(1){
    }



}

Please point me in some direction if possible and thank you in anticipation.

  • Problem resolved. I seemed that the problem was some garbage values in the control register. pushing the reset button before debugging solved the issue.
  • Glad you got it figured out!
  • First of all, your piece of code really helped me. However, I still don't get any values transferred into my buffer... I have the same hardware setup. I connected the ADC channel to 3.3 volts to get some values into RAM. When I use the ADC in the following way:

    ADC_convert(adcch2, &sample);

    I get a value of about 3821 saved in the variable "sample", which at least shows that my ADC is working properly.

    Pretty much all I changed was line 56 from your code:

    uDMAChannelTransferSet(UDMA_CH16_ADC_CH2|UDMA_PRI_SELECT,UDMA_MODE_BASIC,(void*)(ADC_BASE+ADC_O_channel2FIFODATA),(void*)0x20000678,63);

    to this:

    unsigned int uiADCDMABuffer[65]={1024};
    unsigned int* puiADCDMABuffer = uiADCDMABuffer;
    
    ...
    uDMAChannelTransferSet(UDMA_CH16_ADC_CH2|UDMA_PRI_SELECT,UDMA_MODE_BASIC,(void*)(ADC_BASE+ADC_O_channel2FIFODATA),(void *) puiADCDMABuffer,63);
    ...

    I don't think this code change is the problem. I think the problem is that the ADC conversion is not being triggered. You just left a while(1) loop at the end. My intention is to trigger the ADC once and then to receive 63 ADC values into my buffer "uiADCDMABuffer". I thought this ADC triggering is accomplished by:

    uDMAChannelEnable(UDMA_CH16_ADC_CH2); /* launch new burst DMA transaction */

    Is that wrong?

    Furthermore, I'm confused by:

    uDMAChannelAttributeEnable(UDMA_CH16_ADC_CH2,UDMA_ATTR_REQMASK);

    I thought I am not allowed to mask the hardware request from the ADC since the DMA needs this request to be triggered, in order to know "Hey, a new ADC value is ready to be read". Am I wrong?

    Another thing I am wondering about is why you set arbitration size to UDMA_ARB_1, instead of something like UDMA_ARB_64. In the datasheet you can find "The arbitration size is the number of items transferred in a burst". Does your code then make 63 bursts of one integer to fill the array? My intention is to make 1 burst with 64 values, or 63 values, that's not the matter.

    Thanks to anyone answering my questions. It seems like many developers are having trouble with using the DMA in combination with the ADC on the CC3220SF.

    Cheers,

    the BitBooger

  • Alright guys, I now got this little puppy up and running.

    I want to share some important insights that may help others who are trying to get the DMA with the ADC running on the CC3220SF.

    First of all here's the code:

    Header File:

    #include "Board.h"
    
    /* Hardware headers */
    #include <ti/devices/cc32xx/inc/hw_memmap.h>
    #include <ti/devices/cc32xx/inc/hw_ocp_shared.h>
    #include <ti/devices/cc32xx/inc/hw_ints.h>
    #include <ti/devices/cc32xx/inc/hw_types.h>
    #include <ti/devices/cc32xx/inc/hw_adc.h>
    
    /* Driverlib Header Files */
    #include <ti/devices/cc32xx/driverlib/rom.h>
    #include <ti/devices/cc32xx/driverlib/rom_map.h>
    #include <ti/devices/cc32xx/driverlib/udma.h>
    #include <ti/devices/cc32xx/driverlib/adc.h>
    #include <ti/devices/cc32xx/driverlib/pin.h>
    
    
    /* Driver Header files */
    #include <ti/drivers/GPIO.h>
    #include <ti/drivers/dma/UDMACC32XX.h>
    #include <ti/drivers/ADC.h>
    #include <ti/drivers/adc/ADCCC32XX.h>
    
    #define ADC_DMA_BUFFERSIZE 65
    
    void vMyOwnDMAInit(void);
    void vMyOwnADCInit(void);
    void vMyOwnDmaAdcInit(void);
    void ADCIntHandler(void);

    Source File:

    #include "adc_read.h"
    
    /*
     * Initialize ADC_CH2 - ADC Pin 59 - GPO04
     */
    
    uint16_t   sample;
    UDMACC32XX_Handle udma;
    ADC_Handle adc_ch2;
    
    unsigned short uShADCDMABuffer[ADC_DMA_BUFFERSIZE];
    
    void vMyOwnDmaAdcInit(){
        vMyOwnDMAInit();
        vMyOwnADCInit();
    
        while(1);
    }
    
    void vMyOwnDMAInit(void)
    {
        UDMACC32XX_init();
        udma = UDMACC32XX_open();
        uDMAChannelAssign(UDMA_CH16_ADC_CH2);
        uDMAChannelControlSet(UDMA_CH16_ADC_CH2|UDMA_PRI_SELECT, UDMA_SIZE_16|UDMA_SRC_INC_NONE|UDMA_DST_INC_16|UDMA_ARB_1);
        uDMAChannelTransferSet(UDMA_CH16_ADC_CH2|UDMA_PRI_SELECT,UDMA_MODE_BASIC,(void*)(ADC_BASE+ADC_O_channel4FIFODATA),(void *) uShADCDMABuffer, ADC_DMA_BUFFERSIZE);
        uDMAChannelEnable(UDMA_CH16_ADC_CH2);
    }
    
    void vMyOwnADCInit(void)
    {
        ADC_Params adcParams;
        ADC_Params_init(&adcParams);
        adc_ch2=ADC_open(CC3220SF_LAUNCHXL_ADC0,&adcParams);
    
        ADCDMAEnable(ADC_BASE, ADC_CH_2);
        ADCIntRegister(ADC_BASE, ADC_CH_2,ADCIntHandler);
        ADCIntClear(ADC_BASE, ADC_CH_2, ADC_DMA_DONE);
        ADCIntEnable(ADC_BASE, ADC_CH_2,ADC_DMA_DONE);
        ADCChannelEnable(ADC_BASE, ADC_CH_2);
        ADCEnable(ADC_BASE);
    }
    
    void ADCIntHandler(void)
    {
      // Turn off ADC and clear IRQ-Bit
      ADCDisable(ADC_BASE);
      ADCIntClear(ADC_BASE, ADC_CH_2, ADC_DMA_DONE);
    
      // clear leading 4 bits from 16-bit uShADCDMABuffer[i]
      // 12-bit ADC always puts 0x3XXX into uShADCDMABuffer[i],
      // where XXX represents the sampled 12-bit value
      unsigned int i;
      for (i=0; i<ADC_DMA_BUFFERSIZE; i++)
      {
          uShADCDMABuffer[i] &= 0x0FFF;
      }
    
      // Run processing algo
      // ...
      // Done
    
      // Retrigger next ADC-DMA-Sampling Routine
      uDMAChannelTransferSet(UDMA_CH16_ADC_CH2 | UDMA_PRI_SELECT,UDMA_MODE_BASIC, (void*)(ADC_BASE+ADC_O_channel4FIFODATA), (void *) uShADCDMABuffer, ADC_DMA_BUFFERSIZE);
      uDMAChannelEnable(UDMA_CH16_ADC_CH2);
      ADCEnable(ADC_BASE);
    }
    

    Now what really cracked me up, was the fact that the source address is "(void*)(ADC_BASE+ADC_O_channel4FIFODATA)". ADC_0_channel4FIFODATA?! I thought we were using ADC_0_Channel 2, or wait, there was also something with Channel 16, wasn't it? That's right!

    So to get it straight:

    - The CC3220SF has a total of 8 ADC channels. From these 8 channels there are only 4 channels that can actually be used as external ADC input channels. The other 4 are used by the network processor and Wi-Fi.

    - So there are 8 ADC channels on the hardware platform and they are called CH0, CH1, ..., CH7.

    - From these 8 channels, we can use the following four: CH0, CH2, CH4 and CH6 (!!) (Have a look at the Reference Manual, Ch13.3 ADC Register Mapping)

    - In our case ADC_CH2 = CH4

    - So what is up with Channel 16? Well, that's the channel to which the uDMA needs to be connected to, in order to talk to the ADC 4 = CH4 = ADC_CH2.

    Now, that was confusing! I guess that's enough for today!

    Cheers,

    the BitBooger