/*\r
LUFA Library\r
- Copyright (C) Dean Camera, 2010.\r
+ Copyright (C) Dean Camera, 2011.\r
\r
dean [at] fourwalledcubicle [dot] com\r
www.lufa-lib.org\r
*/\r
\r
/*\r
- Copyright 2010 Dean Camera (dean [at] fourwalledcubicle [dot] com)\r
+ Copyright 2011 Dean Camera (dean [at] fourwalledcubicle [dot] com)\r
\r
Permission to use, copy, modify, distribute, and sell this\r
software and its documentation for any purpose is hereby granted\r
*/\r
\r
/** \file\r
- * \brief Lightweight ring buffer, for fast insertion/deletion.\r
+ * \brief Lightweight ring buffer, for fast insertion/deletion of bytes.\r
*\r
* Lightweight ring buffer, for fast insertion/deletion. Multiple buffers can be created of\r
* different sizes to suit different needs.\r
*\r
* Note that for each buffer, insertion and removal operations may occur at the same time (via\r
- * a multithreaded ISR based system) however the same kind of operation (two or more insertions\r
+ * a multi-threaded ISR based system) however the same kind of operation (two or more insertions\r
* or deletions) must not overlap. If there is possibility of two or more of the same kind of\r
- * operating occuring at the same point in time, atomic (mutex) locking should be used.\r
+ * operating occurring at the same point in time, atomic (mutex) locking should be used.\r
*/\r
\r
/** \ingroup Group_MiscDrivers\r
- * @defgroup Group_RingBuff Generic Byte Ring Buffer - LUFA/Drivers/Misc/RingBuffer.h\r
+ * \defgroup Group_RingBuff Generic Byte Ring Buffer - LUFA/Drivers/Misc/RingBuffer.h\r
+ * \brief Lightweight ring buffer, for fast insertion/deletion of bytes.\r
*\r
* \section Sec_Dependencies Module Source Dependencies\r
* The following files must be built with any user project that uses this module:\r
* different sizes to suit different needs.\r
*\r
* Note that for each buffer, insertion and removal operations may occur at the same time (via\r
- * a multithreaded ISR based system) however the same kind of operation (two or more insertions\r
+ * a multi-threaded ISR based system) however the same kind of operation (two or more insertions\r
* or deletions) must not overlap. If there is possibility of two or more of the same kind of\r
- * operating occuring at the same point in time, atomic (mutex) locking should be used.\r
+ * operating occurring at the same point in time, atomic (mutex) locking should be used.\r
*\r
* \section Sec_ExampleUsage Example Usage\r
* The following snippet is an example of how this module may be used within a typical\r
*\r
* \code\r
* // Create the buffer structure and its underlying storage array\r
- * RingBuff_t Buffer;\r
- * uint8_t BufferData[128];\r
+ * RingBuffer_t Buffer;\r
+ * uint8_t BufferData[128];\r
*\r
- * // Initialise the buffer with the created storage array\r
+ * // Initialize the buffer with the created storage array\r
* RingBuffer_InitBuffer(&Buffer, BufferData, sizeof(BufferData));\r
*\r
* // Insert some data into the buffer\r
* @{\r
*/\r
\r
-#ifndef __RING_BUFF_H__\r
-#define __RING_BUFF_H__\r
+#ifndef __RING_BUFFER_H__\r
+#define __RING_BUFFER_H__\r
\r
/* Includes: */\r
- #include <util/atomic.h>\r
- #include <stdint.h>\r
- #include <stdbool.h>\r
+ #include "../../Common/Common.h"\r
\r
- #include <LUFA/Common/Common.h>\r
+ /* Enable C linkage for C++ Compilers: */\r
+ #if defined(__cplusplus)\r
+ extern "C" {\r
+ #endif\r
\r
/* Type Defines: */\r
- /** Type define for a new ring buffer object. Buffers should be initialized via a call to\r
+ /** \brief Ring Buffer Management Structure.\r
+ *\r
+ * Type define for a new ring buffer object. Buffers should be initialized via a call to\r
* \ref RingBuffer_InitBuffer() before use.\r
*/\r
typedef struct\r
{\r
- uint8_t* In; /**< Current storage location in the circular buffer */\r
- uint8_t* Out; /**< Current retrieval location in the circular buffer */\r
- uint8_t* Start; /** Pointer to the start of the buffer's underlying storage array */\r
- uint8_t* End; /** Pointer to the end of the buffer's underlying storage array */\r
- uint8_t Size; /** Size of the buffer's underlying storage array */\r
- uint16_t Count; /** Number of bytes currently stored in the buffer */\r
- } RingBuff_t;\r
+ uint8_t* In; /**< Current storage location in the circular buffer. */\r
+ uint8_t* Out; /**< Current retrieval location in the circular buffer. */\r
+ uint8_t* Start; /**< Pointer to the start of the buffer's underlying storage array. */\r
+ uint8_t* End; /**< Pointer to the end of the buffer's underlying storage array. */\r
+ uint8_t Size; /**< Size of the buffer's underlying storage array. */\r
+ uint16_t Count; /**< Number of bytes currently stored in the buffer. */\r
+ } RingBuffer_t;\r
\r
/* Inline Functions: */\r
/** Initializes a ring buffer ready for use. Buffers must be initialized via this function\r
* before any operations are called upon them. Already initialized buffers may be reset\r
* by re-initializing them using this function.\r
*\r
- * \param[out] Buffer Pointer to a ring buffer structure to initialize\r
- * \param[out] DataPtr Pointer to a global array that will hold the data stored into the ring buffer\r
- * \param[out] Size Maximum number of bytes that can be stored in the underlying data array\r
+ * \param[out] Buffer Pointer to a ring buffer structure to initialize.\r
+ * \param[out] DataPtr Pointer to a global array that will hold the data stored into the ring buffer.\r
+ * \param[out] Size Maximum number of bytes that can be stored in the underlying data array.\r
*/\r
- static inline void RingBuffer_InitBuffer(RingBuff_t* Buffer, uint8_t* const DataPtr, const uint16_t Size)\r
+ static inline void RingBuffer_InitBuffer(RingBuffer_t* Buffer, uint8_t* const DataPtr, const uint16_t Size)\r
{\r
- ATOMIC_BLOCK(ATOMIC_RESTORESTATE)\r
- {\r
- GCC_FORCE_POINTER_ACCESS(Buffer);\r
- \r
- Buffer->In = DataPtr;\r
- Buffer->Out = DataPtr;\r
- Buffer->Start = &DataPtr[0];\r
- Buffer->End = &DataPtr[Size];\r
- Buffer->Size = Size;\r
- Buffer->Count = 0;\r
- }\r
+ GCC_FORCE_POINTER_ACCESS(Buffer);\r
+\r
+ uint_reg_t CurrentGlobalInt = GetGlobalInterruptMask();\r
+ GlobalInterruptDisable();\r
+ \r
+ Buffer->In = DataPtr;\r
+ Buffer->Out = DataPtr;\r
+ Buffer->Start = &DataPtr[0];\r
+ Buffer->End = &DataPtr[Size];\r
+ Buffer->Size = Size;\r
+ Buffer->Count = 0;\r
+\r
+ SetGlobalInterruptMask(CurrentGlobalInt);\r
}\r
\r
/** Retrieves the minimum number of bytes stored in a particular buffer. This value is computed\r
* the returned number should be used only to determine how many successive reads may safely\r
* be performed on the buffer.\r
*\r
- * \param[in] Buffer Pointer to a ring buffer structure whose count is to be computed\r
+ * \param[in] Buffer Pointer to a ring buffer structure whose count is to be computed.\r
*/\r
- static inline uint16_t RingBuffer_GetCount(RingBuff_t* const Buffer)\r
+ static inline uint16_t RingBuffer_GetCount(RingBuffer_t* const Buffer)\r
{\r
uint16_t Count;\r
\r
- ATOMIC_BLOCK(ATOMIC_RESTORESTATE)\r
- {\r
- Count = Buffer->Count;\r
- }\r
+ uint_reg_t CurrentGlobalInt = GetGlobalInterruptMask();\r
+ GlobalInterruptDisable();\r
+ \r
+ Count = Buffer->Count;\r
\r
+ SetGlobalInterruptMask(CurrentGlobalInt);\r
return Count;\r
}\r
\r
* be tested before storing data to the buffer, to ensure that no data is lost due to a\r
* buffer overrun.\r
*\r
- * \param[in,out] Buffer Pointer to a ring buffer structure to insert into\r
+ * \param[in,out] Buffer Pointer to a ring buffer structure to insert into.\r
*\r
- * \return Boolean true if the buffer contains no free space, false otherwise\r
+ * \return Boolean \c true if the buffer contains no free space, false otherwise.\r
*/\r
- static inline bool RingBuffer_IsFull(RingBuff_t* const Buffer)\r
+ static inline bool RingBuffer_IsFull(RingBuffer_t* const Buffer)\r
{\r
return (RingBuffer_GetCount(Buffer) == Buffer->Size);\r
}\r
* buffer (via a call to the \ref RingBuffer_GetCount() function) in a temporary variable\r
* to reduce the time spent in atomicity locks.\r
*\r
- * \param[in,out] Buffer Pointer to a ring buffer structure to insert into\r
+ * \param[in,out] Buffer Pointer to a ring buffer structure to insert into.\r
*\r
- * \return Boolean true if the buffer contains no free space, false otherwise\r
+ * \return Boolean \c true if the buffer contains no free space, false otherwise.\r
*/\r
- static inline bool RingBuffer_IsEmpty(RingBuff_t* const Buffer)\r
+ static inline bool RingBuffer_IsEmpty(RingBuffer_t* const Buffer)\r
{\r
return (RingBuffer_GetCount(Buffer) == 0);\r
}\r
* otherwise data corruption may occur. Insertion and removal may occur from different execution\r
* threads.\r
*\r
- * \param[in,out] Buffer Pointer to a ring buffer structure to insert into\r
- * \param[in] Data Data element to insert into the buffer\r
+ * \param[in,out] Buffer Pointer to a ring buffer structure to insert into.\r
+ * \param[in] Data Data element to insert into the buffer.\r
*/\r
- static inline void RingBuffer_Insert(RingBuff_t* const Buffer,\r
+ static inline void RingBuffer_Insert(RingBuffer_t* Buffer,\r
const uint8_t Data)\r
{\r
+ GCC_FORCE_POINTER_ACCESS(Buffer);\r
+\r
*Buffer->In = Data;\r
\r
if (++Buffer->In == Buffer->End)\r
Buffer->In = Buffer->Start;\r
\r
- ATOMIC_BLOCK(ATOMIC_RESTORESTATE)\r
- {\r
- Buffer->Count++;\r
- }\r
+ uint_reg_t CurrentGlobalInt = GetGlobalInterruptMask();\r
+ GlobalInterruptDisable();\r
+ \r
+ Buffer->Count++;\r
+\r
+ SetGlobalInterruptMask(CurrentGlobalInt);\r
}\r
\r
/** Removes an element from the ring buffer.\r
* otherwise data corruption may occur. Insertion and removal may occur from different execution\r
* threads.\r
*\r
- * \param[in,out] Buffer Pointer to a ring buffer structure to retrieve from\r
+ * \param[in,out] Buffer Pointer to a ring buffer structure to retrieve from.\r
*\r
- * \return Next data element stored in the buffer\r
+ * \return Next data element stored in the buffer.\r
*/\r
- static inline uint8_t RingBuffer_Remove(RingBuff_t* const Buffer)\r
+ static inline uint8_t RingBuffer_Remove(RingBuffer_t* Buffer)\r
{\r
+ GCC_FORCE_POINTER_ACCESS(Buffer);\r
+ \r
uint8_t Data = *Buffer->Out;\r
\r
if (++Buffer->Out == Buffer->End)\r
Buffer->Out = Buffer->Start;\r
\r
- ATOMIC_BLOCK(ATOMIC_RESTORESTATE)\r
- {\r
- Buffer->Count--;\r
- }\r
+ uint_reg_t CurrentGlobalInt = GetGlobalInterruptMask();\r
+ GlobalInterruptDisable();\r
+ \r
+ Buffer->Count--;\r
+\r
+ SetGlobalInterruptMask(CurrentGlobalInt);\r
\r
return Data;\r
}\r
\r
/** Returns the next element stored in the ring buffer, without removing it.\r
*\r
- * \param[in,out] Buffer Pointer to a ring buffer structure to retrieve from\r
+ * \param[in,out] Buffer Pointer to a ring buffer structure to retrieve from.\r
*\r
- * \return Next data element stored in the buffer\r
+ * \return Next data element stored in the buffer.\r
*/\r
- static inline uint8_t RingBuffer_Peek(RingBuff_t* const Buffer)\r
+ static inline uint8_t RingBuffer_Peek(RingBuffer_t* const Buffer)\r
{\r
return *Buffer->Out;\r
}\r
\r
+ /* Disable C linkage for C++ Compilers: */\r
+ #if defined(__cplusplus)\r
+ }\r
+ #endif\r
+\r
#endif\r
\r
/** @} */\r