diff options
Diffstat (limited to 'cores')
-rw-r--r-- | cores/arduino/CDC.cpp | 43 | ||||
-rw-r--r-- | cores/arduino/USBCore.cpp | 13 | ||||
-rw-r--r-- | cores/arduino/USBCore.h | 17 | ||||
-rw-r--r-- | cores/arduino/WString.cpp | 2 | ||||
-rw-r--r-- | cores/arduino/WString.h | 18 |
5 files changed, 69 insertions, 24 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/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; |