Electrical – Efficient size of FIFO buffer for UART

baudratebufferfifomicrocontrolleruart

I am designing a software for a microcontroller that transmits and receive data from various UARTs in a loop every 15ms.
I am using UART interrupts to send and receive data. UART interrupt copy bytes to/from the UART TX/RX registers into the circular(a.k.a. ring) FIFO buffer.
I have read that the RX and TX circular buffer should be larger than data bytes and number is in power of two like 4,8,16,64,256 etc

So my question is what is the efficient size of the circular buffer? How can I calculate it?

I was reading about some queuing models. Can we use them to find the buffer size? What will be its arrival and service rate? Do these rates depend upon the baud rate or periodic system cycle?

Best Answer

There are a number of things for you to think about with regard to using FIFO buffers (i.e. circular queues) when communicating through a channel such as a UART. Thinking about these things should help guide your forward.

  1. Using circular queues does not come for free. The act of queuing data and then later dequeuing it does consume some of your processing bandwidth.
  2. It can often be more efficient, once in the interrupt routine for processing an RX event, to re-check if more data has arrived and to immediately queue it before exiting the interrupt routine. This can come into play particularly when there is also a hardware FIFO enabled in the RX input path.
  3. At high baud rates is can often be more efficient to enable hardware FIFOs in the TX path and to loop in the TX interrupt routine till the FIFO gets full in the case there is more data waiting to be sent.
  4. The choice of making circular queues be an even power of two in size can make sense depending upon how the circular queue software routines are written. With an even power of two size the indexes used to represent the input and output positions in the circular queue can be handled without range checking and instead let the indexes be simply ANDed with a mask after the index has been incremented. Some processor architectures will see little benefit whilst for others this can be a huge advantage.
  5. Your application needs to be able to accept all the RX data coming to it at whatever data rate that is being used. Over the long term if data comes faster than it can be processed no amount of circular queue buffering will help to solve the problem.
  6. The size of the circular queue needs to be large enough to hold all the data stuffed into it by the RX interrupt whilst the processor is off doing some other bursty time consuming events.
  7. Making the buffer larger than necessary is not any problem but will just consume RAM needlessly...especially if it is a tradeoff to use that RAM for another purpose.
  8. In cases of multi channel communications it is best recommended to allocate a set of TX and RX circular queues for each channel rather than trying to use one set of queues with data intermingled with from multiple channels and the added tags to keep track of what data goes where.