Skip to main content
Associate
January 28, 2025
Solved

STM32U585 freezes on DMA transmission with USART peripheral

  • January 28, 2025
  • 3 replies
  • 704 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.

3 replies

gbm
gbmBest answer
Super User
January 29, 2025

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

My STM32 stuff on github - compact USB device stack and more: https://github.com/gbm-ii/gbmUSBdevice
Guenael Cadier
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
Associate
January 29, 2025

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