HSADC with GPDMA Transfer Dropping Samples at 80MSps

Discussion created by lpcware Employee on Jun 15, 2016
Latest reply on Jun 15, 2016 by lpcware
Content originally posted in LPCWare by heffalump on Mon Mar 30 18:39:58 MST 2015
I have an application similar to an oscilloscope, where I am capturing signals that exceed a set threshold. The application requires a sample-rate of 60MSps or above to be feasible.

The operation of my code:
  [*]The samples are moved into a segmented circular buffer using a GPDMA LLI.
  [*]The HSADC throws an interrupt if the trigger threshold is exceeded.
  [*]The interrupt queries the current GPDMA next LLI address and destination address to determine where in the circular buffer the trigger has occurred.
  [*]The interrupt modifies the LLI so that the GPDMA switches to a second circular buffer once it has filled the required number of post-trigger samples. The GPDMA is also set to throw an interrupt signaling the post-fill completion.

The problem is that the transfer is dropping chunks of samples. The samples are most regularly being lost around the time the trigger interrupt is running, i.e. the samples I am most interested in! I have attached a plot of a captured burst of 4 MHz Sine waves.  The trigger point, measured during the interrupt by querying the GPDMA destination address, is 400 Samples. Samples are regularly lost occur in the following 100 HSADC cycles (~1 us).
The effect is present when sampling at 80, 60 and 40 MSps. I have also attached CSVs containing captured signals. The traces are aligned with the trigger point at the 398th samples.

As the sample drops occur around the time of the trigger interrupt, am I doing something to upset the HSADC or GPDMA transfer in my handler code? The handler runs from RAM, otherwise it fails to stop the GPDMA before the circular buffer loops around. The FIFO trigger and GPDMA burst size for the transfer is set to 8 words.

__RAMFUNC(RAM2) void ADCHS_IRQHandler(void);

void ADCHS_IRQHandler(void)

uint32_t sts;
uint32_t triglliaddress, triglli, lastlli,trigaddress;

sts = Chip_HSADC_GetIntStatus(LPC_ADCHS, 1) & Chip_HSADC_GetEnabledInts(LPC_ADCHS, 1);

// Check interrupt caused by threshold crossing

if( adc.ntriggers>0 ) //Ignore the initial forced interrupt
int active = adc.active, next = adc.next;

// Grab Current destination address and next LLI for HSADC transfer
triglliaddress = LPC_GPDMA->CH[HSADC_GDMA_CH].LLI; // Address to Next LLI in CHain

// Calculate when to finish post-fill and switch buffers
triglli = ( triglliaddress - (uint32_t) &HSADC_DMA_LLI[active][0] ) / 16; // LLI Descriptor is 16 bytes
lastlli =  (triglli + s.postsegs);

// Check whether last LLI rolls over
if(lastlli >= RX_SUBBUFF_NUM) lastlli = lastlli-RX_SUBBUFF_NUM;

// Flag that the ADC has Triggered
adc.triggered = 1;

// Once trailing sub-buffers are filled the DMA will switch to the start of the
// second buffer and trigger an interrupt
HSADC_DMA_LLI[active][lastlli].ctrl |= GPDMA_DMACCxControl_I;
HSADC_DMA_LLI[active][lastlli].lli = HSADC_DMA_LLI[next][0].lli;

// Store the Trigger Position Info
adc.triglli = triglli;
adc.lastlli = lastlli;
adc.triglliaddress = triglliaddress;
adc.trigaddress = trigaddress;
adc.trig = ((uint32_t)adc.trigaddress - (uint32_t)&dataRx[active][0][0] ) / 2;

// Disable Interrupts
Chip_HSADC_ClearIntStatus(LPC_ADCHS, 1, sts);

adc.trigfin=1;  // Flag Trigger Interrupt Finished


Chip_HSADC_ClearIntStatus(LPC_ADCHS, 1, sts);


Chip_HSADC_ClearIntStatus(LPC_ADCHS, 1, sts);



Any advice/experience would be much appreciated! Has anyone had success with triggered acquisition at 80MSPS?

For anyone starting with the LPC4370 HSADC, I found the following links most helpful:


Original Attachment has been moved to: 4MHz_SineBurst_40MSps_Triggered.txt.zip

Original Attachment has been moved to: 4MHz_SineBurst_60MSps_Triggered.txt.zip

Original Attachment has been moved to: 4MHz_SineBurst_80MSps_Triggered.txt.zip