Triple buffer handler

This forum is about you. Feel free to discuss anything is related to embedded and electronics, your awesome projects, your ideas, your announcements, not necessarily related to ChibiOS but to embedded in general. This forum is NOT for support.
Post Reply
User avatar
TexZK
Posts: 57
Joined: Sat Sep 22, 2012 7:06 pm

Triple buffer handler

Post by TexZK »

Hello,
I have just added a triple buffer handler to my community repository, with a fully-featured demo for STM32F429 Discovery, and a subset of it for Win32/MinGW. If not using blocking functions, the handler is 100% OSAL-compatible, while blocking functions require semaphores and are both RT- and NIL-compatible.

I developed this handler because sometimes it is useful to dump some big data with loose sampling, the most common example being some display frame buffer. A triple buffer allows to remove any blocking functions between the buffer writer and the buffer reader. Some other use cases can be represented by IMU data or big shared state structures, loosely sampled.
Real-time sampling can still be achieved if the reader thread is faster (both in priority and sampling time) than the writer thread; of course, the reader has to wait (synchronized to the writer output rate), but the writer does not have to, as explained below. This way of operation can also be emulated with proper handling of a memory pool which holds pointers to 3 buffers, but this triple buffer handler library makes it straightforward.

Like the double buffer, there is always a consinstent copy of the front buffer which can be accessed (read) without locks by the reader thread, and the in-work back buffer can be accessed (written) without locks by the writer thread. There is also an orphan buffer, which does not belong neither to the reader nor the writer threads.
When the writer thread finishes to prepare the back buffer, it does not have to wait until the front buffer is released by the reader thread (this is what happens with double buffering), because it can exchange the back buffer with the orphan buffer.
When the reader thread finishes to process the front buffer, it can retrieve a new one by waiting for a back buffer to become an orphan buffer. This can be accomplished either by waiting for a semaphore (fast acquisition of the new front buffer) or by polling the ready status of the orphan buffer (this is what happens with displays, polling at the display refresh rate).

The demo shows how to use a triple buffer handler, with one writer thread and one reader thread.
The writer thread puts a character into the current back buffer, thus swapping the back buffer with the orphan buffer for a new write. The writer then sleeps for a specified delay in milliseconds.
The reader thread waits (if there is a timeout) until the orphan buffer contains available data, becoming the new front buffer. The character is read from the new front buffer and printed. The reader then sleeps for a specified delay in milliseconds.
A simple command shell is activated on virtual serial port SDU1 or SD1. Via command line it is possible to run, stop, set the delay, and set the thread priority of the reader and writer threads. The reader can also be assigned a wait timeout in milliseconds, with special cases of "*" for infinite timeout, and "-" (or 0 ms) for none.
By default, the printer output and the shell are shared by the same channel, and will output garbled data when the reader is running; please modify the demo code by hand should you need decoupled streams (just retarget chout for the printer).

I hope this triple buffer handler can be useful for some of your projects, since it could be suitable for a set of use cases, both loosely-coupled and real-time.
Please tell me if there are any errors, either in the code, or in the logic behind it all. Have fun!
Post Reply