Skip to main content
turboscrew
Senior III
November 1, 2019
Question

Circular DMA seems to "doublebuffer" (STM32F427)

  • November 1, 2019
  • 24 replies
  • 2652 views

What is it that I've been missing...

I set a timer to trig 7-channel ADC with DMA. The DMA is set to make 7 16-bit to 16-bit transfers circularly. It seemed to work fine, but some data started to corrupt. So I made the 7x16-bit buffer 4-fold (28 16-bit numbers) and it got half-written. It looks like the data is stored in two 7x16-bit blocks.

The actual doublebuffering was not used and the DMA_S0M1AR was zero.

(Checked in the Atollic debugger special register view.)

This topic has been closed for replies.

24 replies

waclawek.jan
Super User
November 1, 2019

So, as checked reading back the registers in debugger at a breakpoint just before enabling DMA, is the initial value of NDTR=28?

JW

turboscrew
Senior III
November 1, 2019

I always see 7 in the NDTR. And the both transfer sizes are 1s (half word).

Checked from the special registers in the middle of run. Several times.

The timer triggers the reading every 10 ms, so it's very hard to hit a stop in the middle of transfer.

Tesla DeLorean
Guru
November 1, 2019

DMA here normally has HT (Half Transfer) and TC (Transfer Complete) interrupts to manage a ping-pong arrangement with a singular buffer description.

Tips, Buy me a coffee, or three.. PayPal Venmo (See Profile) Up vote any posts that you find helpful, it shows what's working..
turboscrew
Senior III
November 1, 2019

Only complete-interrupt is used. The idea is that the ADC -reading happens "automatically", and the interrupt routine quickly copies the data for the application use. The reading happens every 10 milliseconds.

RMcCa
Senior II
November 1, 2019

Double check the dma stream CR. Both transfer sizes should be half words. The NDTR should be 7. If you have properly set circular mode the NDTR will get reloaded to 7 after each complete block. I use this with 8 half words with spi and it works fine. Setting up the dma without HAL is pretty easy, just a few lines of code.​

turboscrew
Senior III
November 1, 2019

Yes. NDTR is always 7 and both transfer sizes are '1' (half words). If they were words, every second half word should have been zero. Now that's not the case.

There are 7 16-bit numbers that seem to be about right, then another group of 7 16-bit numbers differing their first group counterparts by less than 10. And the values are quite, what could be expected. I think the differences are just normal small "fluctuations".

turboscrew
Senior III
November 1, 2019

BTW, what are the "bursts" and "beats" the reference manual talks about? Are those for, like, burst-writing to SDRAM?

[edit]

Ah, never mind, I already found out...

waclawek.jan
Super User
November 2, 2019

Ah, so you increased the buffer size without changing NDTR, and found part of buffer unexpectedly being written? I though you increased NDTR to 28 and complain about founding only half of the transfer to happen... =) Misunderstanding.

Strip down the program to absolute minimum but complete compilable example exhibiting the problem, and post.

JW

turboscrew
Senior III
November 2, 2019

Yes.

Getting the code here is not easy, because it's not my personal stuff. I can only access the code at work, and I don't have much time for extra activity at the moment.

I was hoping to hear about some ideas about what I should check.

turboscrew
Senior III
November 2, 2019

Oh, I just realized, there is no hand written code involved. It's all generated by CubeMX.

Only the code in interrupt that copies the contents of the DMA buffer is hand-written, but should not be involved in this.

Maybe I can put the code here.

turboscrew
Senior III
November 2, 2019

A bit off from the original question, but it seems that I haven't really gotten it...

What does NDTR count? I mean, if FIFO is used, the source is 8-bit and destination is 32-bit, what transfers does it count?

[edit]

Aha, AN4031 explains that for non-memory-to-memory case:

"The transfer size is defined by the DMA_SxNDTR register value and by the peripheral side data width".

turboscrew
Senior III
November 2, 2019

I started to wonder if this could be a timing problem. Maybe the clock triggering the ADC sweeps runs faster than intended. Could this happen, if new sweep is started before the previous one is properly finished?

turboscrew
Senior III
November 2, 2019

Just came to my mind... how does MPU fit into the system? Is it also between the DMACs and memory? That is: can it trap illegal memory accesses by DMAC too? I suppose that the DMA peripheral buses are not seen by the MPU.

turboscrew
Senior III
November 3, 2019

Found it. It seems like the MPU is between the processor and the bus. It doesn't see what DMACs are doing. Should have guessed, because of the bus matrix...

Piranha
Principal III
November 2, 2019

Speaking about timings.. Maybe DMA is delayed because of something other and ADC overrun happens. And, by the way, debugger breakpoints almost always cause ADC overrun.

turboscrew
Senior III
November 3, 2019

I just don't see how ADC overrun could cause the "double buffering"-effect.

Piranha
Principal III
November 3, 2019

On overrun interrupt code can restart capture sequence from the beginning, including DMA.

turboscrew
Senior III
November 3, 2019

Maybe I should try with double buffering, but set both memory pointers to the same buffer, and see if that still happens...