Skip to content

Commit cc1e835

Browse files
committed
[AVR] Discover newer bootloader at runtime
Replaces arduino#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)
1 parent 197fe07 commit cc1e835

File tree

5 files changed

+106
-14
lines changed

5 files changed

+106
-14
lines changed

hardware/arduino/avr/boards.txt

+51
Original file line numberDiff line numberDiff line change
@@ -46,6 +46,57 @@ yun.build.extra_flags={build.usb_flags}
4646

4747
##############################################################
4848

49+
yun101.name=Arduino/Genuino Yún 101
50+
yun101.upload.via_ssh=true
51+
52+
yun101.vid.0=0x2341
53+
yun101.pid.0=0x0051
54+
yun101.vid.1=0x2341
55+
yun101.pid.1=0x8051
56+
57+
yun101.upload.tool=avrdude
58+
yun101.upload.protocol=avr109
59+
yun101.upload.maximum_size=28672
60+
yun101.upload.maximum_data_size=2560
61+
yun101.upload.speed=57600
62+
yun101.upload.disable_flushing=true
63+
yun101.upload.use_1200bps_touch=true
64+
yun101.upload.wait_for_upload_port=true
65+
66+
yun101.bootloader.tool=avrdude
67+
yun101.bootloader.low_fuses=0xff
68+
yun101.bootloader.high_fuses=0xd8
69+
yun101.bootloader.extended_fuses=0xfb
70+
yun101.bootloader.file=caterina2/Caterina2_ArduinoYun101.hex
71+
yun101.bootloader.unlock_bits=0x3F
72+
yun101.bootloader.lock_bits=0x2F
73+
74+
yun101.vid.2=0x2341
75+
yun101.pid.2=0x8251
76+
yun101.vid.2.build.vid=0x2341
77+
yun101.vid.2.build.pid=0x8251
78+
yun101.vid.2.build.usb_product="Genuino Yun101"
79+
yun101.vid.2.bootloader.file=caterina2/Caterina2_GenuinoYun101.hex
80+
81+
yun101.vid.3=0x2341
82+
yun101.pid.3=0x0251
83+
yun101.vid.3.build.vid=0x2341
84+
yun101.vid.3.build.pid=0x8251
85+
yun101.vid.3.build.usb_product="Genuino Yun101"
86+
yun101.vid.3.bootloader.file=caterina2/Caterina2_GenuinoYun101.hex
87+
88+
yun101.build.mcu=atmega32u4
89+
yun101.build.f_cpu=16000000L
90+
yun101.build.vid=0x2341
91+
yun101.build.pid=0x8051
92+
yun101.build.usb_product="Arduino Yun101"
93+
yun101.build.board=AVR_YUN
94+
yun101.build.core=arduino
95+
yun101.build.variant=yun
96+
yun101.build.extra_flags={build.usb_flags}
97+
98+
##############################################################
99+
49100
uno.name=Arduino/Genuino Uno
50101

51102
uno.vid.0=0x2341

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

+29-14
Original file line numberDiff line numberDiff line change
@@ -34,6 +34,8 @@ typedef struct
3434
static volatile LineInfo _usbLineInfo = { 57600, 0x00, 0x00, 0x00, 0x00 };
3535
static volatile int32_t breakValue = -1;
3636

37+
bool _updatedLUFAbootloader = false;
38+
3739
#define WEAK __attribute__ ((weak))
3840

3941
extern const CDCDescriptor _cdcInterface PROGMEM;
@@ -99,24 +101,32 @@ bool CDC_Setup(USBSetup& setup)
99101
// with a relatively long period so it can finish housekeeping tasks
100102
// like servicing endpoints before the sketch ends
101103

102-
#ifndef MAGIC_KEY
103-
#define MAGIC_KEY 0x7777
104-
#endif
105-
#ifndef MAGIC_KEY_POS
106-
#define MAGIC_KEY_POS 0x0800
104+
uint16_t magic_key_pos = MAGIC_KEY_POS;
105+
106+
// If we don't use the new RAMEND directly, check manually if we have a newer bootloader.
107+
// This is used to keep compatible with the old leonardo bootloaders.
108+
// You are still able to set the magic key position manually to RAMEND-1 to save a few bytes for this check.
109+
#if MAGIC_KEY_POS != (RAMEND-1)
110+
// For future boards save the key in the inproblematic RAMEND
111+
// Which is reserved for the main() return value (which will never return)
112+
if (_updatedLUFAbootloader) {
113+
// horray, we got a new bootloader!
114+
magic_key_pos = (RAMEND-1);
115+
}
107116
#endif
108117

