Advertisement
Guest User

Arduino Optiboot source used in Arduino.SE question #1046

a guest
Apr 3rd, 2014
319
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
C 22.48 KB | None | 0 0
  1. /**********************************************************/
  2. /* Optiboot bootloader for Arduino                        */
  3. /*                                                        */
  4. /* http://optiboot.googlecode.com                         */
  5. /*                                                        */
  6. /* Arduino-maintained version : See README.TXT            */
  7. /* http://code.google.com/p/arduino/                      */
  8. /*                                                        */
  9. /* Heavily optimised bootloader that is faster and        */
  10. /* smaller than the Arduino standard bootloader           */
  11. /*                                                        */
  12. /* Enhancements:                                          */
  13. /*   Fits in 512 bytes, saving 1.5K of code space         */
  14. /*   Background page erasing speeds up programming        */
  15. /*   Higher baud rate speeds up programming               */
  16. /*   Written almost entirely in C                         */
  17. /*   Customisable timeout with accurate timeconstant      */
  18. /*   Optional virtual UART. No hardware UART required.    */
  19. /*   Optional virtual boot partition for devices without. */
  20. /*                                                        */
  21. /* What you lose:                                         */
  22. /*   Implements a skeleton STK500 protocol which is       */
  23. /*     missing several features including EEPROM          */
  24. /*     programming and non-page-aligned writes            */
  25. /*   High baud rate breaks compatibility with standard    */
  26. /*     Arduino flash settings                             */
  27. /*                                                        */
  28. /* Fully supported:                                       */
  29. /*   ATmega168 based devices  (Diecimila etc)             */
  30. /*   ATmega328P based devices (Duemilanove etc)           */
  31. /*                                                        */
  32. /* Alpha test                                             */
  33. /*   ATmega1280 based devices (Arduino Mega)              */
  34. /*                                                        */
  35. /* Work in progress:                                      */
  36. /*   ATmega644P based devices (Sanguino)                  */
  37. /*   ATtiny84 based devices (Luminet)                     */
  38. /*                                                        */
  39. /* Does not support:                                      */
  40. /*   USB based devices (eg. Teensy)                       */
  41. /*                                                        */
  42. /* Assumptions:                                           */
  43. /*   The code makes several assumptions that reduce the   */
  44. /*   code size. They are all true after a hardware reset, */
  45. /*   but may not be true if the bootloader is called by   */
  46. /*   other means or on other hardware.                    */
  47. /*     No interrupts can occur                            */
  48. /*     UART and Timer 1 are set to their reset state      */
  49. /*     SP points to RAMEND                                */
  50. /*                                                        */
  51. /* Code builds on code, libraries and optimisations from: */
  52. /*   stk500boot.c          by Jason P. Kyle               */
  53. /*   Arduino bootloader    http://arduino.cc              */
  54. /*   Spiff's 1K bootloader http://spiffie.org/know/arduino_1k_bootloader/bootloader.shtml */
  55. /*   avr-libc project      http://nongnu.org/avr-libc     */
  56. /*   Adaboot               http://www.ladyada.net/library/arduino/bootloader.html */
  57. /*   AVR305                Atmel Application Note         */
  58. /*                                                        */
  59. /* This program is free software; you can redistribute it */
  60. /* and/or modify it under the terms of the GNU General    */
  61. /* Public License as published by the Free Software       */
  62. /* Foundation; either version 2 of the License, or        */
  63. /* (at your option) any later version.                    */
  64. /*                                                        */
  65. /* This program is distributed in the hope that it will   */
  66. /* be useful, but WITHOUT ANY WARRANTY; without even the  */
  67. /* implied warranty of MERCHANTABILITY or FITNESS FOR A   */
  68. /* PARTICULAR PURPOSE.  See the GNU General Public        */
  69. /* License for more details.                              */
  70. /*                                                        */
  71. /* You should have received a copy of the GNU General     */
  72. /* Public License along with this program; if not, write  */
  73. /* to the Free Software Foundation, Inc.,                 */
  74. /* 59 Temple Place, Suite 330, Boston, MA  02111-1307 USA */
  75. /*                                                        */
  76. /* Licence can be viewed at                               */
  77. /* http://www.fsf.org/licenses/gpl.txt                    */
  78. /*                                                        */
  79. /**********************************************************/
  80.  
  81.  
  82. /**********************************************************/
  83. /*                                                        */
  84. /* Optional defines:                                      */
  85. /*                                                        */
  86. /**********************************************************/
  87. /*                                                        */
  88. /* BIG_BOOT:                                              */
  89. /* Build a 1k bootloader, not 512 bytes. This turns on    */
  90. /* extra functionality.                                   */
  91. /*                                                        */
  92. /* BAUD_RATE:                                             */
  93. /* Set bootloader baud rate.                              */
  94. /*                                                        */
  95. /* LUDICROUS_SPEED:                                       */
  96. /* 230400 baud :-)                                        */
  97. /*                                                        */
  98. /* SOFT_UART:                                             */
  99. /* Use AVR305 soft-UART instead of hardware UART.         */
  100. /*                                                        */
  101. /* LED_START_FLASHES:                                     */
  102. /* Number of LED flashes on bootup.                       */
  103. /*                                                        */
  104. /* LED_DATA_FLASH:                                        */
  105. /* Flash LED when transferring data. For boards without   */
  106. /* TX or RX LEDs, or for people who like blinky lights.   */
  107. /*                                                        */
  108. /* SUPPORT_EEPROM:                                        */
  109. /* Support reading and writing from EEPROM. This is not   */
  110. /* used by Arduino, so off by default.                    */
  111. /*                                                        */
  112. /* TIMEOUT_MS:                                            */
  113. /* Bootloader timeout period, in milliseconds.            */
  114. /* 500,1000,2000,4000,8000 supported.                     */
  115. /*                                                        */
  116. /**********************************************************/
  117. /**********************************************************/
  118. /* Version Numbers!                                       */
  119. /*                                                        */
  120. /* Arduino Optiboot now includes this Version number in   */
  121. /* the source and object code.                            */
  122. /*                                                        */
  123. /* Version 3 was released as zip from the optiboot        */
  124. /*  repository and was distributed with Arduino 0022.     */
  125. /* Version 4 starts with the arduino repository commit    */
  126. /*  that brought the arduino repository up-to-date with   */
  127. /* the optiboot source tree changes since v3.             */
  128. /*                                                        */
  129. /**********************************************************/
  130.  
  131. /**********************************************************/
  132. /* Edit History:                      */
  133. /*                            */
  134. /* 4.4 WestfW: add initialization of address to keep      */
  135. /*             the compiler happy.  Change SC'ed targets. */
  136. /*             Return the SW version via READ PARAM       */
  137. /* 4.3 WestfW: catch framing errors in getch(), so that   */
  138. /*             AVRISP works without HW kludges.           */
  139. /*  http://code.google.com/p/arduino/issues/detail?id=368n*/
  140. /* 4.2 WestfW: reduce code size, fix timeouts, change     */
  141. /*             verifySpace to use WDT instead of appstart */
  142. /* 4.1 WestfW: put version number in binary.          */
  143. /**********************************************************/
  144.  
  145. #define OPTIBOOT_MAJVER 4
  146. #define OPTIBOOT_MINVER 4
  147.  
  148. #define MAKESTR(a) #a
  149. #define MAKEVER(a, b) MAKESTR(a*256+b)
  150.  
  151. asm("  .section .version\n"
  152.     "optiboot_version:  .word " MAKEVER(OPTIBOOT_MAJVER, OPTIBOOT_MINVER) "\n"
  153.     "  .section .text\n");
  154. #include <inttypes.h>
  155. #include <avr/io.h>
  156. #include <avr/pgmspace.h>
  157.  
  158. // <avr/boot.h> uses sts instructions, but this version uses out instructions
  159. // This saves cycles and program memory.
  160. #include "boot.h"
  161.  
  162.  
  163. // We don't use <avr/wdt.h> as those routines have interrupt overhead we don't need.
  164.  
  165. #include "pin_defs.h"
  166. #include "stk500.h"
  167.  
  168. #ifndef LED_START_FLASHES
  169. #define LED_START_FLASHES 0
  170. #endif
  171.  
  172. #ifdef LUDICROUS_SPEED
  173. #define BAUD_RATE 230400L
  174. #endif
  175.  
  176. /* set the UART baud rate defaults */
  177. #ifndef BAUD_RATE
  178. #if F_CPU >= 8000000L
  179. #define BAUD_RATE   115200L // Highest rate Avrdude win32 will support
  180. #elsif F_CPU >= 1000000L
  181. #define BAUD_RATE   9600L   // 19200 also supported, but with significant error
  182. #elsif F_CPU >= 128000L
  183. #define BAUD_RATE   4800L   // Good for 128kHz internal RC
  184. #else
  185. #define BAUD_RATE 1200L     // Good even at 32768Hz
  186. #endif
  187. #endif
  188.  
  189. /* Switch in soft UART for hard baud rates */
  190. #if (F_CPU/BAUD_RATE) > 280 // > 57600 for 16MHz
  191. #ifndef SOFT_UART
  192. #define SOFT_UART
  193. #endif
  194. #endif
  195.  
  196. /* Watchdog settings */
  197. #define WATCHDOG_OFF    (0)
  198. #define WATCHDOG_16MS   (_BV(WDE))
  199. #define WATCHDOG_32MS   (_BV(WDP0) | _BV(WDE))
  200. #define WATCHDOG_64MS   (_BV(WDP1) | _BV(WDE))
  201. #define WATCHDOG_125MS  (_BV(WDP1) | _BV(WDP0) | _BV(WDE))
  202. #define WATCHDOG_250MS  (_BV(WDP2) | _BV(WDE))
  203. #define WATCHDOG_500MS  (_BV(WDP2) | _BV(WDP0) | _BV(WDE))
  204. #define WATCHDOG_1S     (_BV(WDP2) | _BV(WDP1) | _BV(WDE))
  205. #define WATCHDOG_2S     (_BV(WDP2) | _BV(WDP1) | _BV(WDP0) | _BV(WDE))
  206. #ifndef __AVR_ATmega8__
  207. #define WATCHDOG_4S     (_BV(WDP3) | _BV(WDE))
  208. #define WATCHDOG_8S     (_BV(WDP3) | _BV(WDP0) | _BV(WDE))
  209. #endif
  210.  
  211. /* Function Prototypes */
  212. /* The main function is in init9, which removes the interrupt vector table */
  213. /* we don't need. It is also 'naked', which means the compiler does not    */
  214. /* generate any entry or exit code itself. */
  215. int main(void) __attribute__ ((naked)) __attribute__ ((section (".init9")));
  216. void putch(char);
  217. uint8_t getch(void);
  218. static inline void getNch(uint8_t); /* "static inline" is a compiler hint to reduce code size */
  219. void verifySpace();
  220. static inline void flash_led(uint8_t);
  221. uint8_t getLen();
  222. static inline void watchdogReset();
  223. void watchdogConfig(uint8_t x);
  224. #ifdef SOFT_UART
  225. void uartDelay() __attribute__ ((naked));
  226. #endif
  227. void appStart() __attribute__ ((naked));
  228.  
  229. #if defined(__AVR_ATmega168__)
  230. #define RAMSTART (0x100)
  231. #define NRWWSTART (0x3800)
  232. #elif defined(__AVR_ATmega328P__)
  233. #define RAMSTART (0x100)
  234. #define NRWWSTART (0x7000)
  235. #elif defined (__AVR_ATmega644P__)
  236. #define RAMSTART (0x100)
  237. #define NRWWSTART (0xE000)
  238. #elif defined(__AVR_ATtiny84__)
  239. #define RAMSTART (0x100)
  240. #define NRWWSTART (0x0000)
  241. #elif defined(__AVR_ATmega1280__)
  242. #define RAMSTART (0x200)
  243. #define NRWWSTART (0xE000)
  244. #elif defined(__AVR_ATmega8__) || defined(__AVR_ATmega88__)
  245. #define RAMSTART (0x100)
  246. #define NRWWSTART (0x1800)
  247. #endif
  248.  
  249. /* C zero initialises all global variables. However, that requires */
  250. /* These definitions are NOT zero initialised, but that doesn't matter */
  251. /* This allows us to drop the zero init code, saving us memory */
  252. #define buff    ((uint8_t*)(RAMSTART))
  253. #ifdef VIRTUAL_BOOT_PARTITION
  254. #define rstVect (*(uint16_t*)(RAMSTART+SPM_PAGESIZE*2+4))
  255. #define wdtVect (*(uint16_t*)(RAMSTART+SPM_PAGESIZE*2+6))
  256. #endif
  257.  
  258. /* main program starts here */
  259. int main(void) {
  260.   uint8_t ch;
  261.  
  262.   /*
  263.    * Making these local and in registers prevents the need for initializing
  264.    * them, and also saves space because code no longer stores to memory.
  265.    * (initializing address keeps the compiler happy, but isn't really
  266.    *  necessary, and uses 4 bytes of flash.)
  267.    */
  268.   register uint16_t address = 0;
  269.   register uint8_t  length;
  270.  
  271.   // After the zero init loop, this is the first code to run.
  272.   //
  273.   // This code makes the following assumptions:
  274.   //  No interrupts will execute
  275.   //  SP points to RAMEND
  276.   //  r1 contains zero
  277.   //
  278.   // If not, uncomment the following instructions:
  279.   // cli();
  280.   asm volatile ("clr __zero_reg__");
  281. #ifdef __AVR_ATmega8__
  282.   SP=RAMEND;  // This is done by hardware reset
  283. #endif
  284.  
  285.   // Adaboot no-wait mod
  286.   ch = MCUSR;
  287.   MCUSR = 0;
  288.   if (!(ch & _BV(EXTRF))) appStart();
  289.  
  290. #if LED_START_FLASHES > 0
  291.   // Set up Timer 1 for timeout counter
  292.   TCCR1B = _BV(CS12) | _BV(CS10); // div 1024
  293. #endif
  294. #ifndef SOFT_UART
  295. #ifdef __AVR_ATmega8__
  296.   UCSRA = _BV(U2X); //Double speed mode USART
  297.   UCSRB = _BV(RXEN) | _BV(TXEN);  // enable Rx & Tx
  298.   UCSRC = _BV(URSEL) | _BV(UCSZ1) | _BV(UCSZ0);  // config USART; 8N1
  299.   UBRRL = (uint8_t)( (F_CPU + BAUD_RATE * 4L) / (BAUD_RATE * 8L) - 1 );
  300. #else
  301.   UCSR0A = _BV(U2X0); //Double speed mode USART0
  302.   UCSR0B = _BV(RXEN0) | _BV(TXEN0);
  303.   UCSR0C = _BV(UCSZ00) | _BV(UCSZ01);
  304.   UBRR0L = (uint8_t)( (F_CPU + BAUD_RATE * 4L) / (BAUD_RATE * 8L) - 1 );
  305. #endif
  306. #endif
  307.  
  308.   // Set up watchdog to trigger after 500ms
  309.   watchdogConfig(WATCHDOG_1S);
  310.  
  311.   /* Set LED pin as output */
  312.   LED_DDR |= _BV(LED);
  313.  
  314. #ifdef SOFT_UART
  315.   /* Set TX pin as output */
  316.   UART_DDR |= _BV(UART_TX_BIT);
  317. #endif
  318.  
  319. #if LED_START_FLASHES > 0
  320.   /* Flash onboard LED to signal entering of bootloader */
  321.   flash_led(LED_START_FLASHES * 2);
  322. #endif
  323.  
  324.   /* Forever loop */
  325.   for (;;) {
  326.     /* get character from UART */
  327.     ch = getch();
  328.  
  329.     if(ch == STK_GET_PARAMETER) {
  330.       unsigned char which = getch();
  331.       verifySpace();
  332.       if (which == 0x82) {
  333.     /*
  334.      * Send optiboot version as "minor SW version"
  335.      */
  336.     putch(OPTIBOOT_MINVER);
  337.       } else if (which == 0x81) {
  338.       putch(OPTIBOOT_MAJVER);
  339.       } else {
  340.     /*
  341.      * GET PARAMETER returns a generic 0x03 reply for
  342.          * other parameters - enough to keep Avrdude happy
  343.      */
  344.     putch(0x03);
  345.       }
  346.     }
  347.     else if(ch == STK_SET_DEVICE) {
  348.       // SET DEVICE is ignored
  349.       getNch(20);
  350.     }
  351.     else if(ch == STK_SET_DEVICE_EXT) {
  352.       // SET DEVICE EXT is ignored
  353.       getNch(5);
  354.     }
  355.     else if(ch == STK_LOAD_ADDRESS) {
  356.       // LOAD ADDRESS
  357.       uint16_t newAddress;
  358.       newAddress = getch();
  359.       newAddress = (newAddress & 0xff) | (getch() << 8);
  360. #ifdef RAMPZ
  361.       // Transfer top bit to RAMPZ
  362.       RAMPZ = (newAddress & 0x8000) ? 1 : 0;
  363. #endif
  364.       newAddress += newAddress; // Convert from word address to byte address
  365.       address = newAddress;
  366.       verifySpace();
  367.     }
  368.     else if(ch == STK_UNIVERSAL) {
  369.       // UNIVERSAL command is ignored
  370.       getNch(4);
  371.       putch(0x00);
  372.     }
  373.     /* Write memory, length is big endian and is in bytes */
  374.     else if(ch == STK_PROG_PAGE) {
  375.       // PROGRAM PAGE - we support flash programming only, not EEPROM
  376.       uint8_t *bufPtr;
  377.       uint16_t addrPtr;
  378.  
  379.       getch();          /* getlen() */
  380.       length = getch();
  381.       getch();
  382.  
  383.       // If we are in RWW section, immediately start page erase
  384.       if (address < NRWWSTART) __boot_page_erase_short((uint16_t)(void*)address);
  385.  
  386.       // While that is going on, read in page contents
  387.       bufPtr = buff;
  388.       do *bufPtr++ = getch();
  389.       while (--length);
  390.  
  391.       // If we are in NRWW section, page erase has to be delayed until now.
  392.       // Todo: Take RAMPZ into account
  393.       if (address >= NRWWSTART) __boot_page_erase_short((uint16_t)(void*)address);
  394.  
  395.       // Read command terminator, start reply
  396.       verifySpace();
  397.  
  398.       // If only a partial page is to be programmed, the erase might not be complete.
  399.       // So check that here
  400.       boot_spm_busy_wait();
  401.  
  402. #ifdef VIRTUAL_BOOT_PARTITION
  403.       if ((uint16_t)(void*)address == 0) {
  404.         // This is the reset vector page. We need to live-patch the code so the
  405.         // bootloader runs.
  406.         //
  407.         // Move RESET vector to WDT vector
  408.         uint16_t vect = buff[0] | (buff[1]<<8);
  409.         rstVect = vect;
  410.         wdtVect = buff[8] | (buff[9]<<8);
  411.         vect -= 4; // Instruction is a relative jump (rjmp), so recalculate.
  412.         buff[8] = vect & 0xff;
  413.         buff[9] = vect >> 8;
  414.  
  415.         // Add jump to bootloader at RESET vector
  416.         buff[0] = 0x7f;
  417.         buff[1] = 0xce; // rjmp 0x1d00 instruction
  418.       }
  419. #endif
  420.  
  421.       // Copy buffer into programming buffer
  422.       bufPtr = buff;
  423.       addrPtr = (uint16_t)(void*)address;
  424.       ch = SPM_PAGESIZE / 2;
  425.       do {
  426.         uint16_t a;
  427.         a = *bufPtr++;
  428.         a |= (*bufPtr++) << 8;
  429.         __boot_page_fill_short((uint16_t)(void*)addrPtr,a);
  430.         addrPtr += 2;
  431.       } while (--ch);
  432.  
  433.       // Write from programming buffer
  434.       __boot_page_write_short((uint16_t)(void*)address);
  435.       boot_spm_busy_wait();
  436.  
  437. #if defined(RWWSRE)
  438.       // Reenable read access to flash
  439.       boot_rww_enable();
  440. #endif
  441.  
  442.     }
  443.     /* Read memory block mode, length is big endian.  */
  444.     else if(ch == STK_READ_PAGE) {
  445.       // READ PAGE - we only read flash
  446.       getch();          /* getlen() */
  447.       length = getch();
  448.       getch();
  449.  
  450.       verifySpace();
  451. #ifdef VIRTUAL_BOOT_PARTITION
  452.       do {
  453.         // Undo vector patch in bottom page so verify passes
  454.         if (address == 0)       ch=rstVect & 0xff;
  455.         else if (address == 1)  ch=rstVect >> 8;
  456.         else if (address == 8)  ch=wdtVect & 0xff;
  457.         else if (address == 9) ch=wdtVect >> 8;
  458.         else ch = pgm_read_byte_near(address);
  459.         address++;
  460.         putch(ch);
  461.       } while (--length);
  462. #else
  463. #ifdef __AVR_ATmega1280__
  464. //      do putch(pgm_read_byte_near(address++));
  465. //      while (--length);
  466.       do {
  467.         uint8_t result;
  468.         __asm__ ("elpm %0,Z\n":"=r"(result):"z"(address));
  469.         putch(result);
  470.         address++;
  471.       }
  472.       while (--length);
  473. #else
  474.       do putch(pgm_read_byte_near(address++));
  475.       while (--length);
  476. #endif
  477. #endif
  478.     }
  479.  
  480.     /* Get device signature bytes  */
  481.     else if(ch == STK_READ_SIGN) {
  482.       // READ SIGN - return what Avrdude wants to hear
  483.       verifySpace();
  484.       putch(SIGNATURE_0);
  485.       putch(SIGNATURE_1);
  486.       putch(SIGNATURE_2);
  487.     }
  488.     else if (ch == 'Q') {
  489.       // Adaboot no-wait mod
  490.       watchdogConfig(WATCHDOG_16MS);
  491.       verifySpace();
  492.     }
  493.     else {
  494.       // This covers the response to commands like STK_ENTER_PROGMODE
  495.       verifySpace();
  496.     }
  497.     putch(STK_OK);
  498.   }
  499. }
  500.  
  501. void putch(char ch) {
  502. #ifndef SOFT_UART
  503.   while (!(UCSR0A & _BV(UDRE0)));
  504.   UDR0 = ch;
  505. #else
  506.   __asm__ __volatile__ (
  507.     "   com %[ch]\n" // ones complement, carry set
  508.     "   sec\n"
  509.     "1: brcc 2f\n"
  510.     "   cbi %[uartPort],%[uartBit]\n"
  511.     "   rjmp 3f\n"
  512.     "2: sbi %[uartPort],%[uartBit]\n"
  513.     "   nop\n"
  514.     "3: rcall uartDelay\n"
  515.     "   rcall uartDelay\n"
  516.     "   lsr %[ch]\n"
  517.     "   dec %[bitcnt]\n"
  518.     "   brne 1b\n"
  519.     :
  520.     :
  521.       [bitcnt] "d" (10),
  522.       [ch] "r" (ch),
  523.       [uartPort] "I" (_SFR_IO_ADDR(UART_PORT)),
  524.       [uartBit] "I" (UART_TX_BIT)
  525.     :
  526.       "r25"
  527.   );
  528. #endif
  529. }
  530.  
  531. uint8_t getch(void) {
  532.   uint8_t ch;
  533.  
  534. #ifdef LED_DATA_FLASH
  535. #ifdef __AVR_ATmega8__
  536.   LED_PORT ^= _BV(LED);
  537. #else
  538.   LED_PIN |= _BV(LED);
  539. #endif
  540. #endif
  541.  
  542. #ifdef SOFT_UART
  543.   __asm__ __volatile__ (
  544.     "1: sbic  %[uartPin],%[uartBit]\n"  // Wait for start edge
  545.     "   rjmp  1b\n"
  546.     "   rcall uartDelay\n"          // Get to middle of start bit
  547.     "2: rcall uartDelay\n"              // Wait 1 bit period
  548.     "   rcall uartDelay\n"              // Wait 1 bit period
  549.     "   clc\n"
  550.     "   sbic  %[uartPin],%[uartBit]\n"
  551.     "   sec\n"
  552.     "   dec   %[bitCnt]\n"
  553.     "   breq  3f\n"
  554.     "   ror   %[ch]\n"
  555.     "   rjmp  2b\n"
  556.     "3:\n"
  557.     :
  558.       [ch] "=r" (ch)
  559.     :
  560.       [bitCnt] "d" (9),
  561.       [uartPin] "I" (_SFR_IO_ADDR(UART_PIN)),
  562.       [uartBit] "I" (UART_RX_BIT)
  563.     :
  564.       "r25"
  565. );
  566. #else
  567.   while(!(UCSR0A & _BV(RXC0)))
  568.     ;
  569.   if (!(UCSR0A & _BV(FE0))) {
  570.       /*
  571.        * A Framing Error indicates (probably) that something is talking
  572.        * to us at the wrong bit rate.  Assume that this is because it
  573.        * expects to be talking to the application, and DON'T reset the
  574.        * watchdog.  This should cause the bootloader to abort and run
  575.        * the application "soon", if it keeps happening.  (Note that we
  576.        * don't care that an invalid char is returned...)
  577.        */
  578.     watchdogReset();
  579.   }
  580.  
  581.   ch = UDR0;
  582. #endif
  583.  
  584. #ifdef LED_DATA_FLASH
  585. #ifdef __AVR_ATmega8__
  586.   LED_PORT ^= _BV(LED);
  587. #else
  588.   LED_PIN |= _BV(LED);
  589. #endif
  590. #endif
  591.  
  592.   return ch;
  593. }
  594.  
  595. #ifdef SOFT_UART
  596. // AVR350 equation: #define UART_B_VALUE (((F_CPU/BAUD_RATE)-23)/6)
  597. // Adding 3 to numerator simulates nearest rounding for more accurate baud rates
  598. #define UART_B_VALUE (((F_CPU/BAUD_RATE)-20)/6)
  599. #if UART_B_VALUE > 255
  600. #error Baud rate too slow for soft UART
  601. #endif
  602.  
  603. void uartDelay() {
  604.   __asm__ __volatile__ (
  605.     "ldi r25,%[count]\n"
  606.     "1:dec r25\n"
  607.     "brne 1b\n"
  608.     "ret\n"
  609.     ::[count] "M" (UART_B_VALUE)
  610.   );
  611. }
  612. #endif
  613.  
  614. void getNch(uint8_t count) {
  615.   do getch(); while (--count);
  616.   verifySpace();
  617. }
  618.  
  619. void verifySpace() {
  620.   if (getch() != CRC_EOP) {
  621.     watchdogConfig(WATCHDOG_16MS);    // shorten WD timeout
  622.     while (1)                 // and busy-loop so that WD causes
  623.       ;                   //  a reset and app start.
  624.   }
  625.   putch(STK_INSYNC);
  626. }
  627.  
  628. #if LED_START_FLASHES > 0
  629. void flash_led(uint8_t count) {
  630.   do {
  631.     TCNT1 = -(F_CPU/(1024*16));
  632.     TIFR1 = _BV(TOV1);
  633.     while(!(TIFR1 & _BV(TOV1)));
  634. #ifdef __AVR_ATmega8__
  635.     LED_PORT ^= _BV(LED);
  636. #else
  637.     LED_PIN |= _BV(LED);
  638. #endif
  639.     watchdogReset();
  640.   } while (--count);
  641. }
  642. #endif
  643.  
  644. // Watchdog functions. These are only safe with interrupts turned off.
  645. void watchdogReset() {
  646.   __asm__ __volatile__ (
  647.     "wdr\n"
  648.   );
  649. }
  650.  
  651. void watchdogConfig(uint8_t x) {
  652.   WDTCSR = _BV(WDCE) | _BV(WDE);
  653.   WDTCSR = x;
  654. }
  655.  
  656. void appStart() {
  657.   watchdogConfig(WATCHDOG_OFF);
  658.   __asm__ __volatile__ (
  659. #ifdef VIRTUAL_BOOT_PARTITION
  660.     // Jump to WDT vector
  661.     "ldi r30,4\n"
  662.     "clr r31\n"
  663. #else
  664.     // Jump to RST vector
  665.     "clr r30\n"
  666.     "clr r31\n"
  667. #endif
  668.     "ijmp\n"
  669.   );
  670. }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement