Skip to content

[DO NOT MERGE] Fix bootloader and USB improvements on 32u4 #4793

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 3 commits into from
Closed
Show file tree
Hide file tree
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
43 changes: 29 additions & 14 deletions hardware/arduino/avr/cores/arduino/CDC.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand Down Expand Up @@ -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
Expand All @@ -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;
}
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Here is an error. You need to add an #if around the bracket too.

}
}
return true;
Expand Down
16 changes: 10 additions & 6 deletions hardware/arduino/avr/cores/arduino/USBCore.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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),
Expand Down Expand Up @@ -115,16 +116,10 @@ static inline void Recv(volatile u8* data, u8 count)
{
while (count--)
*data++ = UEDATX;

RXLED1; // light the RX LED
RxLEDPulse = TX_RX_LED_PULSE_MS;
}

static inline u8 Recv8()
{
RXLED1; // light the RX LED
RxLEDPulse = TX_RX_LED_PULSE_MS;

return UEDATX;
}

Expand Down Expand Up @@ -226,6 +221,9 @@ int USB_Recv(u8 ep, void* d, int len)
if (!_usbConfiguration || len < 0)
return -1;

RXLED1; // light the RX LED
RxLEDPulse = TX_RX_LED_PULSE_MS;

LockEP lock(ep);
u8 n = FifoByteCount();
len = min(n,len);
Expand Down Expand Up @@ -806,6 +804,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()
Expand Down
2 changes: 1 addition & 1 deletion hardware/arduino/avr/cores/arduino/USBCore.h
Original file line number Diff line number Diff line change
Expand Up @@ -260,7 +260,7 @@ typedef struct


#define D_DEVICE(_class,_subClass,_proto,_packetSize0,_vid,_pid,_version,_im,_ip,_is,_configs) \
{ 18, 1, 0x200, _class,_subClass,_proto,_packetSize0,_vid,_pid,_version,_im,_ip,_is,_configs }
{ 18, 1, 0x210, _class,_subClass,_proto,_packetSize0,_vid,_pid,_version,_im,_ip,_is,_configs }

#define D_CONFIG(_totalLength,_interfaces) \
{ 9, 2, _totalLength,_interfaces, 1, 0, USB_CONFIG_BUS_POWERED | USB_CONFIG_REMOTE_WAKEUP, USB_CONFIG_POWER_MA(500) }
Expand Down
18 changes: 18 additions & 0 deletions hardware/arduino/avr/variants/leonardo/pins_arduino.h
Original file line number Diff line number Diff line change
Expand Up @@ -366,4 +366,22 @@ const uint8_t PROGMEM analog_pin_to_channel_PGM[] = {
// Alias SerialUSB to Serial
#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 */