Skip to main content
Associate III
August 22, 2026
Solved

UART TX/RX with DMA in Normal mode

  • August 22, 2026
  • 4 replies
  • 76 views

Dear ST experts,

I have configured UART (both RX and TX) in Normal DMA mode. I want to send a small data packet every 500 ms with using HAL_UART_Transmit_DMA (&huart, buffer, 10). But I noticed that only one shot is triggered. What is the problem? Should I do something in HAL_UART_TxCpltCallback(UART_HandleTypeDef *huart) callback?

Best,
Davood.

Best answer by MOBEJ

Yes, you need to enable the UART global interrupt in STM32CubeMX. Go to your UART :

NVIC Settings ? USARTx global interrupt ? Enable

In Normal DMA mode, the HAL uses the UART TC (Transmission Complete) interrupt to reset the UART state to READY after each transfer. Without it, the state stays BUSY and every next HAL_UART_Transmit_DMA() call silently fails with HAL_BUSY.

In Circular mode this interrupt isn't needed because the DMA never stops.

You need both enabled: DMA stream interrupt & UART global interrupt

 

Br 

4 replies

MOBEJ
ST Employee
August 22, 2026

Hello  @Davood_Kesha  ,
In DMA Normal mode, the DMA performs exactly one transfer and stops this is by design, not a bug. The HAL marks the UART state as READY and waits. It will not automatically re-trigger.

Yes, you must re-call HAL_UART_Transmit_DMA() to send again. The correct place is from HAL_UART_TxCpltCallback, combined with a timing mechanism:

volatile uint8_t txDone = 1; // start ready  void HAL_UART_TxCpltCallback(UART_HandleTypeDef *huart) {
txDone = 1; // transfer finished, ready for next }  int main(void) {
HAL_Init();
SystemClock_Config();
MX_DMA_Init();
MX_USART1_UART_Init();
while (1)
{
if (txDone)
{
txDone = 0;
HAL_UART_Transmit_DMA(&huart1, buffer, 10);
}
HAL_Delay(500);
} }

 Br

To give better visibility on the answered topics, please click on Accept as Solution on the reply which solved your issue or answered your question.
Associate III
August 22, 2026

Hello,
I am recalling HAL_UART_Transmit_DMA (&huart, buffer, 10) every 500 ms. But it does not work.
Should I activate the global interrupt of uart in stm32cubemx? In circular mode global interrupt is not needed. 

MOBEJ
MOBEJBest answer
ST Employee
August 22, 2026

Yes, you need to enable the UART global interrupt in STM32CubeMX. Go to your UART :

NVIC Settings ? USARTx global interrupt ? Enable

In Normal DMA mode, the HAL uses the UART TC (Transmission Complete) interrupt to reset the UART state to READY after each transfer. Without it, the state stays BUSY and every next HAL_UART_Transmit_DMA() call silently fails with HAL_BUSY.

In Circular mode this interrupt isn't needed because the DMA never stops.

You need both enabled: DMA stream interrupt & UART global interrupt

 

Br 

To give better visibility on the answered topics, please click on Accept as Solution on the reply which solved your issue or answered your question.
Andrew Neil
Super User
August 22, 2026

@MOBEJ  wrote:

HAL_UART_Transmit_DMA() call silently (sic) fails with HAL_BUSY.


If it gives an error code, then it's not a silent failure.

A complex system that works is invariably found to have evolved from a simple system that worked.A complex system designed from scratch never works and cannot be patched up to make it work.