cancel
Showing results for 
Search instead for 
Did you mean: 

STM32H7 HAL_UARTEx_ReceiveToIdle_DMA fails if there are already transmissions on the UART

IKayk.1
Associate II

I have this code that initiates my UART channels with DMA at startup:

if( HAL_OK == HAL_UART_RegisterRxEventCallback( m_configuration.huart, callbackRx )) {
 
		if( HAL_OK == HAL_UART_RegisterCallback( m_configuration.huart, HAL_UART_TX_COMPLETE_CB_ID, callbackTx )) {
 
			if( HAL_OK == HAL_UARTEx_ReceiveToIdle_DMA( m_configuration.huart, m_configuration.pRxBuffer, m_configuration.rxBufferSize )) {
 
				rc = true ;
			}
		}
	}

And it works fine if the STM32 is not physically connected to that UART and no one is sending anything on that channel during the startup, connecting after the startup allows the UART to work properly. However, if for some reason I need to reset the STM32 (which is a very possible scenario in our application), while the external device connected to this UART keeps transmitting, this code fails.

I did a little debugging:

Inside HAL_UARTEx_ReceiveToIdle_DMA when the code calls UART_Start_Receive_DMA, specifically the DMAR bit is set on CR3 register, the huart->ReceptionType is no longer HAL_UART_RECEPTION_TOIDLE but turns to HAL_UART_RECEPTION_STANDARD.

Just for the sake of it, I tried resetting huart->ReceptionType with HAL_UART_RECEPTION_TOIDLE HAL_UARTEx_ReceiveToIdle_DMA failed and the UART began to work correctly again.

My question are:

  1. Why, when the UART receives messages, the reception type changes to standard? Does it happen in an interrupt somewhere? I could not stop with a watchpoint or breakpoint where it happens...
  2. Why is reception type tested after calling UART_Start_Receive_DMA ? I assume I can't just ignore it.
  3. Is there a way to make the UART ignore incoming transmissions until after the DMA is setup properly?

Thanks!

4 REPLIES 4
TDK
Guru

One option would be to de-initialize the pin during setup and re-initialize it afterwards.

If you feel a post has answered your question, please click "Accept as Solution".
MBC
Associate III

@IKayk.1​ 

Did you ever find an acceptable solution to this?

Pavel A.
Evangelist III

If the UART supports RTO, that is almost always what you want, rather than "receive to idle". See the examples by Tilen Majerle here.

Or, use continuous receive with circular buffer example

The HAL driver unfortunately is too complicated to work reliably.

IDLE and RTO events both are OK and do the same thing. IDLE just has a constant time - one byte, which is the minimum possible one.