Skip to content

Commit c72f6ba

Browse files
committed
Rework CDC reset to discover newer bootloader at runtime
Tested with Hoodloader2, should work with every LUFA-derived bootloader released after 2014 (.apitable_signatures section must be placed at end of the flash) BootloaderAPITable.S : .global BootloaderAPI_Signatures BootloaderAPI_Signatures: .long BOOT_START_ADDR ; Start address of the bootloader .word 0xDF00 ; Signature for the CDC class bootloader .word 0xDCFB ; Signature for a LUFA class bootloader makefile: BOOT_API_LD_FLAGS += $(call BOOT_SECTION_LD_FLAG, .apitable_signatures, BootloaderAPI_Signatures, 8)
1 parent 67dde84 commit c72f6ba

File tree

1 file changed

+35
-9
lines changed
  • hardware/arduino/avr/cores/arduino

1 file changed

+35
-9
lines changed

hardware/arduino/avr/cores/arduino/CDC.cpp

Lines changed: 35 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -102,21 +102,43 @@ bool CDC_Setup(USBSetup& setup)
102102
#ifndef MAGIC_KEY
103103
#define MAGIC_KEY 0x7777
104104
#endif
105+
106+
// Legacy magic key position. Looks for old and new boot key position.
107+
// Use RAMEND-1 as MAGIC_KEY_POS to save a few bytes of flash and force the new bootloader.
105108
#ifndef MAGIC_KEY_POS
106109
#define MAGIC_KEY_POS 0x0800
107110
#endif
108111

112+
#ifndef NEW_LUFA_SIGNATURE
113+
#define NEW_LUFA_SIGNATURE 0xDCFB
114+
#endif
115+
116+
uint16_t magic_key_pos = MAGIC_KEY_POS;
117+
118+
// If we don't use the new RAMEND directly, check manually if we have a newer bootloader.
119+
// This is used to keep compatible with the old leonardo bootloaders.
120+
// You are still able to set the magic key position manually to RAMEND-1 to save a few bytes for this check.
121+
#if MAGIC_KEY_POS != (RAMEND-1)
122+
// For future boards save the key in the inproblematic RAMEND
123+
// Which is reserved for the main() return value (which will never return)
124+
if (pgm_read_word(FLASHEND - 1) == NEW_LUFA_SIGNATURE) {
125+
// horray, we got a new bootloader!
126+
magic_key_pos = (RAMEND-1);
127+
}
128+
#endif
129+
109130
// We check DTR state to determine if host port is open (bit 0 of lineState).
110131
if (1200 == _usbLineInfo.dwDTERate && (_usbLineInfo.lineState & 0x01) == 0)
111132
{
112133
#if MAGIC_KEY_POS != (RAMEND-1)
113-
*(uint16_t *)(RAMEND-1) = *(uint16_t *)MAGIC_KEY_POS;
114-
*(uint16_t *)MAGIC_KEY_POS = MAGIC_KEY;
115-
#else
116-
// for future boards save the key in the inproblematic RAMEND
117-
// which is reserved for the main() return value (which will never return)
118-
*(uint16_t *)MAGIC_KEY_POS = MAGIC_KEY;
134+
// Backup ram value if its not a newer bootloader.
135+
// This should avoid memory corruption at least a bit, not fully
136+
if (magic_key_pos != (RAMEND-1)) {
137+
*(uint16_t *)(RAMEND-1) = *(uint16_t *)magic_key_pos;
138+
}
119139
#endif
140+
// Store boot key
141+
*(uint16_t *)magic_key_pos = MAGIC_KEY;
120142
wdt_enable(WDTO_120MS);
121143
}
122144
else
@@ -129,10 +151,14 @@ bool CDC_Setup(USBSetup& setup)
129151
wdt_disable();
130152
wdt_reset();
131153
#if MAGIC_KEY_POS != (RAMEND-1)
132-
*(uint16_t *)MAGIC_KEY_POS = *(uint16_t *)(RAMEND-1);
133-
#else
134-
*(uint16_t *)MAGIC_KEY_POS = 0x0000;
154+
// Restore backed up (old bootloader) magic key data
155+
if (magic_key_pos != (RAMEND-1)) {
156+
*(uint16_t *)magic_key_pos = *(uint16_t *)(RAMEND-1);
157+
} else {
135158
#endif
159+
// Clean up RAMEND key
160+
*(uint16_t *)magic_key_pos = 0x0000;
161+
}
136162
}
137163
}
138164
return true;

0 commit comments

Comments
 (0)