@ -49,6 +49,15 @@
/** Type of data to store into the buffer. */
/** Type of data to store into the buffer. */
# define RingBuff_Data_t uint8_t
# define RingBuff_Data_t uint8_t
/** Datatype which may be used to store the count of data stored in a buffer, retrieved
* via a call to \ ref RingBuffer_GetCount ( ) .
*/
# if (BUFFER_SIZE <= 0xFF)
# define RingBuff_Count_t uint8_t
# else
# define RingBuff_Count_t uint16_t
# endif
/* Type Defines: */
/* Type Defines: */
/** Type define for a new ring buffer object. Buffers should be initialized via a call to
/** Type define for a new ring buffer object. Buffers should be initialized via a call to
* \ ref RingBuffer_InitBuffer ( ) before use .
* \ ref RingBuffer_InitBuffer ( ) before use .
@ -58,86 +67,85 @@
RingBuff_Data_t Buffer [ BUFFER_SIZE ] ; /**< Internal ring buffer data, referenced by the buffer pointers. */
RingBuff_Data_t Buffer [ BUFFER_SIZE ] ; /**< Internal ring buffer data, referenced by the buffer pointers. */
RingBuff_Data_t * In ; /**< Current storage location in the circular buffer */
RingBuff_Data_t * In ; /**< Current storage location in the circular buffer */
RingBuff_Data_t * Out ; /**< Current retrieval location in the circular buffer */
RingBuff_Data_t * Out ; /**< Current retrieval location in the circular buffer */
uint8_t Count ; /**< Total number of bytes stored in the circular buffer */
RingBuff_Count_t Count ;
} RingBuff_t ;
} RingBuff_t ;
/* Inline Functions: */
/* Inline Functions: */
/** Initiali s es a ring buffer ready for use. Buffers must be initialized via this function
/** Initiali z es a ring buffer ready for use. Buffers must be initialized via this function
* before any operations are called upon them . Already initialized buffers may be reset
* before any operations are called upon them . Already initialized buffers may be reset
* by re - initializing them using this function .
* by re - initializing them using this function .
*
*
* \ param [ out ] Buffer Pointer to a ring buffer structure to initialize
* \ param [ out ] Buffer Pointer to a ring buffer structure to initialize
*/
*/
static inline void RingBuffer_InitBuffer ( RingBuff_t * const Buffer )
static inline void RingBuffer_InitBuffer ( RingBuff_t * const Buffer )
{
ATOMIC_BLOCK ( ATOMIC_RESTORESTATE )
{
{
Buffer - > In = Buffer - > Buffer ;
Buffer - > In = Buffer - > Buffer ;
Buffer - > Out = Buffer - > Buffer ;
Buffer - > Out = Buffer - > Buffer ;
Buffer - > Count = 0 ;
}
}
}
/** Atomically determines if the specified ring buffer contains any free space. This should
/** Retrieves the minimum number of bytes stored in a particular buffer. This value is computed
* be tested before storing data to the buffer , to ensure that no data is lost due to a
* by entering an atomic lock on the buffer while the IN and OUT locations are fetched , so that
* buffer overrun .
* the buffer cannot be modified while the computation takes place . This value should be cached
* when reading out the contents of the buffer , so that as small a time as possible is spent
* in an atomic lock .
*
*
* \ param [ in , out ] Buffer Pointer to a ring buffer structure to insert into
* \ note The value returned by this function is guaranteed to only be the minimum number of bytes
* stored in the given buffer ; this value may change as other threads write new data and so
* the returned number should be used only to determine how many successive reads may safely
* be performed on the buffer .
*
*
* \ return Boolean true if the buffer contains no free space , false otherwise
* \ param [ in ] Buffer Pointer to a ring buffer structure whose count is to be computed
*/
*/
static inline bool RingBuffer_IsFull ( RingBuff_t * const Buffer )
static inline RingBuff_Count_t RingBuffer_GetCount ( RingBuff_t * const Buffer )
{
{
bool IsFull ;
RingBuff_Count_t Count ;
ATOMIC_BLOCK ( ATOMIC_RESTORESTATE )
ATOMIC_BLOCK ( ATOMIC_RESTORESTATE )
{
{
IsFull = ( Buffer - > Count = = BUFFER_SIZE ) ;
Count = Buffer - > Count ;
}
}
return IsFull ;
return Count ;
}
}
/** Atomically inserts an element into the ring buffer.
/** Atomically determines if the specified ring buffer contains any free space. This should
* be tested before storing data to the buffer , to ensure that no data is lost due to a
* buffer overrun .
*
*
* \ param [ in , out ] Buffer Pointer to a ring buffer structure to insert into
* \ param [ in , out ] Buffer Pointer to a ring buffer structure to insert into
* \ param [ in ] Data Data element to insert into the buffer
*
* \ return Boolean true if the buffer contains no free space , false otherwise
*/
*/
static inline void RingBuffer_AtomicInsert ( RingBuff_t * const Buffer ,
static inline bool RingBuffer_IsFull ( RingBuff_t * const Buffer )
const RingBuff_Data_t Data )
{
ATOMIC_BLOCK ( ATOMIC_RESTORESTATE )
{
{
* Buffer - > In = Data ;
return ( RingBuffer_GetCount ( Buffer ) = = BUFFER_SIZE ) ;
if ( + + Buffer - > In = = & Buffer - > Buffer [ BUFFER_SIZE ] )
Buffer - > In = Buffer - > Buffer ;
Buffer - > Count + + ;
}
}
}
/** Atomically retrieves an element from the ring buffer.
/** Atomically determines if the specified ring buffer contains any data. This should
* be tested before removing data from the buffer , to ensure that the buffer does not
* underflow .
*
*
* \ param [ in , out ] Buffer Pointer to a ring buffer structure to retrieve from
* If the data is to be removed in a loop , store the total number of bytes stored in the
* buffer ( via a call to the \ ref RingBuffer_GetCount ( ) function ) in a temporary variable
* to reduce the time spent in atomicity locks .
*
*
* \ return Next data element stored in the buffer
* \ param [ in , out ] Buffer Pointer to a ring buffer structure to insert into
*
* \ return Boolean true if the buffer contains no free space , false otherwise
*/
*/
static inline RingBuff_Data_t RingBuffer_AtomicRemove ( RingBuff_t * const Buffer )
static inline bool RingBuffer_IsEmpty ( RingBuff_t * const Buffer )
{
{
RingBuff_Data_t Data ;
return ( RingBuffer_GetCount ( Buffer ) = = 0 ) ;
ATOMIC_BLOCK ( ATOMIC_RESTORESTATE )
{
Data = * Buffer - > Out ;
if ( + + Buffer - > Out = = & Buffer - > Buffer [ BUFFER_SIZE ] )
Buffer - > Out = Buffer - > Buffer ;
Buffer - > Count - - ;
}
return Data ;
}
}
/** Inserts an element into the ring buffer.
/** Inserts an element into the ring buffer.
*
* \ note Only one execution thread ( main program thread or an ISR ) may insert into a single buffer
* otherwise data corruption may occur . Insertion and removal may occur from different execution
* threads .
*
*
* \ param [ in , out ] Buffer Pointer to a ring buffer structure to insert into
* \ param [ in , out ] Buffer Pointer to a ring buffer structure to insert into
* \ param [ in ] Data Data element to insert into the buffer
* \ param [ in ] Data Data element to insert into the buffer
@ -150,10 +158,17 @@
if ( + + Buffer - > In = = & Buffer - > Buffer [ BUFFER_SIZE ] )
if ( + + Buffer - > In = = & Buffer - > Buffer [ BUFFER_SIZE ] )
Buffer - > In = Buffer - > Buffer ;
Buffer - > In = Buffer - > Buffer ;
ATOMIC_BLOCK ( ATOMIC_RESTORESTATE )
{
Buffer - > Count + + ;
Buffer - > Count + + ;
}
}
}
/** Retrieves an element from the ring buffer.
/** Removes an element from the ring buffer.
*
* \ note Only one execution thread ( main program thread or an ISR ) may remove from a single buffer
* otherwise data corruption may occur . Insertion and removal may occur from different execution
* threads .
*
*
* \ param [ in , out ] Buffer Pointer to a ring buffer structure to retrieve from
* \ param [ in , out ] Buffer Pointer to a ring buffer structure to retrieve from
*
*
@ -166,10 +181,12 @@
if ( + + Buffer - > Out = = & Buffer - > Buffer [ BUFFER_SIZE ] )
if ( + + Buffer - > Out = = & Buffer - > Buffer [ BUFFER_SIZE ] )
Buffer - > Out = Buffer - > Buffer ;
Buffer - > Out = Buffer - > Buffer ;
ATOMIC_BLOCK ( ATOMIC_RESTORESTATE )
{
Buffer - > Count - - ;
Buffer - > Count - - ;
}
return Data ;
return Data ;
}
}
# endif
# endif