Commit 0bcc82ac authored by Dean Camera's avatar Dean Camera
Browse files

Alter the ring buffer library headers to have both atomic and non-atomic...

Alter the ring buffer library headers to have both atomic and non-atomic insertion/removal routines. Modify the existing projects so that buffer operations performed in an ISR use the shorted non-atomic versions, as they are already performed in a blocking ISR.

Alter USBtoSerial demo so that it does not enter a blocking loop to send data from the USB to the USART, as this can cause dropped bytes in the reception code if large amounts of data are sent in both directions at the same time. Added a flush timer to the USBtoSerial code for the USART to USB interface, so that multiple bytes can be sent in the same USB packet.
parent 3fd24604
......@@ -28,6 +28,7 @@
* - Rewrote the implementation of the SwapEndian_16() and SwapEndian_32() functions so that they compile down in most instances to
* minimal loads and stores rather than complicated shifts
* - The software UART in the XPLAINBridge has been largely altered to try to improve upon its performance and reliability
* - The USBtoSerial project now flushes received data via a flush timer, so that several bytes can be transmitted at once
*
* <b>Fixed:</b>
* - Fixed AVRISP project sending a LOAD EXTENDED ADDRESS command to 128KB AVRs after programming or reading from
......
......@@ -100,7 +100,7 @@ int main(void)
/* Echo bytes from the target to the host via the virtual serial port */
while (Tx_Buffer.Count)
{
CDC_Device_SendByte(&VirtualSerial_CDC_Interface, RingBuffer_Remove(&Tx_Buffer));
CDC_Device_SendByte(&VirtualSerial_CDC_Interface, RingBuffer_AtomicRemove(&Tx_Buffer));
LEDs_TurnOnLEDs(LEDMASK_RX);
PulseMSRemaining.RxLEDPulse = TX_RX_LED_PULSE_MS;
......
......@@ -75,12 +75,12 @@
Buffer->Count = 0;
}
/** Inserts an element into the ring buffer.
/** Atomically inserts an element into the ring 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, RingBuff_Data_t Data)
static inline void RingBuffer_AtomicInsert(RingBuff_t* const Buffer, RingBuff_Data_t Data)
{
ATOMIC_BLOCK(ATOMIC_RESTORESTATE)
{
......@@ -93,13 +93,13 @@
}
}
/** Retrieves an element from the ring buffer.
/** Atomically retrieves an element from the ring buffer.
*
* \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)
static inline RingBuff_Data_t RingBuffer_AtomicRemove(RingBuff_t* const Buffer)
{
RingBuff_Data_t Data;
......@@ -116,5 +116,38 @@
return Data;
}
/** Inserts an element into the ring 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, RingBuff_Data_t Data)
{
*Buffer->In = Data;
if (++Buffer->In == &Buffer->Buffer[BUFFER_SIZE])
Buffer->In = Buffer->Buffer;
Buffer->Count++;
}
/** Retrieves an element from the ring buffer.
*
* \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;
Buffer->Count--;
return Data;
}
#endif
\ No newline at end of file
......@@ -75,12 +75,12 @@
Buffer->Count = 0;
}
/** Inserts an element into the ring buffer.
/** Atomically inserts an element into the ring 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, RingBuff_Data_t Data)
static inline void RingBuffer_AtomicInsert(RingBuff_t* const Buffer, RingBuff_Data_t Data)
{
ATOMIC_BLOCK(ATOMIC_RESTORESTATE)
{
......@@ -93,13 +93,13 @@
}
}
/** Retrieves an element from the ring buffer.
/** Atomically retrieves an element from the ring buffer.
*
* \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)
static inline RingBuff_Data_t RingBuffer_AtomicRemove(RingBuff_t* const Buffer)
{
RingBuff_Data_t Data;
......@@ -116,5 +116,38 @@
return Data;
}
/** Inserts an element into the ring 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, RingBuff_Data_t Data)
{
*Buffer->In = Data;
if (++Buffer->In == &Buffer->Buffer[BUFFER_SIZE])
Buffer->In = Buffer->Buffer;
Buffer->Count++;
}
/** Retrieves an element from the ring buffer.
*
* \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;
Buffer->Count--;
return Data;
}
#endif
\ No newline at end of file
......@@ -87,16 +87,22 @@ int main(void)
if (!(BUFFER_SIZE - USBtoUSART_Buffer.Count))
break;
RingBuffer_Insert(&USBtoUSART_Buffer, CDC_Device_ReceiveByte(&VirtualSerial_CDC_Interface));
RingBuffer_AtomicInsert(&USBtoUSART_Buffer, CDC_Device_ReceiveByte(&VirtualSerial_CDC_Interface));
}
/* Read bytes from the USART receive buffer into the USB IN endpoint */
while (USARTtoUSB_Buffer.Count)
CDC_Device_SendByte(&VirtualSerial_CDC_Interface, RingBuffer_Remove(&USARTtoUSB_Buffer));
/* Check if the software USART flush timer has expired */
if (TIFR0 & (1 << TOV0))
{
TIFR0 |= (1 << TOV0);
/* Read bytes from the USART receive buffer into the USB IN endpoint */
while (USARTtoUSB_Buffer.Count)
CDC_Device_SendByte(&VirtualSerial_CDC_Interface, RingBuffer_AtomicRemove(&USARTtoUSB_Buffer));
}
/* Load bytes from the USART transmit buffer into the USART */
while (USBtoUSART_Buffer.Count)
Serial_TxByte(RingBuffer_Remove(&USBtoUSART_Buffer));
/* Load the next byte from the USART transmit buffer into the USART */
if (USBtoUSART_Buffer.Count)
Serial_TxByte(RingBuffer_AtomicRemove(&USBtoUSART_Buffer));
CDC_Device_USBTask(&VirtualSerial_CDC_Interface);
USB_USBTask();
......@@ -117,6 +123,9 @@ void SetupHardware(void)
Serial_Init(9600, false);
LEDs_Init();
USB_Init();
/* Configure the UART flush timer - run at Fcpu/1024 for maximum interval before overflow */
TCCR0B = ((1 << CS02) | (1 << CS00));
}
/** Event handler for the library USB Connection event. */
......
......@@ -75,12 +75,12 @@
Buffer->Count = 0;
}
/** Inserts an element into the ring buffer.
/** Atomically inserts an element into the ring 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, RingBuff_Data_t Data)
static inline void RingBuffer_AtomicInsert(RingBuff_t* const Buffer, RingBuff_Data_t Data)
{
ATOMIC_BLOCK(ATOMIC_RESTORESTATE)
{
......@@ -93,13 +93,13 @@
}
}
/** Retrieves an element from the ring buffer.
/** Atomically retrieves an element from the ring buffer.
*
* \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)
static inline RingBuff_Data_t RingBuffer_AtomicRemove(RingBuff_t* const Buffer)
{
RingBuff_Data_t Data;
......@@ -116,5 +116,38 @@
return Data;
}
/** Inserts an element into the ring 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, RingBuff_Data_t Data)
{
*Buffer->In = Data;
if (++Buffer->In == &Buffer->Buffer[BUFFER_SIZE])
Buffer->In = Buffer->Buffer;
Buffer->Count++;
}
/** Retrieves an element from the ring buffer.
*
* \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;
Buffer->Count--;
return Data;
}
#endif
\ No newline at end of file
......@@ -77,9 +77,6 @@ int main(void)
{
SetupHardware();
RingBuffer_InitBuffer(&USBtoUART_Buffer);
RingBuffer_InitBuffer(&UARTtoUSB_Buffer);
LEDs_SetAllLEDs(LEDMASK_USB_NOTREADY);
sei();
......@@ -124,7 +121,7 @@ void UARTBridge_Task(void)
/* Read bytes from the USB OUT endpoint into the UART transmit buffer */
if (CDC_Device_BytesReceived(&VirtualSerial_CDC_Interface))
RingBuffer_Insert(&USBtoUART_Buffer, CDC_Device_ReceiveByte(&VirtualSerial_CDC_Interface));
RingBuffer_AtomicInsert(&USBtoUART_Buffer, CDC_Device_ReceiveByte(&VirtualSerial_CDC_Interface));
/* Check if the software UART flush timer has expired */
if (TIFR0 & (1 << TOV0))
......@@ -133,7 +130,7 @@ void UARTBridge_Task(void)
/* Read bytes from the UART receive buffer into the USB IN endpoint */
while (UARTtoUSB_Buffer.Count)
CDC_Device_SendByte(&VirtualSerial_CDC_Interface, RingBuffer_Remove(&UARTtoUSB_Buffer));
CDC_Device_SendByte(&VirtualSerial_CDC_Interface, RingBuffer_AtomicRemove(&UARTtoUSB_Buffer));
}
CDC_Device_USBTask(&VirtualSerial_CDC_Interface);
......@@ -180,8 +177,12 @@ void EVENT_USB_Device_ConfigurationChanged(void)
{
EndpointConfigSuccess &= CDC_Device_ConfigureEndpoints(&VirtualSerial_CDC_Interface);
/* Configure the UART flush timer - run at FCPU/1024 for maximum interval before overflow */
/* Configure the UART flush timer - run at Fcpu/1024 for maximum interval before overflow */
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);
}
else
{
......
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment