cancel
Showing results for 
Search instead for 
Did you mean: 

STM32H7 UART DMA Receive unknown length of data.

MJ_1992
Associate II

I use STM32H753 and USART1 with DMA to receive data of unknown length (Min: 8 bytes Max: 512 bytes) from PC. Data will be sent in burst after every one second. My baud rate is 9600. So approx 1ms per byte.

So, maximum, I'm going to get all the data in 512 ms and I'm free to analyze the data for another 488 ms.So, I want some algorithm so that I can parse all data (Min: 8 bytes Max: 512 Bytes) on DMA after all data received.

I am using follwoing methods.

1) Receiving without DMA and interrupt on every byte.

-> Working fine. But the more CPU interference required. 

2) Receiving with Half and Full transfer interrupt with DMA.

-> Working fine but sometime we need to wait for one second (or more than that, depending upon buffer size) till the filling the buffer (HALF or FULL). It makes the communication process slower.

3) Receiving with DMA_CIRCULAR with DMA and keep eye on NDTR of DMA Stream.

-> Working fine but sometime we get error because NDTR updates first after receiving data in UART peripheral. And then DMA will copy data into memory.

4) Receiving with DMA_NORMAL with DMA and using "HAL_UARTEx_ReceiveToIdle_DMA"

-> Working fine but some time call back calls (with "Size") before actual data received in memory. Same problem as point no 3.

So please suggest best method for my case.

13 REPLIES 13

Take a note that for HAL setting the DMA mode to circular and calling HAL_UARTEx_ReceiveToIdle_DMA() is the only combination, which can do a continuous reception. Anything else either stops the USART and DMA at the "end" or doesn't wait for IDLE event.

The whole buffer managing logic, that can be seen in examples given by @JMeye.2​, should have been implemented in the driver. Implementing it at an application layer in every project for every USART instance is just ridiculous. Here is an example of a decent API for USART stream reception:

https://community.st.com/s/question/0D53W00001RiIo1SAF/stm32f407-haluartexreceivetoidle-function-missing

Finally, I got success with option 4 without any errors and minimum CPU intervention. The code is attached. (Only the required lines of code are specified. But you can implement it to your code)

@JMeye.2​  Link2 ( ST's Example) is very useful for me.

@Piranha​  At present, I have used HAL Functions in inturreputs. But I'm optimizing by replacing it with my own code.

Once agin thank you to all.

Piranha
Chief II
for (uint8_t i = 0; i < BufferNeedToparse->RcvdDataSize; i++)
{
	ParseReceivedByte(BufferNeedToparse->Data[i]); // <-- Final parsing for received data
	BufferNeedToparse->Data[i] = 0x00; // Erase data from which is used
}

Generally for loops, indexes and such uses on 32-bit CPUs one should use 32-bit variables. Native sizes perform better because smaller types can sometimes require additional instructions. The best standard integer type for these purposes is the size_t.

@Piranha​ Yeah basically the whole driver is missing. The HAL should only implement a basic abstraction on which the hardware driver should be build upon.

What I can agree with is that all ST HALs and drivers are a complete inconsistent mess.