Skip to main content
Explorer
January 28, 2025
Solved

STM32U585 freezes on DMA transmission with USART peripheral

  • January 28, 2025
  • 2 replies
  • 654 views

Hello,

I am implementing DMA transfers to USART1 peripheral configured as asynchronous UART. I am facing issue that the message transferred with DMA is transferred only once and freezes.

When set to transfer messages in blocking mode (without using DMA), it is transferred fine every time in a loop.

For reference I am attaching my initialization code for DMA and USART1:

Initialize USART1:

huart1.Instance = USART1;
huart1.Init.BaudRate = 115200;
huart1.Init.WordLength = UART_WORDLENGTH_8B;
huart1.Init.StopBits = UART_STOPBITS_1;
huart1.Init.Parity = UART_PARITY_NONE;
huart1.Init.Mode = UART_MODE_TX_RX;
huart1.Init.HwFlowCtl = UART_HWCONTROL_NONE;
huart1.Init.OverSampling = UART_OVERSAMPLING_16;
huart1.Init.OneBitSampling = UART_ONE_BIT_SAMPLE_DISABLE;
huart1.Init.ClockPrescaler = UART_PRESCALER_DIV1;
huart1.AdvancedInit.AdvFeatureInit = UART_ADVFEATURE_NO_INIT;
if (HAL_UART_Init(&huart1) != HAL_OK)
{
Error_Handler();
}
if (HAL_UARTEx_SetTxFifoThreshold(&huart1, UART_TXFIFO_THRESHOLD_1_8) != HAL_OK)
{
Error_Handler();
}
if (HAL_UARTEx_SetRxFifoThreshold(&huart1, UART_RXFIFO_THRESHOLD_1_8) != HAL_OK)
{
Error_Handler();
}
if (HAL_UARTEx_DisableFifoMode(&huart1) != HAL_OK)
{
Error_Handler();
}



Initialize DMA:

handle_GPDMA1_Channel0.Instance = GPDMA1_Channel0;
handle_GPDMA1_Channel0.Init.Request = GPDMA1_REQUEST_USART1_TX;
handle_GPDMA1_Channel0.Init.BlkHWRequest = DMA_BREQ_SINGLE_BURST;
handle_GPDMA1_Channel0.Init.Direction = DMA_MEMORY_TO_PERIPH;
handle_GPDMA1_Channel0.Init.SrcInc = DMA_SINC_INCREMENTED;
handle_GPDMA1_Channel0.Init.DestInc = DMA_DINC_FIXED;
handle_GPDMA1_Channel0.Init.SrcDataWidth = DMA_SRC_DATAWIDTH_BYTE;
handle_GPDMA1_Channel0.Init.DestDataWidth = DMA_DEST_DATAWIDTH_BYTE;
handle_GPDMA1_Channel0.Init.Priority = DMA_LOW_PRIORITY_LOW_WEIGHT;
handle_GPDMA1_Channel0.Init.SrcBurstLength = 1;
handle_GPDMA1_Channel0.Init.DestBurstLength = 1;
handle_GPDMA1_Channel0.Init.TransferAllocatedPort = DMA_SRC_ALLOCATED_PORT0|DMA_DEST_ALLOCATED_PORT0;
handle_GPDMA1_Channel0.Init.TransferEventMode = DMA_TCEM_BLOCK_TRANSFER;
handle_GPDMA1_Channel0.Init.Mode = DMA_NORMAL;
if (HAL_DMA_Init(&handle_GPDMA1_Channel0) != HAL_OK)
{
Error_Handler();
}

__HAL_LINKDMA(huart, hdmatx, handle_GPDMA1_Channel0);

if (HAL_DMA_ConfigChannelAttributes(&handle_GPDMA1_Channel0, DMA_CHANNEL_NPRIV) != HAL_OK)
{
Error_Handler();
}



and this is how I am sending UART messages:

while (1)
{
HAL_UART_Transmit_DMA(&huart1, (uint8_t*)"DMA Message\n", strlen("DMA Message"));
HAL_Delay(2000);
}

 

    This topic has been closed for replies.
    Best answer by gbm

    Make sure that both UART and DMA channel interrupts are enabled in CubeMX.

    2 replies

    gbmAnswer
    Graduate
    January 29, 2025

    Make sure that both UART and DMA channel interrupts are enabled in CubeMX.

    ST Employee
    January 29, 2025

    Hello@_AK 

    As mentioned by @gbm , for completion of a DMA transmission, initiated by HAL_UART_Transmit_DMA(), both interrupts of DMA channel and USART/UART instance, need to be enabled.
    - DMA interrupt will occur once all data have been handled by DMA (i.e. copied from your buffer to USART Data Register, for being sent)

    - Then USART Transmit Complete interrupt indicates that the transfer is actually complete (all data sent on the line).

    So please enable both interrupts, and you could catch end of transfer in HAL_UART_TxCpltCallback() callback execution.
    Regards

    Guenael

    _AKAuthor
    Explorer
    January 29, 2025

    Thanks. It worked. I had to provide C linkage for ISRs written in C++.