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 4.0KB

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