cancel
Showing results for 
Search instead for 
Did you mean: 

DMA UART with HAL remain busy bug

joachim
Associate II
Posted on April 10, 2017 at 12:51

Hi everyone,

I've been struggling with a problem a few years ago.

I want to send data to my computer via uart and to free the mcu, I need it to be done with dma.

The problem was, the first transmission worked fine but I couldn't send a second transmission.

When running my nucleo (f411re) under gdb, I could see that the second transmit never started because huart->gState remain set to HAL_UART_STATE_BUSY_TX.

I modify the stm32f4xx_hal_uart.c source code for the stm32cubeMX HAL library and it worked well.

Today, I start a new project and I realize that 2 years later this bug is still there with the latest HAL library !!!

Here is my modified uart source code. The changes are around line 2000

Could someone from ST confirm that it is indeed an error in the library or I'm misusing the dma somehow...

1 ACCEPTED SOLUTION

Accepted Solutions
Posted on April 10, 2017 at 18:03

Hello,

You should 

enable HAL_UART_IRQHandler() inside 'stm32f4xx_it.c', 

this will ensure the USART communication by checking the flag, as the set of the ready flag is managed inside HAL_UART_IRQHandler() by the UART_EndTransmit_IT().

I suggest you refer to ready-use UART example using DMA in STM32CubeF4:

For more clarification, you can refer to the 'Continuous communication using DMA' paragraph in the reference manual RM0090 and 

follow the UM1725 in the section 'UART Firmware driver API description'.

Hope this helps you.

Imen

When your question is answered, please close this topic by clicking "Accept as Solution".
Thanks
Imen

View solution in original post

4 REPLIES 4
T J
Lead
Posted on April 10, 2017 at 14:35

I checked through your zip file.

what is the bug ?

this is my Uart DMA code.

 void IO::CheckTxDMABufferProgress(void) {
if (DMABufHasData) {
char uartState = HAL_UART_GetState(&huart1);
if ((uartState == HAL_UART_STATE_READY) || (uartState == HAL_UART_STATE_BUSY_RX)) {
DMABufHasData = false;// sending now
if (HAL_UART_Transmit_DMA(&huart1, (uint8_t *)Usart1TxDMABuffer + U1TxBufferPtrOUT, U1TxBufferPtrIN - U1TxBufferPtrOUT) == HAL_OK) {
HAL_UART_Transmit_DMA_Status = UartDMAsuccess; //flag only not needed
U1TxBufferPtrOUT = U1TxBufferPtrIN; //now our buffer is empty, but still transmitting, DO NOT DISTURB whist transmittingempty
}else {
Error_Handler();/* Transfer error in transmission process */
HAL_UART_Transmit_DMA_Status = UartDMAfailed; //flag only not needed
}
}
}
 }�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?

joachim
Associate II
Posted on April 10, 2017 at 16:50

Hi Nick, thanks for taking the time

At around line 2000, I added a line to change the huart.gState flag from HAL_UART_STATE_BUSY_TX to HAL_UART_STATE_READY in the UART_DMATransmitCplt() callback function.

When, in your example, you call :

if (HAL_UART_Transmit_DMA(&huart1, [...] ) == HAL_OK) { ... }

The HAL_UART_Transmit_DMA function (at line 895 in the file I uploaded) sets 'huart->gState' to HAL_UART_STATE_BUSY_TX which is fine but when the transfer is completed, it should be set back to HAL_UART_STATE_READY. The HAL library does not reset the flag when dma transmission is completed and a second transmission cannot be started because the peripheral is still considered busy...

Posted on April 10, 2017 at 18:03

Hello,

You should 

enable HAL_UART_IRQHandler() inside 'stm32f4xx_it.c', 

this will ensure the USART communication by checking the flag, as the set of the ready flag is managed inside HAL_UART_IRQHandler() by the UART_EndTransmit_IT().

I suggest you refer to ready-use UART example using DMA in STM32CubeF4:

For more clarification, you can refer to the 'Continuous communication using DMA' paragraph in the reference manual RM0090 and 

follow the UM1725 in the section 'UART Firmware driver API description'.

Hope this helps you.

Imen

When your question is answered, please close this topic by clicking "Accept as Solution".
Thanks
Imen
Posted on April 11, 2017 at 17:13

Ha HA, Thanks Imen !

It is just a serious case of plain stupid me

I did as you said : '

refer to ready-use UART example

' (a bit annoyed to be honest, because my code came from there, but still... maybe I missed something...)

It turns out that I declared a function in stm32f4xx_it.h named : USARTx_DMA_TX_IRQHandler() ... but It come with the

♯ define 

USARTx_DMA_TX_IRQHandler     DMA1_Stream6_IRQHandler        (in main.h in the example)

So of course the HAL_UART_IRQHandler() function was never called ...........

So, my bad everyone, and Imen I owe you one !