aboutsummaryrefslogtreecommitdiffstats
path: root/Projects/Benito
diff options
context:
space:
mode:
authorDean Camera <dean@fourwalledcubicle.com>2010-08-01 14:03:13 +0000
committerDean Camera <dean@fourwalledcubicle.com>2010-08-01 14:03:13 +0000
commitff09cf9c73bbc2623a8c1420918747840382cc5b (patch)
tree41967f96971d3e1ed2a00f5449f3c83b5a19eba3 /Projects/Benito
parentfb0e6597b611731e31b5d1285e52fc81a5ffd559 (diff)
downloadlufa-ff09cf9c73bbc2623a8c1420918747840382cc5b.tar.gz
lufa-ff09cf9c73bbc2623a8c1420918747840382cc5b.tar.bz2
lufa-ff09cf9c73bbc2623a8c1420918747840382cc5b.zip
Fix XPLAINBridge project discarding characters from the USB interface due to a double read from the endpoint.
Make XPLAINBridge and USBtoSerial projects more reliable by forcing a flush if the UART-to-USB buffer becomes nearly full. Reduce locking in the LightweightRingBuffer.h header files by only locking on the update of the buffer count, and require insertions and removals from each buffer to occur in only one execution thread. Fix CDC_*_ReceiveByte() returning 0 when the interface is not configured, instead of the new -1 error value. Fix CDC_Host_ReceiveByte() not re-freezing the pipe if no packet has been received. Remove redundant Pipe token set commands in the CDC and RNDIS host class drivers.
Diffstat (limited to 'Projects/Benito')
-rw-r--r--Projects/Benito/Benito.c9
-rw-r--r--Projects/Benito/Lib/LightweightRingBuff.h127
2 files changed, 77 insertions, 59 deletions
diff --git a/Projects/Benito/Benito.c b/Projects/Benito/Benito.c
index ac1e064d5..88005eeb0 100644
--- a/Projects/Benito/Benito.c
+++ b/Projects/Benito/Benito.c
@@ -127,13 +127,14 @@ int main(void)
LEDs_TurnOffLEDs(LEDMASK_RX);
/* Check if the receive buffer flush period has expired */
- if (!(--FlushPeriodRemaining) || (Tx_Buffer.Count > 200))
+ RingBuff_Count_t BufferCount = RingBuffer_GetCount(&Tx_Buffer);
+ if (!(--FlushPeriodRemaining) || (BufferCount > 200))
{
/* Echo bytes from the target to the host via the virtual serial port */
- if (Tx_Buffer.Count)
+ if (BufferCount)
{
- while (Tx_Buffer.Count)
- CDC_Device_SendByte(&VirtualSerial_CDC_Interface, RingBuffer_AtomicRemove(&Tx_Buffer));
+ while (BufferCount--)
+ CDC_Device_SendByte(&VirtualSerial_CDC_Interface, RingBuffer_Remove(&Tx_Buffer));
LEDs_TurnOnLEDs(LEDMASK_RX);
PulseMSRemaining.RxLEDPulse = TX_RX_LED_PULSE_MS;
diff --git a/Projects/Benito/Lib/LightweightRingBuff.h b/Projects/Benito/Lib/LightweightRingBuff.h
index 2faef4382..cb0f6112a 100644
--- a/Projects/Benito/Lib/LightweightRingBuff.h
+++ b/Projects/Benito/Lib/LightweightRingBuff.h
@@ -44,10 +44,19 @@
/* Defines: */
/** Size of each ring buffer, in data elements - must be between 1 and 255. */
- #define BUFFER_SIZE 255
+ #define BUFFER_SIZE 255
/** 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 define for a new ring buffer object. Buffers should be initialized via a call to
@@ -58,11 +67,11 @@
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* 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;
/* Inline Functions: */
- /** Initialises a ring buffer ready for use. Buffers must be initialized via this function
+ /** 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.
*
@@ -70,75 +79,74 @@
*/
static inline void RingBuffer_InitBuffer(RingBuff_t* const Buffer)
{
- Buffer->In = Buffer->Buffer;
- Buffer->Out = Buffer->Buffer;
- Buffer->Count = 0;
+ ATOMIC_BLOCK(ATOMIC_RESTORESTATE)
+ {
+ Buffer->In = Buffer->Buffer;
+ Buffer->Out = Buffer->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.
+ /** Retrieves the minimum number of bytes stored in a particular buffer. This value is computed
+ * by entering an atomic lock on the buffer while the IN and OUT locations are fetched, so that
+ * 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
- */
- static inline bool RingBuffer_IsFull(RingBuff_t* const Buffer)
+ * \param[in] Buffer Pointer to a ring buffer structure whose count is to be computed
+ */
+ static inline RingBuff_Count_t RingBuffer_GetCount(RingBuff_t* const Buffer)
{
- bool IsFull;
+ RingBuff_Count_t Count;
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] Data Data element to insert into the buffer
- */
- static inline void RingBuffer_AtomicInsert(RingBuff_t* const Buffer,
- const RingBuff_Data_t Data)
+ *
+ * \return Boolean true if the buffer contains no free space, false otherwise
+ */
+ static inline bool RingBuffer_IsFull(RingBuff_t* const Buffer)
{
- ATOMIC_BLOCK(ATOMIC_RESTORESTATE)
- {
- *Buffer->In = Data;
-
- if (++Buffer->In == &Buffer->Buffer[BUFFER_SIZE])
- Buffer->In = Buffer->Buffer;
-
- Buffer->Count++;
- }
+ return (RingBuffer_GetCount(Buffer) == BUFFER_SIZE);
}
- /** 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
- */
- static inline RingBuff_Data_t RingBuffer_AtomicRemove(RingBuff_t* const 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 bool RingBuffer_IsEmpty(RingBuff_t* const Buffer)
{
- RingBuff_Data_t Data;
-
- ATOMIC_BLOCK(ATOMIC_RESTORESTATE)
- {
- Data = *Buffer->Out;
-
- if (++Buffer->Out == &Buffer->Buffer[BUFFER_SIZE])
- Buffer->Out = Buffer->Buffer;
-
- Buffer->Count--;
- }
-
- return Data;
+ return (RingBuffer_GetCount(Buffer) == 0);
}
/** 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] Data Data element to insert into the buffer
*/
@@ -149,11 +157,18 @@
if (++Buffer->In == &Buffer->Buffer[BUFFER_SIZE])
Buffer->In = Buffer->Buffer;
-
- Buffer->Count++;
+
+ ATOMIC_BLOCK(ATOMIC_RESTORESTATE)
+ {
+ 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
*
@@ -165,11 +180,13 @@
if (++Buffer->Out == &Buffer->Buffer[BUFFER_SIZE])
Buffer->Out = Buffer->Buffer;
-
- Buffer->Count--;
+ ATOMIC_BLOCK(ATOMIC_RESTORESTATE)
+ {
+ Buffer->Count--;
+ }
+
return Data;
}
#endif
-