AnsweredAssumed Answered

USART Rx implementation via DMA on per-byte basis

Question asked by pisarenko.artem on Feb 23, 2015
Latest reply on Mar 30, 2015 by waclawek.jan
I would like to verify whether my solution is correct and robust. I already read a lot of similar topics, but didn't found reliable confirmation of my ideas. I just learned that many people suffer from stupid GP DMA implementation in STM32 and being advised to use dirty hacks like timers or even external rx pin interconnections (holy sh*t!)...
Hope my solution will be useful for others.

System has large interrupt latencies (due to flash programming operations requiring disabling interrupts), which requires to use DMA for USART Rx.
Implementation requirements:
- write to circular buffer (classic circular buffer with read/write pointers, having nothing common with that stupid circular/double-buffering modes in DMA);
- signal each byte reception (since it's not possible to predict DMA transfer size);
- signal overflow condition and stop writing to buffer (in order to not disrupt data still not read by application);
- interrupt handler execution time must be small.

Proposed solution:
Allocate small(!) DMA buffer, configure it in non-circular direct mode.
Use USART RXNE interrupt handler to process reception in this way:
- stop DMA
- read DMA_SxNDTR register to calculate how much bytes received
- flush data from DMA buffer to software circular buffer (if not overflowed)
- restart DMA
- signal reception to application.
Use USART ORE flag to signal overflow to application.
Why small DMA buffer ? Because interrupt handler must have time to process it completely, while DMA suspended and before next symbol arrives from USART shift register. For example, just 12 bytes will be enough to protect 1Mbaud stream from 100us latency, and make interrupt handler execution time short enough.

Things make me worrying:
- Reference Manual states: "Note: If DMA is used for reception, do not enable the RXNEIE bit."
- DMA transfer suspended while peripheral enabled. I expect that it's ok for peripheral-to-memory mode (at least). In case, if USART receive symbol, it should normally assert DMA request, and when DMA transfer enabled again, it should handle request immidiately, and everything should be ok...

Please, confirm that solution is completely correct, i.e. it doesn't use undocumented features, doesn't rely on undefined behavior, does account all possible tricky edge cases.