Skip to main content
Visitor II
June 3, 2019
Question

Unable to receive USART data using DMA normal mode in while loop more than one cycle

  • June 3, 2019
  • 13 replies
  • 4555 views

Hello,

Am using STM32F4 DISC board, with FreeRTOS with CMSIS v1, on CubeIDE with HAL generation.

To receive data from USART, below code has been used:

while(1)

{

.....

            ret = HAL_UART_Receive_IT(&huart6, rx_data, SIZE_RX_BYTES);

            if(ret != HAL_OK) {}

......

         ret = HAL_UART_Transmit_IT(&huart6, temp_data, SIZE_TX_BYTES);

         if(ret != HAL_OK) {}

......

}

void HAL_UART_RxCpltCallback(UART_HandleTypeDef *huart)

{

.......

 }

DMA is set to normal mode in CubeMxIDE, FIFO enabled, data width of both buses as byte, burst as single.

So, it is observed that unless USART global interrupt is enabled, DMA receive / tx doesn't behave cyclic, but happens only once.

What is the relation between USART global interrupt and DMA receive enable/interrupt? Will clearing TC flag in FCR register of DMA solve my problem?

    This topic has been closed for replies.

    13 replies

    Super User
    June 4, 2019

    OK, back to the basics...

    What is the exact behavior you are seeing that makes you say "it is observed that unless USART global interrupt is enabled, DMA receive / tx doesn't behave cyclic, but happens only once"? Are you missing incoming data? Unable to transmit any more data? What is your data stream supposed to look like? Can you really ignore Rx data while you are sending data?

    There is LOTS of relevant code you are not showing us, including the UART/DMA setup code. What determines when you code executes the HAL_UART_Receive_DMA() and HAL_UART_Transmit_DMA() calls? What does your Rx callback actually do and how does it interact with the code loop that receives/sends data? Have you got some kind of priority inversion so that this task gets blocked? Do you even GET to the HAL_UART_Receive_DMA() call the 2nd time? Does some OTHER code use the same UART (by mistake or on purpose)? Does your code actually do any error reporting (that you left out of your example)? Or is your code really

    if(ret != HAL_OK) {}

    Please tell me you aren't really ignoring return codes from HAL function calls. Specially ones that you claim aren't working.

    Do some debugging. When the DMA stuff fails to work as you expect with the global UART interrupt disabled, dump the uart and dma registers and see what is there. Set breakpoints to step through the DMA complete sequence, or the HAL_UART_Receive_DMA() or Transmit_DMA() functions (when they fail to work) and see that is or is not going on.

    Or.... you can simply enable the global USART interrupt, add a comment in the code saying "I don't know why, but I need this for DMA to work". Get on with your project.

    DevBeeAuthor
    Visitor II
    June 4, 2019

    https://community.st.com/s/question/0D50X00009XkfcUSAR/haluarttransmitdma-issues

    This page indicates same issue, though reproduced in earlier version

    Super User
    June 4, 2019

    That thread also shows the UART_DMATransmitCplt() code that does indeed enable the UART "TC" interrupt when DMA is not in circular mode, because the HAL code needs to know when the last byte has been sent so it can disable the UART Tx. So, yes, you need the global UART interrupt enabled.