Skip to main content
KAgga.1
Associate III
November 16, 2023
Question

How to change default UART Idle line Inactivity time

  • November 16, 2023
  • 7 replies
  • 9815 views

Hello There,

I'm utilizing IDLE event functionality of UART and use HAL_UARTEx_ReceiveToIdle_IT() for it.
The issue that I'm facing is that some times this API falsely detects an IDLE event upon reception (May be a Transmitter issue). So, to overcome that, I'm looking to increase IDLE inactivity time.

Kindly help on how to configure this.

Regards,
Keshav Aggarwal

This topic has been closed for replies.

7 replies

Karl Yamashita
Lead III
November 16, 2023

The idle time is hardware dependant. You can't change it in FW. Check to see why the transmitting device is not sending the bytes in a continuous stream. 

If a reply has proven helpful, click on Accept as Solution so that it'll show at top of the post.CAN Jammer an open source CAN bus hacking toolCANableV3 Open Source
KAgga.1
KAgga.1Author
Associate III
November 17, 2023

Hello Karl, Thanks for replying.
Actually, the transmitting device isn't configurable.
I'm using STM32H7A3VIT6. The documentation says it is programmable.


stm32h7xx_hal_uart_ex.c

[..] This subsection also provides a set of additional functions providing enhanced reception
services to user. (For example, these functions allow application to handle use cases
where number of data to be received is unknown).

