0
\$\begingroup\$

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?

\$\endgroup\$

2 Answers 2

2
\$\begingroup\$

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.
\$\endgroup\$
4
  • \$\begingroup\$ You covered my thoughts pretty well (I wouldn't have written #8, since I think that one is too obvious.) But I think a simple answer to the OP can be found in #7. Simply make the buffers too large and track a "high water" mark during operation. After enough testing, a solid idea of how to size the buffers will emerge and can be used to establish them in the final version. \$\endgroup\$
    – jonk
    Commented May 20, 2018 at 5:20
  • \$\begingroup\$ But @jonk, if the OP and his colleagues test and validate the product and its software up toward production with larger than needed circular buffers in place it is reasonable to guess that the extra consumed RAM was not detrimental to the product operation. The testing that should be going on is to validate whether the buffers are large enough with a comfortable margin to cover worst case corner conditions. That would result in making the buffers bigger if there were negative findings. \$\endgroup\$ Commented May 20, 2018 at 6:29
  • \$\begingroup\$ Many times, on projects I've worked on, we started out with the MORE EXPENSIVE device that had the maximum RAM. Then, later, after we knew for sure our RAM requirements, we'd select a cheaper part. \$\endgroup\$
    – jonk
    Commented May 20, 2018 at 8:02
  • \$\begingroup\$ Point 7 is valid but it's not quantified. My devices are programmed to send data in every 15ms and the controller receive it transmit the new control parameters to these devices. I think that since my arrival rate and service rate is same; i should not be needing the buffer. But it didn't work. I have to use the buffer size approximately 1.5x of the data bytes. Why this contradiction? And every UART channel has its owns circular queues. \$\endgroup\$ Commented May 20, 2018 at 10:12
0
\$\begingroup\$

It depends on how many instructions per second you can run to read the buffer, and update pointers. Even as a ISR it will consume instruction cycles.

Install the code you need to do everything else first, then use software or hardware to capture your 'spare' time in which you can manage a buffer. It only needs to be created once, plus a status byte and read and write pointers. Unless you have some built-in automation you will need to poll the buffer often to see how full it is, and compare this to how long it takes to read it. Some built-in buffers offer a half-full flag to trigger an ISR.

You start with 32 bytes and see how much 'spare' time is left. I would not go over 256 bytes/words/dwords just because of the time it takes to clear it and read from it. No CPU or MPU maker I know of goes beyond that, even for Ethernet and USB.

\$\endgroup\$
2
  • 4
    \$\begingroup\$ You never need to clear the buffers, you just need to update the input and output pointers. Any additional writes to clear would be pointless (excuse the pun). \$\endgroup\$ Commented May 20, 2018 at 2:58
  • \$\begingroup\$ @JackCreasey. Thanks for the reminder. Will correct my answer. \$\endgroup\$
    – user105652
    Commented May 20, 2018 at 5:02

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Not the answer you're looking for? Browse other questions tagged or ask your own question.