Skip to content

Rework CDC reset to discover newer bootloader at runtime #4280

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Closed
wants to merge 1 commit into from
Closed
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
44 changes: 35 additions & 9 deletions hardware/arduino/avr/cores/arduino/CDC.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -102,21 +102,43 @@ bool CDC_Setup(USBSetup& setup)
#ifndef MAGIC_KEY
#define MAGIC_KEY 0x7777
#endif

// Legacy magic key position. Looks for old and new boot key position.
// Use RAMEND-1 as MAGIC_KEY_POS to save a few bytes of flash and force the new bootloader.
#ifndef MAGIC_KEY_POS
#define MAGIC_KEY_POS 0x0800
#endif

#ifndef NEW_LUFA_SIGNATURE
#define NEW_LUFA_SIGNATURE 0xDCFB
#endif

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 (pgm_read_word(FLASHEND - 1) == NEW_LUFA_SIGNATURE) {
// 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
Expand All @@ -129,10 +151,14 @@ 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;
Expand Down