Skip to main content
joachim
Associate
April 10, 2017
Solved

DMA UART with HAL remain busy bug

  • April 10, 2017
  • 2 replies
  • 7375 views
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...

    This topic has been closed for replies.
    Best answer by Imen.D
    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

    2 replies

    T J
    Senior III
    April 10, 2017
    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
    joachimAuthor
    Associate
    April 10, 2017
    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...

    Imen.DBest answer
    ST Technical Moderator
    April 10, 2017
    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

    In order to give better visibility on the answered topics, please click on 'Best answer' on the reply which solved your issue or answered your question. Thanks
    joachim
    joachimAuthor
    Associate
    April 11, 2017
    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 !