2025-11-15 1:39 AM
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);
2025-11-15 4:48 AM
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();
}
/*
}