cancel
Showing results for 
Search instead for 
Did you mean: 

F2xx: What can cause an ADC overrun?

infoinfo989
Associate III
Posted on September 09, 2011 at 22:00

I'm having a lot of trouble with ADC overruns on the F2xx part, and I'm wondering if anyone has any suggestions on what might be going on.

I have the ADC running in ''DMA mode 2'', dual ADC mode, simultaneous sampling, being triggered by a timer at 8 kHz. I've fed this timer out to an external pin to confirm it's really at 8 kHz. So what's happening is that every 125 uS the two ADCs (ADC1 and ADC2) each take a sample, put their results in the 32-bit ADC_CDR results register, and raise a DMA request.

So far so good, and I can watch the data in the buffer (being written by the DMA) changing as I change the input voltages to the two ADC pins. I've also been able to confirm timing this way as well (by timing how long the buffer fills I can also determine the ADC rate and again confirm 8 kHz).

The ADC does not have a FIFO, so it's critical that its results register be read in time, otherwise an ADC overrun is tripped. The overrun is an unmitigated disaster for the ADC - the overrun logic shuts off the ADC _and_ it shuts off the DMA - it brings everything to a screeching halt, resulting in the complete cessation of ADC data until everything can be re-initialised and started up again. Hence an overrun really needs to be avoided at pretty much all costs.

As far as I can determine (and experiment) the overrun logic cannot be turned off in DMA Mode 2. It can be turned off for a single ADC, but it appears that once you start using the multi-ADC modes such as Mode 2, the ''sky is falling'' overrun logic becomes enabled by default. If I'm wrong about this, I'd be very happy indeed to hear it.

I've set the priority of the ADC DMA to ''Very High'', and it's the only DMA in the system with that priority - everything else is either high, medium or low. Hence I'd expect the ADC DMA to have little trouble servicing the ADC. In addition, the DMA is in ''double-buffer'' mode, so it's always running (unless the ADC overrun turns if off).

Despite this, an overrun happens every 10 or 20 seconds. Obviously something is preventing the ADC DMA from reading the ADC data register quickly enough.

Any ideas what can block or delay a DMA request? What am I missing here?

Thanks.

#adc
4 REPLIES 4
raptorhal2
Lead
Posted on September 10, 2011 at 01:54

This is just a wild guess, since you didn't say how the timer is set up. The 8 KHz timer will overflow every 8.192 seconds if a 16 bit timer register or count is used. Is timer overflow affecting the ADC sample trigger ?

Cheers, Hal

infoinfo989
Associate III
Posted on September 10, 2011 at 07:27

That's a fair question. The timer is setup to simply toggle its output at an 8 kHz rate. Specifically, it's used in the ''output compare'' mode. So when you output it to a pin (as I did to check it was working as expected) you simply see an 8 kHz square wave, going forever. Used internally, that output is the ADC trigger - on each rising edge an ADC sample is triggered.

I should point out that the amount of time before an ADC overrun occurs is quite random. On average it's once every 10 or maybe 20 seconds, but sometimes it occurs in the first 3 seconds. I'd also been wondering if it had anything to do with DMA rollover, but apparently not - the DMA NDTR register can be any value when the overrun occurs - I've never seen NDTR be empty or full (I'm sure it's possible - just that I've never seen it - NDTR has always been assorted intermediate values).

I've really been wracking my brains trying to think of what might cause a DMA request to be delayed. I'm not programming the flash, which I understand can stall the processor for some time. It's very puzzling.

~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

  /* Time base configuration - used to setup the main TIM2 counter, output compare channel number 3 */

  // The goal is a 32 kHz clock feeding the main counter/timer register. That register will count: 0,1,0,1,0,1 etc

  // so we'll see a 0 at 16 kHz. Then OC3 will invert its output on that zero, to give an OC3 output freq of 8 kHz

  // This Timer 2 output compare 3 frequency of 8kHz will be our ADC sampling rate

  PrescalerValue = (uint16_t) ((SystemCoreClock / 2) / 32000) - 1;

  TIM_TimeBaseStructure.TIM_Prescaler = (uint16_t)PrescalerValue;     // 32 kHz output from prescaler, feeding main CNT counter register

  TIM_TimeBaseStructure.TIM_Period = (uint16_t)1;                     // CNT register goes 0,1,0,1,0,1,0,1 etc

  TIM_TimeBaseStructure.TIM_ClockDivision = 0;

  TIM_TimeBaseStructure.TIM_CounterMode = TIM_CounterMode_Up;

  TIM_TimeBaseInit(TIM2, &TIM_TimeBaseStructure);

  /* Output Compare Toggle Mode configuration: Channel 3 */

  TIM_OCInitStructure.TIM_OCMode = TIM_OCMode_Toggle;

  TIM_OCInitStructure.TIM_OutputState = TIM_OutputState_Enable;

  TIM_OCInitStructure.TIM_Pulse = 0;                                  // OC3 inverts (toggles) each time the main counter register equals zero

  TIM_OCInitStructure.TIM_OCPolarity = TIM_OCPolarity_Low;

  TIM_OC3Init(TIM2, &TIM_OCInitStructure);

  TIM_OC3PreloadConfig(TIM2, TIM_OCPreload_Disable);

  /* TIM enable counter */

  TIM_Cmd(TIM2, ENABLE);

raptorhal2
Lead
Posted on September 11, 2011 at 01:55

Another wild guess - Is the ADCCLK and SYSCLK running at their maximums of 30 and 120 MHZ ? As an experiment, you could change those clocks and see if it makes a difference.

To avoid spending time with more wild guesses and patient responses, I recommend you strip the code to a bare bones example that duplicates the problem, then post it all for review.

Cheers, Hal

infoinfo989
Associate III
Posted on September 11, 2011 at 02:21

''patient responses'' - I had a good laugh at that.

Yes indeed, we're running at 120 Mhz / 30 MHz, although I have tried different clock speeds, different ADC prescaler speeds, with no noticeable difference.

As much as I'd like to create a simple test-case bit of code, it's really tough to do. This problem occurs when a bunch of other DMAs are happening in the system (SDIO, DCMI, etc) - those things require the appropriate hardware to make them work. On its own there's no problem - the ADC is fine on its own. It's when the system gets busier, moving data hither and dither, that the overrun happens. (Hence my fixation on DMA priorities.) Having said that, I'm trying to create a software test case, but I'm not optimisitic that I can without it being hardware-specific. (But I'm trying anyway.)  I've also filed a ticket with ST tech support - if something interesting comes out of that I will post it here. They might have some ideas.