Skip to main content
Visitor II
November 15, 2025
Question

STM32N6 GPDMA: Circular Standard Mode TX Node Aborts/Fires TCF at 50% of Programmed DataSize

  • November 15, 2025
  • 1 reply
  • 136 views

I am implementing a high-speed, continuous UART loopback system using the GPDMA Standard circular mode on an STM32N6 series microcontroller. My setup involves autonomously linking UART_RX to UART_TX via GPDMA.

The system is stable and the RX transfer works perfectly, but the TX transfer consistently aborts at exactly 50% of the programmed DataSize, despite the transfer being configured as a single linear node in a circular queue.

TX Trigger: TX channel is triggered by the TCF (Transfer Complete Flag) of the corresponding RX channel.

 

and this is my configuration:

 if(uartHandle->Instance==UART5)
 {
 /* USER CODE BEGIN UART5_MspInit 0 */

 /* USER CODE END UART5_MspInit 0 */

 /** Initializes the peripherals clock
 */
 PeriphClkInitStruct.PeriphClockSelection = RCC_PERIPHCLK_UART5;
 PeriphClkInitStruct.Uart5ClockSelection = RCC_UART5CLKSOURCE_PCLK1;
 if (HAL_RCCEx_PeriphCLKConfig(&PeriphClkInitStruct) != HAL_OK)
 {
 Error_Handler();
 }

 /* UART5 clock enable */
 __HAL_RCC_UART5_CLK_ENABLE();

 __HAL_RCC_GPIOC_CLK_ENABLE();
 __HAL_RCC_GPIOH_CLK_ENABLE();
 /**UART5 GPIO Configuration
 PC12 ------> UART5_TX
 PH2 ------> UART5_RX
 */
 GPIO_InitStruct.Pin = GPIO_PIN_12;
 GPIO_InitStruct.Mode = GPIO_MODE_AF_PP;
 GPIO_InitStruct.Pull = GPIO_NOPULL;
 GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_LOW;
 GPIO_InitStruct.Alternate = GPIO_AF11_UART5;
 HAL_GPIO_Init(GPIOC, &GPIO_InitStruct);

 GPIO_InitStruct.Pin = GPIO_PIN_2;
 GPIO_InitStruct.Mode = GPIO_MODE_AF_PP;
 GPIO_InitStruct.Pull = GPIO_NOPULL;
 GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_LOW;
 GPIO_InitStruct.Alternate = GPIO_AF11_UART5;
 HAL_GPIO_Init(GPIOH, &GPIO_InitStruct);

 /* UART5 DMA Init */
 /* GPDMA1_REQUEST_UART5_TX Init */
 NodeConfig.NodeType = DMA_GPDMA_LINEAR_NODE;
 NodeConfig.Init.Request = GPDMA1_REQUEST_UART5_TX;
 NodeConfig.Init.BlkHWRequest = DMA_BREQ_SINGLE_BURST;
 NodeConfig.Init.Direction = DMA_MEMORY_TO_PERIPH;
 NodeConfig.Init.SrcInc = DMA_SINC_INCREMENTED;
 NodeConfig.Init.DestInc = DMA_DINC_FIXED;
 NodeConfig.Init.SrcDataWidth = DMA_SRC_DATAWIDTH_BYTE;
 NodeConfig.Init.DestDataWidth = DMA_DEST_DATAWIDTH_BYTE;
 NodeConfig.Init.SrcBurstLength = 1;
 NodeConfig.Init.DestBurstLength = 1;
 NodeConfig.Init.TransferAllocatedPort = DMA_SRC_ALLOCATED_PORT0|DMA_DEST_ALLOCATED_PORT0;
 NodeConfig.Init.TransferEventMode = DMA_TCEM_BLOCK_TRANSFER;
 NodeConfig.Init.Mode = DMA_NORMAL;
 NodeConfig.TriggerConfig.TriggerMode = DMA_TRIGM_BLOCK_TRANSFER;
 NodeConfig.TriggerConfig.TriggerPolarity = DMA_TRIG_POLARITY_RISING;
 NodeConfig.TriggerConfig.TriggerSelection = GPDMA1_TRIGGER_GPDMA1_CH10_TCF;
 NodeConfig.DataHandlingConfig.DataExchange = DMA_EXCHANGE_NONE;
 NodeConfig.DataHandlingConfig.DataAlignment = DMA_DATA_RIGHTALIGN_ZEROPADDED;
 NodeConfig.SrcSecure = DMA_CHANNEL_SRC_SEC;
 NodeConfig.DestSecure = DMA_CHANNEL_DEST_SEC;
 if (HAL_DMAEx_List_BuildNode(&NodeConfig, &Node_GPDMA1_Channel11) != HAL_OK)
 {
 Error_Handler();
 }

 if (HAL_DMAEx_List_InsertNode(&List_GPDMA1_Channel11, NULL, &Node_GPDMA1_Channel11) != HAL_OK)
 {
 Error_Handler();
 }

 if (HAL_DMAEx_List_SetCircularMode(&List_GPDMA1_Channel11) != HAL_OK)
 {
 Error_Handler();
 }

 handle_GPDMA1_Channel11.Instance = GPDMA1_Channel11;
 handle_GPDMA1_Channel11.InitLinkedList.Priority = DMA_LOW_PRIORITY_HIGH_WEIGHT;
 handle_GPDMA1_Channel11.InitLinkedList.LinkStepMode = DMA_LSM_FULL_EXECUTION;
 handle_GPDMA1_Channel11.InitLinkedList.LinkAllocatedPort = DMA_LINK_ALLOCATED_PORT0;
 handle_GPDMA1_Channel11.InitLinkedList.TransferEventMode = DMA_TCEM_BLOCK_TRANSFER;
 handle_GPDMA1_Channel11.InitLinkedList.LinkedListMode = DMA_LINKEDLIST_CIRCULAR;
 if (HAL_DMAEx_List_Init(&handle_GPDMA1_Channel11) != HAL_OK)
 {
 Error_Handler();
 }

 if (HAL_DMAEx_List_LinkQ(&handle_GPDMA1_Channel11, &List_GPDMA1_Channel11) != HAL_OK)
 {
 Error_Handler();
 }

 __HAL_LINKDMA(uartHandle, hdmatx, handle_GPDMA1_Channel11);

 /* GPDMA1_REQUEST_UART5_RX Init */
 NodeConfig.NodeType = DMA_GPDMA_LINEAR_NODE;
 NodeConfig.Init.Request = GPDMA1_REQUEST_UART5_RX;
 NodeConfig.Init.BlkHWRequest = DMA_BREQ_SINGLE_BURST;
 NodeConfig.Init.Direction = DMA_PERIPH_TO_MEMORY;
 NodeConfig.Init.SrcInc = DMA_SINC_FIXED;
 NodeConfig.Init.DestInc = DMA_DINC_INCREMENTED;
 NodeConfig.Init.SrcDataWidth = DMA_SRC_DATAWIDTH_BYTE;
 NodeConfig.Init.DestDataWidth = DMA_DEST_DATAWIDTH_BYTE;
 NodeConfig.Init.SrcBurstLength = 1;
 NodeConfig.Init.DestBurstLength = 1;
 NodeConfig.Init.TransferAllocatedPort = DMA_SRC_ALLOCATED_PORT0|DMA_DEST_ALLOCATED_PORT0;
 NodeConfig.Init.TransferEventMode = DMA_TCEM_BLOCK_TRANSFER;
 NodeConfig.Init.Mode = DMA_NORMAL;
 NodeConfig.TriggerConfig.TriggerPolarity = DMA_TRIG_POLARITY_MASKED;
 NodeConfig.DataHandlingConfig.DataExchange = DMA_EXCHANGE_NONE;
 NodeConfig.DataHandlingConfig.DataAlignment = DMA_DATA_RIGHTALIGN_ZEROPADDED;
 NodeConfig.SrcSecure = DMA_CHANNEL_SRC_SEC;
 NodeConfig.DestSecure = DMA_CHANNEL_DEST_SEC;
 if (HAL_DMAEx_List_BuildNode(&NodeConfig, &Node_GPDMA1_Channel10) != HAL_OK)
 {
 Error_Handler();
 }

 if (HAL_DMAEx_List_InsertNode(&List_GPDMA1_Channel10, NULL, &Node_GPDMA1_Channel10) != HAL_OK)
 {
 Error_Handler();
 }

 if (HAL_DMAEx_List_SetCircularMode(&List_GPDMA1_Channel10) != HAL_OK)
 {
 Error_Handler();
 }

 handle_GPDMA1_Channel10.Instance = GPDMA1_Channel10;
 handle_GPDMA1_Channel10.InitLinkedList.Priority = DMA_LOW_PRIORITY_HIGH_WEIGHT;
 handle_GPDMA1_Channel10.InitLinkedList.LinkStepMode = DMA_LSM_FULL_EXECUTION;
 handle_GPDMA1_Channel10.InitLinkedList.LinkAllocatedPort = DMA_LINK_ALLOCATED_PORT0;
 handle_GPDMA1_Channel10.InitLinkedList.TransferEventMode = DMA_TCEM_BLOCK_TRANSFER;
 handle_GPDMA1_Channel10.InitLinkedList.LinkedListMode = DMA_LINKEDLIST_CIRCULAR;
 if (HAL_DMAEx_List_Init(&handle_GPDMA1_Channel10) != HAL_OK)
 {
 Error_Handler();
 }

 if (HAL_DMAEx_List_LinkQ(&handle_GPDMA1_Channel10, &List_GPDMA1_Channel10) != HAL_OK)
 {
 Error_Handler();
 }

 __HAL_LINKDMA(uartHandle, hdmarx, handle_GPDMA1_Channel10);

 /* USER CODE BEGIN UART5_MspInit 1 */

 /* USER CODE END UART5_MspInit 1 */
 }

 

