cancel
Showing results for 
Search instead for 
Did you mean: 

HPDMA Linked list mode user setting error NUCLEO N6

Hello, I'm trying to use the HPDMA1 with channel 0 to transfer the data from UART1 to AXIRAM5 (from 0x342E0000).

I want to receive all the data (about 150KB) from the UART through DMA at once (it can only transfer 64KB at once because of the limited block size). so I used the Linked list mode to move things in 3 nodes.

However, it doesn't work, every time I start my DMA, it goes to user setting error flag.

Here is my linked list.c file

/* USER CODE BEGIN Header */

/**

******************************************************************************

* File Name : linked_list.c

* Description : This file provides code for the configuration

* of the LinkedList.

******************************************************************************

* @attention

*

* 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.

*

******************************************************************************

*/

/* USER CODE END Header */

/* Includes ------------------------------------------------------------------*/

#include "linked_list.h"



/* Private includes ----------------------------------------------------------*/

/* USER CODE BEGIN Includes */



/* USER CODE END Includes */



DMA_NodeTypeDef First_block __NON_CACHEABLE;

DMA_QListTypeDef UART_Receive_Large_Data;

DMA_NodeTypeDef Second_block __NON_CACHEABLE;

DMA_NodeTypeDef Last_Bytes __NON_CACHEABLE;



/* Private typedef -----------------------------------------------------------*/

/* USER CODE BEGIN PTD */



/* USER CODE END PTD */



/* Private define ------------------------------------------------------------*/

/* USER CODE BEGIN PD */



/* USER CODE END PD */



/* Private macro -------------------------------------------------------------*/

/* USER CODE BEGIN PM */



/* USER CODE END PM */



/**

* @brief DMA Linked-list UART_Receive_Large_Data configuration

* @PAram None

* @retval None

*/

HAL_StatusTypeDef MX_UART_Receive_Large_Data_Config(void)

{

HAL_StatusTypeDef ret = HAL_OK;

/* DMA node configuration declaration */

DMA_NodeConfTypeDef pNodeConfig;



/* Set node configuration ################################################*/

pNodeConfig.NodeType = DMA_HPDMA_LINEAR_NODE;

pNodeConfig.Init.Request = HPDMA1_REQUEST_USART1_RX;

pNodeConfig.Init.BlkHWRequest = DMA_BREQ_SINGLE_BURST;

pNodeConfig.Init.Direction = DMA_PERIPH_TO_MEMORY;

pNodeConfig.Init.SrcInc = DMA_SINC_FIXED;

pNodeConfig.Init.DestInc = DMA_DINC_INCREMENTED;

pNodeConfig.Init.SrcDataWidth = DMA_SRC_DATAWIDTH_BYTE;

pNodeConfig.Init.DestDataWidth = DMA_DEST_DATAWIDTH_BYTE;

pNodeConfig.Init.SrcBurstLength = 1;

pNodeConfig.Init.DestBurstLength = 1;

pNodeConfig.Init.TransferAllocatedPort = DMA_SRC_ALLOCATED_PORT0|DMA_DEST_ALLOCATED_PORT0;

pNodeConfig.Init.TransferEventMode = DMA_TCEM_BLOCK_TRANSFER;

pNodeConfig.Init.Mode = DMA_NORMAL;

pNodeConfig.RepeatBlockConfig.RepeatCount = 1;

pNodeConfig.RepeatBlockConfig.SrcAddrOffset = 0;

pNodeConfig.RepeatBlockConfig.DestAddrOffset = 0;

pNodeConfig.RepeatBlockConfig.BlkSrcAddrOffset = 0;

pNodeConfig.RepeatBlockConfig.BlkDestAddrOffset = 0;

pNodeConfig.TriggerConfig.TriggerPolarity = DMA_TRIG_POLARITY_MASKED;

pNodeConfig.DataHandlingConfig.DataExchange = DMA_EXCHANGE_NONE;

pNodeConfig.DataHandlingConfig.DataAlignment = DMA_DATA_RIGHTALIGN_ZEROPADDED;

pNodeConfig.SrcAddress = (uint32_t)&USART1->RDR;

pNodeConfig.DstAddress = 0x342E0000;

pNodeConfig.DataSize = 65535;

pNodeConfig.SrcSecure = DMA_CHANNEL_SRC_SEC;

pNodeConfig.DestSecure = DMA_CHANNEL_DEST_SEC;



/* Build First_block Node */

ret |= HAL_DMAEx_List_BuildNode(&pNodeConfig, &First_block);



/* Insert First_block to Queue */

ret |= HAL_DMAEx_List_InsertNode_Tail(&UART_Receive_Large_Data, &First_block);



/* Set node configuration ################################################*/

pNodeConfig.DstAddress = (0x342E0000 + 65535);



/* Build Second_block Node */

ret |= HAL_DMAEx_List_BuildNode(&pNodeConfig, &Second_block);



/* Insert Second_block to Queue */

ret |= HAL_DMAEx_List_InsertNode_Tail(&UART_Receive_Large_Data, &Second_block);



/* Set node configuration ################################################*/

pNodeConfig.DstAddress = (0x342E0000 + 65535 + 65535);

pNodeConfig.DataSize = 19458;



/* Build Last_Bytes Node */

ret |= HAL_DMAEx_List_BuildNode(&pNodeConfig, &Last_Bytes);



/* Insert Last_Bytes to Queue */

ret |= HAL_DMAEx_List_InsertNode_Tail(&UART_Receive_Large_Data, &Last_Bytes);



return ret;

}



