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.

177 lines
4.3KB

  1. // Copyright 2013 Olivier Gillet.
  2. //
  3. // This program is free software: you can redistribute it and/or modify
  4. // it under the terms of the GNU General Public License as published by
  5. // the Free Software Foundation, either version 3 of the License, or
  6. // (at your option) any later version.
  7. // This program is distributed in the hope that it will be useful,
  8. // but WITHOUT ANY WARRANTY; without even the implied warranty of
  9. // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  10. // GNU General Public License for more details.
  11. // You should have received a copy of the GNU General Public License
  12. // along with this program. If not, see <http://www.gnu.org/licenses/>.
  13. //
  14. // -----------------------------------------------------------------------------
  15. //
  16. // Simple FSK bootloader
  17. #include <avr/boot.h>
  18. #include <avr/pgmspace.h>
  19. #include <avr/delay.h>
  20. #include "avrlib/gpio.h"
  21. #include "avrlib/serial.h"
  22. #include "avrlib/watchdog_timer.h"
  23. #include "avr_audio_bootloader/fsk/decoder.h"
  24. using namespace avrlib;
  25. using namespace avr_audio_bootloader;
  26. Gpio<PortD, 1> led_1_a;
  27. Gpio<PortD, 2> led_1_k;
  28. Gpio<PortB, 1> led_2_a;
  29. Gpio<PortB, 0> led_2_k;
  30. Gpio<PortD, 4> in_1;
  31. Gpio<PortC, 3> switch_1;
  32. Decoder decoder;
  33. uint16_t page = 0;
  34. uint8_t rx_buffer[SPM_PAGESIZE + 4];
  35. int main(void) __attribute__ ((naked)) __attribute__ ((section (".init9")));
  36. inline void Init() {
  37. cli();
  38. switch_1.set_mode(DIGITAL_INPUT);
  39. switch_1.High();
  40. led_1_a.set_mode(DIGITAL_OUTPUT);
  41. led_1_k.set_mode(DIGITAL_OUTPUT);
  42. led_2_a.set_mode(DIGITAL_OUTPUT);
  43. led_2_k.set_mode(DIGITAL_OUTPUT);
  44. in_1.set_mode(DIGITAL_INPUT);
  45. in_1.High();
  46. }
  47. void WriteBufferToFlash() {
  48. uint16_t i;
  49. const uint8_t* p = rx_buffer;
  50. eeprom_busy_wait();
  51. boot_page_erase(page);
  52. boot_spm_busy_wait();
  53. for (i = 0; i < SPM_PAGESIZE; i += 2) {
  54. uint16_t w = *p++;
  55. w |= (*p++) << 8;
  56. boot_page_fill(page + i, w);
  57. }
  58. boot_page_write(page);
  59. boot_spm_busy_wait();
  60. boot_rww_enable();
  61. }
  62. void FlashLeds(bool error) {
  63. for (uint8_t i = 0; i < 8; ++i) {
  64. _delay_ms(20);
  65. if (error) {
  66. led_1_a.High();
  67. led_1_k.Low();
  68. } else {
  69. led_1_a.Low();
  70. led_1_k.High();
  71. }
  72. _delay_ms(20);
  73. led_1_a.Low();
  74. led_1_k.Low();
  75. }
  76. }
  77. uint32_t crc32 (uint32_t crc, uint8_t* buffer, uint8_t length) {
  78. crc = crc ^ ~0UL;
  79. for (uint8_t i = 0; i < length; ++i) {
  80. crc = crc ^ *buffer++;
  81. for (uint8_t j = 0; j < 8; j++) {
  82. if (crc & 1) {
  83. crc = (crc >> 1) ^ 0xEDB88320;
  84. } else {
  85. crc = crc >> 1;
  86. }
  87. }
  88. }
  89. crc = crc ^ ~0UL;
  90. return crc;
  91. }
  92. inline void LoaderLoop() {
  93. uint8_t page_byte = 0;
  94. decoder.Init();
  95. decoder.Sync();
  96. decoder.set_packet_destination(rx_buffer);
  97. page = 0;
  98. TCCR2A = 0;
  99. TCCR2B = 2;
  100. while (1) {
  101. // Sample the clock input at 15625 Hz and feed to the FSK decoder.
  102. if (TCNT2 >= (8000000 / 8 / 15625 - 1)) {
  103. TCNT2 = 0;
  104. led_2_a.set_value(page_byte & 1);
  105. led_2_k.set_value(!(page_byte & 1));
  106. switch (decoder.PushSample(in_1.value())) {
  107. case DECODER_STATE_ERROR_SYNC:
  108. FlashLeds(true);
  109. decoder.Sync();
  110. break;
  111. case DECODER_STATE_END_OF_TRANSMISSION:
  112. return;
  113. break;
  114. case DECODER_STATE_PACKET_RECEIVED:
  115. {
  116. #ifdef DO_NOT_CHECK_CRC
  117. uint32_t crc = 0;
  118. uint32_t expected_crc = 0;
  119. #else
  120. uint32_t crc = crc32(0, rx_buffer, SPM_PAGESIZE);
  121. uint32_t expected_crc = \
  122. (static_cast<uint32_t>(rx_buffer[SPM_PAGESIZE + 0]) << 24) | \
  123. (static_cast<uint32_t>(rx_buffer[SPM_PAGESIZE + 1]) << 16) | \
  124. (static_cast<uint32_t>(rx_buffer[SPM_PAGESIZE + 2]) << 8) | \
  125. (static_cast<uint32_t>(rx_buffer[SPM_PAGESIZE + 3]) << 0);
  126. #endif // DO_NOT_CHECK_CRC
  127. if (crc == expected_crc) {
  128. WriteBufferToFlash();
  129. page += SPM_PAGESIZE;
  130. ++page_byte;
  131. } else {
  132. FlashLeds(true);
  133. }
  134. }
  135. decoder.Sync();
  136. break;
  137. default:
  138. break;
  139. }
  140. }
  141. }
  142. }
  143. int main(void) {
  144. ResetWatchdog();
  145. Init();
  146. if (!switch_1.value()) {
  147. FlashLeds(false);
  148. LoaderLoop();
  149. FlashLeds(false);
  150. }
  151. void (*main_entry_point)(void) = 0x0000;
  152. main_entry_point();
  153. }