X-Git-Url: http://git.linex4red.de/pub/USBasp.git/blobdiff_plain/2073b96d82433607bd287e3b6529fd0d3cc428cd..55aadf97d5d2bd86f2a0c3a53d4608c0cf96471e:/LUFA/Drivers/Misc/RingBuffer.h
diff --git a/LUFA/Drivers/Misc/RingBuffer.h b/LUFA/Drivers/Misc/RingBuffer.h
index af6a69f83..c95363871 100644
--- a/LUFA/Drivers/Misc/RingBuffer.h
+++ b/LUFA/Drivers/Misc/RingBuffer.h
@@ -1,13 +1,13 @@
/*
LUFA Library
- Copyright (C) Dean Camera, 2010.
+ Copyright (C) Dean Camera, 2011.
dean [at] fourwalledcubicle [dot] com
www.lufa-lib.org
*/
/*
- Copyright 2010 Dean Camera (dean [at] fourwalledcubicle [dot] com)
+ Copyright 2011 Dean Camera (dean [at] fourwalledcubicle [dot] com)
Permission to use, copy, modify, distribute, and sell this
software and its documentation for any purpose is hereby granted
@@ -29,40 +29,44 @@
*/
/** \file
- * \brief Lightweight ring buffer, for fast insertion/deletion.
+ * \brief Lightweight ring buffer, for fast insertion/deletion of bytes.
*
* Lightweight ring buffer, for fast insertion/deletion. Multiple buffers can be created of
* different sizes to suit different needs.
*
* Note that for each buffer, insertion and removal operations may occur at the same time (via
- * a multithreaded ISR based system) however the same kind of operation (two or more insertions
+ * a multi-threaded ISR based system) however the same kind of operation (two or more insertions
* or deletions) must not overlap. If there is possibility of two or more of the same kind of
- * operating occuring at the same point in time, atomic (mutex) locking should be used.
+ * operating occurring at the same point in time, atomic (mutex) locking should be used.
*/
/** \ingroup Group_MiscDrivers
- * @defgroup Group_RingBuff Generic Byte Ring Buffer - LUFA/Drivers/Misc/RingBuffer.h
+ * \defgroup Group_RingBuff Generic Byte Ring Buffer - LUFA/Drivers/Misc/RingBuffer.h
+ * \brief Lightweight ring buffer, for fast insertion/deletion of bytes.
*
* \section Sec_Dependencies Module Source Dependencies
* The following files must be built with any user project that uses this module:
* - None
*
- * \section Module Description
+ * \section Sec_ModDescription Module Description
* Lightweight ring buffer, for fast insertion/deletion. Multiple buffers can be created of
* different sizes to suit different needs.
*
* Note that for each buffer, insertion and removal operations may occur at the same time (via
- * a multithreaded ISR based system) however the same kind of operation (two or more insertions
+ * a multi-threaded ISR based system) however the same kind of operation (two or more insertions
* or deletions) must not overlap. If there is possibility of two or more of the same kind of
- * operating occuring at the same point in time, atomic (mutex) locking should be used.
+ * operating occurring at the same point in time, atomic (mutex) locking should be used.
+ *
+ * \section Sec_ExampleUsage Example Usage
+ * The following snippet is an example of how this module may be used within a typical
+ * application.
*
- * Example Usage:
* \code
* // Create the buffer structure and its underlying storage array
- * RingBuff_t Buffer;
- * uint8_t BufferData[128];
+ * RingBuffer_t Buffer;
+ * uint8_t BufferData[128];
*
- * // Initialise the buffer with the created storage array
+ * // Initialize the buffer with the created storage array
* RingBuffer_InitBuffer(&Buffer, BufferData, sizeof(BufferData));
*
* // Insert some data into the buffer
@@ -86,52 +90,57 @@
* @{
*/
-#ifndef __RING_BUFF_H__
-#define __RING_BUFF_H__
+#ifndef __RING_BUFFER_H__
+#define __RING_BUFFER_H__
/* Includes: */
- #include
- #include
- #include
+ #include "../../Common/Common.h"
- #include
+ /* Enable C linkage for C++ Compilers: */
+ #if defined(__cplusplus)
+ extern "C" {
+ #endif
/* Type Defines: */
- /** Type define for a new ring buffer object. Buffers should be initialized via a call to
+ /** \brief Ring Buffer Management Structure.
+ *
+ * Type define for a new ring buffer object. Buffers should be initialized via a call to
* \ref RingBuffer_InitBuffer() before use.
*/
typedef struct
{
- uint8_t* In; /**< Current storage location in the circular buffer */
- uint8_t* Out; /**< Current retrieval location in the circular buffer */
- uint8_t* Start; /** Pointer to the start of the buffer's underlying storage array */
- uint8_t* End; /** Pointer to the end of the buffer's underlying storage array */
- uint8_t Size; /** Size of the buffer's underlying storage array */
- uint16_t Count; /** Number of bytes currently stored in the buffer */
- } RingBuff_t;
+ uint8_t* In; /**< Current storage location in the circular buffer. */
+ uint8_t* Out; /**< Current retrieval location in the circular buffer. */
+ uint8_t* Start; /**< Pointer to the start of the buffer's underlying storage array. */
+ uint8_t* End; /**< Pointer to the end of the buffer's underlying storage array. */
+ uint8_t Size; /**< Size of the buffer's underlying storage array. */
+ uint16_t Count; /**< Number of bytes currently stored in the buffer. */
+ } RingBuffer_t;
/* Inline Functions: */
/** Initializes 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
* by re-initializing them using this function.
*
- * \param[out] Buffer Pointer to a ring buffer structure to initialize
- * \param[out] DataPtr Pointer to a global array that will hold the data stored into the ring buffer
- * \param[out] Size Maximum number of bytes that can be stored in the underlying data array
+ * \param[out] Buffer Pointer to a ring buffer structure to initialize.
+ * \param[out] DataPtr Pointer to a global array that will hold the data stored into the ring buffer.
+ * \param[out] Size Maximum number of bytes that can be stored in the underlying data array.
*/
- static inline void RingBuffer_InitBuffer(RingBuff_t* Buffer, uint8_t* const DataPtr, const uint16_t Size)
+ static inline void RingBuffer_InitBuffer(RingBuffer_t* Buffer, uint8_t* const DataPtr, const uint16_t Size)
{
- ATOMIC_BLOCK(ATOMIC_RESTORESTATE)
- {
- GCC_FORCE_POINTER_ACCESS(Buffer);
-
- Buffer->In = DataPtr;
- Buffer->Out = DataPtr;
- Buffer->Start = &DataPtr[0];
- Buffer->End = &DataPtr[Size];
- Buffer->Size = Size;
- Buffer->Count = 0;
- }
+ GCC_FORCE_POINTER_ACCESS(Buffer);
+
+ uint_reg_t CurrentGlobalInt = GetGlobalInterruptMask();
+ GlobalInterruptDisable();
+
+ Buffer->In = DataPtr;
+ Buffer->Out = DataPtr;
+ Buffer->Start = &DataPtr[0];
+ Buffer->End = &DataPtr[Size];
+ Buffer->Size = Size;
+ Buffer->Count = 0;
+
+ SetGlobalInterruptMask(CurrentGlobalInt);
}
/** Retrieves the minimum number of bytes stored in a particular buffer. This value is computed
@@ -145,17 +154,18 @@
* the returned number should be used only to determine how many successive reads may safely
* be performed on the buffer.
*
- * \param[in] Buffer Pointer to a ring buffer structure whose count is to be computed
+ * \param[in] Buffer Pointer to a ring buffer structure whose count is to be computed.
*/
- static inline uint16_t RingBuffer_GetCount(RingBuff_t* const Buffer)
+ static inline uint16_t RingBuffer_GetCount(RingBuffer_t* const Buffer)
{
uint16_t Count;
- ATOMIC_BLOCK(ATOMIC_RESTORESTATE)
- {
- Count = Buffer->Count;
- }
+ uint_reg_t CurrentGlobalInt = GetGlobalInterruptMask();
+ GlobalInterruptDisable();
+
+ Count = Buffer->Count;
+ SetGlobalInterruptMask(CurrentGlobalInt);
return Count;
}
@@ -163,11 +173,11 @@
* 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.
*
- * \return Boolean true if the buffer contains no free space, false otherwise
+ * \return Boolean \c true if the buffer contains no free space, false otherwise.
*/
- static inline bool RingBuffer_IsFull(RingBuff_t* const Buffer)
+ static inline bool RingBuffer_IsFull(RingBuffer_t* const Buffer)
{
return (RingBuffer_GetCount(Buffer) == Buffer->Size);
}
@@ -180,11 +190,11 @@
* buffer (via a call to the \ref RingBuffer_GetCount() function) in a temporary variable
* to reduce the time spent in atomicity locks.
*
- * \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.
*
- * \return Boolean true if the buffer contains no free space, false otherwise
+ * \return Boolean \c true if the buffer contains no free space, false otherwise.
*/
- static inline bool RingBuffer_IsEmpty(RingBuff_t* const Buffer)
+ static inline bool RingBuffer_IsEmpty(RingBuffer_t* const Buffer)
{
return (RingBuffer_GetCount(Buffer) == 0);
}
@@ -195,21 +205,25 @@
* 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] Data Data element to insert into the buffer
+ * \param[in,out] Buffer Pointer to a ring buffer structure to insert into.
+ * \param[in] Data Data element to insert into the buffer.
*/
- static inline void RingBuffer_Insert(RingBuff_t* const Buffer,
+ static inline void RingBuffer_Insert(RingBuffer_t* Buffer,
const uint8_t Data)
{
+ GCC_FORCE_POINTER_ACCESS(Buffer);
+
*Buffer->In = Data;
if (++Buffer->In == Buffer->End)
Buffer->In = Buffer->Start;
- ATOMIC_BLOCK(ATOMIC_RESTORESTATE)
- {
- Buffer->Count++;
- }
+ uint_reg_t CurrentGlobalInt = GetGlobalInterruptMask();
+ GlobalInterruptDisable();
+
+ Buffer->Count++;
+
+ SetGlobalInterruptMask(CurrentGlobalInt);
}
/** Removes an element from the ring buffer.
@@ -218,36 +232,45 @@
* 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.
*
- * \return Next data element stored in the buffer
+ * \return Next data element stored in the buffer.
*/
- static inline uint8_t RingBuffer_Remove(RingBuff_t* const Buffer)
+ static inline uint8_t RingBuffer_Remove(RingBuffer_t* Buffer)
{
+ GCC_FORCE_POINTER_ACCESS(Buffer);
+
uint8_t Data = *Buffer->Out;
if (++Buffer->Out == Buffer->End)
Buffer->Out = Buffer->Start;
- ATOMIC_BLOCK(ATOMIC_RESTORESTATE)
- {
- Buffer->Count--;
- }
+ uint_reg_t CurrentGlobalInt = GetGlobalInterruptMask();
+ GlobalInterruptDisable();
+
+ Buffer->Count--;
+
+ SetGlobalInterruptMask(CurrentGlobalInt);
return Data;
}
/** Returns the next element stored in the ring buffer, without removing it.
*
- * \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.
*
- * \return Next data element stored in the buffer
+ * \return Next data element stored in the buffer.
*/
- static inline uint8_t RingBuffer_Peek(RingBuff_t* const Buffer)
+ static inline uint8_t RingBuffer_Peek(RingBuffer_t* const Buffer)
{
return *Buffer->Out;
}
+ /* Disable C linkage for C++ Compilers: */
+ #if defined(__cplusplus)
+ }
+ #endif
+
#endif
/** @} */