akospasztor / stm32-dma-uart

Efficient DMA timeout mechanism for peripheral DMA configured in circular mode demonstrated on a STM32 microcontroller.
MIT License
125 stars 46 forks source link

Receive error when Buffer is full! #3

Closed HoangPhong12 closed 6 years ago

HoangPhong12 commented 6 years ago

I'm trying your code and it's working, but when buffer is full, receive data is split into 2 message. Eg: I want transmit message "123456789" when buffer is full, receive data are "12345" and "6789". How can I fix it?

akospasztor commented 6 years ago

This is not an error, this is how the DMA works.

Let's imagine that you have a DMA buffer of 100 bytes. The first message has 40 bytes, you receive & process it. The DMA will have 60 free bytes after the first message. You can technically reset the DMA to clear the buffer and reset the DMA hardware counter, but this is not advised because you can lose data.

Let's imagine the second message consists of 80 bytes. The DMA buffer gets full after 60 received bytes, an IT will be generated that the DMA buffer is full. Then the MCU automatically resets the DMA HW counter (because it's configured in circular mode) and starts receiving the remaining 20 bytes. After that, an UART IDLE IT will be generated and you can process the rest of the message. So yes, this message is technically it is split into two chunks. However, this is a necessary approach, since we assumed that we have no clue about the incoming message size and frequency.

Let's imagine the scenario when there is a burst of 500 incoming bytes while the DMA buffer consists of only 100 bytes. This method still works, because it's guaranteed that you will receive the whole message without any data loss, although the received message will consist of 5x 100 bytes of chunks.

This method of course can be further improved if we have knowledge about the sizes and frequency of incoming messages. For example, if you have a DMA buffer of 100 bytes and if you can guarantee that incoming messages never exceed 100 bytes, then you can disable the data processing after the Rx Complete event and wait for the next UART IDLE event to put together the two chunks. Again, this will only work correctly without data loss if you guarantee that incoming messages do not exceed 100 bytes and you can safely process the chunks into one until the next message.

PS: you can read my comments in the main.c file to have better understanding how this code works.