diff --git a/cores/arduino/USB/CDC.cpp b/cores/arduino/USB/CDC.cpp
index c0e61a89385fe5d72e7e5b357547890806266341..d68bd8c4919746f9778fccf2992c9f30e8d387a3 100644
--- a/cores/arduino/USB/CDC.cpp
+++ b/cores/arduino/USB/CDC.cpp
@@ -37,8 +37,9 @@ struct ring_buffer {
 	uint8_t buffer[CDC_SERIAL_BUFFER_SIZE];
 	volatile uint32_t head;
 	volatile uint32_t tail;
+	volatile bool full;
 };
-ring_buffer cdc_rx_buffer = { { 0 }, 0, 0};
+ring_buffer cdc_rx_buffer = {{0}, 0, 0, false};
 
 typedef struct {
 	uint32_t dwDTERate;
@@ -160,19 +161,22 @@ void Serial_::accept(void)
 	// current location of the tail), we're about to overflow the buffer
 	// and so we don't write the character or advance the head.
 	uint32_t k = 0;
-	i = (i + 1) % CDC_SERIAL_BUFFER_SIZE;
-	while ((i != ringBuffer->tail) && (len > 0)) {
+	while (len > 0 && !ringBuffer->full) {
 		len--;
-		ringBuffer->buffer[ringBuffer->head] = buffer[k++];
-		ringBuffer->head = i;
-		i = (i + 1) % CDC_SERIAL_BUFFER_SIZE;
+		ringBuffer->buffer[i++] = buffer[k++];
+		i %= CDC_SERIAL_BUFFER_SIZE;
+		if (i == ringBuffer->tail)
+			ringBuffer->full = true;
 	}
+	ringBuffer->head = i;
 	interrupts();
 }
 
 int Serial_::available(void)
 {
 	ring_buffer *buffer = &cdc_rx_buffer;
+	if (buffer->full)
+		return CDC_SERIAL_BUFFER_SIZE;
 	if (buffer->head == buffer->tail) {
 		USB->DEVICE.DeviceEndpoint[2].EPINTENSET.reg = USB_DEVICE_EPINTENCLR_TRCPT(1);
 	}
@@ -182,13 +186,9 @@ int Serial_::available(void)
 int Serial_::peek(void)
 {
 	ring_buffer *buffer = &cdc_rx_buffer;
-
-	if (buffer->head == buffer->tail)
-	{
+	if (buffer->head == buffer->tail && !buffer->full) {
 		return -1;
-	}
-	else
-	{
+	} else {
 		return buffer->buffer[buffer->tail];
 	}
 }
@@ -203,12 +203,12 @@ int Serial_::read(void)
 	ring_buffer *buffer = &cdc_rx_buffer;
 
 	// if the head isn't ahead of the tail, we don't have any characters
-	if (buffer->head == buffer->tail)
+	if (buffer->head == buffer->tail && !buffer->full)
 	{
 		if (usb.available(CDC_ENDPOINT_OUT))
 			accept();
 	}
-	if (buffer->head == buffer->tail)
+	if (buffer->head == buffer->tail && !buffer->full)
 	{
 		return -1;
 	}
@@ -216,6 +216,7 @@ int Serial_::read(void)
 	{
 		unsigned char c = buffer->buffer[buffer->tail];
 		buffer->tail = (uint32_t)(buffer->tail + 1) % CDC_SERIAL_BUFFER_SIZE;
+		buffer->full = false;
 // 		if (usb.available(CDC_ENDPOINT_OUT))
 // 			accept();
 		return c;