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.8KB

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