Skip to main content
Graduate
March 28, 2025
Question

HPDMA Linked list mode user setting error NUCLEO N6

  • March 28, 2025
  • 1 reply
  • 510 views

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.

    This topic has been closed for replies.

    1 reply

    Technical Moderator
    March 28, 2025

    Hello,

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

    Please refer to this link.