aboutsummaryrefslogtreecommitdiff
path: root/cores/arduino
diff options
context:
space:
mode:
Diffstat (limited to 'cores/arduino')
-rw-r--r--cores/arduino/CDC.cpp43
-rw-r--r--cores/arduino/Stream.h3
-rw-r--r--cores/arduino/USBCore.cpp13
-rw-r--r--cores/arduino/USBCore.h17
-rw-r--r--cores/arduino/WString.cpp2
-rw-r--r--cores/arduino/WString.h18
6 files changed, 71 insertions, 25 deletions
diff --git a/cores/arduino/CDC.cpp b/cores/arduino/CDC.cpp
index f19b44c..0a743e1 100644
--- a/cores/arduino/CDC.cpp
+++ b/cores/arduino/CDC.cpp
@@ -34,6 +34,8 @@ typedef struct
static volatile LineInfo _usbLineInfo = { 57600, 0x00, 0x00, 0x00, 0x00 };
static volatile int32_t breakValue = -1;
+bool _updatedLUFAbootloader = false;
+
#define WEAK __attribute__ ((weak))
extern const CDCDescriptor _cdcInterface PROGMEM;
@@ -99,24 +101,32 @@ bool CDC_Setup(USBSetup& setup)
// with a relatively long period so it can finish housekeeping tasks
// like servicing endpoints before the sketch ends
-#ifndef MAGIC_KEY
-#define MAGIC_KEY 0x7777
-#endif
-#ifndef MAGIC_KEY_POS
-#define MAGIC_KEY_POS 0x0800
+ uint16_t magic_key_pos = MAGIC_KEY_POS;
+
+// If we don't use the new RAMEND directly, check manually if we have a newer bootloader.
+// This is used to keep compatible with the old leonardo bootloaders.
+// You are still able to set the magic key position manually to RAMEND-1 to save a few bytes for this check.
+#if MAGIC_KEY_POS != (RAMEND-1)
+ // For future boards save the key in the inproblematic RAMEND
+ // Which is reserved for the main() return value (which will never return)
+ if (_updatedLUFAbootloader) {
+ // horray, we got a new bootloader!
+ magic_key_pos = (RAMEND-1);
+ }
#endif
// We check DTR state to determine if host port is open (bit 0 of lineState).
if (1200 == _usbLineInfo.dwDTERate && (_usbLineInfo.lineState & 0x01) == 0)
{
#if MAGIC_KEY_POS != (RAMEND-1)
- *(uint16_t *)(RAMEND-1) = *(uint16_t *)MAGIC_KEY_POS;
- *(uint16_t *)MAGIC_KEY_POS = MAGIC_KEY;
-#else
- // for future boards save the key in the inproblematic RAMEND
- // which is reserved for the main() return value (which will never return)
- *(uint16_t *)MAGIC_KEY_POS = MAGIC_KEY;
+ // Backup ram value if its not a newer bootloader.
+ // This should avoid memory corruption at least a bit, not fully
+ if (magic_key_pos != (RAMEND-1)) {
+ *(uint16_t *)(RAMEND-1) = *(uint16_t *)magic_key_pos;
+ }
#endif
+ // Store boot key
+ *(uint16_t *)magic_key_pos = MAGIC_KEY;
wdt_enable(WDTO_120MS);
}
else
@@ -129,10 +139,15 @@ bool CDC_Setup(USBSetup& setup)
wdt_disable();
wdt_reset();
#if MAGIC_KEY_POS != (RAMEND-1)
- *(uint16_t *)MAGIC_KEY_POS = *(uint16_t *)(RAMEND-1);
-#else
- *(uint16_t *)MAGIC_KEY_POS = 0x0000;
+ // Restore backed up (old bootloader) magic key data
+ if (magic_key_pos != (RAMEND-1)) {
+ *(uint16_t *)magic_key_pos = *(uint16_t *)(RAMEND-1);
+ } else
#endif
+ {
+ // Clean up RAMEND key
+ *(uint16_t *)magic_key_pos = 0x0000;
+ }
}
}
return true;
diff --git a/cores/arduino/Stream.h b/cores/arduino/Stream.h
index db71bb6..e4fd433 100644
--- a/cores/arduino/Stream.h
+++ b/cores/arduino/Stream.h
@@ -66,7 +66,8 @@ class Stream : public Print
// parsing methods
void setTimeout(unsigned long timeout); // sets maximum milliseconds to wait for stream data, default is 1 second
-
+ unsigned long getTimeout(void) { return _timeout; }
+
bool find(char *target); // reads data from the stream until the target string is found
bool find(uint8_t *target) { return find ((char *)target); }
// returns true if target string is found, false if timed out (see setTimeout)
diff --git a/cores/arduino/USBCore.cpp b/cores/arduino/USBCore.cpp
index 62b90ed..6c8ae63 100644
--- a/cores/arduino/USBCore.cpp
+++ b/cores/arduino/USBCore.cpp
@@ -35,6 +35,7 @@ extern const u8 STRING_PRODUCT[] PROGMEM;
extern const u8 STRING_MANUFACTURER[] PROGMEM;
extern const DeviceDescriptor USB_DeviceDescriptor PROGMEM;
extern const DeviceDescriptor USB_DeviceDescriptorB PROGMEM;
+extern bool _updatedLUFAbootloader;
const u16 STRING_LANGUAGE[2] = {
(3<<8) | (2+2),
@@ -254,7 +255,9 @@ u8 USB_SendSpace(u8 ep)
LockEP lock(ep);
if (!ReadWriteAllowed())
return 0;
- return USB_EP_SIZE - FifoByteCount();
+ // subtract 1 from the EP size to never send a full packet,
+ // this avoids dealing with ZLP's in USB_Send
+ return USB_EP_SIZE - 1 - FifoByteCount();
}
// Blocking Send of data to an endpoint
@@ -730,7 +733,7 @@ static inline void USB_ClockEnable()
ISR(USB_GEN_vect)
{
u8 udint = UDINT;
- UDINT = UDINT &= ~((1<<EORSTI) | (1<<SOFI)); // clear the IRQ flags for the IRQs which are handled here, except WAKEUPI and SUSPI (see below)
+ UDINT &= ~((1<<EORSTI) | (1<<SOFI)); // clear the IRQ flags for the IRQs which are handled here, except WAKEUPI and SUSPI (see below)
// End of Reset
if (udint & (1<<EORSTI))
@@ -806,6 +809,12 @@ void USBDevice_::attach()
UDIEN = (1<<EORSTE) | (1<<SOFE) | (1<<SUSPE); // Enable interrupts for EOR (End of Reset), SOF (start of frame) and SUSPEND
TX_RX_LED_INIT;
+
+#if MAGIC_KEY_POS != (RAMEND-1)
+ if (pgm_read_word(FLASHEND - 1) == NEW_LUFA_SIGNATURE) {
+ _updatedLUFAbootloader = true;
+ }
+#endif
}
void USBDevice_::detach()
diff --git a/cores/arduino/USBCore.h b/cores/arduino/USBCore.h
index 4e08d71..66f3b5b 100644
--- a/cores/arduino/USBCore.h
+++ b/cores/arduino/USBCore.h
@@ -277,5 +277,22 @@ typedef struct
#define D_CDCCS(_subtype,_d0,_d1) { 5, 0x24, _subtype, _d0, _d1 }
#define D_CDCCS4(_subtype,_d0) { 4, 0x24, _subtype, _d0 }
+// Bootloader related fields
+// Old Caterina bootloader places the MAGIC key into unsafe RAM locations (it can be rewritten
+// by the running sketch before to actual reboot).
+// Newer bootloaders, recognizable by the LUFA "signature" at the end of the flash, can handle both
+// the usafe and the safe location. Check once (in USBCore.cpp) if the bootloader in new, then set the global
+// _updatedLUFAbootloader variable to true/false and place the magic key consequently
+#ifndef MAGIC_KEY
+#define MAGIC_KEY 0x7777
+#endif
+
+#ifndef MAGIC_KEY_POS
+#define MAGIC_KEY_POS 0x0800
+#endif
+
+#ifndef NEW_LUFA_SIGNATURE
+#define NEW_LUFA_SIGNATURE 0xDCFB
+#endif
#endif
diff --git a/cores/arduino/WString.cpp b/cores/arduino/WString.cpp
index cd3e0e8..9975303 100644
--- a/cores/arduino/WString.cpp
+++ b/cores/arduino/WString.cpp
@@ -193,7 +193,7 @@ String & String::copy(const __FlashStringHelper *pstr, unsigned int length)
void String::move(String &rhs)
{
if (buffer) {
- if (capacity >= rhs.len) {
+ if (rhs && capacity >= rhs.len) {
strcpy(buffer, rhs.buffer);
len = rhs.len;
rhs.len = 0;
diff --git a/cores/arduino/WString.h b/cores/arduino/WString.h
index b047980..de5632c 100644
--- a/cores/arduino/WString.h
+++ b/cores/arduino/WString.h
@@ -81,7 +81,7 @@ public:
inline unsigned int length(void) const {return len;}
// creates a copy of the assigned value. if the value is null or
- // invalid, or if the memory allocation fails, the string will be
+ // invalid, or if the memory allocation fails, the string will be
// marked as invalid ("if (s)" will be false).
String & operator = (const String &rhs);
String & operator = (const char *cstr);
@@ -92,10 +92,10 @@ public:
#endif
// concatenate (works w/ built-in types)
-
+
// returns true on success, false on failure (in which case, the string
- // is left unchanged). if the argument is null or invalid, the
- // concatenation is considered unsucessful.
+ // is left unchanged). if the argument is null or invalid, the
+ // concatenation is considered unsucessful.
unsigned char concat(const String &str);
unsigned char concat(const char *cstr);
unsigned char concat(char c);
@@ -107,7 +107,7 @@ public:
unsigned char concat(float num);
unsigned char concat(double num);
unsigned char concat(const __FlashStringHelper * str);
-
+
// if there's not enough memory for the concatenated value, the string
// will be left unchanged (but this isn't signalled in any way)
String & operator += (const String &rhs) {concat(rhs); return (*this);}
@@ -159,8 +159,12 @@ public:
char& operator [] (unsigned int index);
void getBytes(unsigned char *buf, unsigned int bufsize, unsigned int index=0) const;
void toCharArray(char *buf, unsigned int bufsize, unsigned int index=0) const
- {getBytes((unsigned char *)buf, bufsize, index);}
- const char * c_str() const { return buffer; }
+ { getBytes((unsigned char *)buf, bufsize, index); }
+ const char* c_str() const { return buffer; }
+ char* begin() { return buffer; }
+ char* end() { return buffer + length(); }
+ const char* begin() const { return c_str(); }
+ const char* end() const { return c_str() + length(); }
// search
int indexOf( char ch ) const;