(#) Compared to standard reception services which only consider number of received
data elements as reception completion criteria, these functions also consider additional events
as triggers for updating reception status to caller :
(+) Detection of inactivity period (RX line has not been active for a given period).
(++) RX inactivity detected by IDLE event, i.e. RX line has been in idle state (normally high state)
for 1 frame time, after last received byte.
(++) RX inactivity detected by RTO, i.e. line has been in idle state
for a programmable time, after last received byte.
(+) Detection that a specific character has been received.

Karl Yamashita
Lead III
November 17, 2023

Well you specifically said "IDLE"  which i know isn't programmable and "and HAL_UARTEx_ReceiveToIdle_IT()"   which uses HAL_UART_RECEPTION_TOIDLE type. I never used RTO as I've always used IDLE, so I totally forgot the RTO HAL driver exists .

If a reply has proven helpful, click on Accept as Solution so that it'll show at top of the post.CAN Jammer an open source CAN bus hacking toolCANableV3 Open Source
Pavel A.
Super User
November 17, 2023

On STM32H7 UARTs have the Receiver timeout feature (RTO). This is what you want to use instead of idle detection. The RTO length can be specified.

KAgga.1
KAgga.1Author
Associate III
November 17, 2023

Hello Pavel,
Thanks for replying. I think RTO and Idle Inactivity time are different things.
By the way, how the Default RTO value could be changed?
Let me also tell you my use case-
Firstly, I'm using UART module in half-duplex receive only mode and STM32 UART would be receiving the data asynchronously every few seconds. The data length is unknown, So I'm using HAL_UARTEx_ReceiveToIdle_IT() .
The problem I'm facing is that I'm receiving data in chunks via multiple interrupts for a single stream of data being sent by the transmitter.
It means STM32 UART is unnecessarily detecting IDLE events and hence raising multiple interrupts for single stream of data.

Karl Yamashita
Lead III
November 17, 2023

What arguments have you passed to HAL_UARTEx_ReceiveToIdle_IT, specifically the size? What is the shortest and longest length of your packet are you receiving? And what are you doing in HAL_UARTEx_RxEventCallback?

If a reply has proven helpful, click on Accept as Solution so that it'll show at top of the post.CAN Jammer an open source CAN bus hacking toolCANableV3 Open Source
KAgga.1
KAgga.1Author
Associate III
November 17, 2023

Hello @Tesla DeLorean @TDK
Could you help on this?

Pavel A.
Super User
November 17, 2023

 I think RTO and Idle Inactivity time are different things.

Yes, different. And when users ask for idle detection for receive, they usually want RTO. Inactivity detection usually is needed for TX.

> how the Default RTO value could be changed

In stm32h7xx_ll_usart.h :

LL_USART_SetRxTimeout() -  the timeout is specified in bit times,  after the last received byte
LL_USART_EnableRxTimeout()  - enable the RTO operation. There is no default RTO value.

 

__STATIC_INLINE 
void LL_USART_EnableRxTimeout(USART_TypeDef *USARTx)
{
 SET_BIT(USARTx->CR2, USART_CR2_RTOEN);
}

__STATIC_INLINE 
void LL_USART_SetRxTimeout(USART_TypeDef *USARTx, uint32_t Timeout)
{
 MODIFY_REG(USARTx->RTOR, USART_RTOR_RTO, Timeout);
}

__STATIC_INLINE 
void LL_USART_EnableIT_RTO(USART_TypeDef *USARTx)
{
 ATOMIC_SET_BIT(USARTx->CR1, USART_CR1_RTOIE);
}

 

Karl Yamashita
Lead III
November 17, 2023

So after playing with RTO, it calls an error callback. 

void HAL_UART_ErrorCallback(UART_HandleTypeDef *huart)

So let's say you set  HAL_UART_Receive_IT or HAL_UARTEx_ReceiveToIdle_IT

to receive 13 bytes, but you only get 5 bytes, then the error callback is called. It doesn't indicate how many bytes have been received. If it's binary then how do you determine if the last byte that may be 0x00 or 0xFF is really data or initialized value? If it's ASCII then you can determine the string length if the buffer was initialized prior to receiving. Using IDLE is better as the callback indicates how many bytes were received.

 

And just to be sure, you do know that HAL_UARTEx_RxEventCallback is called at half callback as well?

 

If a reply has proven helpful, click on Accept as Solution so that it'll show at top of the post.CAN Jammer an open source CAN bus hacking toolCANableV3 Open Source
Pavel A.
Super User
November 17, 2023

Hi @Karl Yamashita 

In any HAL_UART callback, you can get the number of already received bytes in huart-> RxXferCount (or TxXferCount for TX). IMHO the current HAL libraries do not fully support RTO (maybe the latest products which I have not used, do...).  For example here the "RX types" are defined: HAL_UART_RECEPTION_TOIDLE and HAL_UART_RECEPTION_TORTO. But the latter does not appear anywhere in the source.  Advantage of custom code for UARTs over the HAL library is that you do just what is needed and don't have to struggle with limitations of someone else's code.

Karl Yamashita
Lead III
November 17, 2023

I know about HAL_UART_RECEPTION_TOIDLE and HAL_UART_RECEPTION_TORTO, That is why I told the OP that HAL_UARTEx_ReceiveToIdle_IT() would not work.

Also won't work for LPUART as it doesn't have a flag for RTO.

If a reply has proven helpful, click on Accept as Solution so that it'll show at top of the post.CAN Jammer an open source CAN bus hacking toolCANableV3 Open Source
Karl Yamashita
Lead III
November 20, 2023

So to clarify, your Buffer size is 1024 bytes and the longest packet you'd expect is near half the size, or slightly less than 512 bytes? So that means you are solely relying on the IDLE bit to interrupt, as half or full complete callback will never be called. And some of those packets fall short of all being received into the Buffer before you get an IDLE interrupt?

 

Now i'm not sure if this will work as i have not tried it. So instead of using  HAL_UARTEx_ReceiveToIdle_IT, use HAL_UART_Receive_IT? That way you're not going to get an IDLE callback. Set up the USART to trigger on RTO that is greater than IDLE detection of 8 bits but no longer than when you expect your next packet to be received. Then in HAL_UART_ErrorCallback do what you would have done in HAL_UARTEx_RxEventCallback. As @Pavel A.  pointed out, you can check huart-> RxXferCount for the size that was received before the timeout

 

If a reply has proven helpful, click on Accept as Solution so that it'll show at top of the post.CAN Jammer an open source CAN bus hacking toolCANableV3 Open Source