[AVR] Discover newer bootloader at runtime
Replaces #4280, only checks for the bootloader once 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)
This commit is contained in:
parent
71b87bf26b
commit
5e194bd8ef
|
@ -34,6 +34,8 @@ typedef struct
|
||||||
static volatile LineInfo _usbLineInfo = { 57600, 0x00, 0x00, 0x00, 0x00 };
|
static volatile LineInfo _usbLineInfo = { 57600, 0x00, 0x00, 0x00, 0x00 };
|
||||||
static volatile int32_t breakValue = -1;
|
static volatile int32_t breakValue = -1;
|
||||||
|
|
||||||
|
bool _updatedLUFAbootloader = false;
|
||||||
|
|
||||||
#define WEAK __attribute__ ((weak))
|
#define WEAK __attribute__ ((weak))
|
||||||
|
|
||||||
extern const CDCDescriptor _cdcInterface PROGMEM;
|
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
|
// with a relatively long period so it can finish housekeeping tasks
|
||||||
// like servicing endpoints before the sketch ends
|
// like servicing endpoints before the sketch ends
|
||||||
|
|
||||||
#ifndef MAGIC_KEY
|
uint16_t magic_key_pos = MAGIC_KEY_POS;
|
||||||
#define MAGIC_KEY 0x7777
|
|
||||||
#endif
|
// If we don't use the new RAMEND directly, check manually if we have a newer bootloader.
|
||||||
#ifndef MAGIC_KEY_POS
|
// This is used to keep compatible with the old leonardo bootloaders.
|
||||||
#define MAGIC_KEY_POS 0x0800
|
// 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
|
#endif
|
||||||
|
|
||||||
// We check DTR state to determine if host port is open (bit 0 of lineState).
|
// We check DTR state to determine if host port is open (bit 0 of lineState).
|
||||||
if (1200 == _usbLineInfo.dwDTERate && (_usbLineInfo.lineState & 0x01) == 0)
|
if (1200 == _usbLineInfo.dwDTERate && (_usbLineInfo.lineState & 0x01) == 0)
|
||||||
{
|
{
|
||||||
#if MAGIC_KEY_POS != (RAMEND-1)
|
#if MAGIC_KEY_POS != (RAMEND-1)
|
||||||
*(uint16_t *)(RAMEND-1) = *(uint16_t *)MAGIC_KEY_POS;
|
// Backup ram value if its not a newer bootloader.
|
||||||
*(uint16_t *)MAGIC_KEY_POS = MAGIC_KEY;
|
// This should avoid memory corruption at least a bit, not fully
|
||||||
#else
|
if (magic_key_pos != (RAMEND-1)) {
|
||||||
// for future boards save the key in the inproblematic RAMEND
|
*(uint16_t *)(RAMEND-1) = *(uint16_t *)magic_key_pos;
|
||||||
// which is reserved for the main() return value (which will never return)
|
}
|
||||||
*(uint16_t *)MAGIC_KEY_POS = MAGIC_KEY;
|
|
||||||
#endif
|
#endif
|
||||||
|
// Store boot key
|
||||||
|
*(uint16_t *)magic_key_pos = MAGIC_KEY;
|
||||||
wdt_enable(WDTO_120MS);
|
wdt_enable(WDTO_120MS);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
|
@ -129,10 +139,15 @@ bool CDC_Setup(USBSetup& setup)
|
||||||
wdt_disable();
|
wdt_disable();
|
||||||
wdt_reset();
|
wdt_reset();
|
||||||
#if MAGIC_KEY_POS != (RAMEND-1)
|
#if MAGIC_KEY_POS != (RAMEND-1)
|
||||||
*(uint16_t *)MAGIC_KEY_POS = *(uint16_t *)(RAMEND-1);
|
// Restore backed up (old bootloader) magic key data
|
||||||
#else
|
if (magic_key_pos != (RAMEND-1)) {
|
||||||
*(uint16_t *)MAGIC_KEY_POS = 0x0000;
|
*(uint16_t *)magic_key_pos = *(uint16_t *)(RAMEND-1);
|
||||||
|
} else
|
||||||
#endif
|
#endif
|
||||||
|
{
|
||||||
|
// Clean up RAMEND key
|
||||||
|
*(uint16_t *)magic_key_pos = 0x0000;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return true;
|
return true;
|
||||||
|
|
|
@ -35,6 +35,7 @@ extern const u8 STRING_PRODUCT[] PROGMEM;
|
||||||
extern const u8 STRING_MANUFACTURER[] PROGMEM;
|
extern const u8 STRING_MANUFACTURER[] PROGMEM;
|
||||||
extern const DeviceDescriptor USB_DeviceDescriptor PROGMEM;
|
extern const DeviceDescriptor USB_DeviceDescriptor PROGMEM;
|
||||||
extern const DeviceDescriptor USB_DeviceDescriptorB PROGMEM;
|
extern const DeviceDescriptor USB_DeviceDescriptorB PROGMEM;
|
||||||
|
extern bool _updatedLUFAbootloader;
|
||||||
|
|
||||||
const u16 STRING_LANGUAGE[2] = {
|
const u16 STRING_LANGUAGE[2] = {
|
||||||
(3<<8) | (2+2),
|
(3<<8) | (2+2),
|
||||||
|
@ -806,6 +807,12 @@ void USBDevice_::attach()
|
||||||
UDIEN = (1<<EORSTE) | (1<<SOFE) | (1<<SUSPE); // Enable interrupts for EOR (End of Reset), SOF (start of frame) and SUSPEND
|
UDIEN = (1<<EORSTE) | (1<<SOFE) | (1<<SUSPE); // Enable interrupts for EOR (End of Reset), SOF (start of frame) and SUSPEND
|
||||||
|
|
||||||
TX_RX_LED_INIT;
|
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()
|
void USBDevice_::detach()
|
||||||
|
|
|
@ -366,4 +366,22 @@ const uint8_t PROGMEM analog_pin_to_channel_PGM[] = {
|
||||||
// Alias SerialUSB to Serial
|
// Alias SerialUSB to Serial
|
||||||
#define SerialUSB SERIAL_PORT_USBVIRTUAL
|
#define SerialUSB SERIAL_PORT_USBVIRTUAL
|
||||||
|
|
||||||
|
// Bootloader related fields
|
||||||
|
// Old Caterian 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 /* Pins_Arduino_h */
|
#endif /* Pins_Arduino_h */
|
||||||
|
|
Loading…
Reference in New Issue