]> git.donarmstrong.com Git - tmk_firmware.git/blob - common/bootloader.c
023220414bb6dedf3890e88b608e1fee8a373164
[tmk_firmware.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