2021-05-21 03:14 AM
Currently I am working on UART DMA and I encountered problems after transmitting data via DMA UART. After 1 successful data transmission, the state flag remains on BUSY. After a search, I ended up on this thread and this fixed the problem.
static
void
UART_DMATransmitCplt(DMA_HandleTypeDef *hdma)
{
UART_HandleTypeDef* huart = ( UART_HandleTypeDef* )((DMA_HandleTypeDef* )hdma)->Parent;
/* DMA Normal mode*/
if
( HAL_IS_BIT_CLR(hdma->Instance->CCR, DMA_CCR_CIRC) )
{
huart->TxXferCount = 0;
/* Disable the DMA transfer for transmit request by setting the DMAT bit
in the UART CR3 register */
CLEAR_BIT(huart->Instance->CR3, USART_CR3_DMAT);
/* Enable the UART Transmit Complete Interrupt */
__HAL_UART_ENABLE_IT(huart, UART_IT_TC);
huart->State=HAL_UART_STATE_READY;
//<--- i add this line to solve the //problem
}
/* DMA Circular mode */
else
{
HAL_UART_TxCpltCallback(huart);
}
}
Line 31 in code snippet
However, is this a good solution (and should this be implemented in the stm32f3 library) or am I missing something that causes this problem of only 1 successful transmission?
Solved! Go to Solution.
2021-05-21 05:08 AM
Hello @Ade J.2
Here is how UART DMA Tx transfers are expected to work :
In your case, could you check that UART IRQ is properly enabled, with corresponding IRQ handler ?
(that could be an explanation why state remains in BUSY and HAL_UART_TxCpltCallback() is not called).
FYI, requirement of checking TC status of last transmitted byte was required by some applications that enter low power modes just after an transmission. If HAL sets state to ready directly in UART_DMATransmitCplt(), and user disables UART clocks after state is back to ready, last data copied by DMA, is not transmitted. As I mentioned, at a given instant, transfer is completed from DMA point of view, but not from UART Tx line yet.
Hope this will help you.
Regards
Guenael
2021-05-21 05:08 AM
Hello @Ade J.2
Here is how UART DMA Tx transfers are expected to work :
In your case, could you check that UART IRQ is properly enabled, with corresponding IRQ handler ?
(that could be an explanation why state remains in BUSY and HAL_UART_TxCpltCallback() is not called).
FYI, requirement of checking TC status of last transmitted byte was required by some applications that enter low power modes just after an transmission. If HAL sets state to ready directly in UART_DMATransmitCplt(), and user disables UART clocks after state is back to ready, last data copied by DMA, is not transmitted. As I mentioned, at a given instant, transfer is completed from DMA point of view, but not from UART Tx line yet.
Hope this will help you.
Regards
Guenael
2021-05-31 12:48 AM
Sorry for the late response, was on vacation for a week.
Thanks for the clear explanation. When I indeed enable USARTx global interrupt, it works as it should.
Thanks for the solution.
2024-10-18 11:30 AM - edited 2024-10-18 11:33 AM
STM32F411 , I have the same problem and spent almost half of day with this! Using CubeMX 6.12. and calling function HAL_UART_Transmit_DMA in dma normal mode it send only one packet and every next packet not sending since uart is stuck in busy state. Even enabling uart global interupt didn't help! Solution for this bug is to add to USART1_IRQHandler this:
if (USART1->SR & USART_SR_IDLE)
{
USART1->DR; //fake read to clear flag
}
After this piece of code HAL_UART_Transmit_DMA is working in dma normal mode. My hope ST devs do something for this bug, thank you.