]> git.gir.st - tmk_keyboard.git/blob - common/bootloader.c
Fix watchdog in bootloader jump
[tmk_keyboard.git] / common / 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 <util/delay.h>
7 #include "bootloader.h"
8
9 #ifdef PROTOCOL_LUFA
10 #include <LUFA/Drivers/USB/USB.h>
11 #endif
12
13
14 /* Boot Section Size in *BYTEs*
15 * Teensy halfKay 512
16 * Teensy++ halfKay 1024
17 * Atmel DFU loader 4096
18 * LUFA bootloader 4096
19 */
20 #ifndef BOOT_SIZE
21 #define BOOT_SIZE 512
22 #endif
23 #define FLASH_SIZE (FLASHEND + 1L)
24 #define BOOTLOADER_START (FLASH_SIZE - BOOT_SIZE)
25
26
27 /*
28 * Entering the Bootloader via Software
29 * http://www.fourwalledcubicle.com/files/LUFA/Doc/120730/html/_page__software_bootloader_start.html
30 */
31 #define BOOTLOADER_RESET_KEY 0xB007B007
32 uint32_t reset_key __attribute__ ((section (".noinit")));
33
34 /* initialize MCU status by watchdog reset */
35 void bootloader_jump(void) {
36 #ifdef PROTOCOL_LUFA
37 USB_Disable();
38 cli();
39 _delay_ms(2000);
40 #endif
41
42 #ifdef PROTOCOL_PJRC
43 cli();
44 UDCON = 1;
45 USBCON = (1<<FRZCLK);
46 UCSR1B = 0;
47 _delay_ms(5);
48 #endif
49
50 // watchdog reset
51 reset_key = BOOTLOADER_RESET_KEY;
52 wdt_enable(WDTO_250MS);
53 for (;;);
54 }
55
56
57 /* this runs before main() */
58 void bootloader_jump_after_watchdog_reset(void) __attribute__ ((used, naked, section (".init3")));
59 void bootloader_jump_after_watchdog_reset(void)
60 {
61 if ((MCUSR & (1<<WDRF)) && reset_key == BOOTLOADER_RESET_KEY) {
62 reset_key = 0;
63
64 // My custom USBasploader requires this to come up.
65 MCUSR = 0;
66
67 // Seems like Teensy halfkay loader requires clearing WDRF and disabling watchdog.
68 MCUSR &= ~(1<<WDRF);
69 wdt_disable();
70
71 ((void (*)(void))BOOTLOADER_START)();
72 }
73 }
74
75
76 #if 0
77 /* Jumping To The Bootloader
78 * http://www.pjrc.com/teensy/jump_to_bootloader.html
79 *
80 * This method doen't work when using LUFA. idk why.
81 * - needs to initialize more regisers or interrupt setting?
82 */
83 void bootloader_jump(void) {
84 #ifdef PROTOCOL_LUFA
85 USB_Disable();
86 cli();
87 _delay_ms(2000);
88 #endif
89
90 #ifdef PROTOCOL_PJRC
91 cli();
92 UDCON = 1;
93 USBCON = (1<<FRZCLK);
94 UCSR1B = 0;
95 _delay_ms(5);
96 #endif
97
98 /*
99 * Initialize
100 */
101 #if defined(__AVR_AT90USB162__)
102 EIMSK = 0; PCICR = 0; SPCR = 0; ACSR = 0; EECR = 0;
103 TIMSK0 = 0; TIMSK1 = 0; UCSR1B = 0;
104 DDRB = 0; DDRC = 0; DDRD = 0;
105 PORTB = 0; PORTC = 0; PORTD = 0;
106 #elif defined(__AVR_ATmega32U4__)
107 EIMSK = 0; PCICR = 0; SPCR = 0; ACSR = 0; EECR = 0; ADCSRA = 0;
108 TIMSK0 = 0; TIMSK1 = 0; TIMSK3 = 0; TIMSK4 = 0; UCSR1B = 0; TWCR = 0;
109 DDRB = 0; DDRC = 0; DDRD = 0; DDRE = 0; DDRF = 0; TWCR = 0;
110 PORTB = 0; PORTC = 0; PORTD = 0; PORTE = 0; PORTF = 0;
111 #elif defined(__AVR_AT90USB646__)
112 EIMSK = 0; PCICR = 0; SPCR = 0; ACSR = 0; EECR = 0; ADCSRA = 0;
113 TIMSK0 = 0; TIMSK1 = 0; TIMSK2 = 0; TIMSK3 = 0; UCSR1B = 0; TWCR = 0;
114 DDRA = 0; DDRB = 0; DDRC = 0; DDRD = 0; DDRE = 0; DDRF = 0;
115 PORTA = 0; PORTB = 0; PORTC = 0; PORTD = 0; PORTE = 0; PORTF = 0;
116 #elif defined(__AVR_AT90USB1286__)
117 EIMSK = 0; PCICR = 0; SPCR = 0; ACSR = 0; EECR = 0; ADCSRA = 0;
118 TIMSK0 = 0; TIMSK1 = 0; TIMSK2 = 0; TIMSK3 = 0; UCSR1B = 0; TWCR = 0;
119 DDRA = 0; DDRB = 0; DDRC = 0; DDRD = 0; DDRE = 0; DDRF = 0;
120 PORTA = 0; PORTB = 0; PORTC = 0; PORTD = 0; PORTE = 0; PORTF = 0;
121 #endif
122
123 /*
124 * USBaspLoader
125 */
126 #if defined(__AVR_ATmega168__) || defined(__AVR_ATmega168P__) || defined(__AVR_ATmega328P__)
127 // This makes custom USBasploader come up.
128 MCUSR = 0;
129
130 // initialize ports
131 PORTB = 0; PORTC= 0; PORTD = 0;
132 DDRB = 0; DDRC= 0; DDRD = 0;
133
134 // disable interrupts
135 EIMSK = 0; EECR = 0; SPCR = 0;
136 ACSR = 0; SPMCSR = 0; WDTCSR = 0; PCICR = 0;
137 TIMSK0 = 0; TIMSK1 = 0; TIMSK2 = 0;
138 ADCSRA = 0; TWCR = 0; UCSR0B = 0;
139 #endif
140
141 // start Bootloader
142 ((void (*)(void))BOOTLOADER_START)();
143 }
144 #endif
Imprint / Impressum