From 52237c845b5371b229dee0152ceaae62e1998bdd Mon Sep 17 00:00:00 2001 From: Cristian Maglie <c.maglie@arduino.cc> Date: Fri, 13 Feb 2015 16:46:58 +0100 Subject: [PATCH] CDC-ACM bugfix --- cores/arduino/USB/CDC.cpp | 25 +++++++++++++------------ cores/arduino/USB/USBCore.cpp | 17 +++++++++++------ cores/arduino/USB/samd21_device.c | 31 ++++++++++++++++--------------- 3 files changed, 40 insertions(+), 33 deletions(-) diff --git a/cores/arduino/USB/CDC.cpp b/cores/arduino/USB/CDC.cpp index 40fadaa2..33c7b7e8 100644 --- a/cores/arduino/USB/CDC.cpp +++ b/cores/arduino/USB/CDC.cpp @@ -160,25 +160,26 @@ void Serial_::end(void) void Serial_::accept(void) { - ring_buffer *buffer = &cdc_rx_buffer; - uint32_t i = (uint32_t)(buffer->head+1) % CDC_SERIAL_BUFFER_SIZE; + uint8_t buffer[CDC_SERIAL_BUFFER_SIZE]; + uint32_t len = USBD_Recv(CDC_ENDPOINT_OUT, (void*)&buffer, CDC_SERIAL_BUFFER_SIZE); + + noInterrupts(); + ring_buffer *ringBuffer = &cdc_rx_buffer; + uint32_t i = ringBuffer->head; // if we should be storing the received character into the location // just before the tail (meaning that the head would advance to the // current location of the tail), we're about to overflow the buffer // and so we don't write the character or advance the head. - while (i != buffer->tail) { - uint32_t c; - if (!USBD_Available(CDC_ENDPOINT_OUT)) { - UDD_ReleaseRX(CDC_ENDPOINT_OUT); - break; - } - c = USBD_Recv(CDC_ENDPOINT_OUT); - buffer->buffer[buffer->head] = c; - buffer->head = i; - + uint32_t k = 0; + i = (i + 1) % CDC_SERIAL_BUFFER_SIZE; + while (i != ringBuffer->tail && len>0) { + len--; + ringBuffer->buffer[ringBuffer->head] = buffer[k++]; + ringBuffer->head = i; i = (i + 1) % CDC_SERIAL_BUFFER_SIZE; } + interrupts(); } int Serial_::available(void) diff --git a/cores/arduino/USB/USBCore.cpp b/cores/arduino/USB/USBCore.cpp index 41285d4f..8164f252 100644 --- a/cores/arduino/USB/USBCore.cpp +++ b/cores/arduino/USB/USBCore.cpp @@ -108,12 +108,17 @@ uint32_t USBD_Recv(uint32_t ep, void* d, uint32_t len) if (!_usbConfiguration) return -1; - uint32_t n = UDD_FifoByteCount(ep); - len = min(n,len); - n = len; - uint8_t* dst = (uint8_t*)d; - while (n--) - *dst++ = UDD_Recv_data(ep, 8); + uint8_t *buffer; + uint8_t *data = (uint8_t *)d; + + len = min(UDD_FifoByteCount(ep), len); + + UDD_Recv_data(ep, len); + UDD_Recv(ep, &buffer); + for (uint32_t i=0; i<len; i++) { + data[i] = buffer[i]; + } + if (len && !UDD_FifoByteCount(ep)) // release empty buffer UDD_ReleaseRX(ep); diff --git a/cores/arduino/USB/samd21_device.c b/cores/arduino/USB/samd21_device.c index 82342405..271243a3 100644 --- a/cores/arduino/USB/samd21_device.c +++ b/cores/arduino/USB/samd21_device.c @@ -266,22 +266,23 @@ uint32_t UDD_Send(uint32_t ep, const void* data, uint32_t len) return len; } -uint8_t UDD_Recv_data(uint32_t ep, uint32_t len) -{ - TRACE_DEVICE(printf("=> UDD_Recvdata : ep=%d\r\n", (char)ep);) - - usb_endpoint_table[ep].DeviceDescBank[0].ADDR.reg = (uint32_t)&udd_ep_out_cache_buffer[ep]; - usb_endpoint_table[ep].DeviceDescBank[0].PCKSIZE.bit.MULTI_PACKET_SIZE = len; - usb_endpoint_table[ep].DeviceDescBank[0].PCKSIZE.bit.BYTE_COUNT = 0; +uint8_t UDD_Recv_data(uint32_t ep, uint32_t len) +{ + TRACE_DEVICE(printf("=> UDD_Recvdata : ep=%d\r\n", (char)ep);) + + if (len>64) len=64; + usb_endpoint_table[ep].DeviceDescBank[0].ADDR.reg = (uint32_t)&udd_ep_out_cache_buffer[ep]; + usb_endpoint_table[ep].DeviceDescBank[0].PCKSIZE.bit.MULTI_PACKET_SIZE = len; + usb_endpoint_table[ep].DeviceDescBank[0].PCKSIZE.bit.BYTE_COUNT = 0; udd_OUT_transfer_allowed(ep); - TRACE_DEVICE(printf("=> UDD_Recv_data : data=%lu\r\n", (unsigned long)data);) - - /* Wait for transfer to complete */ - while (!udd_is_OUT_transf_cplt(ep)); - /* Clear Transfer complete 0 flag */ - udd_clear_OUT_transf_cplt(ep); - - return udd_ep_out_cache_buffer[ep][0]; + TRACE_DEVICE(printf("=> UDD_Recv_data : data=%lu\r\n", (unsigned long)data);) + + /* Wait for transfer to complete */ + while (!udd_is_OUT_transf_cplt(ep)); + /* Clear Transfer complete 0 flag */ + udd_clear_OUT_transf_cplt(ep); + + return udd_ep_out_cache_buffer[ep][0]; } void UDD_Recv(uint32_t ep, uint8_t** ppData) -- GitLab