aboutsummaryrefslogtreecommitdiff
path: root/tmk_core/common/avr/bootloader.c
diff options
context:
space:
mode:
authorJack Humbert <jack.humb@gmail.com>2017-11-27 23:08:21 -0500
committerGitHub <noreply@github.com>2017-11-27 23:08:21 -0500
commit9fdc27626097ae03b767a09427efc90475d90955 (patch)
treea555c38f1b714af6e2c2c96187552757d08224b9 /tmk_core/common/avr/bootloader.c
parent9113f3387a670373919fe62899b0ab27e9d89eba (diff)
downloadqmk_firmware-9fdc27626097ae03b767a09427efc90475d90955.tar.gz
qmk_firmware-9fdc27626097ae03b767a09427efc90475d90955.zip
Updates bootloader settings, adds file size check (#2029)
* pull fuse settings for bootloader jump * fix 32a chips * make automatic bootloader selection optional * quantify bootloaders * fixs #164, speeds up dfu reset * fix for chips w/o usb * missing an n * fix bootloader sizes, use words for addresses * fix bmini, pearl, and [[ issue, make things quiet * ignore avr errors on arm for now * update settings for the light * document bootloader stuff * add bootloader title
Diffstat (limited to 'tmk_core/common/avr/bootloader.c')
-rw-r--r--tmk_core/common/avr/bootloader.c196
1 files changed, 105 insertions, 91 deletions
diff --git a/tmk_core/common/avr/bootloader.c b/tmk_core/common/avr/bootloader.c
index 34db8d0b0..ee150817c 100644
--- a/tmk_core/common/avr/bootloader.c
+++ b/tmk_core/common/avr/bootloader.c
@@ -6,6 +6,7 @@
6#include <avr/wdt.h> 6#include <avr/wdt.h>
7#include <util/delay.h> 7#include <util/delay.h>
8#include "bootloader.h" 8#include "bootloader.h"
9#include <avr/boot.h>
9 10
10#ifdef PROTOCOL_LUFA 11#ifdef PROTOCOL_LUFA
11#include <LUFA/Drivers/USB/USB.h> 12#include <LUFA/Drivers/USB/USB.h>
@@ -56,14 +57,17 @@
56 * | Bootloader | 512B | Bootloader | 1KB 57 * | Bootloader | 512B | Bootloader | 1KB
57 * 0x7FFF +---------------+ 0x1FFFF +---------------+ 58 * 0x7FFF +---------------+ 0x1FFFF +---------------+
58 */ 59 */
59#ifndef BOOTLOADER_SIZE
60#warning To use bootloader_jump() you need to define BOOTLOADER_SIZE in config.h.
61#define BOOTLOADER_SIZE 4096
62#endif
63 60
64#define FLASH_SIZE (FLASHEND + 1L) 61#define FLASH_SIZE (FLASHEND + 1L)
65#define BOOTLOADER_START (FLASH_SIZE - BOOTLOADER_SIZE) 62
63#if !defined(BOOTLOADER_SIZE)
64 uint16_t bootloader_start;
65#endif
66 66
67#define BOOT_SIZE_256 0b110
68#define BOOT_SIZE_512 0b100
69#define BOOT_SIZE_1024 0b010
70#define BOOT_SIZE_2048 0b000
67 71
68/* 72/*
69 * Entering the Bootloader via Software 73 * Entering the Bootloader via Software
@@ -74,34 +78,62 @@ uint32_t reset_key __attribute__ ((section (".noinit")));
74 78
75/* initialize MCU status by watchdog reset */ 79/* initialize MCU status by watchdog reset */
76void bootloader_jump(void) { 80void bootloader_jump(void) {
77 #ifndef CATERINA_BOOTLOADER
78
79 #ifdef PROTOCOL_LUFA
80 USB_Disable();
81 cli();
82 _delay_ms(2000);
83 #endif
84
85 #ifdef PROTOCOL_PJRC
86 cli();
87 UDCON = 1;
88 USBCON = (1<<FRZCLK);
89 UCSR1B = 0;
90 _delay_ms(5);
91 #endif
92
93 #ifdef BOOTLOADHID_BOOTLOADER
94 // force bootloadHID to stay in bootloader mode, so that it waits
95 // for a new firmware to be flashed
96 eeprom_write_byte((uint8_t *)1, 0x00);
97 #endif
98 81
99 // watchdog reset 82 #if !defined(BOOTLOADER_SIZE)
100 reset_key = BOOTLOADER_RESET_KEY; 83 uint8_t high_fuse = boot_lock_fuse_bits_get(GET_HIGH_FUSE_BITS);
101 wdt_enable(WDTO_250MS); 84
102 for (;;); 85 if (high_fuse & BOOT_SIZE_256) {
86 bootloader_start = (FLASH_SIZE - 512) >> 1;
87 } else if (high_fuse & BOOT_SIZE_512) {
88 bootloader_start = (FLASH_SIZE - 1024) >> 1;
89 } else if (high_fuse & BOOT_SIZE_1024) {
90 bootloader_start = (FLASH_SIZE - 2048) >> 1;
91 } else {
92 bootloader_start = (FLASH_SIZE - 4096) >> 1;
93 }
94 #endif
103 95
104 #else 96 // Something like this might work, but it compiled larger than the block above
97 // bootloader_start = FLASH_SIZE - (256 << (~high_fuse & 0b110 >> 1));
98
99
100 #if defined(BOOTLOADER_HALFKAY)
101 // http://www.pjrc.com/teensy/jump_to_bootloader.html
102 cli();
103 // disable watchdog, if enabled (it's not)
104 // disable all peripherals
105 // a shutdown call might make sense here
106 UDCON = 1;
107 USBCON = (1<<FRZCLK); // disable USB
108 UCSR1B = 0;
109 _delay_ms(5);
110 #if defined(__AVR_AT90USB162__) // Teensy 1.0
111 EIMSK = 0; PCICR = 0; SPCR = 0; ACSR = 0; EECR = 0;
112 TIMSK0 = 0; TIMSK1 = 0; UCSR1B = 0;
113 DDRB = 0; DDRC = 0; DDRD = 0;
114 PORTB = 0; PORTC = 0; PORTD = 0;
115 asm volatile("jmp 0x3E00");
116 #elif defined(__AVR_ATmega32U4__) // Teensy 2.0
117 EIMSK = 0; PCICR = 0; SPCR = 0; ACSR = 0; EECR = 0; ADCSRA = 0;
118 TIMSK0 = 0; TIMSK1 = 0; TIMSK3 = 0; TIMSK4 = 0; UCSR1B = 0; TWCR = 0;
119 DDRB = 0; DDRC = 0; DDRD = 0; DDRE = 0; DDRF = 0; TWCR = 0;
120 PORTB = 0; PORTC = 0; PORTD = 0; PORTE = 0; PORTF = 0;
121 asm volatile("jmp 0x7E00");
122 #elif defined(__AVR_AT90USB646__) // Teensy++ 1.0
123 EIMSK = 0; PCICR = 0; SPCR = 0; ACSR = 0; EECR = 0; ADCSRA = 0;
124 TIMSK0 = 0; TIMSK1 = 0; TIMSK2 = 0; TIMSK3 = 0; UCSR1B = 0; TWCR = 0;
125 DDRA = 0; DDRB = 0; DDRC = 0; DDRD = 0; DDRE = 0; DDRF = 0;
126 PORTA = 0; PORTB = 0; PORTC = 0; PORTD = 0; PORTE = 0; PORTF = 0;
127 asm volatile("jmp 0xFC00");
128 #elif defined(__AVR_AT90USB1286__) // Teensy++ 2.0
129 EIMSK = 0; PCICR = 0; SPCR = 0; ACSR = 0; EECR = 0; ADCSRA = 0;
130 TIMSK0 = 0; TIMSK1 = 0; TIMSK2 = 0; TIMSK3 = 0; UCSR1B = 0; TWCR = 0;
131 DDRA = 0; DDRB = 0; DDRC = 0; DDRD = 0; DDRE = 0; DDRF = 0;
132 PORTA = 0; PORTB = 0; PORTC = 0; PORTD = 0; PORTE = 0; PORTF = 0;
133 asm volatile("jmp 0x1FC00");
134 #endif
135
136 #elif defined(BOOTLOADER_CATERINA)
105 // this block may be optional 137 // this block may be optional
106 // TODO: figure it out 138 // TODO: figure it out
107 139
@@ -118,83 +150,65 @@ void bootloader_jump(void) {
118 150
119 while(1) {} // wait for watchdog timer to trigger 151 while(1) {} // wait for watchdog timer to trigger
120 152
153 #else // Assume remaining boards are DFU, even if the flag isn't set
154
155 #ifndef __AVR_ATmega32A__ // no USB - maybe BOOTLOADER_BOOTLOADHID instead though?
156 UDCON = 1;
157 USBCON = (1<<FRZCLK); // disable USB
158 UCSR1B = 0;
159 _delay_ms(5); // 5 seems to work fine
160 #endif
161
162 #ifdef BOOTLOADER_BOOTLOADHID
163 // force bootloadHID to stay in bootloader mode, so that it waits
164 // for a new firmware to be flashed
165 eeprom_write_byte((uint8_t *)1, 0x00);
166 #endif
167
168 // watchdog reset
169 reset_key = BOOTLOADER_RESET_KEY;
170 wdt_enable(WDTO_250MS);
171 for (;;);
121 #endif 172 #endif
173
122} 174}
123 175
124#ifdef __AVR_ATmega32A__ 176#ifdef __AVR_ATmega32A__
125// MCUSR is actually called MCUCSR in ATmega32A 177 // MCUSR is actually called MCUCSR in ATmega32A
126#define MCUSR MCUCSR 178 #define MCUSR MCUCSR
127#endif 179#endif
128 180
129/* this runs before main() */ 181/* this runs before main() */
130void bootloader_jump_after_watchdog_reset(void) __attribute__ ((used, naked, section (".init3"))); 182void bootloader_jump_after_watchdog_reset(void) __attribute__ ((used, naked, section (".init3")));
131void bootloader_jump_after_watchdog_reset(void) 183void bootloader_jump_after_watchdog_reset(void)
132{ 184{
133 if ((MCUSR & (1<<WDRF)) && reset_key == BOOTLOADER_RESET_KEY) { 185 #ifndef BOOTLOADER_HALFKAY
134 reset_key = 0; 186 if ((MCUSR & (1<<WDRF)) && reset_key == BOOTLOADER_RESET_KEY) {
187 reset_key = 0;
188
189 // My custom USBasploader requires this to come up.
190 MCUSR = 0;
135 191
136 // My custom USBasploader requires this to come up. 192 // Seems like Teensy halfkay loader requires clearing WDRF and disabling watchdog.
137 MCUSR = 0; 193 MCUSR &= ~(1<<WDRF);
194 wdt_disable();
138 195
139 // Seems like Teensy halfkay loader requires clearing WDRF and disabling watchdog.
140 MCUSR &= ~(1<<WDRF);
141 wdt_disable();
142 196
143 // This is compled into 'icall', address should be in word unit, not byte. 197 // This is compled into 'icall', address should be in word unit, not byte.
144 ((void (*)(void))(BOOTLOADER_START/2))(); 198 #ifdef BOOTLOADER_SIZE
145 } 199 ((void (*)(void))( (FLASH_SIZE - BOOTLOADER_SIZE) >> 1))();
200 #else
201 asm("ijmp" :: "z" (bootloader_start));
202 #endif
203 }
204 #endif
146} 205}
147 206
148 207
149#if 0 208#if 0
150/* Jumping To The Bootloader
151 * http://www.pjrc.com/teensy/jump_to_bootloader.html
152 *
153 * This method doen't work when using LUFA. idk why.
154 * - needs to initialize more regisers or interrupt setting?
155 */
156void bootloader_jump(void) {
157#ifdef PROTOCOL_LUFA
158 USB_Disable();
159 cli();
160 _delay_ms(2000);
161#endif
162
163#ifdef PROTOCOL_PJRC
164 cli();
165 UDCON = 1;
166 USBCON = (1<<FRZCLK);
167 UCSR1B = 0;
168 _delay_ms(5);
169#endif
170
171 /*
172 * Initialize
173 */
174#if defined(__AVR_AT90USB162__)
175 EIMSK = 0; PCICR = 0; SPCR = 0; ACSR = 0; EECR = 0;
176 TIMSK0 = 0; TIMSK1 = 0; UCSR1B = 0;
177 DDRB = 0; DDRC = 0; DDRD = 0;
178 PORTB = 0; PORTC = 0; PORTD = 0;
179#elif defined(__AVR_ATmega32U4__)
180 EIMSK = 0; PCICR = 0; SPCR = 0; ACSR = 0; EECR = 0; ADCSRA = 0;
181 TIMSK0 = 0; TIMSK1 = 0; TIMSK3 = 0; TIMSK4 = 0; UCSR1B = 0; TWCR = 0;
182 DDRB = 0; DDRC = 0; DDRD = 0; DDRE = 0; DDRF = 0; TWCR = 0;
183 PORTB = 0; PORTC = 0; PORTD = 0; PORTE = 0; PORTF = 0;
184#elif defined(__AVR_AT90USB646__)
185 EIMSK = 0; PCICR = 0; SPCR = 0; ACSR = 0; EECR = 0; ADCSRA = 0;
186 TIMSK0 = 0; TIMSK1 = 0; TIMSK2 = 0; TIMSK3 = 0; UCSR1B = 0; TWCR = 0;
187 DDRA = 0; DDRB = 0; DDRC = 0; DDRD = 0; DDRE = 0; DDRF = 0;
188 PORTA = 0; PORTB = 0; PORTC = 0; PORTD = 0; PORTE = 0; PORTF = 0;
189#elif defined(__AVR_AT90USB1286__)
190 EIMSK = 0; PCICR = 0; SPCR = 0; ACSR = 0; EECR = 0; ADCSRA = 0;
191 TIMSK0 = 0; TIMSK1 = 0; TIMSK2 = 0; TIMSK3 = 0; UCSR1B = 0; TWCR = 0;
192 DDRA = 0; DDRB = 0; DDRC = 0; DDRD = 0; DDRE = 0; DDRF = 0;
193 PORTA = 0; PORTB = 0; PORTC = 0; PORTD = 0; PORTE = 0; PORTF = 0;
194#endif
195
196 /* 209 /*
197 * USBaspLoader 210 * USBaspLoader - I'm not sure if this is used at all in any projects
211 * would love to support it if it is -Jack
198 */ 212 */
199#if defined(__AVR_ATmega168__) || defined(__AVR_ATmega168P__) || defined(__AVR_ATmega328P__) 213#if defined(__AVR_ATmega168__) || defined(__AVR_ATmega168P__) || defined(__AVR_ATmega328P__)
200 // This makes custom USBasploader come up. 214 // This makes custom USBasploader come up.