Keyboard firmwares for Atmel AVR and Cortex-M
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

bootloader.c 3.9KB

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