cancel
Showing results for 
Search instead for 
Did you mean: 

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

DevBee
Associate II

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?

17 REPLIES 17
DevBee
Associate II

Can anyone provide correct explanation of this please?

Bob S
Principal

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.

DevBee
Associate II

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

This page indicates same issue, though reproduced in earlier version

Bob S
Principal

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.

Thanks Bob for pointing out the misnomer! this solved my problem :) I'm on version 5.6.1 and it is still named "DMA on RX Error" Set it to disabled and all good now!

Can you advice me, where I should look for this setting?

In CubeMX 5.6.1 I'm not able to see any parameter like that...0693W000001t1XPQAY.png

Hi, you seem to be in the right location already. but I don't see the setting in your page. perhaps it is not available for your device?

2 things:

(1) Yeah, this feature would appear under "Advanced Features" in the "Parameter Settings" if your CPU supports it.

(2) Turns out my original answer was only partially correct. The CubeMX "DMA on RX Error" setting only controls whether the UART/USART CR3 "DDRE" bit gets set (in CPUs that support it). There is ALSO code in the "stm32XXXX_hal_uart.c" that, totally separate from the DDRE support, will abort DMA RX when it detects a framing/overrun/etc. error. I had to go disable/modiify sections of that code to keep RX going and just ignore the garbled data. At least in the STM32L4xx and G4xxx HAL code. Look for code that references UART_DMAAbortOnError (again, at least in the L4xx and G4xx HAL code).