and this is my application in main.c:

 HAL_UART_Receive_DMA(&huart5, Buffer_UART_5, 1000);

 HAL_UART_Transmit_DMA(&huart5, Buffer_UART_5, 1000);

 

 

    This topic has been closed for replies.

    1 reply

    Adel_9Author
    Visitor II
    November 15, 2025

    Just to note that i have enabled the D_Cache and I_Cache memory ...
    and the cubeMX generated this Function:

    static void SystemIsolation_Config(void)
    {
    
     /* set all required IPs as secure privileged */
     __HAL_RCC_RIFSC_CLK_ENABLE();
    
     /* RIF-Aware IPs Config */
     /* set up GPDMA configuration */
     /* set GPDMA1 channel 10 used by GPDMA1 */
     if (HAL_DMA_ConfigChannelAttributes(&handle_GPDMA1_Channel10,DMA_CHANNEL_SEC|DMA_CHANNEL_PRIV|DMA_CHANNEL_SRC_NSEC|DMA_CHANNEL_DEST_NSEC)!= HAL_OK )
     {
     Error_Handler();
     }
     /* set GPDMA1 channel 11 used by GPDMA1 */
     if (HAL_DMA_ConfigChannelAttributes(&handle_GPDMA1_Channel11,DMA_CHANNEL_SEC|DMA_CHANNEL_PRIV|DMA_CHANNEL_SRC_NSEC|DMA_CHANNEL_DEST_NSEC)!= HAL_OK )
     {
     Error_Handler();
     }
     /* 
    }