on
2024-10-16
05:30 AM
- edited on
2024-10-23
05:19 AM
by
Laurids_PETERSE
This article provides a step-by-step guide on configuring the GPDMA linked list in STM32CubeMX. It does not cover the legacy standard DMA approach, which is described in the article "How to configure the GPDMA."
The versions used in this tutorial are:
Alternatively to the direct programming mode, a channel can be programmed by a list of transfers, known as a list of linked-list items (LLI). Each LLI is defined by its data structure. The LLI is mapped in memory and contains an image of the values to be initialized into the DMA channel registers. Thus, the DMA channel registers programming becomes an indirect operation.
The GPDMA has lists containing configuration nodes that the GPDMA uses.
Each linked list node will update the following GPDMA registers after the previous GPDMA node is finished:
Transfer register 1 |
Transfer register 2 |
Block register 1 |
Source address register |
Destination address register |
Transfer register 3 |
Block register 2 |
Linked list register |
TR1 |
TR2 |
BR1 |
SAR |
DAR |
TR3 |
BR2 |
LLR |
Start a new project and enable the instruction cache [ICACHE] to reach the maximum performance.
The first node in the loop is where the LLR from the last node in the queue is pointed. If there is only one node, it reloads the same configuration upon completion.
Now, generate the code and switch to STM32CubeIDE.
Firstly, include the linked_list.h in the main.c by adding between /*USER CODE BEGIN Includes*\ and /*USER CODE END Includes*\
/* USER CODE BEGIN Includes */
#include "linked_list.h"
/* USER CODE END Includes */
/* USER CODE BEGIN PV */
extern uint32_t aSRC_Buffer1[8U];
extern uint32_t aSRC_Buffer2[16U];
extern uint32_t aSRC_Buffer3[24U];
extern uint32_t aDST_Buffer1[8U];
extern uint32_t aDST_Buffer2[16U];
extern uint32_t aDST_Buffer3[24U];
/* USER CODE END PV */
/* USER CODE BEGIN PFP */
static void TransferComplete(DMA_HandleTypeDef *hdma);
static void TransferError(DMA_HandleTypeDef *hdma);
/* USER CODE END PFP */
/* USER CODE BEGIN 0 */
__IO uint32_t TransferCompleteDetected = 0U, TransferErrorDetected = 0U;
/* USER CODE END 0 */
/* USER CODE BEGIN Private defines */
#define BUFFER1_SIZE 8U
#define BUFFER2_SIZE 16U
#define BUFFER3_SIZE 24U
/* USER CODE END Private defines */
/* Private macro -------------------------------------------------------------*/
/* USER CODE BEGIN PM */
uint32_t aSRC_Buffer1[BUFFER1_SIZE] =
{
0x01020304, 0x05060708, 0x090A0B0C, 0x0D0E0F10,
0x11121314, 0x15161718, 0x191A1B1C, 0x1D1E1F20,
};
uint32_t aSRC_Buffer2[BUFFER2_SIZE] =
{
0x01020304, 0x05060708, 0x090A0B0C, 0x0D0E0F10,
0x11121314, 0x15161718, 0x191A1B1C, 0x1D1E1F20,
0x21222324, 0x25262728, 0x292A2B2C, 0x2D2E2F30,
0x31323334, 0x35363738, 0x393A3B3C, 0x3D3E3F40,
};
uint32_t aSRC_Buffer3[BUFFER3_SIZE] =
{
0x01020304, 0x05060708, 0x090A0B0C, 0x0D0E0F10,
0x11121314, 0x15161718, 0x191A1B1C, 0x1D1E1F20,
0x21222324, 0x25262728, 0x292A2B2C, 0x2D2E2F30,
0x31323334, 0x35363738, 0x393A3B3C, 0x3D3E3F40,
0x41424344, 0x45464748, 0x494A4B4C, 0x4D4E4F50,
0x51525354, 0x55565758, 0x595A5B5C, 0x5D5E5F60,
};
uint32_t aDST_Buffer1[BUFFER1_SIZE];
uint32_t aDST_Buffer2[BUFFER2_SIZE];
uint32_t aDST_Buffer3[BUFFER3_SIZE];
/* USER CODE END PM */
/* USER CODE BEGIN PV */
extern DMA_QListTypeDef Queue;
/* USER CODE END PV */
/* USER CODE BEGIN 2 */
MX_Queue_Config();
/* USER CODE END 2 */
This function creates the node configuration from the structure by using HAL_DMAEx_List_BuildNode. The node is copied in GPDMA registers without linking the nodes yet.
To link the nodes together STM32CubeMX, use HAL_DMAEx_List_InsertNode_Tail to create the queue.
/* USER CODE BEGIN 2 */
MX_Queue_Config();
HAL_DMAEx_List_LinkQ(&handle_GPDMA1_Channel0, &Queue);
/* USER CODE END 2 */
/* USER CODE BEGIN 4 */
static void TransferComplete(DMA_HandleTypeDef *hdma)
{
TransferCompleteDetected = 1U;
}
static void TransferError(DMA_HandleTypeDef *hdma)
{
TransferErrorDetected = 1U;
}
/* USER CODE END 4 */
/* USER CODE BEGIN 2 */
MX_Queue_Config();
HAL_DMAEx_List_LinkQ(&handle_GPDMA1_Channel0, &Queue);
HAL_DMA_RegisterCallback(&handle_GPDMA1_Channel7, HAL_DMA_XFER_CPLT_CB_ID, TransferComplete);
HAL_DMA_RegisterCallback(&handle_GPDMA1_Channel0, HAL_DMA_XFER_ERROR_CB_ID, TransferError);
/* USER CODE END 2 */
if (HAL_DMAEx_List_Start_IT(&handle_GPDMA1_Channel0) != HAL_OK)
{
Error_Handler();
}
while ((TransferCompleteDetected == 0) && (TransferErrorDetected == 0U));
if (TransferErrorDetected == 1U)
{
Error_Handler();
}
/* USER CODE END 2 */
By following these steps, you can successfully configure the GPDMA linked list in STM32CubeMX and run it using STM32CubeIDE.