Add Leonardo compatibility to most bootloaders, run user application if BOOTRST fuse...
authorDean Camera <dean@fourwalledcubicle.com>
Sat, 11 Oct 2014 05:43:41 +0000 (16:43 +1100)
committerDean Camera <dean@fourwalledcubicle.com>
Sat, 11 Oct 2014 05:43:41 +0000 (16:43 +1100)
Bootloaders/CDC/BootloaderCDC.c
Bootloaders/CDC/BootloaderCDC.txt
Bootloaders/DFU/BootloaderDFU.c
Bootloaders/DFU/BootloaderDFU.txt
Bootloaders/MassStorage/BootloaderMassStorage.c
Bootloaders/MassStorage/BootloaderMassStorage.txt
Bootloaders/Printer/BootloaderPrinter.c
Bootloaders/Printer/BootloaderPrinter.txt
LUFA/DoxygenPages/ChangeLog.txt

index c7eeb92..1f07653 100644 (file)
@@ -72,7 +72,17 @@ void Application_Jump_Check(void)
 {
        bool JumpToApplication = false;
 
-       #if ((BOARD == BOARD_XPLAIN) || (BOARD == BOARD_XPLAIN_REV1))
+       #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);
+
+               /* If IO13 is not jumpered to ground, start the user application instead */
+               JumpToApplication = ((PINC & (1 << 7)) != 0);
+
+               /* Disable pull-up after the check has completed */
+               PORTC &= ~(1 << 7);
+       #elif ((BOARD == BOARD_XPLAIN) || (BOARD == BOARD_XPLAIN_REV1))
                /* Disable JTAG debugging */
                JTAG_DISABLE();
 
@@ -81,25 +91,30 @@ void Application_Jump_Check(void)
                Delay_MS(10);
 
                /* If the TCK pin is not jumpered to ground, start the user application instead */
-               JumpToApplication |= ((PINF & (1 << 4)) != 0);
+               JumpToApplication = ((PINF & (1 << 4)) != 0);
 
                /* Re-enable JTAG debugging */
                JTAG_ENABLE();
-       #endif
+       #else
+               /* 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))
+                         JumpToApplication = true;
 
-       /* If the reset source was the bootloader and the key is correct, clear it and jump to the application */
-       if ((MCUSR & (1 << WDRF)) && (MagicBootKey == MAGIC_BOOT_KEY))
-         JumpToApplication |= true;
+                       MCUSR &= ~(1 << EXTRF);
+               }
+       #endif
 
        /* Don't run the user application if the reset vector is blank (no app loaded) */
-       if (pgm_read_word_near(0) == 0xFFFF)
-         JumpToApplication = false;
+       bool ApplicationValid = (pgm_read_word_near(0) != 0xFFFF);
 
        /* If a request has been made to jump to the user application, honor it */
