Make a new general RingBuffer.h misc library driver, instead of the per-application LightweightRingBuff.h ring buffers. Change over projects to use the new driver.

Add ORDERED_EP_CONFIG to the device Projects (only) that use only a single class driver, or where the endpoint ordering is fixed, to save on compiled binary size.

Added new GCC_FORCE_POINTER_ACCESS() macro to correct GCC's mishandling of struct pointers.
pull/1469/head
Dean Camera 14 years ago
parent 12418e6eaf
commit 39ac72f2d1

File diff suppressed because one or more lines are too long

@ -85,14 +85,14 @@
*
* \ingroup Group_Debugging
*/
#define JTAG_DEBUG_POINT() __asm__ volatile ("NOP" ::)
#define JTAG_DEBUG_POINT() __asm__ __volatile__ ("NOP" ::)
/** Defines an explicit JTAG break point in the resulting binary via the ASM BREAK statement. When
* a JTAG is used, this causes the program execution to halt when reached until manually resumed.
*
* \ingroup Group_Debugging
*/
#define JTAG_DEBUG_BREAK() __asm__ volatile ("BREAK" ::)
#define JTAG_DEBUG_BREAK() __asm__ __volatile__ ("BREAK" ::)
/** Macro for testing condition "x" and breaking via JTAG_DEBUG_BREAK() if the condition is false.
*
@ -112,6 +112,16 @@
"Assertion \"%s\" failed.\r\n"), \
__FILE__, __func__, __LINE__, #x); } }MACROE
/** Forces GCC to use pointer indirection (via the AVR's pointer register pairs) when accessing the given
* struct pointer. In some cases GCC will emit non-optimal assembly code when accessing a structure through
* a pointer, resulting in a larger binary. When this macro is used on a (non-const) structure pointer before
* use, it will force GCC to use pointer indirection on the elements rather than direct store and load
* instructions.
*
* \param[in, out] StructPtr Pointer to a structure which is to be forced into indirect access mode.
*/
#define GCC_FORCE_POINTER_ACCESS(StructPtr) __asm__ __volatile__("" : "=b" (StructPtr) : "0" (StructPtr))
#if !defined(pgm_read_ptr) || defined(__DOXYGEN__)
/** Reads a pointer out of PROGMEM space. This is currently a wrapper for the avr-libc pgm_read_ptr()
* macro with a void* cast, so that its value can be assigned directly to a pointer variable or used

@ -29,10 +29,10 @@
*/
/** \file
* \brief Lightweight ring buffer, for fast insertion/deletion.
*
* Ultra lightweight ring buffer, for fast insertion/deletion. This uses inlined functions
* for maximum speed. All buffers created with this library must be of the same size, however
* multiple independant buffers can be created.
* 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
@ -40,30 +40,61 @@
* operating occuring at the same point in time, atomic (mutex) locking should be used.
*/
#ifndef _ULW_RING_BUFF_H_
#define _ULW_RING_BUFF_H_
/** \ingroup Group_MiscDrivers
* @defgroup Group_RingBuff Generic Byte Ring Buffer - LUFA/Drivers/Misc/RingBuffer.h
*
* \section Sec_Dependencies Module Source Dependencies
* The following files must be built with any user project that uses this module:
* - None
*
* \section 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
* 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.
*
* Example Usage:
* \code
* // Create the buffer structure and its underlying storage array
* RingBuff_t Buffer;
* uint8_t BufferData[128];
*
* // Initialise the buffer with the created storage array
* RingBuffer_InitBuffer(&Buffer, BufferData, sizeof(BufferData));
*
* // Insert some data into the buffer
* RingBuffer_Insert(Buffer, 'H');
* RingBuffer_Insert(Buffer, 'E');
* RingBuffer_Insert(Buffer, 'L');
* RingBuffer_Insert(Buffer, 'L');
* RingBuffer_Insert(Buffer, 'O');
*
* // Cache the number of stored bytes in the buffer
* uint16_t BufferCount = RingBuffer_GetCount(&Buffer);
*
* // Printer stored data length
* printf("Buffer Length: %d, Buffer Data:\r\n", BufferCount);
*
* // Print contents of the buffer one character at a time
* while (BufferCount--)
* putc(RingBuffer_Remove(&Buffer));
* \endcode
*
* @{
*/
#ifndef __RING_BUFF_H__
#define __RING_BUFF_H__
/* Includes: */
#include <util/atomic.h>
#include <stdint.h>
#include <stdbool.h>
/* Defines: */
/** Size of each ring buffer, in data elements - must be between 1 and 255. */
#define BUFFER_SIZE 128
/** Type of data to store into the buffer. */
#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
#include <LUFA/Common/Common.h>
/* Type Defines: */
/** Type define for a new ring buffer object. Buffers should be initialized via a call to
@ -71,10 +102,12 @@
*/
typedef struct
{
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 */
RingBuff_Count_t Count;
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;
/* Inline Functions: */
@ -82,14 +115,22 @@
* 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] 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* const Buffer)
static inline void RingBuffer_InitBuffer(RingBuff_t* Buffer, uint8_t* const DataPtr, const uint16_t Size)
{
ATOMIC_BLOCK(ATOMIC_RESTORESTATE)
{
Buffer->In = Buffer->Buffer;
Buffer->Out = Buffer->Buffer;
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;
}
}
@ -106,9 +147,9 @@
*
* \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)
static inline uint16_t RingBuffer_GetCount(RingBuff_t* const Buffer)
{
RingBuff_Count_t Count;
uint16_t Count;
ATOMIC_BLOCK(ATOMIC_RESTORESTATE)
{
@ -128,7 +169,7 @@
*/
static inline bool RingBuffer_IsFull(RingBuff_t* const Buffer)
{
return (RingBuffer_GetCount(Buffer) == BUFFER_SIZE);
return (RingBuffer_GetCount(Buffer) == Buffer->Size);
}
/** Atomically determines if the specified ring buffer contains any data. This should
@ -158,12 +199,12 @@
* \param[in] Data Data element to insert into the buffer
*/
static inline void RingBuffer_Insert(RingBuff_t* const Buffer,
const RingBuff_Data_t Data)
const uint8_t Data)
{
*Buffer->In = Data;
if (++Buffer->In == &Buffer->Buffer[BUFFER_SIZE])
Buffer->In = Buffer->Buffer;
if (++Buffer->In == Buffer->End)
Buffer->In = Buffer->Start;
ATOMIC_BLOCK(ATOMIC_RESTORESTATE)
{
@ -181,12 +222,12 @@
*
* \return Next data element stored in the buffer
*/
static inline RingBuff_Data_t RingBuffer_Remove(RingBuff_t* const Buffer)
static inline uint8_t RingBuffer_Remove(RingBuff_t* const Buffer)
{
RingBuff_Data_t Data = *Buffer->Out;
uint8_t Data = *Buffer->Out;
if (++Buffer->Out == &Buffer->Buffer[BUFFER_SIZE])
Buffer->Out = Buffer->Buffer;
if (++Buffer->Out == Buffer->End)
Buffer->Out = Buffer->Start;
ATOMIC_BLOCK(ATOMIC_RESTORESTATE)
{
@ -202,10 +243,12 @@
*
* \return Next data element stored in the buffer
*/
static inline RingBuff_Data_t RingBuffer_Peek(RingBuff_t* const Buffer)
static inline uint8_t RingBuffer_Peek(RingBuff_t* const Buffer)
{
return *Buffer->Out;
}
#endif
/** @} */

@ -12,6 +12,8 @@
* - Added new MIDIToneGenerator project
* - Added new ORDERED_EP_CONFIG compile time option to restrict endpoint/pipe configuration to ascending order
* in exchange for a smaller compiled program binary size
* - Added a new general RingBuff.h miscellaneous ring buffer library driver header
* - Added new GCC_FORCE_POINTER_ACCESS() macro to correct GCC's mishandling of struct pointer accesses
* - Library Applications:
* - Added new incomplete MIDIToneGenerator project
* - Added ability to write protect Mass Storage disk write operations from the host OS
@ -27,6 +29,7 @@
* via the Input Capture register, to reduce user confusion
* - Combined page and word ISP programming mode code in the AVRISP-MKII clone project to reduce compiled size and
* increase maintainability of the code
* - Changed over library projects to use the new general ring buffer library driver module
*
* <b>Fixed:</b>
* - Core:

@ -21,7 +21,6 @@
* -# Add HID report macros to make HID report editing easier
* -# Investigate dynamically created device descriptors
* - Known Bugs
* -# Errors with AVRISP-MKII program with full EEPROM programming on the ATMEGA8 (and others?)
* -# No wakeup when plugged into hub, and hub plugged into host
* -# Incomplete TMC class demo errors
* - Documentation/Support

@ -39,6 +39,9 @@
/** Circular buffer to hold data from the serial port before it is sent to the host. */
RingBuff_t USARTtoUSB_Buffer;
/** Underlying data buffer for \ref USARTtoUSB_Buffer, where the stored bytes are located. */
uint8_t USARTtoUSB_Buffer_Data[128];
/** Pulse generation counters to keep track of the number of milliseconds remaining for each pulse type */
volatile struct
{
@ -85,7 +88,7 @@ int main(void)
{
SetupHardware();
RingBuffer_InitBuffer(&USARTtoUSB_Buffer);
RingBuffer_InitBuffer(&USARTtoUSB_Buffer, USARTtoUSB_Buffer_Data, sizeof(USARTtoUSB_Buffer_Data));
sei();
@ -126,7 +129,7 @@ int main(void)
LEDs_TurnOffLEDs(LEDMASK_RX);
/* Check if the receive buffer flush period has expired */
RingBuff_Count_t BufferCount = RingBuffer_GetCount(&USARTtoUSB_Buffer);
uint16_t BufferCount = RingBuffer_GetCount(&USARTtoUSB_Buffer);
if (!(--FlushPeriodRemaining) || (BufferCount > 200))
{
/* Echo bytes from the target to the host via the virtual serial port */

@ -42,11 +42,11 @@
#include <avr/interrupt.h>
#include "Descriptors.h"
#include "Lib/LightweightRingBuff.h"
#include <LUFA/Version.h>
#include <LUFA/Drivers/Board/LEDs.h>
#include <LUFA/Drivers/Peripheral/Serial.h>
#include <LUFA/Drivers/Misc/RingBuffer.h>
#include <LUFA/Drivers/USB/USB.h>
/* Macros: */

@ -118,6 +118,7 @@ LUFA_PATH = ../..
# LUFA library compile-time options and predefined tokens
LUFA_OPTS = -D USB_DEVICE_ONLY
LUFA_OPTS += -D DEVICE_STATE_AS_GPIOR=0
LUFA_OPTS += -D ORDERED_EP_CONFIG
LUFA_OPTS += -D FIXED_CONTROL_ENDPOINT_SIZE=8
LUFA_OPTS += -D FIXED_NUM_CONFIGURATIONS=1
LUFA_OPTS += -D USE_FLASH_DESCRIPTORS

@ -117,6 +117,8 @@ LUFA_PATH = ../../..
# LUFA library compile-time options and predefined tokens
LUFA_OPTS += -D DEVICE_STATE_AS_GPIOR=0
LUFA_OPTS += -D HOST_STATE_AS_GPIOR=1
LUFA_OPTS += -D ORDERED_EP_CONFIG
LUFA_OPTS += -D FIXED_CONTROL_ENDPOINT_SIZE=8
LUFA_OPTS += -D FIXED_NUM_CONFIGURATIONS=1
LUFA_OPTS += -D USE_FLASH_DESCRIPTORS

@ -118,6 +118,7 @@ LUFA_PATH = ../..
# LUFA library compile-time options and predefined tokens
LUFA_OPTS = -D USB_DEVICE_ONLY
LUFA_OPTS += -D DEVICE_STATE_AS_GPIOR=0
LUFA_OPTS += -D ORDERED_EP_CONFIG
LUFA_OPTS += -D FIXED_CONTROL_ENDPOINT_SIZE=8
LUFA_OPTS += -D FIXED_NUM_CONFIGURATIONS=1
LUFA_OPTS += -D USE_FLASH_DESCRIPTORS

@ -118,6 +118,7 @@ LUFA_PATH = ../../
# LUFA library compile-time options and predefined tokens
LUFA_OPTS = -D USB_DEVICE_ONLY
LUFA_OPTS += -D DEVICE_STATE_AS_GPIOR=0
LUFA_OPTS += -D ORDERED_EP_CONFIG
LUFA_OPTS += -D FIXED_CONTROL_ENDPOINT_SIZE=8
LUFA_OPTS += -D FIXED_NUM_CONFIGURATIONS=1
LUFA_OPTS += -D USE_FLASH_DESCRIPTORS

@ -118,6 +118,7 @@ LUFA_PATH = ../..
# LUFA library compile-time options and predefined tokens
LUFA_OPTS = -D USB_DEVICE_ONLY
LUFA_OPTS += -D DEVICE_STATE_AS_GPIOR=0
LUFA_OPTS += -D ORDERED_EP_CONFIG
LUFA_OPTS += -D FIXED_CONTROL_ENDPOINT_SIZE=8
LUFA_OPTS += -D FIXED_NUM_CONFIGURATIONS=1
LUFA_OPTS += -D USE_FLASH_DESCRIPTORS

@ -118,6 +118,7 @@ LUFA_PATH = ../..
# LUFA library compile-time options and predefined tokens
LUFA_OPTS = -D USB_HOST_ONLY
LUFA_OPTS += -D HOST_STATE_AS_GPIOR=0
LUFA_OPTS += -D ORDERED_EP_CONFIG
LUFA_OPTS += -D USE_STATIC_OPTIONS="(USB_OPT_REG_ENABLED | USB_OPT_AUTO_PLL)"
LUFA_OPTS += -D NO_STREAM_CALLBACKS

@ -118,6 +118,7 @@ LUFA_PATH = ../..
# LUFA library compile-time options and predefined tokens
LUFA_OPTS = -D USB_DEVICE_ONLY
LUFA_OPTS += -D DEVICE_STATE_AS_GPIOR=0
LUFA_OPTS += -D ORDERED_EP_CONFIG
LUFA_OPTS += -D FIXED_CONTROL_ENDPOINT_SIZE=8
LUFA_OPTS += -D FIXED_NUM_CONFIGURATIONS=1
LUFA_OPTS += -D CONTROL_ONLY_DEVICE

@ -1,211 +0,0 @@
/*
LUFA Library
Copyright (C) Dean Camera, 2010.
dean [at] fourwalledcubicle [dot] com
www.lufa-lib.org
*/
/*
Copyright 2010 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
without fee, provided that the above copyright notice appear in
all copies and that both that the copyright notice and this
permission notice and warranty disclaimer appear in supporting
documentation, and that the name of the author not be used in
advertising or publicity pertaining to distribution of the
software without specific, written prior permission.
The author disclaim all warranties with regard to this
software, including all implied warranties of merchantability
and fitness. In no event shall the author be liable for any
special, indirect or consequential damages or any damages
whatsoever resulting from loss of use, data or profits, whether
in an action of contract, negligence or other tortious action,
arising out of or in connection with the use or performance of
this software.
*/
/** \file
*
* Ultra lightweight ring buffer, for fast insertion/deletion. This uses inlined functions
* for maximum speed. All buffers created with this library must be of the same size, however
* multiple independant buffers can be created.
*
* 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
* 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.
*/
#ifndef _ULW_RING_BUFF_H_
#define _ULW_RING_BUFF_H_
/* Includes: */
#include <util/atomic.h>
#include <stdint.h>
#include <stdbool.h>
/* Defines: */
/** Size of each ring buffer, in data elements - must be between 1 and 255. */
#define BUFFER_SIZE 128
/** Type of data to store into the buffer. */
#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
* \ref RingBuffer_InitBuffer() before use.
*/
typedef struct
{
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 */
RingBuff_Count_t Count;
} RingBuff_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
*/
static inline void RingBuffer_InitBuffer(RingBuff_t* const Buffer)
{
ATOMIC_BLOCK(ATOMIC_RESTORESTATE)
{
Buffer->In = Buffer->Buffer;
Buffer->Out = Buffer->Buffer;
}
}
/** 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.
*
* \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.
*
* \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)
{
RingBuff_Count_t Count;
ATOMIC_BLOCK(ATOMIC_RESTORESTATE)
{
Count = Buffer->Count;
}
return Count;
}
/** 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
*
* \return Boolean true if the buffer contains no free space, false otherwise
*/
static inline bool RingBuffer_IsFull(RingBuff_t* const Buffer)
{
return (RingBuffer_GetCount(Buffer) == BUFFER_SIZE);
}
/** 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.
*
* 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.
*
* \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)
{
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
*/
static inline void RingBuffer_Insert(RingBuff_t* const Buffer,
const RingBuff_Data_t Data)
{
*Buffer->In = Data;
if (++Buffer->In == &Buffer->Buffer[BUFFER_SIZE])
Buffer->In = Buffer->Buffer;
ATOMIC_BLOCK(ATOMIC_RESTORESTATE)
{
Buffer->Count++;
}
}
/** 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
*
* \return Next data element stored in the buffer
*/
static inline RingBuff_Data_t RingBuffer_Remove(RingBuff_t* const Buffer)
{
RingBuff_Data_t Data = *Buffer->Out;
if (++Buffer->Out == &Buffer->Buffer[BUFFER_SIZE])
Buffer->Out = Buffer->Buffer;
ATOMIC_BLOCK(ATOMIC_RESTORESTATE)
{
Buffer->Count--;
}
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
*
* \return Next data element stored in the buffer
*/
static inline RingBuff_Data_t RingBuffer_Peek(RingBuff_t* const Buffer)
{
return *Buffer->Out;
}
#endif

@ -39,9 +39,16 @@
/** Circular buffer to hold data from the host before it is sent to the device via the serial port. */
RingBuff_t USBtoUSART_Buffer;
/** Underlying data buffer for \ref USBtoUSART_Buffer, where the stored bytes are located. */
uint8_t USBtoUSART_Buffer_Data[128];
/** Circular buffer to hold data from the serial port before it is sent to the host. */
RingBuff_t USARTtoUSB_Buffer;
/** Underlying data buffer for \ref USARTtoUSB_Buffer, where the stored bytes are located. */
uint8_t USARTtoUSB_Buffer_Data[128];
/** LUFA CDC Class driver interface configuration and state information. This structure is
* passed to all CDC Class driver functions, so that multiple instances of the same class
* within a device can be differentiated from one another.
@ -73,8 +80,8 @@ int main(void)
{
SetupHardware();
RingBuffer_InitBuffer(&USBtoUSART_Buffer);
RingBuffer_InitBuffer(&USARTtoUSB_Buffer);
RingBuffer_InitBuffer(&USBtoUSART_Buffer, USBtoUSART_Buffer_Data, sizeof(USBtoUSART_Buffer_Data));
RingBuffer_InitBuffer(&USARTtoUSB_Buffer, USARTtoUSB_Buffer_Data, sizeof(USARTtoUSB_Buffer_Data));
LEDs_SetAllLEDs(LEDMASK_USB_NOTREADY);
sei();
@ -92,7 +99,7 @@ int main(void)
}
/* Check if the UART receive buffer flush timer has expired or the buffer is nearly full */
RingBuff_Count_t BufferCount = RingBuffer_GetCount(&USARTtoUSB_Buffer);
uint16_t BufferCount = RingBuffer_GetCount(&USARTtoUSB_Buffer);
if ((TIFR0 & (1 << TOV0)) || (BufferCount > 200))
{
/* Clear flush timer expiry flag */

@ -44,11 +44,10 @@
#include "Descriptors.h"
#include "Lib/LightweightRingBuff.h"
#include <LUFA/Version.h>
#include <LUFA/Drivers/Board/LEDs.h>
#include <LUFA/Drivers/Peripheral/Serial.h>
#include <LUFA/Drivers/Misc/RingBuffer.h>
#include <LUFA/Drivers/USB/USB.h>
/* Macros: */

@ -118,6 +118,7 @@ LUFA_PATH = ../..
# LUFA library compile-time options and predefined tokens
LUFA_OPTS = -D USB_DEVICE_ONLY
LUFA_OPTS += -D DEVICE_STATE_AS_GPIOR=0
LUFA_OPTS += -D ORDERED_EP_CONFIG
LUFA_OPTS += -D FIXED_CONTROL_ENDPOINT_SIZE=8
LUFA_OPTS += -D FIXED_NUM_CONFIGURATIONS=1
LUFA_OPTS += -D USE_FLASH_DESCRIPTORS

@ -1,211 +0,0 @@
/*
LUFA Library
Copyright (C) Dean Camera, 2010.
dean [at] fourwalledcubicle [dot] com
www.lufa-lib.org
*/
/*
Copyright 2010 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
without fee, provided that the above copyright notice appear in
all copies and that both that the copyright notice and this
permission notice and warranty disclaimer appear in supporting
documentation, and that the name of the author not be used in
advertising or publicity pertaining to distribution of the
software without specific, written prior permission.
The author disclaim all warranties with regard to this
software, including all implied warranties of merchantability
and fitness. In no event shall the author be liable for any
special, indirect or consequential damages or any damages
whatsoever resulting from loss of use, data or profits, whether
in an action of contract, negligence or other tortious action,
arising out of or in connection with the use or performance of
this software.
*/
/** \file
*
* Ultra lightweight ring buffer, for fast insertion/deletion. This uses inlined functions
* for maximum speed. All buffers created with this library must be of the same size, however
* multiple independant buffers can be created.
*
* 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
* 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.
*/
#ifndef _ULW_RING_BUFF_H_
#define _ULW_RING_BUFF_H_
/* Includes: */
#include <util/atomic.h>
#include <stdint.h>
#include <stdbool.h>
/* Defines: */
/** Size of each ring buffer, in data elements - must be between 1 and 255. */
#define BUFFER_SIZE 255
/** Type of data to store into the buffer. */
#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
* \ref RingBuffer_InitBuffer() before use.
*/
typedef struct
{
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 */
RingBuff_Count_t Count;
} RingBuff_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
*/
static inline void RingBuffer_InitBuffer(RingBuff_t* const Buffer)
{
ATOMIC_BLOCK(ATOMIC_RESTORESTATE)
{
Buffer->In = Buffer->Buffer;
Buffer->Out = Buffer->Buffer;
}
}
/** 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.
*
* \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.
*
* \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)
{
RingBuff_Count_t Count;
ATOMIC_BLOCK(ATOMIC_RESTORESTATE)
{
Count = Buffer->Count;
}
return Count;
}
/** 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
*
* \return Boolean true if the buffer contains no free space, false otherwise
*/
static inline bool RingBuffer_IsFull(RingBuff_t* const Buffer)
{
return (RingBuffer_GetCount(Buffer) == BUFFER_SIZE);
}
/** 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.
*
* 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.
*
* \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)
{
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
*/
static inline void RingBuffer_Insert(RingBuff_t* const Buffer,
const RingBuff_Data_t Data)
{
*Buffer->In = Data;
if (++Buffer->In == &Buffer->Buffer[BUFFER_SIZE])
Buffer->In = Buffer->Buffer;
ATOMIC_BLOCK(ATOMIC_RESTORESTATE)
{
Buffer->Count++;
}
}
/** 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
*
* \return Next data element stored in the buffer
*/
static inline RingBuff_Data_t RingBuffer_Remove(RingBuff_t* const Buffer)
{
RingBuff_Data_t Data = *Buffer->Out;
if (++Buffer->Out == &Buffer->Buffer[BUFFER_SIZE])
Buffer->Out = Buffer->Buffer;
ATOMIC_BLOCK(ATOMIC_RESTORESTATE)
{
Buffer->Count--;
}
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
*
* \return Next data element stored in the buffer
*/
static inline RingBuff_Data_t RingBuffer_Peek(RingBuff_t* const Buffer)
{
return *Buffer->Out;
}
#endif

@ -44,7 +44,6 @@
#include <stdbool.h>
#include "../XPLAINBridge.h"
#include "LightweightRingBuff.h"
/* Macros: */
#define SRX PD0

@ -66,9 +66,15 @@ USB_ClassInfo_CDC_Device_t VirtualSerial_CDC_Interface =
/** Circular buffer to hold data from the host before it is sent to the device via the serial port. */
RingBuff_t USBtoUART_Buffer;
/** Underlying data buffer for \ref USBtoUART_Buffer, where the stored bytes are located. */
uint8_t USBtoUART_Buffer_Data[128];
/** Circular buffer to hold data from the serial port before it is sent to the host. */
RingBuff_t UARTtoUSB_Buffer;
/** Underlying data buffer for \ref UARTtoUSB_Buffer, where the stored bytes are located. */
uint8_t UARTtoUSB_Buffer_Data[128];
/** Main program entry point. This routine contains the overall program flow, including initial
* setup of all components and the main program loop.
@ -130,7 +136,7 @@ void UARTBridge_Task(void)
}
/* Check if the UART receive buffer flush timer has expired or buffer is nearly full */
RingBuff_Count_t BufferCount = RingBuffer_GetCount(&UARTtoUSB_Buffer);
uint16_t BufferCount = RingBuffer_GetCount(&UARTtoUSB_Buffer);
if ((TIFR0 & (1 << TOV0)) || (BufferCount > 200))
{
/* Clear flush timer expiry flag */
@ -199,8 +205,8 @@ void EVENT_USB_Device_ConfigurationChanged(void)
TCCR0B = ((1 << CS02) | (1 << CS00));
/* Initialize ring buffers used to hold serial data between USB and software UART interfaces */
RingBuffer_InitBuffer(&USBtoUART_Buffer);
RingBuffer_InitBuffer(&UARTtoUSB_Buffer);
RingBuffer_InitBuffer(&USBtoUART_Buffer, USBtoUART_Buffer_Data, sizeof(USBtoUART_Buffer_Data));
RingBuffer_InitBuffer(&UARTtoUSB_Buffer, UARTtoUSB_Buffer_Data, sizeof(UARTtoUSB_Buffer_Data));
/* Start the software USART */
SoftUART_Init();

@ -46,12 +46,12 @@
#include "AVRISPDescriptors.h"
#include "USARTDescriptors.h"
#include "Lib/LightweightRingBuff.h"
#include "Lib/SoftUART.h"
#include "Lib/V2Protocol.h"
#include <LUFA/Version.h>
#include <LUFA/Drivers/Board/LEDs.h>
#include <LUFA/Drivers/Misc/RingBuffer.h>
#include <LUFA/Drivers/USB/USB.h>
/* Macros: */

@ -122,6 +122,7 @@ AVRISP_PATH = ../AVRISP-MKII
# LUFA library compile-time options and predefined tokens
LUFA_OPTS = -D USB_DEVICE_ONLY
LUFA_OPTS += -D DEVICE_STATE_AS_GPIOR=0
LUFA_OPTS += -D ORDERED_EP_CONFIG
LUFA_OPTS += -D FIXED_CONTROL_ENDPOINT_SIZE=8
LUFA_OPTS += -D FIXED_NUM_CONFIGURATIONS=1
LUFA_OPTS += -D USE_FLASH_DESCRIPTORS

Loading…
Cancel
Save