From 44b5096e0507fb058de7b8dc44962ee304e3c916 Mon Sep 17 00:00:00 2001 From: Cristian Maglie Date: Sat, 24 May 2014 00:13:07 +0200 Subject: [PATCH 1/4] Backported Print class from ide-1.5.x branch Close #1951 --- hardware/arduino/cores/arduino/Print.cpp | 8 ++------ hardware/arduino/cores/arduino/Print.h | 3 +++ 2 files changed, 5 insertions(+), 6 deletions(-) diff --git a/hardware/arduino/cores/arduino/Print.cpp b/hardware/arduino/cores/arduino/Print.cpp index 53961ec47..5df56306e 100755 --- a/hardware/arduino/cores/arduino/Print.cpp +++ b/hardware/arduino/cores/arduino/Print.cpp @@ -41,7 +41,7 @@ size_t Print::write(const uint8_t *buffer, size_t size) size_t Print::print(const __FlashStringHelper *ifsh) { - const char PROGMEM *p = (const char PROGMEM *)ifsh; + PGM_P p = reinterpret_cast(ifsh); size_t n = 0; while (1) { unsigned char c = pgm_read_byte(p++); @@ -53,11 +53,7 @@ size_t Print::print(const __FlashStringHelper *ifsh) size_t Print::print(const String &s) { - size_t n = 0; - for (uint16_t i = 0; i < s.length(); i++) { - n += write(s[i]); - } - return n; + return write(s.c_str(), s.length()); } size_t Print::print(const char str[]) diff --git a/hardware/arduino/cores/arduino/Print.h b/hardware/arduino/cores/arduino/Print.h index dc7615087..7b53aa4d1 100755 --- a/hardware/arduino/cores/arduino/Print.h +++ b/hardware/arduino/cores/arduino/Print.h @@ -51,6 +51,9 @@ class Print return write((const uint8_t *)str, strlen(str)); } virtual size_t write(const uint8_t *buffer, size_t size); + size_t write(const char *buffer, size_t size) { + return write((const uint8_t *)buffer, size); + } size_t print(const __FlashStringHelper *); size_t print(const String &); From b822091a7827040fa8346f9cf719e6c78c969973 Mon Sep 17 00:00:00 2001 From: Justin Rajewski Date: Tue, 18 Mar 2014 14:15:41 -0700 Subject: [PATCH 2/4] improved USB write speeds --- hardware/arduino/cores/arduino/CDC.cpp | 7 ++++++- hardware/arduino/cores/arduino/USBAPI.h | 1 + 2 files changed, 7 insertions(+), 1 deletion(-) diff --git a/hardware/arduino/cores/arduino/CDC.cpp b/hardware/arduino/cores/arduino/CDC.cpp index e1e859d18..fb0c0e09c 100644 --- a/hardware/arduino/cores/arduino/CDC.cpp +++ b/hardware/arduino/cores/arduino/CDC.cpp @@ -199,6 +199,11 @@ void Serial_::flush(void) } size_t Serial_::write(uint8_t c) +{ + return write(&c, 1); +} + +size_t Serial_::write(const uint8_t *buffer, size_t size) { /* only try to send bytes if the high-level CDC connection itself is open (not just the pipe) - the OS should set lineState when the port @@ -210,7 +215,7 @@ size_t Serial_::write(uint8_t c) // open connection isn't broken cleanly (cable is yanked out, host dies // or locks up, or host virtual serial port hangs) if (_usbLineInfo.lineState > 0) { - int r = USB_Send(CDC_TX,&c,1); + int r = USB_Send(CDC_TX,buffer,size); if (r > 0) { return r; } else { diff --git a/hardware/arduino/cores/arduino/USBAPI.h b/hardware/arduino/cores/arduino/USBAPI.h index 7a14285db..1c5ecf0fc 100644 --- a/hardware/arduino/cores/arduino/USBAPI.h +++ b/hardware/arduino/cores/arduino/USBAPI.h @@ -40,6 +40,7 @@ public: virtual int read(void); virtual void flush(void); virtual size_t write(uint8_t); + virtual size_t write(const uint8_t*, size_t); using Print::write; // pull in write(str) and write(buf, size) from Print operator bool(); }; From 13c0db5834a78f8abd511268dd8e2b0c43063d6d Mon Sep 17 00:00:00 2001 From: Paul Brook Date: Thu, 20 Mar 2014 22:44:41 +0000 Subject: [PATCH 3/4] Fix race condition in USB CDC transmit If the Start of Frame interrupt triggers just after the call to USB_SendSpace in USB_Send then we can get data loss. When the first bank is full and the second partially full, the SOF handler will release the second bank via USB_Flush. Data is then lost due to overflow as USB_Send continues writing data to the now-closed bank. Fix this by re-checking the FIFO status inside LockEP, immediately before doing the data write. Signed-off-by: Paul Brook --- hardware/arduino/cores/arduino/USBCore.cpp | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/hardware/arduino/cores/arduino/USBCore.cpp b/hardware/arduino/cores/arduino/USBCore.cpp index d3e017065..76ceb0154 100644 --- a/hardware/arduino/cores/arduino/USBCore.cpp +++ b/hardware/arduino/cores/arduino/USBCore.cpp @@ -290,9 +290,12 @@ int USB_Send(u8 ep, const void* d, int len) if (n > len) n = len; - len -= n; { LockEP lock(ep); + // Frame may have been released by the SOF interrupt handler + if (!ReadWriteAllowed()) + continue; + len -= n; if (ep & TRANSFER_ZERO) { while (n--) From ddbb6b39145b3068da28e76e8238ea960cc29821 Mon Sep 17 00:00:00 2001 From: Paul Brook Date: Fri, 21 Mar 2014 18:43:19 +0000 Subject: [PATCH 4/4] Improve CDC read code Read CDC data from USB FIFO on demand instead of in ISR. Remove superfluous ring buffer. Signed-off-by: Paul Brook --- hardware/arduino/cores/arduino/CDC.cpp | 66 ++++------------------ hardware/arduino/cores/arduino/USBAPI.h | 3 +- hardware/arduino/cores/arduino/USBCore.cpp | 2 - 3 files changed, 13 insertions(+), 58 deletions(-) diff --git a/hardware/arduino/cores/arduino/CDC.cpp b/hardware/arduino/cores/arduino/CDC.cpp index fb0c0e09c..3dbf15df3 100644 --- a/hardware/arduino/cores/arduino/CDC.cpp +++ b/hardware/arduino/cores/arduino/CDC.cpp @@ -23,21 +23,6 @@ #if defined(USBCON) #ifdef CDC_ENABLED -#if (RAMEND < 1000) -#define SERIAL_BUFFER_SIZE 16 -#else -#define SERIAL_BUFFER_SIZE 64 -#endif - -struct ring_buffer -{ - unsigned char buffer[SERIAL_BUFFER_SIZE]; - volatile int head; - volatile int tail; -}; - -ring_buffer cdc_rx_buffer = { { 0 }, 0, 0}; - typedef struct { u32 dwDTERate; @@ -129,7 +114,6 @@ bool WEAK CDC_Setup(Setup& setup) } -int _serialPeek = -1; void Serial_::begin(unsigned long baud_count) { } @@ -142,55 +126,29 @@ void Serial_::end(void) { } -void Serial_::accept(void) -{ - ring_buffer *buffer = &cdc_rx_buffer; - int i = (unsigned int)(buffer->head+1) % 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. - - // while we have room to store a byte - while (i != buffer->tail) { - int c = USB_Recv(CDC_RX); - if (c == -1) - break; // no more data - buffer->buffer[buffer->head] = c; - buffer->head = i; - - i = (unsigned int)(buffer->head+1) % SERIAL_BUFFER_SIZE; - } -} - int Serial_::available(void) { - ring_buffer *buffer = &cdc_rx_buffer; - return (unsigned int)(SERIAL_BUFFER_SIZE + buffer->head - buffer->tail) % SERIAL_BUFFER_SIZE; + if (peek_buffer >= 0) { + return 1; + } + return USB_Available(CDC_RX); } int Serial_::peek(void) { - ring_buffer *buffer = &cdc_rx_buffer; - if (buffer->head == buffer->tail) { - return -1; - } else { - return buffer->buffer[buffer->tail]; - } + if (peek_buffer < 0) + peek_buffer = USB_Recv(CDC_RX); + return peek_buffer; } 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) { - return -1; - } else { - unsigned char c = buffer->buffer[buffer->tail]; - buffer->tail = (unsigned int)(buffer->tail + 1) % SERIAL_BUFFER_SIZE; + if (peek_buffer >= 0) { + int c = peek_buffer; + peek_buffer = -1; return c; - } + } + return USB_Recv(CDC_RX); } void Serial_::flush(void) diff --git a/hardware/arduino/cores/arduino/USBAPI.h b/hardware/arduino/cores/arduino/USBAPI.h index 1c5ecf0fc..d506b585f 100644 --- a/hardware/arduino/cores/arduino/USBAPI.h +++ b/hardware/arduino/cores/arduino/USBAPI.h @@ -28,14 +28,13 @@ extern USBDevice_ USBDevice; class Serial_ : public Stream { private: - ring_buffer *_cdc_rx_buffer; + int peek_buffer; public: void begin(unsigned long); void begin(unsigned long, uint8_t); void end(void); virtual int available(void); - virtual void accept(void); virtual int peek(void); virtual int read(void); virtual void flush(void); diff --git a/hardware/arduino/cores/arduino/USBCore.cpp b/hardware/arduino/cores/arduino/USBCore.cpp index 76ceb0154..f8123e518 100644 --- a/hardware/arduino/cores/arduino/USBCore.cpp +++ b/hardware/arduino/cores/arduino/USBCore.cpp @@ -614,8 +614,6 @@ ISR(USB_GEN_vect) { #ifdef CDC_ENABLED USB_Flush(CDC_TX); // Send a tx frame if found - if (USB_Available(CDC_RX)) // Handle received bytes (if any) - Serial.accept(); #endif // check whether the one-shot period has elapsed. if so, turn off the LED