Dear All,
I am trying to implement a generic DMA-version of the buffered, interrupt-driven UART-driver, and realized that it is not that straightforward, so I thought I would ask some more experienced developers for some ideas/hints/design guidelines.
The goal is to be able to transmit arrays of data (messages) varying in length and frequency at high speed (with a good combination of overhead, resource need and latency). The examples I found usually expects fixed length and/or fixed interval data transfers (ADC, SPI etc.)
The reason I am looking for a solution is that although the interrupt-driven, (ring-)buffered UART implementation is simple, elegant and effective, at high speeds (2-5-10 Mbps) it introduces a undesirable amount of processing overhead. This is usually where DMA comes to the picture.
At first glance for the DMA-version there is a need for some buffering as being non-blocking (for reasonable amount of data) is a requirement.
The following ideas came to my mind:
Add the message to the ring-buffer, then
- use basic/single shot DMA-transfer for the entire message. Pro: easy to implement. Con: 1. need to separate to two transmits if the write pointer is below the read one; 2. A large message blocks the buffer until the transmission is complete.
- use 1. but transmit fixed chunks of data. Pro: less resource need; Con: harder to implement, need to handle fractions of chunks.
- overlay a ping-pong buffer over the ring-buffer (divide by half). Pro: easy to implement. Con: 1. introduces latency, if the messages are small and infrequent; 2. need to turn on/off regularly; 3. halves the buffer size (one half is usable, one half is being transmitted)
- divide the ring-buffer to n equal blocks and use scatter-gather by turning on/off blocks based on the ring-buffer pointers. Pro: sounds nice but Con: all the above... :)
I would be really grateful if you would share your thoughts.
Marton