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.

CC3220SF-LAUNCHXL: Wi-Fi forum

Part Number: CC3220SF-LAUNCHXL


Hi,

I have been trying to implement a DMA transfer of ADC readings by the reading the FIFO into the RAM buffer.

I haven't had any success with this. Could you please help me.

Here's the code which I am trying to use for the purpose.

#define ADC_BUFFER_SIZE 128
#define MY_BUFF_SIZE 64

static uint16_t adc_samples [ADC_BUFFER_SIZE] = {};
static uint16_t my_buff [MY_BUFF_SIZE] = {};

void adc_dma_init(void);
void adc_start_dma_sampling(void);
void adc_dma_reenable(void);
void ADCIntHandler(void);


void main(void)
{
	adc_dma_init();
    adc_start_dma_sampling();

    while(1)
	{
		// the flag is set in the interrupt handler
		if (g_AdcDmaTfrDone)
		{
			g_AdcDmaTfrDone = false;
			memcpy(my_buff, adc_samples, MY_BUFF_SIZE);
			sleep(2);
			
			// trigger the next set of adc data transfer
			adc_dma_reenable();
		}
	}
    return;
}


void adc_dma_init(void)
{
  UDMACC32XX_init();
  udma = UDMACC32XX_open();
  uDMAChannelAssign(UDMA_CH15_ADC_CH1);
  uDMAChannelControlSet(
		UDMA_CH15_ADC_CH1|UDMA_PRI_SELECT, 
		UDMA_SIZE_16|UDMA_SRC_INC_NONE|UDMA_DST_INC_16|UDMA_ARB_1);
  uDMAChannelTransferSet(
		UDMA_CH15_ADC_CH1|UDMA_PRI_SELECT, 
		UDMA_MODE_BASIC, 
		(void*)(ADC_BASE+ADC_O_channel2FIFODATA), 
		adc_samples, 
		ADC_BUFFER_SIZE);
  uDMAChannelEnable(UDMA_CH15_ADC_CH1);
  uDMAEnable();


  // Initialize the ADC
  ADC_init();
  ADC_Params adc_params;
  ADC_Params_init(&adc_params);
  adc_handle = ADC_open(CONFIG_ADC_0, &adc_params);
}


void adc_start_dma_sampling(void)
{
    ADCChannelDisable(ADC_BASE, ADC_CH_1);
    ADCDMAEnable(ADC_BASE, ADC_CH_1);
    ADCIntRegister(ADC_BASE, ADC_CH_1, ADCIntHandler);
    ADCIntClear(ADC_BASE, ADC_CH_1, ADC_DMA_DONE);
    ADCIntEnable(ADC_BASE, ADC_CH_1, ADC_DMA_DONE);
    ADCChannelEnable(ADC_BASE, ADC_CH_1);
    uDMAChannelRequest(UDMA_CH15_ADC_CH1);
    ADCEnable(ADC_BASE);
}


void adc_dma_reenable(void)
{
    ADCIntEnable(ADC_BASE, ADC_CH_1, ADC_DMA_DONE);
    uDMAChannelEnable(UDMA_CH15_ADC_CH1);
    uDMAChannelRequest(UDMA_CH15_ADC_CH1);
    ADCEnable(ADC_BASE);
}


void ADCIntHandler(void)
{
    uint32_t ui32Mode;
    uint32_t ui32Stat;

    ui32Stat = ADCIntStatus(ADC_BASE, ADC_CH_1);
    ADCIntClear(ADC_BASE, ADC_CH_1, ui32Stat);

    ui32Mode = uDMAChannelModeGet(UDMA_CH15_ADC_CH1|UDMA_PRI_SELECT);
	
    if(!uDMAChannelIsEnabled(UDMA_CH15_ADC_CH1))
    {
        // Turn off ADC and clear IRQ-Bit
        ADCDisable(ADC_BASE);
        ADCIntClear(ADC_BASE, ADC_CH_1, ADC_DMA_DONE);
        ADCIntDisable(ADC_BASE, ADC_CH_1, ADC_DMA_DONE);
        uDMAChannelTransferSet(
				UDMA_CH15_ADC_CH1|UDMA_PRI_SELECT, 
				UDMA_MODE_BASIC, 
				(void*)(ADC_BASE+ADC_O_channel2FIFODATA), 
				adc_samples, 
				ADC_BUFFER_SIZE);
        uDMAChannelEnable(UDMA_CH15_ADC_CH1);

        g_AdcDmaTfrDone = true;
    }
}

#define ADC_BUFFER_SIZE 128
#define MY_BUFF_SIZE 64

static uint16_t adc_samples [ADC_BUFFER_SIZE] = {};
static uint16_t my_buff [MY_BUFF_SIZE] = {};

void adc_dma_init(void);
void adc_start_dma_sampling(void);
void adc_dma_reenable(void);
void ADCIntHandler(void);


void main(void)
{
	adc_dma_init();
    adc_start_dma_sampling();

    while(1)
	{
		// the flag is set in the interrupt handler
		if (g_AdcDmaTfrDone)
		{
			g_AdcDmaTfrDone = false;
			memcpy(my_buff, adc_samples, MY_BUFF_SIZE);
			sleep(2);
			
			// trigger the next set of adc data transfer
			adc_dma_reenable();
		}
	}
    return;
}


