5.4 DMA Guide
This chapter describes the file layout and the 12 public functions of the DMA driver in the N32G033 standard peripheral library, together with the single example (FLASH_RAM). Read the “DMA” chapter of the user manual for request remapping, transfer direction, and memory-to-memory mode, and the errata sheet for known chip issues.
5.4.1 Related files
| Relative path | Purpose |
|---|---|
firmware/n32g033_std_periph_driver/inc/n32g033_dma.h |
Defines the DMA_InitType structure and the macros for transfer direction, address increment, data width, priority, and request remapping, and declares 12 public functions in one contiguous block |
firmware/n32g033_std_periph_driver/src/n32g033_dma.c |
Implements those 12 functions: channel reset and initialization, enable and transfer counting, interrupt and flag handling, and request remapping |
projects/n32g033_EVAL/examples/DMA/ |
DMA example root directory, with 1 example: FLASH_RAM |
projects/n32g033_EVAL/examples/DMA/FLASH_RAM/ |
Project layout of this example: MDK-ARM/, EWARM/, inc/, src/, and readme.txt |
projects/n32g033_EVAL/bsp/ |
Board support files shared by the examples: the serial log interface in log.h |
5.4.2 API reference
The following 12 public functions are listed in the declaration order of n32g033_dma.h in 1 group; each entry gives a summary and the original comment above the function in n32g033_dma.c.
Reset, initialization, and transfer control
DMA_DeInit, DMA_Init, DMA_StructInit, DMA_EnableChannel, DMA_ConfigInt, DMA_SetCurrDataCounter, DMA_GetCurrDataCounter, DMA_GetFlagStatus, DMA_ClearFlag, DMA_GetIntStatus, DMA_ClrIntPendingBit, 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
return none
void DMA_Init(DMA_ChannelType* DMAChx, 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
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
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
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
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
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
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.
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
return Returns the number of bytes 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
param DMAy (The input parameters must be the following values):
- DMA
return SET or RESET.
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
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
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
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_UART1_TX
- DMA_REMAP_UART1_RX
- DMA_REMAP_UART2_TX
- DMA_REMAP_UART2_RX
- DMA_REMAP_UART3_TX
- DMA_REMAP_UART3_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_TIM1_CH1
- DMA_REMAP_TIM1_CH2
- DMA_REMAP_TIM1_CH3
- DMA_REMAP_TIM1_CH4
- DMA_REMAP_TIM1_COM
- DMA_REMAP_TIM1_UP
- DMA_REMAP_TIM1_TRIG
- DMA_REMAP_TIM3_CH1
- DMA_REMAP_TIM3_CH2
- DMA_REMAP_TIM3_CH3
- DMA_REMAP_TIM3_CH4
- DMA_REMAP_TIM3_UP
- DMA_REMAP_TIM3_TRIG
- DMA_REMAP_TIM4_CH1
- DMA_REMAP_TIM4_CH2
- DMA_REMAP_TIM4_CH3
- DMA_REMAP_TIM4_UP
- DMA_REMAP_TIM4_TRIG
- DMA_REMAP_TIM6_UP
- DMA_REMAP_RESERVED
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
param Cmd:(The input parameters must be the following values)
- ENABLE
- DISABLE
return none.
5.4.3 Demo descriptions
This section describes the single DMA example: FLASH_RAM moves a constant array from FLASH into RAM in memory-to-memory mode and checks the result.
5.4.3.1 FLASH_RAM Memory-to-memory transfer
Example directory: projects/n32g033_EVAL/examples/DMA/FLASH_RAM/
Enable the DMA clock and the channel interrupt→Configure the source address, destination address, and transfer length→Start the memory-to-memory transfer→The transfer-complete interrupt reads the remaining count and clears the flag→Print the verification result over the serial port
| Item | Source analysis |
|---|---|
| Function | Moves the FLASH constant array SRC_Const_Buffer into the RAM array DST_Buffer with DMA in memory-to-memory mode, then compares the two with memcmp and prints the result over the serial port. |
| Source files | src/main.c holds main, RCC_Configuration, and NVIC_Configuration;DMA_IRQ_HANDLER in src/n32g033_it.c reads the remaining count and clears the interrupt flag;inc/main.h and inc/n32g033_it.h give the declarations;readme.txt gives the test steps;the project files are in MDK-ARM/ and EWARM/. |
| Key configuration | Channel: DMA_CH1;source is the FLASH constant array SRC_Const_Buffer and destination is the RAM array DST_Buffer;transfer direction DMA_DIR_PERIPH_SRC, memory-to-memory enabled, word data width;both addresses increment, normal mode, high priority; transfer-complete interrupt enabled, the request source remapped to the reserved item. |
| Program and data path | main -> RCC_Configuration enables the DMA clock on the AHB bus -> NVIC_Configuration enables the DMA interrupt -> DMA_DeInit, DMA_StructInit, and DMA_Init configure the channel -> DMA_RequestRemap maps the reserved request -> DMA_ConfigInt enables the transfer-complete interrupt -> DMA_EnableChannel starts the transfer -> wait for the remaining count to reach zero -> memcmp verifies the data and the result is printed. |
| Main APIs | DMA_DeInit, DMA_StructInit, DMA_Init, DMA_RequestRemap, DMA_ConfigInt, DMA_GetCurrDataCounter, DMA_EnableChannel, DMA_GetIntStatus, DMA_ClrIntPendingBit |
| Verification | The hardware is the N32G033K8Q7-1_STB V1.0 evaluation board, with UART TX on PA9 and RX on PA10 at 115200 baud; after downloading, resetting, and running, the serial port prints DMA Flash to RAM passed, which means the transfer and the check succeeded. |
| Use note | The system clock is 64 MHz; memory-to-memory mode uses no peripheral request, so the example remaps the request source to the reserved item, otherwise the request would land on UART1_TX. |
Core-code walkthrough and porting
The example moves data between FLASH and RAM in DMA memory-to-memory mode and checks that both sides match afterwards.
Data path: RCC_Configuration enables the DMA clock → NVIC_Configuration enables the DMA interrupt → DMA_Init sets the source address, destination address, and transfer length → DMA_EnableChannel starts the transfer → the transfer-complete interrupt reads the remaining count and clears the flag → memcmp verifies the data
1. Enable the clock and the interrupt together. DMA sits on the AHB bus, so its clock must be enabled first and the channel interrupt routed into the NVIC, otherwise the transfer-complete event never reaches the handler.
void RCC_Configuration(void)
{
/* Enable DMA clock */
RCC_EnableAHBPeriphClk(RCC_AHB_PERIPH_DMA, ENABLE);
}
NVIC_InitType NVIC_InitStructure;
/* Enable DMA IRQ Channel */
NVIC_InitStructure.NVIC_IRQChannel = DMA_IRQN;
NVIC_InitStructure.NVIC_IRQChannelPriority = 0;
NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;
NVIC_Init(&NVIC_InitStructure);
Change the interrupt number when you use another DMA channel; the DMA clock bit is on the AHB bus rather than the APB bus, so the wrong bus keeps the channel from working.
2. Give the addresses and transfer parameters in one structure. After DMA_StructInit fills the defaults, the structure sets the source and destination addresses, the transfer direction, the data width, and the memory-to-memory mode.
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);
Direction set to DMA_DIR_PERIPH_SRC treats PeriphAddr as the data source; in memory-to-memory mode both addresses may increment.
3. Remap the request and read the initial value before starting. Memory-to-memory mode recommends remapping the request source to the reserved item, after which the transfer-complete interrupt is enabled and the start count is read before the channel is enabled.
/* In memory-to-memory mode, it is recommended to set an reserved
peripheral request source in the system, otherwise the request
will be mapped to the UART1_TX. */
DMA_RequestRemap(DMA_REMAP_RESERVED, DMA, DMA_CHANNEL_USED, ENABLE);
/* Enable DMA Channel Transfer Complete interrupt */
DMA_ConfigInt(DMA_CHANNEL_USED, DMA_INT_TXC, ENABLE);
/* Get Current Data Counter value before transfer begins */
CurrDataCounterBegin = DMA_GetCurrDataCounter(DMA_CHANNEL_USED);
/* Enable DMA Channel transfer */
DMA_EnableChannel(DMA_CHANNEL_USED, ENABLE);
/* Wait the end of transmission */
while (CurrDataCounterEnd != 0)
{
}
The while loop that waits for the remaining count to reach zero is how the example synchronizes; in real code a flag or interrupt is a more robust way to detect the end.
4. The handler reads back the remaining count and clears the flag, the main flow checks the data. DMA_IRQ_HANDLER reads the remaining data count and clears the global interrupt flag on transfer completion, and the main flow then compares source and destination with memcmp.
void DMA_IRQ_HANDLER(void)
{
/* Test on DMA channel Transfer Complete interrupt */
if (DMA_GetIntStatus(DMA_IT_FLAG_TC, DMA))
{
/* Get Current Data Counter value after complete transfer */
CurrDataCounterEnd = DMA_GetCurrDataCounter(DMA_CHANNEL_USED);
/* Clear DMA channel Half Transfer, Transfer Complete and Global interrupt pending bits */
DMA_ClrIntPendingBit(DMA_IT_FLAG_GL, DMA);
}
}
if (memcmp(SRC_Const_Buffer, DST_Buffer, BUFFER_SIZE) == 0)
{
log_info("DMA Flash to RAM passed\n");
}
else
{
log_error("DMA Flash to RAM failed\n");
}
The comment above DMA_IRQ_HANDLER keeps the name SysTick_Handler, which differs from the actual function name; read the function definition as authoritative.
Corresponding source files: src/main.c, src/n32g033_it.c, firmware/n32g033_std_periph_driver/inc/n32g033_dma.h
5.4.4 Notes and troubleshooting
| Scenario | Check & action | Source |
|---|---|---|
| Memory-to-memory mode | The DMA chapter of the user manual states that this mode uses no peripheral request and needs the request source remapped; map the request source to the reserved item as the manual describes, so the request does not land on UART1_TX. |
User manual |
| Number of data items | The DMA chapter of the user manual states that the transfer count must be set before the channel is enabled and that DMA_SetCurrDataCounter may only be called while the channel is off;disable the channel before changing the transfer length. |
User manual |
| Interrupt and flag clearing | The DMA chapter of the user manual states that the global interrupt status is the logical OR of transfer complete, half transfer, and transfer error; clearing the three interrupt states also clears the global interrupt state. |
User manual |
| Peripheral clock bus | The DMA chapter of the user manual states that DMA uses the AHB clock; confirm the AHB peripheral bit is the one selected when enabling the clock. |
User manual |
Errata sheet V1.0.0 (2025.9.25) covers revision A silicon and lists no DMA entries.