From af9a91f53f322346a6323a8ab2849c03d11b80df Mon Sep 17 00:00:00 2001 From: Sandeep Mistry Date: Tue, 23 Feb 2016 09:16:25 -0500 Subject: [PATCH 1/9] Check if there is enough buffer space in Serial_::accept, to make sure data is not dropped --- cores/arduino/USB/CDC.cpp | 11 +++++++++-- 1 file changed, 9 insertions(+), 2 deletions(-) diff --git a/cores/arduino/USB/CDC.cpp b/cores/arduino/USB/CDC.cpp index 5a111dce9..8237a24ea 100644 --- a/cores/arduino/USB/CDC.cpp +++ b/cores/arduino/USB/CDC.cpp @@ -163,8 +163,15 @@ void Serial_::end(void) void Serial_::accept(void) { - uint8_t buffer[CDC_SERIAL_BUFFER_SIZE]; - uint32_t len = usb.recv(CDC_ENDPOINT_OUT, &buffer, CDC_SERIAL_BUFFER_SIZE); + uint32_t ringBufferSpace = CDC_SERIAL_BUFFER_SIZE - available(); + if (ringBufferSpace < EPX_SIZE) { + // usb.recv will always try to receive up to EPX_SIZE bytes on the endpoint + // make sure there is enough space, so that data is not lost + return; + } + + uint8_t buffer[EPX_SIZE]; + uint32_t len = usb.recv(CDC_ENDPOINT_OUT, &buffer, sizeof(buffer)); uint8_t enableInterrupts = ((__get_PRIMASK() & 0x1) == 0); __disable_irq(); From 874b1bbb5583bbe6218d94a0dcd433322ceaa854 Mon Sep 17 00:00:00 2001 From: Sandeep Mistry Date: Tue, 23 Feb 2016 09:17:43 -0500 Subject: [PATCH 2/9] Handle ZLP in USBDeviceClass::handleEndpoint for CDC_ENDPOINT_OUT --- cores/arduino/USB/USBCore.cpp | 12 ++++++++++++ 1 file changed, 12 insertions(+) diff --git a/cores/arduino/USB/USBCore.cpp b/cores/arduino/USB/USBCore.cpp index cd356d578..f7d9d3a38 100644 --- a/cores/arduino/USB/USBCore.cpp +++ b/cores/arduino/USB/USBCore.cpp @@ -250,7 +250,19 @@ void USBDeviceClass::handleEndpoint(uint8_t ep) // Handle received bytes if (available(CDC_ENDPOINT_OUT)) + { SerialUSB.accept(); + } + else + { + // ZLP received + + // The RAM Buffer is empty: we can receive data + usbd.epBank0ResetReady(CDC_ENDPOINT_OUT); + + // Clear Transfer complete 0 flag + usbd.epBank0AckTransferComplete(CDC_ENDPOINT_OUT); + } } if (ep == CDC_ENDPOINT_IN) { From 69d85a26ce53b2fdfdd332f662c2580714f97bc0 Mon Sep 17 00:00:00 2001 From: Sandeep Mistry Date: Tue, 23 Feb 2016 09:19:19 -0500 Subject: [PATCH 3/9] Always disable transfer complete in USBDeviceClass::handleEndpoint for CDC_ENDPOINT_OUT, in case the CDC receive buffer is full --- cores/arduino/USB/USBCore.cpp | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/cores/arduino/USB/USBCore.cpp b/cores/arduino/USB/USBCore.cpp index f7d9d3a38..dfdde872b 100644 --- a/cores/arduino/USB/USBCore.cpp +++ b/cores/arduino/USB/USBCore.cpp @@ -251,6 +251,10 @@ void USBDeviceClass::handleEndpoint(uint8_t ep) // Handle received bytes if (available(CDC_ENDPOINT_OUT)) { + // always disable transfer complete, + // in case the CDC receive buffer is full + usbd.epBank0DisableTransferComplete(CDC_ENDPOINT_OUT); + SerialUSB.accept(); } else From d76647ff07ae5aba04332a459cdaa13546dba0d1 Mon Sep 17 00:00:00 2001 From: Sandeep Mistry Date: Tue, 23 Feb 2016 09:21:39 -0500 Subject: [PATCH 4/9] Enable transfer complete in USBDeviceClass::recv once bank is empty --- cores/arduino/USB/USBCore.cpp | 3 +++ 1 file changed, 3 insertions(+) diff --git a/cores/arduino/USB/USBCore.cpp b/cores/arduino/USB/USBCore.cpp index dfdde872b..a9a0cc3cc 100644 --- a/cores/arduino/USB/USBCore.cpp +++ b/cores/arduino/USB/USBCore.cpp @@ -551,6 +551,9 @@ uint32_t USBDeviceClass::recv(uint32_t ep, void *_data, uint32_t len) // Clear Transfer complete 0 flag usbd.epBank0AckTransferComplete(ep); + + // Enable Transfer complete 0 interrupt + usbd.epBank0EnableTransferComplete(ep); } return len; From 21a52585e99d92ab1970755d798f12b9e10ad5de Mon Sep 17 00:00:00 2001 From: Sandeep Mistry Date: Tue, 23 Feb 2016 09:22:23 -0500 Subject: [PATCH 5/9] Remove some commented out code --- cores/arduino/USB/CDC.cpp | 3 +-- cores/arduino/USB/USBCore.cpp | 3 --- 2 files changed, 1 insertion(+), 5 deletions(-) diff --git a/cores/arduino/USB/CDC.cpp b/cores/arduino/USB/CDC.cpp index 8237a24ea..87232eb6e 100644 --- a/cores/arduino/USB/CDC.cpp +++ b/cores/arduino/USB/CDC.cpp @@ -243,8 +243,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; } } diff --git a/cores/arduino/USB/USBCore.cpp b/cores/arduino/USB/USBCore.cpp index a9a0cc3cc..96713ec30 100644 --- a/cores/arduino/USB/USBCore.cpp +++ b/cores/arduino/USB/USBCore.cpp @@ -245,9 +245,6 @@ void USBDeviceClass::handleEndpoint(uint8_t ep) #if defined(CDC_ENABLED) if (ep == CDC_ENDPOINT_OUT) { - // The RAM Buffer is empty: we can receive data - //usbd.epBank0ResetReady(CDC_ENDPOINT_OUT); - // Handle received bytes if (available(CDC_ENDPOINT_OUT)) { From 173db65c8864f2db516dc0ca707ae0cfb4f03165 Mon Sep 17 00:00:00 2001 From: Sandeep Mistry Date: Tue, 23 Feb 2016 09:24:03 -0500 Subject: [PATCH 6/9] If buffer is empty in Serial_::available, check if there are bytes that can be received --- cores/arduino/USB/CDC.cpp | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/cores/arduino/USB/CDC.cpp b/cores/arduino/USB/CDC.cpp index 87232eb6e..3687e9828 100644 --- a/cores/arduino/USB/CDC.cpp +++ b/cores/arduino/USB/CDC.cpp @@ -204,7 +204,8 @@ int Serial_::available(void) return CDC_SERIAL_BUFFER_SIZE; } if (buffer->head == buffer->tail) { - USB->DEVICE.DeviceEndpoint[CDC_ENDPOINT_OUT].EPINTENSET.reg = USB_DEVICE_EPINTENCLR_TRCPT(1); + if (usb.available(CDC_ENDPOINT_OUT)) + accept(); } return (uint32_t)(CDC_SERIAL_BUFFER_SIZE + buffer->head - buffer->tail) % CDC_SERIAL_BUFFER_SIZE; } From 3381188f268782023a4490d07e20472d2ec970b5 Mon Sep 17 00:00:00 2001 From: Sandeep Mistry Date: Tue, 23 Feb 2016 09:36:34 -0500 Subject: [PATCH 7/9] Add private availableForStore method, and use in Serial_::accept --- cores/arduino/USB/CDC.cpp | 11 ++++++++++- cores/arduino/USB/USBAPI.h | 2 ++ 2 files changed, 12 insertions(+), 1 deletion(-) diff --git a/cores/arduino/USB/CDC.cpp b/cores/arduino/USB/CDC.cpp index 3687e9828..806d31653 100644 --- a/cores/arduino/USB/CDC.cpp +++ b/cores/arduino/USB/CDC.cpp @@ -163,7 +163,7 @@ void Serial_::end(void) void Serial_::accept(void) { - uint32_t ringBufferSpace = CDC_SERIAL_BUFFER_SIZE - available(); + uint32_t ringBufferSpace = availableForStore(); if (ringBufferSpace < EPX_SIZE) { // usb.recv will always try to receive up to EPX_SIZE bytes on the endpoint // make sure there is enough space, so that data is not lost @@ -352,6 +352,15 @@ bool Serial_::rts() { return _usbLineInfo.lineState & 0x2; } +int Serial_::availableForStore(void) { + ring_buffer *buffer = &cdc_rx_buffer; + + if (buffer->head >= buffer->tail) + return CDC_SERIAL_BUFFER_SIZE - 1 - buffer->head + buffer->tail; + else + return buffer->tail - buffer->head - 1; +} + Serial_ SerialUSB(USBDevice); #endif diff --git a/cores/arduino/USB/USBAPI.h b/cores/arduino/USB/USBAPI.h index 1de826608..16adb6d09 100644 --- a/cores/arduino/USB/USBAPI.h +++ b/cores/arduino/USB/USBAPI.h @@ -167,6 +167,8 @@ class Serial_ : public Stream }; private: + int availableForStore(void); + USBDeviceClass &usb; RingBuffer *_cdc_rx_buffer; }; From 397d8b3efb5702088febc792109bc72633875eab Mon Sep 17 00:00:00 2001 From: Sandeep Mistry Date: Tue, 23 Feb 2016 10:05:31 -0500 Subject: [PATCH 8/9] Add full buffer condition to Serial_::availableForStore --- cores/arduino/USB/CDC.cpp | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/cores/arduino/USB/CDC.cpp b/cores/arduino/USB/CDC.cpp index 806d31653..67cc7f70e 100644 --- a/cores/arduino/USB/CDC.cpp +++ b/cores/arduino/USB/CDC.cpp @@ -355,8 +355,10 @@ bool Serial_::rts() { int Serial_::availableForStore(void) { ring_buffer *buffer = &cdc_rx_buffer; - if (buffer->head >= buffer->tail) - return CDC_SERIAL_BUFFER_SIZE - 1 - buffer->head + buffer->tail; + if (buffer->full) + return 0; + else if (buffer->head >= buffer->tail) + return CDC_SERIAL_BUFFER_SIZE - 1 - buffer->head + buffer->tail; else return buffer->tail - buffer->head - 1; } From b14d7d8a23f273a9ee44396bc3e959b6b1f957fb Mon Sep 17 00:00:00 2001 From: Sandeep Mistry Date: Tue, 23 Feb 2016 14:33:42 -0500 Subject: [PATCH 9/9] Remove commented out code for epBankXDisableAutoZLP, it is disabled by default --- cores/arduino/USB/USBCore.cpp | 4 ---- 1 file changed, 4 deletions(-) diff --git a/cores/arduino/USB/USBCore.cpp b/cores/arduino/USB/USBCore.cpp index 96713ec30..bfd0a214c 100644 --- a/cores/arduino/USB/USBCore.cpp +++ b/cores/arduino/USB/USBCore.cpp @@ -447,10 +447,6 @@ void USBDeviceClass::initEP(uint32_t ep, uint32_t config) } else if (config == USB_ENDPOINT_TYPE_CONTROL) { - // XXX: Needed? -// usbd.epBank0DisableAutoZLP(ep); -// usbd.epBank1DisableAutoZLP(ep); - // Setup Control OUT usbd.epBank0SetSize(ep, 64); usbd.epBank0SetAddress(ep, &udd_ep_out_cache_buffer[ep]);