HSADC with GPDMA Transfer Dropping Samples at 80MSps

cancel
Showing results for 
Show  only  | Search instead for 
Did you mean: 

HSADC with GPDMA Transfer Dropping Samples at 80MSps

3,076 Views
lpcware
NXP Employee
NXP Employee
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:
[list]
  [*]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.
[/list]

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 (sts & ( HSADC_INT1_THCMP_UCROSS(HSADC_CHANNEL))) {

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
trigaddress = LPC_GPDMA->CH[HSADC_GDMA_CH].DESTADDR;
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);
Chip_HSADC_DisableInts(LPC_ADCHS, 1, (HSADC_INT1_THCMP_UCROSS(HSADC_CHANNEL)));

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

}
else{

Chip_HSADC_ClearIntStatus(LPC_ADCHS, 1, sts);
}

}
else{

Chip_HSADC_ClearIntStatus(LPC_ADCHS, 1, sts);
}

adc.ntriggers++;

}





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:

[list]
  [*]http://www.lpcware.com/content/forum/lpc4370-acdhs-speed
  [*]http://www.lpcware.com/content/forum/gpdma-library-hsadc
  [*]https://github.com/embeddedartists/labtool/tree/master/fw/program/source
[/list]


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

Labels (1)
9 Replies

1,933 Views
lpcware
NXP Employee
NXP Employee
Content originally posted in LPCWare by wsinter on Sun Apr 24 19:20:55 MST 2016
Hi,All, thanks for your reply.

I want to get the exactly position of DMA (the vaiue of DMA channel control&LLI register)in a hardware trigger interrupt(GPIO Interrupt),but if I set the burst size and FIFO Level to 8, there may be some lags because the HSADC has not arrive the DMA trigger FIFO Level , so the DMA position may not be right, and the trigger will not be stable. I tried to set the FIFO Level and burst size to 1, I think this would help me get the exactly position of DMA when the hardware trigger interrupt comes. But the result is bad, I would get 0x8000. I do not know how to solve it .
0 Kudos

1,934 Views
lpcware
NXP Employee
NXP Employee
Content originally posted in LPCWare by heffalump on Sun Apr 24 18:35:26 MST 2016
Hi all,

I didn't overcome this issue with dropping samples, particularly when reading the interrupt register during a trigger event. Embedded Artists also encountered this behavior when developing the Labtool. It is thought to be due to bandwidth limitations of the buses.

As my application needs both hardware triggering and the higher sample rates, I haven't done any further work with NXP4370.

NXP could not tell me about any planned updates/ successors to the NXP4370.

Good luck!
0 Kudos

1,934 Views
lpcware
NXP Employee
NXP Employee
Content originally posted in LPCWare by mch0 on Sat Apr 23 22:20:14 MST 2016
Yes, indeed, I now remember also some experiments with threshold+burst size.
I even went so far as to trigger the DMA before the burst length data was available. I hoped to gain extra slack on the FIFO.
Say trigger at 6 samples with as burst length of 8. The idea was that the missing samples would be in the FIFO before the DMA would read them.
It did work (no "Fifo empty"-samples), but it did not solve the problem with occasionally missing samples.

I really should restart work on that, it was still nice enough a chip and I still feel I have not done a complete analysis of what happens when. So there might still be a solution by carefully aranging all data in non-confliczing memory (includung the location of the LLI) and making use of the 2 DMA masters accordingly.

Should I resume and find a solution I hope I won't forget to post it.

Good luck!

Mike
0 Kudos

1,934 Views
lpcware
NXP Employee
NXP Employee
Content originally posted in LPCWare by wsinter on Sat Apr 23 19:58:28 MST 2016
I also found a problem for HSADC and GPDMA. If I set the HSADC FIFO Level to 8, and DMA source and destiny burst size to 8, the ADC sample result is correct, but if I set the the FIFO Level to 4, and DMA source and destiny burst size to 4, there would be some error result,  0x8000(the fifo is empty), also ,if I set both to 1,result would be some 0x8000,
0 Kudos

