From eae5a78ce129c49e38d18ce1258b46b74bc0eb49 Mon Sep 17 00:00:00 2001 From: NicoHood Date: Sun, 22 May 2016 09:32:05 +0200 Subject: [PATCH 1/8] Made CALLBACK_USB_GetDescriptor() smaller --- Bootloaders/CDC/Descriptors.c | 54 +++++++++++++++++------------------ 1 file changed, 26 insertions(+), 28 deletions(-) diff --git a/Bootloaders/CDC/Descriptors.c b/Bootloaders/CDC/Descriptors.c index 48306165f..174249214 100644 --- a/Bootloaders/CDC/Descriptors.c +++ b/Bootloaders/CDC/Descriptors.c @@ -208,37 +208,35 @@ uint16_t CALLBACK_USB_GetDescriptor(const uint16_t wValue, const void* Address = NULL; uint16_t Size = NO_DESCRIPTOR; - switch (DescriptorType) + if (DescriptorType == DTYPE_Device) { - case DTYPE_Device: - Address = &DeviceDescriptor; - Size = sizeof(USB_Descriptor_Device_t); - break; - case DTYPE_Configuration: - Address = &ConfigurationDescriptor; - Size = sizeof(USB_Descriptor_Configuration_t); - break; - case DTYPE_String: - if (DescriptorNumber == STRING_ID_Language) - { - Address = &LanguageString; - Size = LanguageString.Header.Size; - } - else if (DescriptorNumber == STRING_ID_Manufacturer) - { - Address = &ManufacturerString; - Size = ManufacturerString.Header.Size; - } - else if (DescriptorNumber == STRING_ID_Product) - { - Address = &ProductString; - Size = ProductString.Header.Size; - } - - break; + Address = &DeviceDescriptor; + Size = sizeof(USB_Descriptor_Device_t); + } + else if (DescriptorType == DTYPE_Configuration) + { + Address = &ConfigurationDescriptor; + Size = sizeof(USB_Descriptor_Configuration_t); + } + else if (DescriptorType == DTYPE_String) + { + if (DescriptorNumber == STRING_ID_Language) + { + Address = &LanguageString; + Size = LanguageString.Header.Size; + } + else if (DescriptorNumber == STRING_ID_Manufacturer) + { + Address = &ManufacturerString; + Size = ManufacturerString.Header.Size; + } + else if (DescriptorNumber == STRING_ID_Product) + { + Address = &ProductString; + Size = ProductString.Header.Size; + } } *DescriptorAddress = Address; return Size; } - From 9ba5306491a4a48201c402c54caac8b1148e0f24 Mon Sep 17 00:00:00 2001 From: NicoHood Date: Sun, 22 May 2016 09:44:15 +0200 Subject: [PATCH 2/8] Improved watchdog handling --- Bootloaders/CDC/BootloaderCDC.c | 27 +++++++++------------------ 1 file changed, 9 insertions(+), 18 deletions(-) diff --git a/Bootloaders/CDC/BootloaderCDC.c b/Bootloaders/CDC/BootloaderCDC.c index 625a99685..6cc909bf8 100644 --- a/Bootloaders/CDC/BootloaderCDC.c +++ b/Bootloaders/CDC/BootloaderCDC.c @@ -70,6 +70,11 @@ uint16_t MagicBootKey ATTR_NO_INIT; */ void Application_Jump_Check(void) { + /* Turn off the watchdog */ + uint8_t mcusr_state = MCUSR; + MCUSR = 0; + wdt_disable(); + bool JumpToApplication = false; #if (BOARD == BOARD_LEONARDO) @@ -99,22 +104,16 @@ void Application_Jump_Check(void) /* Check if the device's BOOTRST fuse is set */ if (boot_lock_fuse_bits_get(GET_HIGH_FUSE_BITS) & FUSE_BOOTRST) { - /* If the reset source was not an external reset or the key is correct, clear it and jump to the application */ - if (!(MCUSR & (1 << EXTRF)) || (MagicBootKey == MAGIC_BOOT_KEY)) + /* If the reset source was not an external reset or the key is correct, jump to the application */ + if (!(mcusr_state & (1 << EXTRF)) || (MagicBootKey == MAGIC_BOOT_KEY)) JumpToApplication = true; - - /* Clear reset source */ - MCUSR &= ~(1 << EXTRF); } else { - /* If the reset source was the bootloader and the key is correct, clear it and jump to the application; + /* If the reset source was the bootloader and the key is correct, jump to the application; * this can happen in the HWBE fuse is set, and the HBE pin is low during the watchdog reset */ - if ((MCUSR & (1 << WDRF)) && (MagicBootKey == MAGIC_BOOT_KEY)) + if ((mcusr_state & (1 << WDRF)) && (MagicBootKey == MAGIC_BOOT_KEY)) JumpToApplication = true; - - /* Clear reset source */ - MCUSR &= ~(1 << WDRF); } #endif @@ -124,10 +123,6 @@ void Application_Jump_Check(void) /* If a request has been made to jump to the user application, honor it */ if (JumpToApplication && ApplicationValid) { - /* Turn off the watchdog */ - MCUSR &= ~(1 << WDRF); - wdt_disable(); - /* Clear the boot key and jump to the user application */ MagicBootKey = 0; @@ -175,10 +170,6 @@ int main(void) /** Configures all hardware required for the bootloader. */ static void SetupHardware(void) { - /* Disable watchdog if enabled by bootloader/fuses */ - MCUSR &= ~(1 << WDRF); - wdt_disable(); - /* Disable clock division */ clock_prescale_set(clock_div_1); From 0c299abaf6a8a7598df0030a45e1f29eb406b115 Mon Sep 17 00:00:00 2001 From: NicoHood Date: Sun, 22 May 2016 10:18:25 +0200 Subject: [PATCH 3/8] Used a fixed, but less problematic MagicBootkey position This address is used by gcc as main() return value. Because main() never returns this is unproblematic. RAMEND - 1 is used in the newer Arduino IDE to make the sketch more safe from memory corruption. --- Bootloaders/CDC/BootloaderCDC.c | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/Bootloaders/CDC/BootloaderCDC.c b/Bootloaders/CDC/BootloaderCDC.c index 6cc909bf8..de5bc4d26 100644 --- a/Bootloaders/CDC/BootloaderCDC.c +++ b/Bootloaders/CDC/BootloaderCDC.c @@ -61,8 +61,7 @@ static bool RunBootloader = true; * low when the application attempts to start via a watchdog reset, the bootloader will re-start. If set to the value * \ref MAGIC_BOOT_KEY the special init function \ref Application_Jump_Check() will force the application to start. */ -uint16_t MagicBootKey ATTR_NO_INIT; - +#define MagicBootKey (*(uint16_t *)(RAMEND-1)) /** Special startup routine to check if the bootloader was started via a watchdog reset, and if the magic application * start key has been loaded into \ref MagicBootKey. If the bootloader started via the watchdog and the key is valid, From 360801a32b8bb58bd0bc81a80aecaed12280b31d Mon Sep 17 00:00:00 2001 From: NicoHood Date: Sun, 22 May 2016 10:20:22 +0200 Subject: [PATCH 4/8] Used Arduino Magic Bootkey Since the actuall value of the key does not matter, we want to use an Arduino compatible key. --- Bootloaders/CDC/BootloaderCDC.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Bootloaders/CDC/BootloaderCDC.h b/Bootloaders/CDC/BootloaderCDC.h index e3cfb25c5..999b1646f 100644 --- a/Bootloaders/CDC/BootloaderCDC.h +++ b/Bootloaders/CDC/BootloaderCDC.h @@ -75,7 +75,7 @@ #define SOFTWARE_IDENTIFIER "LUFACDC" /** Magic bootloader key to unlock forced application start mode. */ - #define MAGIC_BOOT_KEY 0xDC42 + #define MAGIC_BOOT_KEY 0x7777 /* Enums: */ /** Possible memory types that can be addressed via the bootloader. */ From ec9a9257330703264c3945bc2cf64415ba6a906b Mon Sep 17 00:00:00 2001 From: NicoHood Date: Sun, 22 May 2016 10:21:26 +0200 Subject: [PATCH 5/8] Made application jump check faster and smaller --- Bootloaders/CDC/BootloaderCDC.c | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/Bootloaders/CDC/BootloaderCDC.c b/Bootloaders/CDC/BootloaderCDC.c index de5bc4d26..4dcbf1a71 100644 --- a/Bootloaders/CDC/BootloaderCDC.c +++ b/Bootloaders/CDC/BootloaderCDC.c @@ -74,6 +74,9 @@ void Application_Jump_Check(void) MCUSR = 0; wdt_disable(); + /* Don't run the user application if the reset vector is blank (no app loaded) */ + bool ApplicationValid = (pgm_read_word_near(0) != 0xFFFF); + bool JumpToApplication = false; #if (BOARD == BOARD_LEONARDO) @@ -116,11 +119,8 @@ void Application_Jump_Check(void) } #endif - /* Don't run the user application if the reset vector is blank (no app loaded) */ - bool ApplicationValid = (pgm_read_word_near(0) != 0xFFFF); - /* If a request has been made to jump to the user application, honor it */ - if (JumpToApplication && ApplicationValid) + if (ApplicationValid && JumpToApplication) { /* Clear the boot key and jump to the user application */ MagicBootKey = 0; From e7f5434761ced564010a962711d14108576f25f5 Mon Sep 17 00:00:00 2001 From: NicoHood Date: Sun, 22 May 2016 10:22:05 +0200 Subject: [PATCH 6/8] Typos --- Bootloaders/CDC/BootloaderCDC.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/Bootloaders/CDC/BootloaderCDC.c b/Bootloaders/CDC/BootloaderCDC.c index 4dcbf1a71..4b87211a9 100644 --- a/Bootloaders/CDC/BootloaderCDC.c +++ b/Bootloaders/CDC/BootloaderCDC.c @@ -113,7 +113,7 @@ void Application_Jump_Check(void) else { /* If the reset source was the bootloader and the key is correct, jump to the application; - * this can happen in the HWBE fuse is set, and the HBE pin is low during the watchdog reset */ + * this can happen if the HWBE fuse is set, and the HBE pin is low during the watchdog reset */ if ((mcusr_state & (1 << WDRF)) && (MagicBootKey == MAGIC_BOOT_KEY)) JumpToApplication = true; } @@ -125,7 +125,7 @@ void Application_Jump_Check(void) /* Clear the boot key and jump to the user application */ MagicBootKey = 0; - // cppcheck-suppress constStatement + /* cppcheck-suppress constStatement */ ((void (*)(void))0x0000)(); } } From 3a89db6ff92d598e5c30c76dde3cbdd9bb168908 Mon Sep 17 00:00:00 2001 From: NicoHood Date: Sun, 22 May 2016 10:25:36 +0200 Subject: [PATCH 7/8] Made CDC Bootloader Arduino compatible --- Bootloaders/CDC/BootloaderCDC.c | 42 ++++++++++++++++++++++++++------- 1 file changed, 33 insertions(+), 9 deletions(-) diff --git a/Bootloaders/CDC/BootloaderCDC.c b/Bootloaders/CDC/BootloaderCDC.c index 4b87211a9..9ee8926a7 100644 --- a/Bootloaders/CDC/BootloaderCDC.c +++ b/Bootloaders/CDC/BootloaderCDC.c @@ -80,15 +80,37 @@ void Application_Jump_Check(void) bool JumpToApplication = false; #if (BOARD == BOARD_LEONARDO) - /* Enable pull-up on the IO13 pin so we can use it to select the mode */ - PORTC |= (1 << 7); - Delay_MS(10); + /* First case: external reset, bootKey NOT in memory. We'll put the bootKey in memory, then spin + * our wheels for about 1000ms, then proceed to the sketch, if there is one. If, during that 1000ms, + * another external reset occurs, on the next pass through this decision tree, execution will fall + * through to the bootloader. */ + if ((mcusr_state & (1 << EXTRF))) { + if (MagicBootKey != MAGIC_BOOT_KEY) + { + /* Set Bootkey and give the user a few ms to repress and enter bootloader mode */ + MagicBootKey = MAGIC_BOOT_KEY; + + /* Wait for a possible double tab */ + _delay_ms(1000); - /* If IO13 is not jumpered to ground, start the user application instead */ - JumpToApplication = ((PINC & (1 << 7)) != 0); + /* User was too slow/normal reset, start sketch now */ + MagicBootKey = 0; - /* Disable pull-up after the check has completed */ - PORTC &= ~(1 << 7); + /* Single rab reset, start sketch */ + JumpToApplication = true; + } + } + + /* On a power-on reset, we ALWAYS want to go to the sketch if there is one. */ + else if ((mcusr_state & (1 << PORF))) { + JumpToApplication = true; + } + + /* On a watchdog reset, if the bootKey isn't set, and there's a sketch, we should just + * go straight to the sketch. */ + else if ((mcusr_state & (1 << WDRF)) && (MagicBootKey != MAGIC_BOOT_KEY)) { + JumpToApplication = true; + } #elif ((BOARD == BOARD_XPLAIN) || (BOARD == BOARD_XPLAIN_REV1)) /* Disable JTAG debugging */ JTAG_DISABLE(); @@ -157,8 +179,10 @@ int main(void) /* Disconnect from the host - USB interface will be reset later along with the AVR */ USB_Detach(); - /* Unlock the forced application start mode of the bootloader if it is restarted */ - MagicBootKey = MAGIC_BOOT_KEY; + #if (BOARD != BOARD_LEONARDO) + /* Unlock the forced application start mode of the bootloader if it is restarted */ + MagicBootKey = MAGIC_BOOT_KEY; + #endif /* Enable the watchdog and force a timeout to reset the AVR */ wdt_enable(WDTO_250MS); From 6f7b59f6a6d5da9e91d288130c8ce8a7445cd8ea Mon Sep 17 00:00:00 2001 From: NicoHood Date: Sun, 22 May 2016 11:53:52 +0200 Subject: [PATCH 8/8] Improved readablitity --- Bootloaders/CDC/BootloaderCDC.c | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/Bootloaders/CDC/BootloaderCDC.c b/Bootloaders/CDC/BootloaderCDC.c index 9ee8926a7..8db8b1cd6 100644 --- a/Bootloaders/CDC/BootloaderCDC.c +++ b/Bootloaders/CDC/BootloaderCDC.c @@ -102,14 +102,16 @@ void Application_Jump_Check(void) } /* On a power-on reset, we ALWAYS want to go to the sketch if there is one. */ - else if ((mcusr_state & (1 << PORF))) { + else if (mcusr_state & (1 << PORF)) { JumpToApplication = true; } /* On a watchdog reset, if the bootKey isn't set, and there's a sketch, we should just * go straight to the sketch. */ - else if ((mcusr_state & (1 << WDRF)) && (MagicBootKey != MAGIC_BOOT_KEY)) { - JumpToApplication = true; + else if (mcusr_state & (1 << WDRF)) { + if(MagicBootKey != MAGIC_BOOT_KEY){ + JumpToApplication = true; + } } #elif ((BOARD == BOARD_XPLAIN) || (BOARD == BOARD_XPLAIN_REV1)) /* Disable JTAG debugging */