diff --git a/build/shared/revisions.txt b/build/shared/revisions.txt index 50426bb77..0e1da0190 100644 --- a/build/shared/revisions.txt +++ b/build/shared/revisions.txt @@ -23,8 +23,9 @@ ARDUINO 1.5.2 BETA - 2012.01.23 * sam: fixed BSoD on some Windows machine (louismdavis) * sam: added CANRX1/CANTX1 pins 88/89 (same physical pin for 66/53) * sam: fixed analogWrite when used in very thight write loops (V.Dorrich) -* sam: fixed USBSerial.write() while sending big buffers (Bill Dreschel) -* sam: USBSerial receive buffer size is now 512 (PeterVH) +* sam: fixed SerialUSB.write() while sending big buffers (Bill Dreschel) +* sam: SerialUSB receive buffer size is now 512 (PeterVH) +* sam: Fixed SerialUSB data handshake when host sends a lot of data (PeterVH, stimmer) [libraries] * sam: Added Servo library diff --git a/hardware/arduino/sam/cores/arduino/USB/CDC.cpp b/hardware/arduino/sam/cores/arduino/USB/CDC.cpp index 6b7749ee2..76e17e8f5 100644 --- a/hardware/arduino/sam/cores/arduino/USB/CDC.cpp +++ b/hardware/arduino/sam/cores/arduino/USB/CDC.cpp @@ -155,18 +155,39 @@ void Serial_::end(void) void Serial_::accept(void) { + static uint32_t guard = 0; + + // synchronized access to guard + do { + if (__LDREXW(&guard) != 0) { + __CLREX(); + return; // busy + } + } while (__STREXW(1, &guard) != 0); // retry until write succeed + ring_buffer *buffer = &cdc_rx_buffer; - uint32_t c = USBD_Recv(CDC_RX); uint32_t i = (uint32_t)(buffer->head+1) % CDC_SERIAL_BUFFER_SIZE; // 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. - if (i != buffer->tail) { + while (i != buffer->tail) { + uint32_t c; + if (!USBD_Available(CDC_RX)) { + udd_ack_fifocon(CDC_RX); + break; + } + c = USBD_Recv(CDC_RX); + // c = UDD_Recv8(CDC_RX & 0xF); buffer->buffer[buffer->head] = c; buffer->head = i; + + i = (i + 1) % CDC_SERIAL_BUFFER_SIZE; } + + // release the guard + guard = 0; } int Serial_::available(void) @@ -202,6 +223,8 @@ int Serial_::read(void) { unsigned char c = buffer->buffer[buffer->tail]; buffer->tail = (unsigned int)(buffer->tail + 1) % CDC_SERIAL_BUFFER_SIZE; + if (USBD_Available(CDC_RX)) + accept(); return c; } } diff --git a/hardware/arduino/sam/cores/arduino/USB/USBCore.cpp b/hardware/arduino/sam/cores/arduino/USB/USBCore.cpp index 38418f10c..8cb01a51a 100644 --- a/hardware/arduino/sam/cores/arduino/USB/USBCore.cpp +++ b/hardware/arduino/sam/cores/arduino/USB/USBCore.cpp @@ -601,10 +601,8 @@ static void USB_ISR(void) udd_ack_out_received(CDC_RX); // Handle received bytes - while (USBD_Available(CDC_RX)) + if (USBD_Available(CDC_RX)) SerialUSB.accept(); - - udd_ack_fifocon(CDC_RX); } if (Is_udd_sof())