void adc_dma_init(void)
{
  UDMACC32XX_init();
  udma = UDMACC32XX_open();
  uDMAChannelAssign(UDMA_CH15_ADC_CH1);
  uDMAChannelControlSet(
		UDMA_CH15_ADC_CH1|UDMA_PRI_SELECT, 
		UDMA_SIZE_16|UDMA_SRC_INC_NONE|UDMA_DST_INC_16|UDMA_ARB_1);
  uDMAChannelTransferSet(
		UDMA_CH15_ADC_CH1|UDMA_PRI_SELECT, 
		UDMA_MODE_BASIC, 
		(void*)(ADC_BASE+ADC_O_channel2FIFODATA), 
		adc_samples, 
		ADC_BUFFER_SIZE);
  uDMAChannelEnable(UDMA_CH15_ADC_CH1);
  uDMAEnable();


  // Initialize the ADC
  ADC_init();
  ADC_Params adc_params;
  ADC_Params_init(&adc_params);
  adc_handle = ADC_open(CONFIG_ADC_0, &adc_params);
}


void adc_start_dma_sampling(void)
{
    ADCChannelDisable(ADC_BASE, ADC_CH_1);
    ADCDMAEnable(ADC_BASE, ADC_CH_1);
    ADCIntRegister(ADC_BASE, ADC_CH_1, ADCIntHandler);
    ADCIntClear(ADC_BASE, ADC_CH_1, ADC_DMA_DONE);
    ADCIntEnable(ADC_BASE, ADC_CH_1, ADC_DMA_DONE);
    ADCChannelEnable(ADC_BASE, ADC_CH_1);
    uDMAChannelRequest(UDMA_CH15_ADC_CH1);
    ADCEnable(ADC_BASE);
}


void adc_dma_reenable(void)
{
    ADCIntEnable(ADC_BASE, ADC_CH_1, ADC_DMA_DONE);
    uDMAChannelEnable(UDMA_CH15_ADC_CH1);
    uDMAChannelRequest(UDMA_CH15_ADC_CH1);
    ADCEnable(ADC_BASE);
}


void ADCIntHandler(void)
{
    uint32_t ui32Mode;
    uint32_t ui32Stat;

    ui32Stat = ADCIntStatus(ADC_BASE, ADC_CH_1);
    ADCIntClear(ADC_BASE, ADC_CH_1, ui32Stat);

    ui32Mode = uDMAChannelModeGet(UDMA_CH15_ADC_CH1|UDMA_PRI_SELECT);
	
    if(!uDMAChannelIsEnabled(UDMA_CH15_ADC_CH1))
    {
        // Turn off ADC and clear IRQ-Bit
        ADCDisable(ADC_BASE);
        ADCIntClear(ADC_BASE, ADC_CH_1, ADC_DMA_DONE);
        ADCIntDisable(ADC_BASE, ADC_CH_1, ADC_DMA_DONE);
        uDMAChannelTransferSet(
				UDMA_CH15_ADC_CH1|UDMA_PRI_SELECT, 
				UDMA_MODE_BASIC, 
				(void*)(ADC_BASE+ADC_O_channel2FIFODATA), 
				adc_samples, 
				ADC_BUFFER_SIZE);
        uDMAChannelEnable(UDMA_CH15_ADC_CH1);

        g_AdcDmaTfrDone = true;
    }
}

Thanks,

Vasav

  • Hi Vasav,

    I would not recommend trying to create your own library for ADC. Instead, I would suggest to use the ADC driver that is a part of the simplelink library. For documentation, you can read the "TI Drivers API Documentation". We also have an ADC example. 

    Have you tried the example or the ADC driver?

  • I am not trying to create a new ADC driver and indeed am trying to use the one supplied by TI in their SDK. I did not see any examples of using the DMA with the ADC, if you have any suggestions can you please point me to it? Additionally, I have read the documentation and it is fairly limited on the DMA implementation with an ADC.

    If you have any suggestions can you please link me to them?

    Thank you!

    Vasav

  • Hi Vasav,

    Thank you for correcting me; I now understand that you want to use the DMA with the ADC. Since we don't have an example of the ADC and the DMA, then I would refer the CC3220 TRM to you. https://www.ti.com/lit/ug/swru465/swru465.pdf 

    It seems like other posters have got something working also: https://e2e.ti.com/support/wireless-connectivity/wi-fi-group/wifi/f/wi-fi-forum/680229/rtos-cc3220sf-launchxl-adc-with-dma-transfer 

  • Hi Sabeeh,

    Thank you for this information. I have read the TRM in a lot of a detail and still unable to get this DMA working as intended. To clarify, I have been able to sample using the DMA however, where I am lost is that the sampling is done near the end of the buffer. My current setup is to use a function gnerator and produce a sine wave that gets connected to the ADC line. When I start sampling, I see about 900 0s and then I see some data in the buffer. Do you have any clue why this could be happening?

    Also If you are able to provide with some sample code that would work with this scenario in mind, I would greatly appreciate it! My code was initially based off the the code that is linked in the other post.

    Thanks for your help!

    Vasav