Using Direct Memory Access (DMA) in STM32 Projects
Using Direct Memory Access (DMA) in STM32 Projects
Low and medium density ST32 microcontrollers have single 7 channel DMA unit while high density devices
have two DMA controllers with 12 independent channels. In STM32VLDiscovery there ST32F100RB
microcontroller with single DMA unit having 7 channels.
DMA can do automated memory to memory data transfers, also do peripheral to memory and peripheral to
peripheral. DMA channels can be assigned one of four priority level: very high, high, medium and low. And if
two same priority channels are requested at same time – the lowest number channel gets priority. DMA
channel can be configured to transfer data in to circular buffer. So DMA is ideal solution for any
peripheral data stream.
Speaking of physical DMA buss access it is important to note, that DMA only access bus for actual data
transfer. Because DMA request phase, address computation and Ack pulse are performed during other DMA
channel bus transfer. So when one DMA channel finishes bus transfer, another channel is already ready to do
transfer immediately. This ensures minimal bus occupation and fast transfers. Another interesting feature of
DMA bus access is that it doesn’t occupy 100% of bus time. DMA takes 5 AHB bus cycles for single word
transfer between memory – three of them are still left for CPU access. This means that DMA only
takes maximum 40% of buss time. So even if DMA is doing intense data transfer CPU can access
any memory area, peripheral at any time. If you look at block diagram you will see that CPU has
separate Ibus for Flash access. So program fetch isn’t affected by DMA.
Programming DMA
Simply speaking programming DMA is easy. Each channel can be controlled using four registers: Memory
address, peripheral address, number of data and configuration. And all channels have two dedicated
registers: DMA interrupt status register and interrupt flag clear register. Once set DMA takes care of memory
address increment without disturbing CPU. DMA channels can generate three interrupts: transfer finished,
half-finished and transfer error.
Where we could toggle LED and change status flag giving signal to start CPU transfer test.
1 void DMA1_Channel1_IRQHandler(void)
2 {
3 //Test on DMA1 Channel1 Transfer Complete interrupt
4 if(DMA_GetITStatus(DMA1_IT_TC1))
5 {
6 status=1;
7 LEDToggle(LEDG);
8 //Clear DMA1 Channel1 Half Transfer, Transfer Complete and Global interrupt pending bits
9 DMA_ClearITPendingBit(DMA1_IT_GL1);
10 }
11 }
Since LEDG is connected to GPIOC pin 9 and LEDB is connected to GPIOC pin 8 we could track start and end
pulses using scope:
This shows significant increase of data transfer speed (more than two times). And with DMA biggest benefit is
that CPU is totally unoccupied during transfer and may do other intense tasks or simply go in to sleep mode.
Hope this example gives an idea of DMA importance. With DMA we can do loads of work only in hardware
level. We will get back to it when we get to other STM32 features like ADC.