109118
// We check DTR state to determine if host port is open (bit 0 of lineState).
110119
if (1200 == _usbLineInfo.dwDTERate && (_usbLineInfo.lineState & 0x01) == 0)
111120
{
112121
#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;
122+
// Backup ram value if its not a newer bootloader.
123+
// This should avoid memory corruption at least a bit, not fully
124+
if (magic_key_pos != (RAMEND-1)) {
125+
*(uint16_t *)(RAMEND-1) = *(uint16_t *)magic_key_pos;
126+
}
119127
#endif
128+
// Store boot key
129+
*(uint16_t *)magic_key_pos = MAGIC_KEY;
120130
wdt_enable(WDTO_120MS);
121131
}
122132
else
@@ -129,10 +139,15 @@ bool CDC_Setup(USBSetup& setup)
129139
wdt_disable();
130140
wdt_reset();
131141
#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;
142+
// Restore backed up (old bootloader) magic key data
143+
if (magic_key_pos != (RAMEND-1)) {
144+
*(uint16_t *)magic_key_pos = *(uint16_t *)(RAMEND-1);
145+
} else
135146
#endif
147+
{
148+
// Clean up RAMEND key
149+
*(uint16_t *)magic_key_pos = 0x0000;
150+
}
136151
}
137152
}
138153
return true;

hardware/arduino/avr/cores/arduino/USBCore.cpp

+7
Original file line numberDiff line numberDiff line change
@@ -35,6 +35,7 @@ extern const u8 STRING_PRODUCT[] PROGMEM;
3535
extern const u8 STRING_MANUFACTURER[] PROGMEM;
3636
extern const DeviceDescriptor USB_DeviceDescriptor PROGMEM;
3737
extern const DeviceDescriptor USB_DeviceDescriptorB PROGMEM;
38+
extern bool _updatedLUFAbootloader;
3839

3940
const u16 STRING_LANGUAGE[2] = {
4041
(3<<8) | (2+2),
@@ -803,6 +804,12 @@ void USBDevice_::attach()
803804
UDIEN = (1<<EORSTE) | (1<<SOFE) | (1<<SUSPE); // Enable interrupts for EOR (End of Reset), SOF (start of frame) and SUSPEND
804805

805806
TX_RX_LED_INIT;
807+
808+
#if MAGIC_KEY_POS != (RAMEND-1)
809+
if (pgm_read_word(FLASHEND - 1) == NEW_LUFA_SIGNATURE) {
810+
_updatedLUFAbootloader = true;
811+
}
812+
#endif
806813
}
807814

808815
void USBDevice_::detach()

hardware/arduino/avr/platform.txt

+1
Original file line numberDiff line numberDiff line change
@@ -109,6 +109,7 @@ tools.avrdude.bootloader.params.verbose=-v
109109
tools.avrdude.bootloader.params.quiet=-q -q
110110
tools.avrdude.bootloader.pattern="{cmd.path}" "-C{config.path}" {bootloader.verbose} -p{build.mcu} -c{protocol} {program.extra_params} "-Uflash:w:{runtime.platform.path}/bootloaders/{bootloader.file}:i" -Ulock:w:{bootloader.lock_bits}:m
111111

112+
tools.avrdude_remote.upload.pattern=/usr/bin/run-avrdude /tmp/sketch.hex {upload.verbose} -p{build.mcu} -l{bootloader.low_fuses} -h{bootloader.high_fuses} -e{bootloader.extended_fuses}
112113

113114
# USB Default Flags
114115
# Default blank usb manufacturer will be filled in at compile time

hardware/arduino/avr/variants/leonardo/pins_arduino.h

+18
Original file line numberDiff line numberDiff line change
@@ -366,4 +366,22 @@ const uint8_t PROGMEM analog_pin_to_channel_PGM[] = {
366366
// Alias SerialUSB to Serial
367367
#define SerialUSB SERIAL_PORT_USBVIRTUAL
368368

369+
// Bootloader related fields
370+
// Old Caterian bootloader places the MAGIC key into unsafe RAM locations (it can be rewritten
371+
// by the running sketch before to actual reboot).
372+
// Newer bootloaders, recognizable by the LUFA "signature" at the end of the flash, can handle both
373+
// the usafe and the safe location. Check once (in USBCore.cpp) if the bootloader in new, then set the global
374+
// _updatedLUFAbootloader variable to true/false and place the magic key consequently
375+
#ifndef MAGIC_KEY
376+
#define MAGIC_KEY 0x7777
377+
#endif
378+
379+
#ifndef MAGIC_KEY_POS
380+
#define MAGIC_KEY_POS 0x0800
381+
#endif
382+
383+
#ifndef NEW_LUFA_SIGNATURE
384+
#define NEW_LUFA_SIGNATURE 0xDCFB
385+
#endif
386+
369387
#endif /* Pins_Arduino_h */

0 commit comments

Comments
 (0)