]> git.friedersdorff.com Git - max/tmk_keyboard.git/blob - tmk_core/common/avr/bootloader.c
xt_usb: Fix XT soft reset
[max/tmk_keyboard.git] / tmk_core / common / avr / bootloader.c
1 #include <stdint.h>
2 #include <stdbool.h>
3 #include <avr/io.h>
4 #include <avr/interrupt.h>
5 #include <avr/wdt.h>
6 #include <avr/boot.h>
7 #include <util/delay.h>
8 #include "bootloader.h"
9
10 #ifdef PROTOCOL_LUFA
11 #include <LUFA/Drivers/USB/USB.h>
12 #endif
13
14
15 /* Bootloader Size in *bytes*
16  *
17  * AVR Boot section size are defined by setting BOOTSZ fuse in fact. Consult with your MCU datasheet.
18  * Note that 'Word'(2 bytes) size and address are used in datasheet while TMK uses 'Byte'.
19  *
20  * Size of Bootloaders in bytes:
21  *   Atmel DFU loader(ATmega32U2)   4096
22  *   Atmel DFU loader(ATmega32U4)   4096
23  *   Atmel DFU loader(AT90USB128)   8192
24  *   LUFA bootloader(ATmega32U4)    4096
25  *   Arduino Caterina(ATmega32U4)   4096
26  *   USBaspLoader(ATmega***)        2048
27  *   Teensy   halfKay(ATmega32U4)   512
28  *   Teensy++ halfKay(AT90USB128)   1024
29  *
30  *
31  * AVR Boot section is located at the end of Flash memory.
32  *
33  * byte     ATMega32u4 with 4096-byte Boot section
34  * 0x0000   +---------------+
35  *          |               |
36  *          |               |
37  *          |  Application  | 28KB
38  *          |               |
39  *          =               =
40  *          |               |
41  * 0x7000   +---------------+ <---- BOOTLOADER_START
42  *          |  Bootloader   | 4KB   BOOTLOADER_SIZE
43  * 0x7FFF   +---------------+ <---- FLASHEND
44  */
45
46 /* bootloader start address in byte */
47 #define BOOTLOADER_START      (FLASHEND - bootloader_size() + 1)
48
49 /* boot section size in byte */
50 static inline uint16_t bootloader_size(void)
51 {
52 #if defined(BOOTLOADER_SIZE)
53     return BOOTLOADER_SIZE;
54 #else
55     #if defined(__AVR_ATmega32U4__) || defined(__AVR_ATmega32U2__) || \
56             defined(__AVR_ATmega16U4__) || defined(__AVR_ATmega16U2__) || \
57             defined(__AVR_ATmega328__) || defined(__AVR_ATmega328P__)
58         uint8_t hfuse = boot_lock_fuse_bits_get(GET_HIGH_FUSE_BITS);
59         switch ((hfuse >> 1) & 3) {
60             case 0: return 4096;
61             case 1: return 2048;
62             case 2: return 1024;
63             case 3: return 512;
64         }
65         return 4096;
66     #elif defined(__AVR_AT90USB646__) || defined(__AVR_AT90USB647__) || \
67             defined(__AVR_AT90USB1286__) || defined(__AVR_AT90USB1287__)
68         uint8_t hfuse = boot_lock_fuse_bits_get(GET_HIGH_FUSE_BITS);
69         switch ((hfuse >> 1) & 3) {
70             case 0: return 8192;
71             case 1: return 4096;
72             case 2: return 2048;
73             case 3: return 1024;
74         }
75         return 8192;
76     #else
77         #error Set Boot section size to BOOTLOADER_SIZE in config.h
78     #endif
79 #endif
80 }
81
82
83 /*
84  * Entering the Bootloader via Software
85  * http://www.fourwalledcubicle.com/files/LUFA/Doc/120730/html/_page__software_bootloader_start.html
86  */
87 #define BOOTLOADER_RESET_KEY 0xB007B007
88 uint32_t reset_key  __attribute__ ((section (".noinit")));
89
90 /* initialize MCU status by watchdog reset */
91 void bootloader_jump(void) {
92 #ifdef PROTOCOL_LUFA
93     USB_Disable();
94     cli();
95 #endif
96
97 #ifdef PROTOCOL_PJRC
98     cli();
99     UDCON = 1;
100     USBCON = (1<<FRZCLK);
101     UCSR1B = 0;
102     _delay_ms(5);
103 #endif
104
105 #ifndef NO_BOOTLOADER_CATERINA_BOOTKEY
106     // Set bootkey for Arduino Leonardo and Pro Micro bootloader
107     // Watchdog reset with bootkey causes the bootloader to enter program mode instead of starting application.
108     // https://github.com/arduino/ArduinoCore-avr/blob/master/bootloaders/caterina/Caterina.c#L68-L69
109     // https://github.com/sparkfun/SF32u4_boards/blob/master/sparkfun/avr/bootloaders/caterina/Caterina.c#L88-L89
110     *(volatile uint16_t *)0x0800 = 0x7777;
111 #endif
112
113     // watchdog reset
114     reset_key = BOOTLOADER_RESET_KEY;
115     wdt_enable(WDTO_250MS);
116     for (;;);
117 }
118
119
120 /* this runs before main() */
121 void bootloader_jump_after_watchdog_reset(void) __attribute__ ((used, naked, section (".init3")));
122 void bootloader_jump_after_watchdog_reset(void)
123 {
124     if ((MCUSR & (1<<WDRF)) && reset_key == BOOTLOADER_RESET_KEY) {
125         reset_key = 0;
126
127         // some of bootloaders may need to preseve?
128         MCUSR = 0;
129
130         // disable watchdog timer
131         wdt_disable();
132
133 #ifndef NO_BOOTLOADER_CATERINA_BOOTKEY
134         // Clear bootkey of Caterina bootloader for other bootloaders
135         // Leonardo and Pro Micro with Arduino default fuse setting don't reach here
136         // because bootloader section are executed before application everytime.
137         *(volatile uint16_t *)0x0800 = 0;
138 #endif
139
140         // This is compled into 'icall', address should be in word unit, not byte.
141         ((void (*)(void))( (uint16_t)(BOOTLOADER_START / 2) ))();
142     }
143 }