And this is my main()



int main(void)

{



/* USER CODE BEGIN 1 */



/* USER CODE END 1 */



/* MCU Configuration--------------------------------------------------------*/

HAL_Init();



/* USER CODE BEGIN Init */



/* USER CODE END Init */



/* Configure the system clock */

SystemClock_Config();



/* USER CODE BEGIN SysInit */



/* USER CODE END SysInit */



/* Initialize all configured peripherals */

MX_GPIO_Init();

MX_HPDMA1_Init();

NPURam_enable();

MX_USART1_UART_Init();

/* USER CODE BEGIN 2 */

// try whether the RAM is able to write

// memcpy((void*)0x342E0000, &hi, 1);

MX_UART_Receive_Large_Data_Config();

HAL_DMAEx_List_LinkQ(&handle_HPDMA1_Channel0, &UART_Receive_Large_Data);

HAL_DMA_RegisterCallback(&handle_HPDMA1_Channel0, HAL_DMA_XFER_CPLT_CB_ID, TransferComplete);

HAL_DMA_RegisterCallback(&handle_HPDMA1_Channel0, HAL_DMA_XFER_ERROR_CB_ID, TransferError);

HAL_DMAEx_List_Start_IT(&handle_HPDMA1_Channel0);



// HAL_NVIC_SetPriority(USART1_IRQn, 0, 0);

// HAL_NVIC_EnableIRQ(USART1_IRQn);



ATOMIC_SET_BIT(huart1.Instance->CR3, USART_CR3_DMAR);

__HAL_UART_ENABLE(&huart1);



// while (!dma_done_flag)

// {

// HAL_Delay(10);

// }



while ((TransferCompleteDetected == 0) && (TransferErrorDetected == 0U));

/* USER CODE END 2 */



/* Infinite loop */

/* USER CODE BEGIN WHILE */

while (1)

{

char dma_done_msg[] = "DMA Transfer Finished\r\n";

HAL_UART_Transmit(&huart1, (uint8_t *)dma_done_msg, sizeof(dma_done_msg) - 1, HAL_MAX_DELAY);

HAL_Delay(1000);

/* USER CODE END WHILE */



/* USER CODE BEGIN 3 */

}

/* USER CODE END 3 */

}

This is a photo of my debugging:

Inside HAL_DMAEx_List_Start_IT(DMA_HandleTypeDef *const hdma),

everything is working similar to Linked mode examples, right side is the registers

Einstein_rookie_version_0-1743174824308.png

After the line: __HAL_DMA_ENABLE(hdma);It seems that the User setting error is arosed and then, all the registers are set to default.

Einstein_rookie_version_1-1743174907649.png

I checked the User manual for many times, and did a lot of debugging, but never figure out whats going on.

Could you please help me figure out whats wrong with this? Thank you.

2 REPLIES 2
mƎALLEm
ST Employee

Hello,

Please kindly use </> button to paste your code. I've edited your post.

Please refer to this link.

To give better visibility on the answered topics, please click on "Accept as Solution" on the reply which solved your issue or answered your question.

Thank you very much for your help. However, I still haven't been able to fix this issue — the Linked List mode simply doesn't work in my case.
I've searched through many posts but couldn't find any similar problems, and honestly, I'm not sure what to try next.
I would really appreciate it if someone from ST could provide some guidance or suggestions.

Any help would be highly appreciated!