2025-01-12 03:10 PM
Hi,
MCU - STM32h743
I have a use case where I need to receive a large chunk of data on UART, and the RX data length is unknown. I have read ST articles about how to do this using the IDLE feature with circular DMA (HAL_UARTEx_ReceiveToIdle_DMA). However, I have a few doubts about this.
I read that you can enable interrupts for DMA TC, HT, and IDLE events to handle this. For example, if I have a DMA buffer of 3 KB and I receive 1 KB of data on UART, and if I understand correctly, this should trigger an IDLE interrupt when communication stops after receiving 1 KB. But will this interrupt also confirm that the data has already been copied to the DMA buffer? How can I be sure that the data has already been copied when I have the IDLE interrupt so that I can copy the data from the DMA buffer ?
2025-01-12 03:41 PM
Hi,
so you have a real fast cpu and receive RS232 (slow data rate) - but with unknown length.
So you dont need the dma here to avoid data loss (with slow cpu and high data speed the game is different),
rather the opposite : the dma might create big problems with unknown size of data blocks.
I would recommend only using receive with INT , because no problem with any length and time/pause between data.
Just dont forget both callbacks: receive and receive/error .
2025-01-12 04:51 PM
Within the IDLE IRQ completion routine you have several conditions to check. For your question, check the UART receive data flag to see if there is any data still pending in the UART. If not, the DMA controller has completed the last cycle with plenty of time to spare. This should not be an issue since, assuming you are framing packets by inter-message gap (for example, binary MODBUS), the IDLE timeout period will provide an ample period of time to complete the last DMA cycle.
The other issues are RX errors and DMA completion (typically a sign of data overrun). This assumes your DMA length is greater than one (preferably two if continuous receive) maximum data packet. DMA would normally be terminated in the IDLE completion routine or updating buffer pointers if there's no incoming flow control.
No idea how the ST libraries handle this, I don't use them.
Jack Peacock
2025-01-13 09:56 AM
Hi @AScha.3 ,
Thank you for your prompt response
so you have a real fast cpu and receive RS232 (slow data rate) - but with unknown length.
The baud rate is 921600. So I do not think it is slow.
Hi @JPeac.1
Thank you for your reponse.
Are you saying that the DMA transfer would be completed by the time the IDLE interrupt is triggered ? IS there any way to confirm this ?
check the UART receive data flag to see if there is any data still pending in the UART
Sorry, which flag/register is this ?
2025-01-13 10:23 AM - edited 2025-01-13 10:23 AM
Hi,
ok, almost 1 Mbit , is not "slow" .
But anyway your cpu (lets say at 400 MHz) needs for a received byte (assuming you handle it in the rx INT , without much overhead) maybe 100 cycles, so about 0,25 us . And your bytes can come at about 10 us rate max.
So just under 3% cpu load at max. receive speed. And no problem with any/uncertain length of data.
So i would recommend only using receive with INT .
Just try it...then you see.
2025-01-13 12:31 PM
As the UART receives bytes, the DMA copies the byte to the buffer. So yes when there is an idle event, the packet is already in the buffer. To be sure it was an IDLE event and not TC or HT event, you can check the RxEventType for HAL_UART_RXEVENT_IDLE.
To better understand the type of data you're working with, how do you determine which packet is what in order to parse the data? Is there a command byte? How often are the packets coming?
Knowing this, you can shorten the DMA buffer size to something like 256 bytes instead of using a DMA buffer of 3KB. Then you can take advantage of the HT, TC and IDLE to copy the DMA data in smaller chunks to a secondary buffer, which can be 3KB. So instead of copying 1KB of DMA data to another buffer, you are copying 128 bytes for either HT or TC, less bytes for IDLE. This will reduce the time in the interrupt so you can exit right away, so other interrupts can fire.