5.6 DMA Guide
This chapter describes the file composition and the 12 public functions of the DMA driver in the N32G41x standard peripheral library: channel reset and initialization, peripheral and memory address and data-width configuration, channel and interrupt enabling, transfer-count read and write, flag and interrupt management, and request remapping. It also shows how the FLASH_RAM example moves data between FLASH and RAM in memory-to-memory mode. Read the DMA request mapping table and the register bit definitions together with the “DMA controller” chapter of the user manual, and take the errata sheet as the authority on known chip issues.
5.6.1 Related files
| Relative path | Purpose |
|---|---|
firmware/n32g41x_std_periph_driver/inc/n32g41x_dma.h |
Defines the DMA_InitType structure and the macros for transfer direction, data width, priority, circular mode, memory-to-memory mode and request remapping, and declares 12 public functions in the six sections reset and initialization, channel enabling, configuration, read/write, interrupt and flag management, and request remapping |
firmware/n32g41x_std_periph_driver/src/n32g41x_dma.c |
Implements those 12 functions: channel register reset and configuration, transfer-count and peripheral and memory address read and write, flag and interrupt status read and clear, and request remapping |
projects/n32g41x_EVAL/examples/DMA/ |
DMA example root directory, containing 1 example, FLASH_RAM |
projects/n32g41x_EVAL/examples/DMA/FLASH_RAM/ |
Directory composition of that example: MDK-ARM/, EWARM/, inc/, src/, readme.txt |
projects/n32g41x_EVAL/bsp/ |
Board support files referenced by the example: the serial log init and print interface and the millisecond delay function |
5.6.2 API reference
The following 12 public functions are listed in the declaration order of n32g41x_dma.h in 6 groups; each entry gives a summary and the original comment above the function in n32g41x_dma.c.
Reset and initialization
DMA_DeInit, DMA_Init, DMA_StructInit
Channel enabling
DMA_EnableChannel
Configuration
DMA_ConfigInt
Read/write
DMA_SetCurrDataCounter, DMA_GetCurrDataCounter
Interrupt and flag management
DMA_GetFlagStatus, DMA_ClearFlag, DMA_GetIntStatus, DMA_ClrIntPendingBit
Request remap
DMA_RequestRemap
void DMA_DeInit(DMA_ChannelType *DMAChx)Reset CHCFG, TXNUM, PADDR, MADDR, INTCLR registers of DMA Channel x to their default reset values.
name DMA_DeInit.
fun Reset CHCFG, TXNUM, PADDR, MADDR, INTCLR registers of DMA Channel x
to their default reset values.
param DMAChx (The input parameters must be the following values):
- DMA_CH1
- DMA_CH2
- DMA_CH3
- DMA_CH4
- DMA_CH5
- DMA_CH6
- DMA_CH7
return none
Use note: The implementation first clears the channel enable bit of DMA_CHCFGx, then clears CHCFG, TXNUM, PADDR and MADDR, and writes the interrupt mask of the corresponding channel to DMA_INTCLR to clear all its interrupt flags.
void DMA_Init(DMA_ChannelType *DMAChx, const DMA_InitType *DMA_InitParam)Initializes the DMA Channel x by the structure parameter DMA_InitParam of type DMA_InitType. Includes configuration peripheral/memory address, transmission direction, address increment mode, data bit width, priority, etc.
name DMA_Init.
fun Initializes the DMA Channel x by the structure parameter
DMA_InitParam of type DMA_InitType. Includes configuration
peripheral/memory address, transmission direction, address
increment mode, data bit width, priority, etc.
param DMAChx (The input parameters must be the following values):
- DMA_CH1
- DMA_CH2
- DMA_CH3
- DMA_CH4
- DMA_CH5
- DMA_CH6
- DMA_CH7
param DMA_InitParam (The input parameters must be the following values):
- PeriphAddr
-0x00000000~0xFFFFFFFF
- MemAddr
-0x00000000~0xFFFFFFFF
- Direction
- DMA_DIR_PERIPH_DST
- DMA_DIR_PERIPH_SRC
- BufSize
-0x0000~0xFFFF
- PeriphInc
- DMA_PERIPH_INC_ENABLE
- DMA_PERIPH_INC_DISABLE
- DMA_MemoryInc
- DMA_MEM_INC_ENABLE
- DMA_MEM_INC_DISABLE
- PeriphDataSize
- DMA_PERIPH_DATA_SIZE_BYTE
- DMA_PERIPH_DATA_SIZE_HALFWORD
- DMA_PERIPH_DATA_SIZE_WORD
- MemDataSize
- DMA_MemoryDataSize_Byte
- DMA_MemoryDataSize_HalfWord
- DMA_MemoryDataSize_Word
- CircularMode
- DMA_MODE_CIRCULAR
- DMA_MODE_NORMAL
- Priority
- DMA_PRIORITY_VERY_HIGH
- DMA_PRIORITY_HIGH
- DMA_PRIORITY_MEDIUM
- DMA_PRIORITY_LOW
- Mem2Mem
- DMA_M2M_ENABLE
- DMA_M2M_DISABLE
return none
Use note: The implementation first reads DMA_CHCFGx and clears the bits defined by CCR_CLEAR_Mask (0xFFFF800F), then sets the configuration bits, and afterwards writes DMA_TXNUMx, DMA_PADDRx and DMA_MADDRx; apart from the masked bits, the channel enable bit and the interrupt enable bits are left unchanged.
void DMA_StructInit(DMA_InitType *DMA_InitParam)Initializes the structure parameter of type DMA_InitType used to initialize DMA. This function is usually called before initializing a parameter of type DMA_InitType.
name DMA_StructInit.
fun Initializes the structure parameter of type DMA_InitType used to
initialize DMA. This function is usually called before initializing
a parameter of type DMA_InitType.
param DMA_InitParam :
- Pointer to the DMA_InitType structure which will be initialized.
return none
Use note: The implementation sets PeriphAddr, MemAddr and BufSize to 0, Direction to DMA_DIR_PERIPH_SRC, the address increment, data width and circular mode to their disabled or smallest configuration, Priority to DMA_PRIORITY_LOW, and Mem2Mem to DMA_M2M_DISABLE.
void DMA_EnableChannel(DMA_ChannelType *DMAChx, FunctionalState Cmd)DMA Channel x Channel enable. This function is called after DMA initialization is successful to start moving data.
name DMA_EnableChannel.
fun DMA Channel x Channel enable. This function is called after DMA
initialization is successful to start moving data.
param DMAChx (The input parameters must be the following values):
- DMA_CH1
- DMA_CH2
- DMA_CH3
- DMA_CH4
- DMA_CH5
- DMA_CH6
- DMA_CH7
param Cmd (The input parameters must be the following values):
- ENABLE
- DISABLE
return none
void DMA_ConfigInt(DMA_ChannelType *DMAChx, uint32_t DMAInt, FunctionalState Cmd)DMA Channel x interrupts enable. Before enabling a DMA channel, enabling transfer completion interrupt, half-transfer interrupt or transfer error interrupt will cause an interrupt when the corresponding event occurs.
name DMA_ConfigInt.
fun DMA Channel x interrupts enable. Before enabling a DMA channel,
enabling transfer completion interrupt, half-transfer interrupt
or transfer error interrupt will cause an interrupt when the
corresponding event occurs.
param DMAChx (The input parameters must be the following values):
- DMA_CH1
- DMA_CH2
- DMA_CH3
- DMA_CH4
- DMA_CH5
- DMA_CH6
- DMA_CH7
param DMAInt (The input parameters must be the following values):
- DMA_INT_TXC
- DMA_INT_HTX
- DMA_INT_ERR
param Cmd (The input parameters must be the following values):
- ENABLE
- DISABLE
return none
void DMA_SetCurrDataCounter(DMA_ChannelType *DMAChx, uint16_t DataNumber)Set the current number of data transfers for DMA Channel x.
name DMA_SetCurrDataCounter.
fun Set the current number of data transfers for DMA Channel x.
param DMAChx (The input parameters must be the following values):
- DMA_CH1
- DMA_CH2
- DMA_CH3
- DMA_CH4
- DMA_CH5
- DMA_CH6
- DMA_CH7
param DataNumber(The input parameters must be the following values) :
- 0~0xFFFF
return none
note This function can only be used when the DMAChx is disabled.
Use note: The implementation writes DataNumber directly to DMA_TXNUMx; the source comment states that this function can only be used while the channel is disabled.
uint16_t DMA_GetCurrDataCounter(const DMA_ChannelType *DMAChx)Get the current number of remaining data for DMA Channel x.
name DMA_GetCurrDataCounter.
fun Get the current number of remaining data for DMA Channel x.
param DMAChx (The input parameters must be the following values):
- DMA_CH1
- DMA_CH2
- DMA_CH3
- DMA_CH4
- DMA_CH5
- DMA_CH6
- DMA_CH7
return Returns the number of data units remaining to be transferred.
FlagStatus DMA_GetFlagStatus(uint32_t DMAFlag, const DMA_Module *DMAy)Get DMA Channel x flag status. Contains the global flag, transfer completion flag, half-transfer flag, and transfer error flag for the corresponding channel.
name DMA_GetFlagStatus.
fun Get DMA Channel x flag status. Contains the global flag, transfer
completion flag, half-transfer flag, and transfer error flag for
the corresponding channel.
param DMAFlag (The input parameters must be the following values):
- DMA_FLAG_GL1
- DMA_FLAG_TC1
- DMA_FLAG_HT1
- DMA_FLAG_TE1
- DMA_FLAG_GL2
- DMA_FLAG_TC2
- DMA_FLAG_HT2
- DMA_FLAG_TE2
- DMA_FLAG_GL3
- DMA_FLAG_TC3
- DMA_FLAG_HT3
- DMA_FLAG_TE3
- DMA_FLAG_GL4
- DMA_FLAG_TC4
- DMA_FLAG_HT4
- DMA_FLAG_TE4
- DMA_FLAG_GL5
- DMA_FLAG_TC5
- DMA_FLAG_HT5
- DMA_FLAG_TE5
- DMA_FLAG_GL6
- DMA_FLAG_TC6
- DMA_FLAG_HT6
- DMA_FLAG_TE6
- DMA_FLAG_GL7
- DMA_FLAG_TC7
- DMA_FLAG_HT7
- DMA_FLAG_TE7
param DMAy (The input parameters must be the following values):
- DMA
return SET or RESET.
Use note: The implementation reads DMA_INTSTS and ANDs it with DMAFlag; the DMA_FLAG_* macros are defined in the header as the clear bits of DMA_INTCLR, at the same bit positions as the status bits of DMA_INTSTS.
void DMA_ClearFlag(uint32_t DMAFlag, DMA_Module *DMAy)Clear DMA Channel x flag status. Contains the global flag, transfer completion flag, half-transfer flag, and transfer error flag for the corresponding channel.
name DMA_ClearFlag.
fun Clear DMA Channel x flag status. Contains the global flag, transfer
completion flag, half-transfer flag, and transfer error flag for the
corresponding channel.
param DMAFlag (The input parameters must be the following values):
- DMA_FLAG_GL1
- DMA_FLAG_TC1
- DMA_FLAG_HT1
- DMA_FLAG_TE1
- DMA_FLAG_GL2
- DMA_FLAG_TC2
- DMA_FLAG_HT2
- DMA_FLAG_TE2
- DMA_FLAG_GL3
- DMA_FLAG_TC3
- DMA_FLAG_HT3
- DMA_FLAG_TE3
- DMA_FLAG_GL4
- DMA_FLAG_TC4
- DMA_FLAG_HT4
- DMA_FLAG_TE4
- DMA_FLAG_GL5
- DMA_FLAG_TC5
- DMA_FLAG_HT5
- DMA_FLAG_TE5
- DMA_FLAG_GL6
- DMA_FLAG_TC6
- DMA_FLAG_HT6
- DMA_FLAG_TE6
- DMA_FLAG_GL7
- DMA_FLAG_TC7
- DMA_FLAG_HT7
- DMA_FLAG_TE7
param DMAy (The input parameters must be the following values):
- DMA
return none.
INTStatus DMA_GetIntStatus(uint32_t DMA_IT, const DMA_Module *DMAy)Get DMA Channel x interrupt status. Contains the global interrupt, transfer completion interrupt, half-transfer interrupt, and transfer error interrupt for the corresponding channel.
name DMA_GetIntStatus.
fun Get DMA Channel x interrupt status. Contains the global interrupt,
transfer completion interrupt, half-transfer interrupt, and transfer
error interrupt for the corresponding channel.
param DMA_IT (The input parameters must be the following values):
- DMA_INT_GLB1
- DMA_INT_TXC1
- DMA_INT_HTX1
- DMA_INT_ERR1
- DMA_INT_GLB2
- DMA_INT_TXC2
- DMA_INT_HTX2
- DMA_INT_ERR2
- DMA_INT_GLB3
- DMA_INT_TXC3
- DMA_INT_HTX3
- DMA_INT_ERR3
- DMA_INT_GLB4
- DMA_INT_TXC4
- DMA_INT_HTX4
- DMA_INT_ERR4
- DMA_INT_GLB5
- DMA_INT_TXC5
- DMA_INT_HTX5
- DMA_INT_ERR5
- DMA_INT_GLB6
- DMA_INT_TXC6
- DMA_INT_HTX6
- DMA_INT_ERR6
- DMA_INT_GLB7
- DMA_INT_TXC7
- DMA_INT_HTX7
- DMA_INT_ERR7
param DMAy (The input parameters must be the following values):
- DMA
return SET or RESET.
note Global interrupt status is the logic or generation of transfer completion
interrupt, half-transfer interrupt, transfer error interrupt.
void DMA_ClrIntPendingBit(uint32_t DMA_IT, DMA_Module *DMAy)Clear DMA Channel x interrupt status bits. Contains the global interrupt, transfer completion interrupt, half-transfer interrupt, and transfer error interrupt for the corresponding channel.
name DMA_ClrIntPendingBit.
fun Clear DMA Channel x interrupt status bits. Contains the global interrupt,
transfer completion interrupt, half-transfer interrupt, and transfer
error interrupt for the corresponding channel.
param DMA_IT (The input parameters must be the following values):
- DMA_INT_GLB1
- DMA_INT_TXC1
- DMA_INT_HTX1
- DMA_INT_ERR1
- DMA_INT_GLB2
- DMA_INT_TXC2
- DMA_INT_HTX2
- DMA_INT_ERR2
- DMA_INT_GLB3
- DMA_INT_TXC3
- DMA_INT_HTX3
- DMA_INT_ERR3
- DMA_INT_GLB4
- DMA_INT_TXC4
- DMA_INT_HTX4
- DMA_INT_ERR4
- DMA_INT_GLB5
- DMA_INT_TXC5
- DMA_INT_HTX5
- DMA_INT_ERR5
- DMA_INT_GLB6
- DMA_INT_TXC6
- DMA_INT_HTX6
- DMA_INT_ERR6
- DMA_INT_GLB7
- DMA_INT_TXC7
- DMA_INT_HTX7
- DMA_INT_ERR7
param DMAy (The input parameters must be the following values):
- DMA
return none.
note Global interrupt state is the logic or generation of transfer completion
interrupt, half-transfer interrupt, transfer error interrupt. In fact,
after clearing the three interrupt states, the global interrupt state
will also be cleared.
void DMA_RequestRemap(uint32_t DMA_REMAP, const DMA_Module *DMAy, DMA_ChannelType *DMAChx, FunctionalState Cmd)Set DMA Channel x’s remap request. Channel request mapping is flexible, allowing users to map any DMA request to any DMA channel as needed. It is important to note that there can be only one DMA request per DMA channel at a time.
name DMA_RequestRemap.
fun Set DMA Channel x's remap request. Channel request mapping is flexible,
allowing users to map any DMA request to any DMA channel as needed. It
is important to note that there can be only one DMA request per DMA
channel at a time.
param DMA_REMAP (The input parameters must be the following values):
- DMA_REMAP_ADC1
- DMA_REMAP_ADC2
- DMA_REMAP_USART1_TX
- DMA_REMAP_USART1_RX
- DMA_REMAP_USART2_TX
- DMA_REMAP_USART2_RX
- DMA_REMAP_USART3_TX
- DMA_REMAP_USART3_RX
- DMA_REMAP_USART4_TX
- DMA_REMAP_USART4_RX
- DMA_REMAP_SPI1_TX
- DMA_REMAP_SPI1_RX
- DMA_REMAP_SPI2_TX
- DMA_REMAP_SPI2_RX
- DMA_REMAP_I2C1_TX
- DMA_REMAP_I2C1_RX
- DMA_REMAP_I2C2_TX
- DMA_REMAP_I2C2_RX
- DMA_REMAP_ATIM1_CH1
- DMA_REMAP_ATIM1_CH2
- DMA_REMAP_ATIM1_CH3
- DMA_REMAP_ATIM1_CH4
- DMA_REMAP_ATIM1_COM
- DMA_REMAP_ATIM1_UP
- DMA_REMAP_ATIM1_TRIG
- DMA_REMAP_ATIM2_CH1
- DMA_REMAP_ATIM2_CH2
- DMA_REMAP_ATIM2_CH3
- DMA_REMAP_ATIM2_CH4
- DMA_REMAP_ATIM2_COM
- DMA_REMAP_ATIM2_UP
- DMA_REMAP_ATIM2_TRIG
- DMA_REMAP_GTIM1_CH1
- DMA_REMAP_GTIM1_CH2
- DMA_REMAP_GTIM1_CH3
- DMA_REMAP_GTIM1_CH4
- DMA_REMAP_GTIM1_UP
- DMA_REMAP_GTIM1_TRIG
- DMA_REMAP_GTIM2_CH1
- DMA_REMAP_GTIM2_CH2
- DMA_REMAP_GTIM2_CH3
- DMA_REMAP_GTIM2_CH4
- DMA_REMAP_GTIM2_UP
- DMA_REMAP_GTIM2_TRIG
- DMA_REMAP_GTIM3_CH1
- DMA_REMAP_GTIM3_CH2
- DMA_REMAP_GTIM3_CH3
- DMA_REMAP_GTIM3_CH4
- DMA_REMAP_GTIM3_COM
- DMA_REMAP_GTIM3_UP
- DMA_REMAP_GTIM3_TRIG
- DMA_REMAP_GTIM4_CH1
- DMA_REMAP_GTIM4_CH2
- DMA_REMAP_GTIM4_CH3
- DMA_REMAP_GTIM4_CH4
- DMA_REMAP_GTIM4_COM
- DMA_REMAP_GTIM4_UP
- DMA_REMAP_GTIM4_TRIG
- DMA_REMAP_BIM1_UP
- DMA_REMAP_BIM2_UP
param DMAy (The input parameters must be the following values):
- DMA
param DMAChx (The input parameters must be the following values):
- DMA_CH1
- DMA_CH2
- DMA_CH3
- DMA_CH4
- DMA_CH5
- DMA_CH6
- DMA_CH7
param Cmd (The input parameters must be the following values):
- ENABLE
- DISABLE
return none.
Use note: The implementation ignores the DMAy parameter and writes DMA_REMAP to CHSEL of DMAChx according to Cmd, writing the reserved value DMA_REMAP_NONE (0x3F) when Cmd is DISABLE; that reserved value is defined in the header but is not in the parameter list of the comment.
5.6.3 Demo descriptions
This section describes the 1 example of DMA: FLASH_RAM moves a constant array from FLASH to a RAM buffer in memory-to-memory mode and compares the two buffers after the transfer.
5.6.3.1 FLASH_RAM Memory-to-memory transfer
Example directory: projects/n32g41x_EVAL/examples/DMA/FLASH_RAM/
Enable the DMA clock and set up the serial log→configure DMA channel 1 for a memory-to-memory transfer→map the channel request to a reserved source→enable the transfer-complete interrupt and start the channel→set the completion flag in the transfer-complete interrupt→compare the source and destination buffers and print the result
| Item | Source analysis |
|---|---|
| Function | Uses DMA in memory-to-memory mode to move a 32-word constant array from FLASH to a RAM buffer, then compares the source and destination buffers with memcmp and prints a pass message over the serial port when they match. |
| Source files | src/main.c: main, RCC_Configuration, NVIC_Configuration, DMA_IRQ_HANDLER and the constant array;inc/main.h: the channel, clock, interrupt and buffer-size macros;src/n32g41x_it.c, inc/n32g41x_it.h: exception and SysTick handlers;readme.txt: function, environment and usage;MDK-ARM/, EWARM/: Keil and IAR projects.The log interface log_init, log_info and log_error comes from bsp/inc/log.h. |
| Key configuration | Channel DMA_CH1 with clock RCC_AHB_PERIPH_DMA;PeriphAddr points to SRC_Const_Buffer in FLASH and MemAddr points to DST_Buffer in RAM, direction DMA_DIR_PERIPH_SRC, BufSize is BUFFER_SIZE (32);both the peripheral and the memory address increment, both data widths are word, normal mode, high priority, Mem2Mem enabled;the request is remapped to a reserved source; the interrupt is DMA_INT_TXC1 with NVIC preemption and sub-priority both 0 and IRQ number DMA_CH1_IRQn. The system clock is HSI+PLL, 80 MHz on the N32G412 and 96 MHz on the N32G415. |
| Program and data path | main calls log_init;RCC_Configuration enables the DMA clock and NVIC_Configuration enables the DMA interrupt;after memset clears DST_Buffer, DMA_StructInit loads the defaults and DMA_Init writes the channel registers;DMA_RequestRemap maps the request to a reserved source, DMA_ConfigInt enables the transfer-complete interrupt and DMA_EnableChannel starts the channel;main polls until the interrupt sets TransferCompleteFlag, then the two buffers are compared and the result printed. |
| Main APIs | DMA_DeInit, DMA_StructInit, DMA_Init, DMA_RequestRemap, DMA_ConfigInt, DMA_EnableChannel, DMA_GetIntStatus, DMA_ClrIntPendingBit |
| Verification | After compiling, downloading and resetting, the serial port first prints DMA Flash to RAM demo go...;when the transfer completes and the check matches it prints DMA Flash to RAM passed, otherwise DMA Flash to RAM failed. |
| Use note | The clock source is HSI+PLL, 80 MHz on the N32G412 and 96 MHz on the N32G415; the serial port uses PA9 for TX and PA10 for RX at 115200 bps; the development environment is KEIL MDK-ARM V5.34 or IAR EWARM 8.50.1. |
Core-code walkthrough and porting
The example selects the DMA channel and buffer size with one group of macros, fills DMA_InitType, starts a memory-to-memory transfer, and lets the transfer-complete interrupt notify the main program to check the result.
Data path: SRC_Const_Buffer (FLASH) -> the PeriphAddr and MemAddr fields of DMA_InitStructure -> DMA_Init writes PADDR, MADDR and TXNUM of DMA_CH1 -> the transfer-complete interrupt sets TransferCompleteFlag -> memcmp compares DST_Buffer -> the result is printed over the serial port
1. Define the channel and buffer size with macros. inc/main.h groups the channel, clock, interrupt and buffer length into one set of macros that the rest of the code references by name.
#define DMA_USED DMA
#define DMA_CLK RCC_AHB_PERIPH_DMA
#define DMA_CHANNEL_USED DMA_CH1
#define DMA_IRQ_HANDLER DMA_CH1_IRQHandler
#define DMA_IT_FLAG_TC DMA_INT_TXC1
#define DMA_IT_FLAG_GL DMA_INT_GLB1
#define DMA_IRQN DMA_CH1_IRQn
#define BUFFER_SIZE (sizeof(SRC_Const_Buffer) / sizeof(SRC_Const_Buffer[0]))
extern const uint32_t SRC_Const_Buffer[];
When moving to another channel or changing the transfer length, only this group of macros changes; the configuration and the interrupt handler in main stay the same.
2. Fill DMA_InitType and write the channel registers. main first resets the channel with DMA_DeInit and loads the defaults with DMA_StructInit, then sets the source and destination addresses, direction, buffer length, address increment, data widths, circular mode, priority and the memory-to-memory bit field by field, and finally DMA_Init writes them.
DMA_DeInit(DMA_CHANNEL_USED);
DMA_StructInit(&DMA_InitStructure);
DMA_InitStructure.PeriphAddr = (uint32_t)SRC_Const_Buffer;
DMA_InitStructure.MemAddr = (uint32_t)DST_Buffer;
DMA_InitStructure.Direction = DMA_DIR_PERIPH_SRC;
DMA_InitStructure.BufSize = BUFFER_SIZE;
DMA_InitStructure.PeriphInc = DMA_PERIPH_INC_ENABLE;
DMA_InitStructure.DMA_MemoryInc = DMA_MEM_INC_ENABLE;
DMA_InitStructure.PeriphDataSize = DMA_PERIPH_DATA_SIZE_WORD;
DMA_InitStructure.MemDataSize = DMA_MemoryDataSize_Word;
DMA_InitStructure.CircularMode = DMA_MODE_NORMAL;
DMA_InitStructure.Priority = DMA_PRIORITY_HIGH;
DMA_InitStructure.Mem2Mem = DMA_M2M_ENABLE;
DMA_Init(DMA_CHANNEL_USED, &DMA_InitStructure);
The direction is DMA_DIR_PERIPH_SRC, so the PeriphAddr side is the source; both peripheral and memory data widths are word, so no width alignment is performed while they match.
3. Map the request first, then enable the interrupt and the channel. In memory-to-memory mode the example maps the channel request to a reserved source, enables the transfer-complete interrupt, and finally enables the channel to start the transfer.
DMA_RequestRemap(DMA_REMAP_NONE, DMA, DMA_CHANNEL_USED, ENABLE);
DMA_ConfigInt(DMA_CHANNEL_USED, DMA_INT_TXC, ENABLE);
DMA_EnableChannel(DMA_CHANNEL_USED, ENABLE);
The DMA_REMAP_NONE passed to DMA_RequestRemap is the reserved request value defined in the header; for a peripheral-triggered transfer this must be changed to the corresponding DMA_REMAP_* source.
4. The interrupt sets the completion flag and the main program compares the buffers. The transfer-complete interrupt reads and clears the completion flag of channel 1 and sets TransferCompleteFlag; after the wait loop the main program compares the source and destination buffers with memcmp.
void DMA_IRQ_HANDLER(void)
{
if (DMA_GetIntStatus(DMA_IT_FLAG_TC, DMA_USED))
{
DMA_ClrIntPendingBit(DMA_IT_FLAG_TC, DMA_USED);
TransferCompleteFlag = 1;
}
}
while (TransferCompleteFlag == 0) {}
if (memcmp(SRC_Const_Buffer, DST_Buffer, sizeof(SRC_Const_Buffer)) == 0)
{
log_info("DMA Flash to RAM passed\n");
}
else
{
log_error("DMA Flash to RAM failed\n");
}
DMA_INT_TXC1 and DMA_IT_FLAG_TC refer to the transfer-complete interrupt of channel 1; when another channel is used, DMA_IT_FLAG_TC, DMA_IRQN and the interrupt handler name must be changed to that channel’s macros and handler.
Corresponding source files: src/main.c, inc/main.h
5.6.4 Notes and troubleshooting
| Scenario | Check & action | Source |
|---|---|---|
| Moving data to FLASH with DMA | Chapter 7 of the user manual states that DMA must not be used to program FLASH, to avoid timing errors; a memory-to-memory transfer involving FLASH only reads, and FLASH writing is done by other means. |
User manual |
| Request mapping in memory-to-memory mode | The user manual says that when a channel is configured for memory-to-memory mode its request selection value must be set to a reserved value (for example 63); the channel configuration flow requires the MEM2MEM bit to be configured first and the channel to be enabled last. |
User manual |
| Interrupt state before enabling the channel | The interrupt description in the user manual requires all interrupts of that channel to be cleared before the channel is enabled; an interrupt status bit is cleared by writing 1 to the corresponding bit of the clear register. |
User manual |
| Writing registers after the channel is enabled | DMA_TXNUMx is read-only once the channel is enabled, and DMA_PADDRx and DMA_MADDRx can be written only while the channel is disabled (DMA_CHCFGx.CHEN is 0);disable the channel before changing these registers. |
User manual |
| Turning off circular mode | The user manual says circular mode is turned off by writing 0 to DMA_CHCFGx.CHEN to disable the channel and then writing 0 to CIRC;while the channel is enabled the other bits of DMA_CHCFGx cannot be rewritten. |
User manual |
| Several channels sharing one request source | The request mapping notes in the user manual state that different channels must not use the same request source, otherwise only the higher-priority channel is triggered when several channels are enabled. | User manual |
| Alignment when the data widths differ | When DMA_CHCFGx.PSIZE and DMA_CHCFGx.MSIZE differ, DMA aligns the data according to the programmable data width table of the user manual;to write an 8-bit register at a 32-bit address boundary, set the peripheral size to 8 bits and the memory size to 32 bits. |
User manual |
The N32G412 and N32G415 series errata sheet V1.0.0 (2026.6.30) lists a single row for revision A chips with an empty errata link column, and gives no DMA-related entries.