-       if (JumpToApplication)
+       if (JumpToApplication && ApplicationValid)
        {
                /* Turn off the watchdog */
-               MCUSR &= ~(1<<WDRF);
+               MCUSR &= ~(1 << WDRF);
                wdt_disable();
 
                /* Clear the boot key and jump to the user application */
index 55e5e55..5f24a16 100644 (file)
  *
  *  \section Sec_Running Running the Bootloader
  *
- *  This bootloader is designed to be started via the HWB mechanism of the USB AVRs; ground the HWB pin (see device
- *  datasheet) then momentarily ground /RESET to start the bootloader. This assumes the HWBE fuse is set and the BOOTRST
- *  fuse is cleared.
+ *  On the USB AVR8 devices, setting the \c HWBE device fuse will cause the bootloader to run if the \c HWB pin of
+ *  the AVR is grounded when the device is reset.
+ *
+ *  The are two behaviours of this bootloader, depending on the device's fuses:
+ *
+ *  <b>If the device's BOOTRST fuse is set</b>, the bootloader will run any time the system is not reset from
+ *  the external reset pin, unless no valid user application has been loaded. To initiate the bootloader, the
+ *  device's external reset pin should be grounded.
+ *
+ *  <b>If the device's BOOTRST fuse is not set</b>, the bootloader will run only if initiated via a software
+ *  jump, or if the \c HWB pin was low during the last device reset (if the \c HWBE fuse is set).
+ *
+ *  For board specific exceptions to the above, see below.
+ *
+ *  \subsection SSec_XPLAIN Atmel Xplain Board
+ *  Ground the USB AVR JTAG's \c TCK pin to ground when powering on the board to start the bootloader. This assumes the
+ *  \c HWBE fuse is cleared and the \c BOOTRST fuse is set as the HWBE pin is not user accessible on this board.
+ *
+ *  \subsection SSec_Leonardo Arduino Leonardo Board
+ *  Ground \c IO13 when powering the board to start the bootloader. This assumes the \c HWBE fuse is cleared and the
+ *  \c BOOTRST fuse is set as the HWBE pin is not user accessible on this board.
  *
  *  For board specific exceptions to the above, see below.
  *
index 160b9f6..cebc0f4 100644 (file)
@@ -108,7 +108,17 @@ void Application_Jump_Check(void)
 {
        bool JumpToApplication = false;
 
-       #if ((BOARD == BOARD_XPLAIN) || (BOARD == BOARD_XPLAIN_REV1))
+       #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);
+
+               /* If IO13 is not jumpered to ground, start the user application instead */
+               JumpToApplication = ((PINC & (1 << 7)) != 0);
+
+               /* Disable pull-up after the check has completed */
+               PORTC &= ~(1 << 7);
+       #elif ((BOARD == BOARD_XPLAIN) || (BOARD == BOARD_XPLAIN_REV1))
                /* Disable JTAG debugging */
                JTAG_DISABLE();
 
@@ -117,25 +127,30 @@ void Application_Jump_Check(void)
                Delay_MS(10);
 
                /* If the TCK pin is not jumpered to ground, start the user application instead */
-               JumpToApplication |= ((PINF & (1 << 4)) != 0);
+               JumpToApplication = ((PINF & (1 << 4)) != 0);
 
                /* Re-enable JTAG debugging */
                JTAG_ENABLE();
-       #endif
+       #else
+               /* 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))
+                         JumpToApplication = true;
 
-       /* If the reset source was the bootloader and the key is correct, clear it and jump to the application */
-       if ((MCUSR & (1 << WDRF)) && (MagicBootKey == MAGIC_BOOT_KEY))
-         JumpToApplication |= true;
+                       MCUSR &= ~(1 << EXTRF);
+               }
+       #endif
 
        /* Don't run the user application if the reset vector is blank (no app loaded) */
-
-         JumpToApplication = false;
+       bool ApplicationValid = (pgm_read_word_near(0) != 0xFFFF);
 
        /* If a request has been made to jump to the user application, honor it */
-       if (JumpToApplication)
+       if (JumpToApplication && ApplicationValid)
        {
                /* Turn off the watchdog */
-               MCUSR &= ~(1<<WDRF);
+               MCUSR &= ~(1 << WDRF);
                wdt_disable();
 
                /* Clear the boot key and jump to the user application */
index e63bcc1..d0bb6e1 100644 (file)
  *
  *  \section Sec_Running Running the Bootloader
  *
- *  This bootloader is designed to be started via the HWB mechanism of the USB AVRs; ground the HWB pin (see device
- *  datasheet) then momentarily ground /RESET to start the bootloader. This assumes the HWBE fuse is set and the BOOTRST
- *  fuse is cleared.
+ *  On the USB AVR8 devices, setting the \c HWBE device fuse will cause the bootloader to run if the \c HWB pin of
+ *  the AVR is grounded when the device is reset.
+ *
+ *  The are two behaviours of this bootloader, depending on the device's fuses:
+ *
+ *  <b>If the device's BOOTRST fuse is set</b>, the bootloader will run any time the system is not reset from
+ *  the external reset pin, unless no valid user application has been loaded. To initiate the bootloader, the
+ *  device's external reset pin should be grounded.
+ *
+ *  <b>If the device's BOOTRST fuse is not set</b>, the bootloader will run only if initiated via a software
+ *  jump, or if the \c HWB pin was low during the last device reset (if the \c HWBE fuse is set).
  *
  *  For board specific exceptions to the above, see below.
  *
index 191d49e..afbc250 100644 (file)
@@ -91,11 +91,11 @@ void Application_Jump_Check(void)
 
        #if (BOARD == BOARD_LEONARDO)
                /* Enable pull-up on the IO13 pin so we can use it to select the mode */
-               PORTC |=  (1 << 7);
+               PORTC |= (1 << 7);
                Delay_MS(10);
 
                /* If IO13 is not jumpered to ground, start the user application instead */
-               JumpToApplication |= ((PINC & (1 << 7)) != 0);
+               JumpToApplication = ((PINC & (1 << 7)) != 0);
 
                /* Disable pull-up after the check has completed */
                PORTC &= ~(1 << 7);
@@ -108,25 +108,30 @@ void Application_Jump_Check(void)
                Delay_MS(10);
 
                /* If the TCK pin is not jumpered to ground, start the user application instead */
-               JumpToApplication |= ((PINF & (1 << 4)) != 0);
+               JumpToApplication = ((PINF & (1 << 4)) != 0);
 
                /* Re-enable JTAG debugging */
                JTAG_ENABLE();
+       #else
+               /* 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))
+                         JumpToApplication = true;
+
+                       MCUSR &= ~(1 << EXTRF);
+               }
        #endif
 
-       /* If the reset source was the bootloader and the key is correct, clear it and jump to the application */
-       if ((MCUSR & (1 << WDRF)) && (MagicBootKey == MAGIC_BOOT_KEY))
-         JumpToApplication |= true;
-
        /* Don't run the user application if the reset vector is blank (no app loaded) */
-       if (pgm_read_word_near(0) == 0xFFFF)
-         JumpToApplication = false;
+       bool ApplicationValid = (pgm_read_word_near(0) != 0xFFFF);
 
        /* If a request has been made to jump to the user application, honor it */
-       if (JumpToApplication)
+       if (JumpToApplication && ApplicationValid)
        {
                /* Turn off the watchdog */
-               MCUSR &= ~(1<<WDRF);
+               MCUSR &= ~(1 << WDRF);
                wdt_disable();
 
                /* Clear the boot key and jump to the user application */
index e094847..467972c 100644 (file)
  *
  *  \section Sec_Running Running the Bootloader
  *
- *  This bootloader is designed to be started via the HWB mechanism of the USB AVRs; ground the HWB pin (see device
- *  datasheet) then momentarily ground /RESET to start the bootloader. This assumes the HWBE fuse is set and the BOOTRST
- *  fuse is cleared.
+ *  On the USB AVR8 devices, setting the \c HWBE device fuse will cause the bootloader to run if the \c HWB pin of
+ *  the AVR is grounded when the device is reset.
+ *
+ *  The are two behaviours of this bootloader, depending on the device's fuses:
+ *
+ *  <b>If the device's BOOTRST fuse is set</b>, the bootloader will run any time the system is not reset from
+ *  the external reset pin, unless no valid user application has been loaded. To initiate the bootloader, the
+ *  device's external reset pin should be grounded.
+ *
+ *  <b>If the device's BOOTRST fuse is not set</b>, the bootloader will run only if initiated via a software
+ *  jump, or if the \c HWB pin was low during the last device reset (if the \c HWBE fuse is set).
  *
  *  For board specific exceptions to the above, see below.
  *
index 716a23a..151d16f 100644 (file)
@@ -123,11 +123,11 @@ void Application_Jump_Check(void)
 
        #if (BOARD == BOARD_LEONARDO)
                /* Enable pull-up on the IO13 pin so we can use it to select the mode */
-               PORTC |=  (1 << 7);
+               PORTC |= (1 << 7);
                Delay_MS(10);
 
                /* If IO13 is not jumpered to ground, start the user application instead */
-               JumpToApplication |= ((PINC & (1 << 7)) != 0);
+               JumpToApplication = ((PINC & (1 << 7)) != 0);
 
                /* Disable pull-up after the check has completed */
                PORTC &= ~(1 << 7);
@@ -140,25 +140,30 @@ void Application_Jump_Check(void)
                Delay_MS(10);
 
                /* If the TCK pin is not jumpered to ground, start the user application instead */
-               JumpToApplication |= ((PINF & (1 << 4)) != 0);
+               JumpToApplication = ((PINF & (1 << 4)) != 0);
 
                /* Re-enable JTAG debugging */
                JTAG_ENABLE();
-       #endif
+       #else
+               /* 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))
+                         JumpToApplication = true;
 
-       /* If the reset source was the bootloader and the key is correct, clear it and jump to the application */
-       if ((MCUSR & (1 << WDRF)) && (MagicBootKey == MAGIC_BOOT_KEY))
-         JumpToApplication |= true;
+                       MCUSR &= ~(1 << EXTRF);
+               }
+       #endif
 
        /* Don't run the user application if the reset vector is blank (no app loaded) */
-       if (pgm_read_word_near(0) == 0xFFFF)
-         JumpToApplication = false;
+       bool ApplicationValid = (pgm_read_word_near(0) != 0xFFFF);
 
        /* If a request has been made to jump to the user application, honor it */
-       if (JumpToApplication)
+       if (JumpToApplication && ApplicationValid)
        {
                /* Turn off the watchdog */
-               MCUSR &= ~(1<<WDRF);
+               MCUSR &= ~(1 << WDRF);
                wdt_disable();
 
                /* Clear the boot key and jump to the user application */
index cfa51d4..99dc7d5 100644 (file)
  *
  *  \section Sec_Running Running the Bootloader
  *
- *  This bootloader is designed to be started via the HWB mechanism of the USB AVRs; ground the HWB pin (see device
- *  datasheet) then momentarily ground /RESET to start the bootloader. This assumes the HWBE fuse is set and the BOOTRST
- *  fuse is cleared.
+ *  On the USB AVR8 devices, setting the \c HWBE device fuse will cause the bootloader to run if the \c HWB pin of
+ *  the AVR is grounded when the device is reset.
+ *
+ *  The are two behaviours of this bootloader, depending on the device's fuses:
+ *
+ *  <b>If the device's BOOTRST fuse is set</b>, the bootloader will run any time the system is not reset from
+ *  the external reset pin, unless no valid user application has been loaded. To initiate the bootloader, the
+ *  device's external reset pin should be grounded.
+ *
+ *  <b>If the device's BOOTRST fuse is not set</b>, the bootloader will run only if initiated via a software
+ *  jump, or if the \c HWB pin was low during the last device reset (if the \c HWBE fuse is set).
+ *
+ *  For board specific exceptions to the above, see below.
+ *
+ *  \subsection SSec_XPLAIN Atmel Xplain Board
+ *  Ground the USB AVR JTAG's \c TCK pin to ground when powering on the board to start the bootloader. This assumes the
+ *  \c HWBE fuse is cleared and the \c BOOTRST fuse is set as the HWBE pin is not user accessible on this board.
+ *
+ *  \subsection SSec_Leonardo Arduino Leonardo Board
+ *  Ground \c IO13 when powering the board to start the bootloader. This assumes the \c HWBE fuse is cleared and the
+ *  \c BOOTRST fuse is set as the HWBE pin is not user accessible on this board.
  *
  *  \section Sec_Installation Driver Installation
  *
index 57277eb..647f621 100644 (file)
@@ -14,7 +14,9 @@
   *  - Library Applications:
   *   - The CDC, DFU, Mass Storage and Printer class bootloaders will no longer run the user application if the application reset
   *     vector is blank (thanks to Alex Kazik)
-  *   - The Printer class bootloader is now compatible with the original Atmel XPLAIN and Arduino Leonardo boards.
+  *   - The CDC, DFU and Printer class bootloaders are now compatible with the original Atmel XPLAIN and Arduino Leonardo boards.
+  *   - The CDC, DFU, Mass Storage and Printer class bootloaders are not compatible with devices with the BOOTRST fuse set and will
+  *     exit automatically unless an external reset was the last reset cause (thanks to Alex Kazik)
   *
   *  <b>Fixed:</b>
   *   - None.