cancel
Showing results for 
Search instead for 
Did you mean: 

STM32U585 freezes on DMA transmission with USART peripheral

_AK
Associate

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);
}

 

3 REPLIES 3
gbm
Lead III

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

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

_AK
Associate

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