on 2026-03-18 6:00 AM
This guide describes how to enable and configure DMA in memory-to-memory mode using STM32CubeMX2. The example uses the NUCLEO-C562RE board.
Direct memory access (DMA) enables data transfers between memory and peripherals, or between memory regions, without CPU intervention. This nonblocking operation allows the CPU to perform other tasks while data transfer occurs in the background, improving system efficiency.
This guide provides an example of configuring a memory-to-memory DMA transfer.
Install the following tools:
The hardware used in this tutorial is the NUCLEO-C562RE board.
Follow these steps to create an application project for the NUCLEO-C562RE board. The hands-on creates a simple memory-to-memory transfer using DMA.
Open STM32CubeMX2. On the Home page, click the MCU square to create a new project.
In the search field under MCU name, enter STM32C562RE and select the MCU. Click [Continue].
Enter the project name and location. Click [Automatically Download, Install & Create Project] to finish project creation.
Select Launch Project to start.
To configure DMA in STM32CubeMX2:
To generate the code:
Open Visual Studio Code and open the project folder.
If prompted, select the configuration. If not prompted, press Ctrl+Shift+P, type CMake: Select Configure Preset, and choose the debug configuration.
Build the project to ensure everything is set, then proceed to code implementation.
Go to the main.c file and add the following code in the indicated sections. Setup an application to copy data from one buffer to another using DMA. The entire main.c is provided below to facilitate.
/**
******************************************************************************
* file : main.c
* brief : Main program body
* Calls target system initialization then loop in main.
******************************************************************************
*
* Copyright (c) 2025 STMicroelectronics.
* All rights reserved.
*
* This software is licensed under terms that can be found in the LICENSE file
* in the root directory of this software component.
* If no LICENSE file comes with this software, it is provided AS-IS.
*
******************************************************************************
*/
/* Includes ------------------------------------------------------------------*/
#include "main.h"
/* Private typedef -----------------------------------------------------------*/
/* Private define ------------------------------------------------------------*/
#define BUFFER_SIZE 2
/* Private macro -------------------------------------------------------------*/
/* Private variables ---------------------------------------------------------*/
hal_dma_handle_t *dmaHandle;
uint32_t sourceBuffer[BUFFER_SIZE] = {32, 64};
__attribute__((section(".bss.non_cacheable_variables"), aligned(32U))) uint32_t destinationBuffer[BUFFER_SIZE];
volatile uint8_t completeDMA = 0U;
/* Private functions prototype -----------------------------------------------*/
/**
* brief: The application entry point.
* retval: none but we specify int to comply with C99 standard
*/
int main(void)
{
/** System Init: this code placed in targets folder initializes your system.
* It calls the initialization (and sets the initial configuration) of the peripherals.
* You can use STM32CubeMX to generate and call this code or not in this project.
* It also contains the HAL initialization and the initial clock configuration.
*/
if (mx_system_init() != SYSTEM_OK)
{
return (-1);
}
else
{
/*
* You can start your application code here
*/
dmaHandle = mx_lpdma1_ch0_init();
if (dmaHandle == NULL) {
return -1;
}
if (HAL_DMA_StartDirectXfer_IT(dmaHandle, (uint32_t)sourceBuffer,
(uint32_t)destinationBuffer,
4 * BUFFER_SIZE) != HAL_OK) {
return -1;
}
while (1) {
if (completeDMA == 1U) {
__NOP();
}
}
}
}
void HAL_DMA_XferCpltCallback(hal_dma_handle_t *hdma)
{
STM32_UNUSED(hdma);
completeDMA = 1U;
}
/* end main */
After building the application, select the [Run and Debug] icon. Create a debug session by selecting the [STLINK GDB Server] option.
At the start of execution, the destination buffer contains zeros. Use the Watch feature in Visual Studio Code’s "Run and Debug" tab to monitor variable values in real time..
Add a breakpoint in the DMA callback and, after running the program, the DMA transfer complete callback function is called, indicating that the data transfer finished successfully.
By observing the Watch window, verify that the source buffer’s contents were copied to the destination buffer.
This guide describes how to configure and use the DMA feature in STM32CubeMX2 with the NUCLEO-C562RE board. By enabling and setting up the LPDMA1 channel, configuring NVIC for interrupts, and generating the necessary code, you can perform memory-to-memory data transfers without CPU intervention. The example application demonstrates how to use DMA to copy data between buffers asynchronously, improving system performance by freeing the CPU for other tasks.