]> git.donarmstrong.com Git - qmk_firmware.git/blobdiff - tmk_core/common/avr/bootloader.c
Merge remote-tracking branch 'refs/remotes/qmk/master'
[qmk_firmware.git] / tmk_core / common / avr / bootloader.c
index 7c744e8c79ec8aaed46a25dc37282fcb242a481e..34db8d0b0aa66c18538f978fac66e44f9938ed5c 100644 (file)
@@ -1,6 +1,7 @@
 #include <stdint.h>
 #include <stdbool.h>
 #include <avr/io.h>
+#include <avr/eeprom.h>
 #include <avr/interrupt.h>
 #include <avr/wdt.h>
 #include <util/delay.h>
@@ -38,7 +39,7 @@
  *          |               |                        |               |
  *          =               =                        =               =
  *          |               | 32KB-4KB               |               | 128KB-8KB
- * 0x6000   +---------------+               0x1FC00  +---------------+
+ * 0x7000   +---------------+               0x1E000  +---------------+
  *          |  Bootloader   | 4KB                    |  Bootloader   | 8KB
  * 0x7FFF   +---------------+               0x1FFFF  +---------------+
  *
@@ -64,8 +65,8 @@
 #define BOOTLOADER_START    (FLASH_SIZE - BOOTLOADER_SIZE)
 
 
-/* 
- * Entering the Bootloader via Software 
+/*
+ * Entering the Bootloader via Software
  * http://www.fourwalledcubicle.com/files/LUFA/Doc/120730/html/_page__software_bootloader_start.html
  */
 #define BOOTLOADER_RESET_KEY 0xB007B007
@@ -73,26 +74,57 @@ uint32_t reset_key  __attribute__ ((section (".noinit")));
 
 /* initialize MCU status by watchdog reset */
 void bootloader_jump(void) {
-#ifdef PROTOCOL_LUFA
-    USB_Disable();
-    cli();
-    _delay_ms(2000);
-#endif
+    #ifndef CATERINA_BOOTLOADER
 
-#ifdef PROTOCOL_PJRC
-    cli();
-    UDCON = 1;
-    USBCON = (1<<FRZCLK);
-    UCSR1B = 0;
-    _delay_ms(5);
-#endif
+        #ifdef PROTOCOL_LUFA
+            USB_Disable();
+            cli();
+            _delay_ms(2000);
+        #endif
 
-    // watchdog reset
-    reset_key = BOOTLOADER_RESET_KEY;
-    wdt_enable(WDTO_250MS);
-    for (;;);
+        #ifdef PROTOCOL_PJRC
+            cli();
+            UDCON = 1;
+            USBCON = (1<<FRZCLK);
+            UCSR1B = 0;
+            _delay_ms(5);
+        #endif
+
+        #ifdef BOOTLOADHID_BOOTLOADER
+            // force bootloadHID to stay in bootloader mode, so that it waits
+            // for a new firmware to be flashed
+            eeprom_write_byte((uint8_t *)1, 0x00);
+        #endif
+
+        // watchdog reset
+        reset_key = BOOTLOADER_RESET_KEY;
+        wdt_enable(WDTO_250MS);
+        for (;;);
+
+    #else
+        // this block may be optional
+        // TODO: figure it out
+
+        uint16_t *const bootKeyPtr = (uint16_t *)0x0800;
+
+        // Value used by Caterina bootloader use to determine whether to run the
+        // sketch or the bootloader programmer.
+        uint16_t bootKey = 0x7777;
+
+        *bootKeyPtr = bootKey;
+
+        // setup watchdog timeout
+        wdt_enable(WDTO_60MS);
+
+        while(1) {} // wait for watchdog timer to trigger
+
+    #endif
 }
 
+#ifdef __AVR_ATmega32A__
+// MCUSR is actually called MCUCSR in ATmega32A
+#define MCUSR MCUCSR
+#endif
 
 /* this runs before main() */
 void bootloader_jump_after_watchdog_reset(void) __attribute__ ((used, naked, section (".init3")));
@@ -117,7 +149,7 @@ void bootloader_jump_after_watchdog_reset(void)
 #if 0
 /* Jumping To The Bootloader
  * http://www.pjrc.com/teensy/jump_to_bootloader.html
- * 
+ *
  * This method doen't work when using LUFA. idk why.
  * - needs to initialize more regisers or interrupt setting?
  */