# STM32F4 - DMA with bigger steps

I'm programming an STM32F4 Discovery board to push a sequence of 12 bit values into the DAC data register. This works well using timer interrupts: inside my IRQ handler, I have code that looks like:

phase += phaseIncrement;
DAC_SetChannel1Data(DAC_Align_12b_R, function[phase]);


and the output of the DAC looks like I think it should. Note that phaseIncrement doesn't have to be 1 - if I want a high frequency output, I can skip points in function[], sacrificing the accuracy of the signal for a bit of extra speed.

Now, I am reading about DMA. It looks like the STM32F4 can only increment by one of three amounts - 1 byte, 2 bytes, and 4 bytes, depending on the size of the variable being transferred. Is this correct? Is there a workaround that will let me skip some of these memory addresses so that I can emulate my current output without less CPU usage?

• Pretty sure there's a register that takes an actual increment value - have you checked the programmer's manual? It may be a trick to get phase accumulator wrapping right without involvement of a soft interrupt on wrap, and I don't immediately see how you could do fractional phase increment while using only the whole part for lookup. Feb 6, 2015 at 16:33
• I got a bit overwhelmed by the DMA section. I'll take another look. I can live without fractional phase increment - changing the timer period will probably be good enough for me. Feb 6, 2015 at 16:35
• @ChrisStratton: The programmer's manual says that either (or both) the peripheral and memory address can be incremented by 1, 2, or 4 (byte, half-word, and word). Feb 6, 2015 at 17:19
• Too bad - that's less flexible than I would have thought. Depending on what you are doing, could it make sense to preselect the data by writing it to a new buffer that can be sent out 1:1 ? Feb 6, 2015 at 17:26
• @Scott - I don't think the increment desired here is simply to account for the peripheral width, but rather to increment a table index by larger values as in a DDS, ie, to skip entries. Feb 6, 2015 at 17:27

## 1 Answer

As far as I know the STM32F4's DMA controller cannot do what you want. DMA can feed the DAC much faster than interrupt driven software (up to 10.5 Msps) so you might not need to skip samples anyway.

If DMA is not fast enough then the classical solution is to make multiple copies of your waveform, each with half as many samples as the previous one. This will use a maximum of twice as much sample memory (1 + 1/2 + 1/4 + 1/8 etc). If you have several waveforms that take up a lot of space then you might not have enough memory to store all the higher octaves. However if you only need to play one waveform at a time then you may still have enough RAM to precompute and store the octave(s) required for just the current waveform.

• I now have DMA pushing data into the DAC. The improvement is unbelievable (literally an order of magnitude faster), but I will still need to skip samples for the higher frequencies. I think your "classical solution" is the one I will use. Feb 6, 2015 at 20:19
• Bruce, the skipping step is how traditional DDS uses an "oversized" table to allow for low phase noise / finer adjustment. See: analog.com/en/analog-dialogue/articles/… Think about this problem: say I want to generate a sine wave using a DAC & table in memory. If I don't have a way to finely adjust the update frequency (i.e. integer fractions of fclk are too coarse) then there needs to be a way to vary the steps in the table in order to be able to change from say, 100kHz output to 100.01kHz output. Dec 10, 2021 at 16:43