lpcware

Can't get DMA transfers for ADC working correctly on a LPC1768

Discussion created by lpcware Employee on Jun 15, 2016
Latest reply on Jun 15, 2016 by lpcware
Content originally posted in LPCWare by eTLA on Mon May 05 01:42:46 MST 2014
I bet I'm missing something obvious here, but I've been banging my head against this problem for days, read tons of code found on the net and I simply can't get it to work.

What I would like to do is handling DMA transfers for conversions of channel 0-2 but the errata for the LPC17xx gave me the impression that this won't work due to a bug so for now I'll settle for one channel at a time. Right now I'm trying to get it to work with channel 0 but I must be missing something (probably/hopefully obvious)...

This is the code:


#define SAMPLE_BUFFER_LENGTH 32

uint32_t adcInputBuffer[SAMPLE_BUFFER_LENGTH];
uint32_t holdingInputBuffer[SAMPLE_BUFFER_LENGTH];

void hw_adc_setup(void)
{
SC->PCONP |= PCONP_PCAD | PCONP_PCGPDMA;
SC->PCLKSEL0 |= 1<<24;
PINCON->PINSEL1 &= (uint32_t) ~(0x3f << 14);
PINCON->PINSEL1 |= 0x15 << 14;
ADC->ADCR = (uint32_t) ((1 << 21) | (1 << 8) | 0x01);

/* Enable DMA */
GPDMA->DMACConfig = 0x01;

/* Clear errors etc */
GPDMA->DMACIntTCClear = 0xff;
GPDMA->DMACIntErrClr  = 0xff;

/* Set up DMA channel */
GPDMACH0->DMACCConfig   = 0;
GPDMACH0->DMACCControl  =
(SAMPLE_BUFFER_LENGTH << 0) |   /* Transfer size */
(0x00 << 12) |  /* Source burst size */
(0x00 << 15) |  /* Destination burst size */
(0x02 << 18) |  /* 32 bit word source transfer width */
(0x02 << 21) |  /* 32 bit word destination transfer width */
(0x01 << 27) |  /* Destination increment */
(0x01UL << 31); /* Terminal count interrupt enable bit */
GPDMACH0->DMACCLLI      = (uint32_t) NULL;
GPDMACH0->DMACCDestAddr = (uint32_t) adcInputBuffer;
GPDMACH0->DMACCSrcAddr  = ADC->ADDR0;

/* Fixme: Don't know if this is needed but it was in the example... */
while((GPDMA->DMACConfig & 0x01) == 0);

GPDMACH0->DMACCConfig =
(4 << 1)  | /* Source peripheral ADC */
(2 << 11) | /* Transfer type; P->M */
(1 << 14) | /* Interrupt error mask */
(1 << 15);  /* Terminal count interrupt mask */

ADC->ADINTEN = 1<<8;

NVIC_EnableIRQ(DMA_IRQn);
NVIC_SetPriority(DMA_IRQn, 5);
}

void hw_adc_trig(void)
{
/* Set buffer address */
GPDMACH0->DMACCDestAddr = (uint32_t) adcInputBuffer;

/* Enable DMA-channel*/
GPDMACH0->DMACCConfig |= 0x01;

/* Burst mode */
ADC->ADCR |= 1 << 16;

hw_gpio_set_testpin_1(true);
}

void DMA_IRQHandler (void)
{
uint32_t IntTCStat = GPDMA->DMACRawIntTCStat;
uint32_t IntErrStat = GPDMA->DMACRawIntErrStat;

memcpy(holdingInputBuffer, adcInputBuffer, SAMPLE_BUFFER_LENGTH * 4);

GPDMA->DMACIntErrClr = IntTCStat;
GPDMA->DMACIntErrClr = IntErrStat;

hw_gpio_set_testpin_1(false);

/* Turn off burst mode */
ADC->ADCR &= ~(1UL << 16);

/* Disable DMA-channel*/
GPDMACH0->DMACCConfig &= ~0x01UL;
}


The ADC conversion and DMA transfer should start when hw_adc_trig is called and then 32 conversions should be done, ie it should take approximately 160 us. However, when I measure testpin 1 I get only 7.2 us the first time trig is called (2.6 us every other call after the first) which leads me to the conclusion that the DMA transfer only transfer the first ADC sample 32 times instead of transferring 32 unique samples.

This is, of course, not what I desire.

It's probably just a very stupid mistake I've done, but I seem unable to figure this out on my own. Sooo... Help?

Outcomes