cancel
Showing results for 
Search instead for 
Did you mean: 

USART timeout counter does not operate after a long gap in iincoming characters

Krenek.Steve
Associate III

Hi,

I'm receiving characters in polling mode on USART2 in an STM32L476VG.

The USART is set up and enabled. I have set the timeout period using

 LL_USART_SetRxTimeout(USART2, 30000);

ie 3 seconds at 9600 baud.

My Get Char routine is as follows:

int8_t AquaGetChar() {
	int8_t chr;
	int8_t dummyChr;
	uint32_t timeoutFlag = 0;
 
	// Enable the receiver timeout
	LL_USART_EnableRxTimeout(USART2);
 
	// clear the receiver timeout flag if it's set for some reason
	LL_USART_ClearFlag_RTO(USART2);
 
	while (!LL_USART_IsActiveFlag_RXNE(USART2)) {
		timeoutFlag = LL_USART_IsActiveFlag_RTO(USART2);
		if (timeoutFlag) {   // no char received - set the return value to 0;
			chr = 0;
			break;
		}
	}
 
	//  if the timeout flag is not set then we must have got a char in the buffer
 	if (!timeoutFlag) {
 		chr = LL_USART_ReceiveData8(USART2);
 	}
 	else {
 		dummyChr = LL_USART_ReceiveData8(USART2);  // this should not be necessary - its a test to ensure both paths do exactly the same thing
 	}
 
	// disable the receiver timeout or we will get one very shortly (when no more chars coming in)
	LL_USART_DisableRxTimeout(USART2);
	LL_USART_ClearFlag_RTO(USART2);
 
	return chr;
}

This routine is in a continuous loop looking for incoming characters

If I receive a character successfully, then send no more characters, the timeout occurs properly. However, if I continue to not send characters, the routine goes into the while loop indefinitely, ie the timeout flag never comes up.

If I then send another character and pause, the timeout flag gets set again.

The crushing disadvantage of this is that if I am expecting a response from a connected item, and no characters at all come in, then the routine gets permanently stuck in the while loop.

Is this the way it is intended to work, or have I missed something? As it is, it makes the timeout function unusable.

Note that I have tried commenting out the line

LL_USART_DisableRxTimeout(USART2);

This makes no difference.

Hoping someone can spot the issue,

Steve Krenek

4 REPLIES 4

> Is this the way it is intended to work?

Probably. As the USART_RTOR register's description says:

In standard mode, the RTOF flag is set if, after the last received character, no new start bit is

detected for more than the RTO value.

> As it is, it makes the timeout function unusable.

Yes, its usage is limited to non-stop protocols and maybe half-duplex protocols (those where Rx "sees" an echo of Tx, whether connected internally or externally). RM explicitly talks about Modbus RTU.

Unfortunately, the ST IP designers are not known for wide application-oriented knowledge and foresight, see SPI.

Chalk it up in the "wishlist" thread. Wait, there's no thread so far. We are still waiting for the "new features" in salesforce... @Amel NASRI​ @Camilo LEMOS​ @brk​ 

JW

Krenek.Steve
Associate III

Thanks, Jan. That sets my mind at rest. I will simply implement my own timeout code in the GetChar routine.

Steve

Pavel A.
Evangelist III

@Krenek.Steve​ Of course, this is what the RX timeout is intended for.

If you want to just wait for a single char with timeout, just use HAL_UART_Receive. It has a timeout as a parameter.

If you want asynchronous receive with interrupt, use HAL_UART_Receive_IT and implement timeout by your own.

The RTO is intended to delay processing of burst of received characters until the burst ends. It is activated by arrival of at least one character.

-- pa

Krenek.Steve
Associate III

Pavel, Ah, that makes sense now. I had not gleaned that it is intended for burst mode. I will use the method in HAL_USART_Receive.