1,934 Views
lpcware
NXP Employee
NXP Employee
Content originally posted in LPCWare by mch0 on Sat Apr 23 12:23:01 MST 2016
Hi,

I think there is a more general problem with the GPDMA and it might be impossible to get the 80 MSPS without dropping some samples.
More than a year ago I also wanted to push the ADCHS to the limit, i.e. read samples continuosly into a ring buffer at maximum speed.
I tried all optimizations I could think of (memory layout, GPDMA settings, FIFO threshhold of ADCHS) but I always lost some samples.
As far as I remember (I gave up on the project a year ago) it might have to do with the exact timing of a LLI reload. When reaching the end of a block the GPDMA has to load the next set of descriptors and this might take just too long at times.
In theory there is enough time, but I could not find a setup to make it work at all times.

Of course, if you have other transfers with real-time requirements, such as feeding the DAC, it doesn't help either.

What really killed my project at that time was that I was seeing some kind of signal crosstalk from the selected ADCHS input (say from ADCHS_0 to the reference voltage at ADCHS_NEG). The higher the sampling rate the higher the crosstalk, clearly visible on an oscilloscope at ADCHS_NEG (despite some attached C and an otherwise clean supply voltage). I used the internal source then.

I'd really love to see a solution myself to continue my project.
Some time in the future I'll try to drive ADCHS_NEG from an external low-impedance source, the test board for that is already collecting dust ...

Sorry for the news for now - I wish I had better ones.

Mike

0 Kudos

1,935 Views
lpcware
NXP Employee
NXP Employee
Content originally posted in LPCWare by wsinter on Sat Apr 23 02:49:10 MST 2016
Hi,have you solved the problem? I also found  the dropping in 80MSPS
0 Kudos

1,935 Views
lpcware
NXP Employee
NXP Employee
Content originally posted in LPCWare by heffalump on Tue Mar 31 23:49:11 MST 2015
To further pin down the problem, I’ve disabled the HSADC threshold and set the GPDMA to capture a set number of samples. The main thread loops, waiting for the GPDMA interrupt to signal the end of the capture.

while (adc.prefilled == 0);


In this case samples are rarely dropped; sample 673 in the attached plot (80MSPS_NoTrigger.png) for example.

I then placed lines of code from the above ADCHS interrupt handler into the waiting loop, to test their effect on the HSADC capture and transfer. The lines associated with the HSADC interrupt status seem to cause the greatest disturbance. The following line causes a significant amount of samples to be lost (80MSPS_NoTrigger_QueryInterrupt.png):

while (adc.prefilled == 0) {
sts = Chip_HSADC_GetIntStatus(LPC_ADCHS, 1) & Chip_HSADC_GetEnabledInts(LPC_ADCHS, 1);
}


I suppose I try avoiding the interrogation of the HSADC interrupt status.

I’d love to hear whether anyone has successfully used the LPC4370 HSADC at 80MSps with a threshold-triggered scheme like this? Or even with a non-triggered block-processing approach.

I wonder if samples are lost using the LabTool code, I don’t have one at the moment. Sample loss may not be so obvious with the 12Mhz maximum bandwidth.
0 Kudos

1,935 Views
lpcware
NXP Employee
NXP Employee
Content originally posted in LPCWare by heffalump on Tue Mar 31 16:26:09 MST 2015
Thanks for the idea Starblue, I'll take a look at the memory layout.

Currently the main thread loops, waiting for the interrupt handlers to signal that the acquisition is complete. There is no processing/access of the complete buffer while the other is receiving ADC samples ...yet!

Update:

I have tried running the code with the receive buffer located in RamLoc72 (RAM2) and then in RanAHB32 (RAM3). The rest of the variables and RAM functions are located in RamLoc128 (RAM). The problem remains in both cases.

0 Kudos

1,934 Views
lpcware
NXP Employee
NXP Employee
Content originally posted in LPCWare by starblue on Tue Mar 31 00:52:50 MST 2015
Did you optimize the memory layout, so that CPU and DMA don't interfere? I.e. put the two circular buffers into separate memory regions which are only used for that purpose?
0 Kudos