DMA
DMA has 2 instances, one in HCPU and one in LCPU, both supporting memory-to-memory, memory-to-peripheral, peripheral-to-memory, and peripheral-to-peripheral transfers.
Main Features
8 independent configurable channels
Each channel’s DMA request can select 1 from 16 hardware requests, or be triggered by software
Each channel supports 4 priority levels, with same priority resolved by channel number
Supports memory-to-memory, memory-to-peripheral, peripheral-to-memory, peripheral-to-peripheral transfers
Source and destination addresses independently support single byte/double byte/4-byte access, and both can independently select whether address auto-increment
Supports circular buffer mode, automatically restarts after single transfer completion
Each channel supports 3 event flags - transfer complete, half transfer, transfer error, each can independently generate interrupt requests
Single configuration maximum transfer unit count is 65536, each unit is single byte/double byte/4-byte transfer according to different configurations
Single configuration transfer address range is limited within 1M bytes, i.e., during transfer process, source and destination addresses cannot cross 1M byte boundary (address bit31-bit20 cannot change)
DMAC Corresponding Peripheral Request ID
req_sel |
DMAC1 |
DMAC2 |
DMAC3 |
|---|---|---|---|
0 |
mpi1 |
i2s1_tx |
usart4_tx |
1 |
mpi2/i2c4 |
i2s1_rx |
usart4_rx |
2 |
mpi3 |
i2s2_tx |
usart5_tx |
3 |
mpi4 |
i2s2_rx |
usart5_rx |
4 |
usart1_tx |
pdm1_rx_l |
usart6_tx |
5 |
usart1_rx |
pdm1_rx_r |
usart6_rx |
6 |
usart2_tx |
pdm2_rx_l |
btim3 |
7 |
usart2_rx |
pdm2_rx_r |
btim4 |
8 |
gptim1_update |
/ |
gptim3_update |
9 |
gptim1_trigger |
dac0 |
gptim3_trigger |
10 |
gptim1_cc1 |
dac1 |
gptim3_cc1 |
11 |
gptim1_cc2 |
gptim2_update |
gptim3_cc2 |
12 |
gptim1_cc3 |
gptim2_trigger |
gptim3_cc3 |
13 |
gptim1_cc4 |
gptim2_cc1 |
gptim3_cc4 |
14 |
btim1 |
audprc_tx_out_ch1 |
gptim5_update |
15 |
btim2 |
audprc_tx_out_ch0 |
gptim5_trigger |
16 |
atim1_update |
audprc_tx_ch3 |
spi3_tx |
17 |
atim1_trigger |
audprc_tx_ch2 |
spi3_rx |
18 |
atim1_cc1 |
audprc_tx_ch1 |
spi4_tx |
19 |
atim1_cc2 |
audprc_tx_ch0 |
spi4_rx |
20 |
atim1_cc3 |
audprc_rx_ch1 |
mpi5 |
21 |
atim1_cc4 |
audprc_rx_ch0 |
i2c5 |
22 |
i2c1 |
gptim2_cc2 |
i2c6 |
23 |
i2c2 |
gptim2_cc3 |
i2c7 |
24 |
i2c3 |
gptim2_cc4 |
gptim4_update |
25 |
atim1_com |
atim2_update |
gptim4_trigger |
26 |
usart3_tx |
atim2_trigger |
i2s3_rx/gptim4_cc1 |
27 |
usart3_rx |
atim2_cc1 |
i2s3_tx/gptim4_cc2 |
28 |
spi1_tx |
atim2_cc2 |
audadc_ch0/gptim4_cc3 |
29 |
spi1_rx |
atim2_cc3 |
audadc_ch1/gptim4_cc4 |
30 |
spi2_tx |
atim2_cc4 |
gpadc |
31 |
spi2_rx |
atim2_com |
sdadc |
32 |
/ |
/ |
/ |
33 |
/ |
/ |
/ |
34 |
/ |
/ |
/ |
35 |
/ |
/ |
/ |
36 |
/ |
/ |
/ |
37 |
/ |
/ |
/ |
38 |
/ |
/ |
/ |
39 |
/ |
/ |
/ |
40 |
/ |
/ |
/ |
41 |
/ |
/ |
/ |
42 |
/ |
/ |
/ |
43 |
/ |
/ |
/ |
44 |
/ |
/ |
/ |
45 |
/ |
/ |
/ |
46 |
/ |
/ |
/ |
47 |
/ |
/ |
/ |
48 |
/ |
/ |
/ |
49 |
/ |
/ |
/ |
50 |
/ |
/ |
/ |
51 |
/ |
/ |
/ |
52 |
/ |
/ |
/ |
53 |
/ |
/ |
/ |
54 |
/ |
/ |
/ |
55 |
/ |
/ |
/ |
56 |
/ |
/ |
/ |
57 |
/ |
/ |
/ |
58 |
/ |
/ |
/ |
59 |
/ |
/ |
/ |
60 |
/ |
/ |
/ |
61 |
/ |
/ |
/ |
62 |
/ |
/ |
/ |
63 |
/ |
/ |
/ |
DMA Example 1
Memory-to-memory 4-byte transfer 4096 bytes.
DMA_HandleTypeDef hdma;
HAL_StatusTypeDef err;
uint32_t SrcAddress = 0x10000000;
uint32_t DstAddress = 0x20000000;
uint32_t Counts = 1024; //Transfer unit is word, so Counts= 4096 / 4
/* Init DMA configure*/
hdma.Instance = DMA1_Channel6;
hdma.Init.Request = 0; //Request id is useless while memory to memory, just set to 0
hdma.Init.Direction = DMA_MEMORY_TO_MEMORY;
hdma.Init.PeriphDataAlignment = DMA_PDATAALIGN_WORD;
hdma.Init.MemDataAlignment = DMA_MDATAALIGN_WORD;
hdma.Init.PeriphInc = DMA_PINC_ENABLE;
hdma.Init.MemInc = DMA_MINC_ENABLE;
hdma.Init.Mode = DMA_NORMAL;
hdma.Init.Priority = DMA_PRIORITY_MEDIUM;
hdma.XferHalfCpltCallback = DMA_Xfer_Half_Callback_Func;
hdma.XferCpltCallback = DMA_Xfer_Complete_Callback_Func;
hdma.XferErrorCallback = DMA_Xfer_Error_Callback_Func;
err = HAL_DMA_Init(&hdma);
if (err != HAL_OK)
return err;
err = HAL_DMA_Start_IT(hadc->DMA_Handle, SrcAddress, DstAddress, Counts);
if (err != HAL_OK)
return err;
DMA Example 2
ADC module-to-memory 4-byte transfer 4096 bytes.
DMA_HandleTypeDef hdma;
HAL_StatusTypeDef err;
uint32_t SrcAddress = 0x10000000;
uint32_t DstAddress = 0x20000000;
uint32_t Counts = 1024; //Transfer unit is word, so Counts= 4096 / 4
/* Init DMA configure*/
hdma.Instance = DMA1_Channel6;
hdma.Init.Request = DMA_REQUEST_12;
hdma.Init.Direction = DMA_PERIPH_TO_MEMORY;
hdma.Init.PeriphDataAlignment = DMA_PDATAALIGN_WORD;
hdma.Init.MemDataAlignment = DMA_MDATAALIGN_WORD;
hdma.Init.PeriphInc = DMA_PINC_DISABLE; //Peripheral address NOT auto-increment
hdma.Init.MemInc = DMA_MINC_ENABLE;
hdma.Init.Mode = DMA_NORMAL;
hdma.Init.Priority = DMA_PRIORITY_MEDIUM;
hdma.XferHalfCpltCallback = DMA_Xfer_Half_Callback_Func;
hdma.XferCpltCallback = DMA_Xfer_Complete_Callback_Func;
hdma.XferErrorCallback = DMA_Xfer_Error_Callback_Func;
err = HAL_DMA_Init(&hdma);
if (err != HAL_OK)
return err;
err = HAL_DMA_Start_IT(hadc->DMA_Handle, SrcAddress, DstAddress, Counts);
if (err != HAL_OK)
return err;
DMA Example 3
Memory-to-FLASH1 module 1-byte transfer 4096 bytes.
DMA_HandleTypeDef hdma;
HAL_StatusTypeDef err;
uint32_t SrcAddress = 0x20000000;
uint32_t DstAddress = hflash->Instance->DR;
uint32_t Counts = 4096; //Transfer unit is byte, so Counts= 4096 / 1
/* Init DMA configure*/
hdma.Instance = DMA1_Channel6;
hdma.Init.Request = DMA_REQUEST_0;
hdma.Init.Direction = DMA_MEMORY_TO_PERIPH;
hdma.Init.PeriphDataAlignment = DMA_PDATAALIGN_BYTE;
hdma.Init.MemDataAlignment = DMA_MDATAALIGN_BYTE;
hdma.Init.PeriphInc = DMA_PINC_DISABLE; //Peripheral address NOT auto-increment
hdma.Init.MemInc = DMA_MINC_ENABLE;
hdma.Init.Mode = DMA_NORMAL;
hdma.Init.Priority = DMA_PRIORITY_MEDIUM;
hdma.XferHalfCpltCallback = DMA_Xfer_Half_Callback_Func;
hdma.XferCpltCallback = DMA_Xfer_Complete_Callback_Func;
hdma.XferErrorCallback = DMA_Xfer_Error_Callback_Func;
err = HAL_DMA_Init(&hdma);
if (err != HAL_OK)
return err;
err = HAL_DMA_Start_IT(hadc->DMA_Handle, SrcAddress, DstAddress, Counts);
if (err != HAL_OK)
return err;