cancel
Showing results for 
Search instead for 
Did you mean: 

Data corruption while reading multiple channels of ADC1 with DMA

NKunwar
Associate II

I am working on a old code written by someone (without a design document). The application requires reading 13 ADC channels roughly at 8k samples per second. The read values

are written in two buffers in double buffer mode (4096 each).

The ADC is implemented in scan mode with the sequence of channels in ADC_SQRx registers. ADC is configured in 12 bit mode. ADC conversion is triggered by rising

edge of timer2 channel 2 set at a ~8Khz frequency.

DMA is configured peripheral to memory transfer in double buffer mode, with DMA2 Stream0 which can take ADC1 as source.The NDTR register in DMA is written with a value of 4082,

(multiple of 13 channels). DMA stream threshold is set as half full.

I wanted to understand how long does it take the controller to swap memory address at end of each buffer fill. I am reading sine waves on some of the channels and can see some data points being missed when the memory address changes from buffer 1 to buffer 0.

The time period for which data is missed is in range 3-4ms.

I have checked other things which can lead to this issue like - timer trigger not happening properly, FIFO or transfer error, but none of these seem to be an issue.

I wanted to understand if the destination address swap can lead to this issue.

7 REPLIES 7

Which STM32?

> DMA stream threshold is set as half full.

If you use FIFO in DMA, set the number of samples (NDTR value) so that it represents integer multiple of the amount given by the FIFO threshold, otherwise some samples remain in the FIFO at the transfer-complete interrupt.

JW

NKunwar
Associate II

The controller is STM32F407VG.

The destination buffers are 16 bit with a size 4096.

FIFO threshold is half full ( 4 half words as threshold). NDTR value if 4082 which is not multiple of 4. I can not change the NDTR value because I also want it to be multiple of 13 ( the way code uses the filled buffer for processing).

Since my destination and source data size are same, it might make sense to do a direct DMA transfer instead of using FIFO. I will try this and update here if it helped.

Even if the FIFO threshold is an issue I think it can cause at max 4 samples to miss which will be ~520us of time . I am missing samples in range of ms time. Also I have configured to trigger a FIFO error interrupt too which does not seem to triggering.

NKunwar
Associate II

I tried with direct DMA mode too. Did not help.

Read out and post the DMA registers content.

How do you know that ADC samples are missing? Where exactly are those missing samples located in the array?

JW

NKunwar
Associate II

Attached dump of DMA2 register (using stream 0 for ADC read). This readout is for DMA FIFO threshold quarter full.

The data being read on ADC is a sine wave of 100Hz. An interrupt is configured to trigger every 10ms where address pointer of the present memory location being filed is stored. NDTR value is read and subtracted from max value of 4082; depending on which memory (0 or 1) is being used the address pointer is stored in a variable, which is used later for processing.

For data cycles where the memory source changes from 0 to 1 or vice versa, the data is ignored.

I did a dump of the memory and plotted the data using address pointers stored. The sine waves looks consistent until a change of memory source happens and the next cycle is shifted from the previous ones by some number of samples ( As said above the cycle where the changes happens is not used in further processing). I am understanding the shift as some portion of data being missed from initial part of the cycle.

Attached screenshot of the data plotted from the memory dump.

NKunwar
Associate II

Screen shot of data dump plot.

I have also checked the 10ms interrupt on scope. It is consistently happening at 10ms duration.

NKunwar
Associate II

Is there a way where we can route the DMA2 channel0 stream 0 interrupt on GPIO to see if it is continuously happening or not?

What I have checked before is the ADC Transfer complete interrupt on GPIO which is continuous.