Switch StaticAnalysisTest build test to use the new build system CPPCHECK module...
[pub/USBasp.git] / Bootloaders / DFU / BootloaderDFU.c
index 3ce2a62..f5c8d17 100644 (file)
@@ -92,6 +92,34 @@ static uint16_t StartAddr = 0x0000;
  */
 static uint16_t EndAddr = 0x0000;
 
+/** Magic lock for forced application start. If the HWBE fuse is programmed and BOOTRST is unprogrammed, the bootloader
+ *  will start if the /HWB line of the AVR is held low and the system is reset. However, if the /HWB line is still held
+ *  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.
+ */
+uint32_t MagicBootKey ATTR_NO_INIT;
+
+
+/** 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,
+ *  this will force the user application to start via a software jump.
+ */
+void Application_Jump_Check(void)
+{
+       /* 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))
+       {
+               /* Turn off the watchdog */
+               MCUSR &= ~(1<<WDRF);
+               wdt_disable(); 
+
+               /* Clear the boot key and jump to the user application */
+               MagicBootKey = 0;
+
+               // cppcheck-suppress constStatement
+               ((void (*)(void))0x0000)();
+       }
+}
 
 /** Main program entry point. This routine configures the hardware required by the bootloader, then continuously
  *  runs the bootloader processing routine until instructed to soft-exit, or hard-reset via the watchdog to start
@@ -165,6 +193,10 @@ static void ResetHardware(void)
        /* Shut down the USB and other board hardware drivers */
        USB_Disable();
        LEDs_Disable();
+       
+       /* Disable Bootloader active LED toggle timer */
+       TIMSK1 = 0;
+       TCCR1B = 0;
 
        /* Relocate the interrupt vector table back to the application section */
        MCUCR = (1 << IVCE);
@@ -641,7 +673,7 @@ static void ProcessMemReadCommand(void)
        {
                uint32_t CurrFlashAddress = 0;
 
-               while (CurrFlashAddress < BOOT_START_ADDR)
+               while (CurrFlashAddress < (uint32_t)BOOT_START_ADDR)
                {
                        /* Check if the current byte is not blank */
                        #if (FLASHEND > 0xFFFF)
@@ -695,6 +727,9 @@ static void ProcessWriteCommand(void)
                {
                        if (SentCommand.Data[1] == 0x00)                                   // Start via watchdog
                        {
+                               /* Unlock the forced application start mode of the bootloader if it is restarted */
+                               MagicBootKey = MAGIC_BOOT_KEY;
+
                                /* Start the watchdog to reset the AVR once the communications are finalized */
                                wdt_enable(WDTO_250MS);
                        }
@@ -710,7 +745,7 @@ static void ProcessWriteCommand(void)
                uint32_t CurrFlashAddress = 0;
 
                /* Clear the application section of flash */
-               while (CurrFlashAddress < BOOT_START_ADDR)
+               while (CurrFlashAddress < (uint32_t)BOOT_START_ADDR)
                {
                        boot_page_erase(CurrFlashAddress);
                        boot_spm_busy_wait();