cancel
Showing results for 
Search instead for 
Did you mean: 

UART timeout in DMA Circular mode.

federico.massimi
Associate III

Hi, I have a question about UART + DMA.

I have a sensor that needs to send data to my STM32. When the sensor is stimulated, for the duration of the event, it sends a byte approximately every 1 ms.

To receive the data there are no problems, I used DMA and when the HAL_UART_RxCpltCallback function is called I copy the data into the main buffer in an external memory.

An event can also be quite long, and the DMA buffer is filled and data copied to main buffer dozens of times. The problem is how to know when an event has ended.

The first thing I tried is to use the IDLE LINE interrupt, but since the data comes in slowly, the interrupt is generated practically every byte. So, the first question then is: is there a way to set the UART idle time before the IDLE LINE interrupt is called?

Currently the way I use is: through a timer and a flag I check when the HAL_UART_RxCpltCallback function is no longer called for a certain time, at which point I copy in the main buffer what is left in the DMA buffer and consider the event concluded. But it is a complicated and inefficient way, looking in the UART functions I saw one called HAL_UART_EnableReceiverTimeout, the second question therefore is: can I set a timeout on the UART while working in DMA circular mode?

What I would like is that as long as the data arrives, the HAL_UART_RxCpltCallback function is called regularly, but if for a certain time, for example 200 ms, no data arrives, even if the DMA buffer is not full, the interrupt is still called (or even another interrupt callback).

If anyone can help me with these two questions it would help me a lot.

Thanks in advance.

6 REPLIES 6
TDK
Guru

> is there a way to set the UART idle time before the IDLE LINE interrupt is called?

No.

> can I set a timeout on the UART while working in DMA circular mode?

No.

You can set a periodic timer interrupt to poll for new data as it becomes available. If you don't want the IDLE event, that's your best option. An interrupt every 1ms isn't that much, though, so consider using interrupt mode to handle each byte as it comes it and throw it in a circular buffer or whatever.

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

@TDK​ Thanks for the replies.

Actually an interrupt every 1 ms is not much, but sometimes there are sensors that are much faster, and can get to send a data every 0.1 ms (100 us), so an interrupt every 100 us.

Is an interrupt every 100 us still easily manageable with an STM32L476 that works with a 48Mhz clock?

TDK
Guru

A 10kHz interrupt frequency should be doable. That's 4800 ticks per interrupt which should be plenty.

There are certainly more efficient ways to do it. Circular DMA + polling for new data is probably the most CPU efficient, but has more code complexity.

If you feel a post has answered your question, please click "Accept as Solution".
Pavel A.
Evangelist II

On STM32L476 almost all U(S)ARTs have Receive Timeout feature. This is what you want to use rather than idle detection. Works great with continuous DMA.

Piranha
Chief II
federico.massimi
Associate III

@Pavel A.​ Thanks a lot for the answer.

@Piranha​ Thanks a lot to you too for the answer. I read the link you sent me, it actually talks about this:

  • RTO (Receiver Timeout) event: Triggered when line has been in idle state for programmable time. It is fully configured by firmware.

which is exactly what I need, the problem is that in the code there is no example of how to use it, it just says it exists.

However, knowing that this function exists, and the name of the function is a good place to start.

Now I start looking for some examples on the internet. If you have some examples of code to use the RTO (Receiver Timeout) event are welcome :D .

Thanks again.