Browse Source

Update to version 2. Implement AVR305 soft-UART for higher speed communication. Upgrade all targets to highest speeds.

cathedrow 15 years ago
parent
commit
9e7b95db5b

+ 9 - 8
optiboot/boards.txt

@@ -1,4 +1,5 @@
 # Optiboot Arduino support
+# http://optiboot.googlecode.com
 # Peter Knight, 2010
 
 ##############################################################
@@ -6,7 +7,7 @@
 atmega328o.name=[Optiboot] Arduino Duemilanove or Nano w/ ATmega328
 atmega328o.upload.protocol=stk500
 atmega328o.upload.maximum_size=32256
-atmega328o.upload.speed=115200
+atmega328o.upload.speed=230400
 atmega328o.bootloader.low_fuses=0xff
 atmega328o.bootloader.high_fuses=0xde
 atmega328o.bootloader.extended_fuses=0x05
@@ -23,7 +24,7 @@ atmega328o.build.core=arduino
 diecimilao.name=[Optiboot] Arduino Diecimila, Duemilanove, or Nano w/ ATmega168
 diecimilao.upload.protocol=stk500
 diecimilao.upload.maximum_size=15360
-diecimilao.upload.speed=19200
+diecimilao.upload.speed=230400
 diecimilao.bootloader.low_fuses=0xff
 diecimilao.bootloader.high_fuses=0xdd
 diecimilao.bootloader.extended_fuses=0x02
@@ -40,7 +41,7 @@ diecimilao.build.core=arduino
 minio.name=[Optiboot] Arduino Mini
 minio.upload.protocol=stk500
 minio.upload.maximum_size=15360
-minio.upload.speed=19200
+minio.upload.speed=230400
 minio.bootloader.low_fuses=0xff
 minio.bootloader.high_fuses=0xdd
 minio.bootloader.extended_fuses=0x02
@@ -57,7 +58,7 @@ minio.build.core=arduino
 lilypad328o.name=[Optiboot] LilyPad Arduino w/ ATmega328
 lilypad328o.upload.protocol=stk500
 lilypad328o.upload.maximum_size=31744
-lilypad328o.upload.speed=57600
+lilypad328o.upload.speed=115200
 lilypad328o.bootloader.low_fuses=0xff
 lilypad328o.bootloader.high_fuses=0xdc
 lilypad328o.bootloader.extended_fuses=0x05
@@ -74,7 +75,7 @@ lilypad328o.build.core=arduino
 lilypado.name=[Optiboot] LilyPad Arduino w/ ATmega168
 lilypado.upload.protocol=stk500
 lilypado.upload.maximum_size=14336
-lilypado.upload.speed=19200
+lilypado.upload.speed=115200
 lilypado.bootloader.low_fuses=0xe2
 lilypado.bootloader.high_fuses=0xdd
 lilypado.bootloader.extended_fuses=0x02
@@ -91,7 +92,7 @@ lilypado.build.core=arduino
 pro328o.name=[Optiboot] Arduino Pro or Pro Mini (3.3V, 8 MHz) w/ ATmega328
 pro328o.upload.protocol=stk500
 pro328o.upload.maximum_size=30720
-pro328o.upload.speed=57600
+pro328o.upload.speed=115200
 pro328o.bootloader.low_fuses=0xff
 pro328o.bootloader.high_fuses=0xdc
 pro328o.bootloader.extended_fuses=0x05
@@ -108,7 +109,7 @@ pro328o.build.core=arduino
 proo.name=[Optiboot] Arduino Pro or Pro Mini (3.3V, 8 MHz) w/ ATmega168
 proo.upload.protocol=stk500
 proo.upload.maximum_size=14336
-proo.upload.speed=19200
+proo.upload.speed=115200
 proo.bootloader.low_fuses=0xc6
 proo.bootloader.high_fuses=0xdd
 proo.bootloader.extended_fuses=0x02
@@ -125,7 +126,7 @@ proo.build.core=arduino
 atmega168o.name=[Optiboot] Arduino NG or older w/ ATmega168
 atmega168o.upload.protocol=stk500
 atmega168o.upload.maximum_size=14336
-atmega168o.upload.speed=19200
+atmega168o.upload.speed=230400
 atmega168o.bootloader.low_fuses=0xff
 atmega168o.bootloader.high_fuses=0xdd
 atmega168o.bootloader.extended_fuses=0x02

+ 17 - 9
optiboot/bootloaders/optiboot/Makefile

@@ -64,7 +64,7 @@ OBJCOPY        = avr-objcopy
 OBJDUMP        = avr-objdump
 
 lilypad: TARGET = lilypad
-lilypad: CFLAGS += '-DMAX_TIME_COUNT=F_CPU>>1' '-DNUM_LED_FLASHES=3'
+lilypad: CFLAGS += '-DLED_START_FLASHES=3' '-DSOFT_UART' '-DBAUD_RATE=115200'
 lilypad: AVR_FREQ = 8000000L
 lilypad: $(PROGRAM)_lilypad.hex
 lilypad: $(PROGRAM)_lilypad.lst
@@ -77,7 +77,7 @@ lilypad_isp: EFUSE = 02
 lilypad_isp: isp
 
 lilypad_resonator: TARGET = lilypad_resonator
-lilypad_resonator: CFLAGS += '-DMAX_TIME_COUNT=F_CPU>>4' '-DNUM_LED_FLASHES=3'
+lilypad_resonator: CFLAGS += '-DLED_START_FLASHES=3' '-DSOFT_UART' '-DBAUD_RATE=115200'
 lilypad_resonator: AVR_FREQ = 8000000L
 lilypad_resonator: $(PROGRAM)_lilypad_resonator.hex
 lilypad_resonator: $(PROGRAM)_lilypad_resonator.lst
@@ -90,7 +90,7 @@ lilypad_resonator_isp: EFUSE = 02
 lilypad_resonator_isp: isp
 
 pro8: TARGET = pro_8MHz
-pro8: CFLAGS += '-DMAX_TIME_COUNT=F_CPU>>4' '-DNUM_LED_FLASHES=1' '-DWATCHDOG_MODS'
+pro8: CFLAGS += '-DLED_START_FLASHES=3' '-DSOFT_UART' '-DBAUD_RATE=115200'
 pro8: AVR_FREQ = 8000000L
 pro8: $(PROGRAM)_pro_8MHz.hex
 pro8: $(PROGRAM)_pro_8MHz.lst
@@ -103,7 +103,7 @@ pro8_isp: EFUSE = 02
 pro8_isp: isp
 
 pro16: TARGET = pro_16MHz
-pro16: CFLAGS += '-DMAX_TIME_COUNT=F_CPU>>4' '-DNUM_LED_FLASHES=1' '-DWATCHDOG_MODS'
+pro16: CFLAGS += '-DLED_START_FLASHES=3' '-DSOFT_UART' '-DBAUD_RATE=230400'
 pro16: AVR_FREQ = 16000000L
 pro16: $(PROGRAM)_pro_16MHz.hex
 pro16: $(PROGRAM)_pro_16MHz.lst
@@ -116,7 +116,7 @@ pro16_isp: EFUSE = 02
 pro16_isp: isp
 
 pro20: TARGET = pro_20mhz
-pro20: CFLAGS += '-DMAX_TIME_COUNT=F_CPU>>4' '-DNUM_LED_FLASHES=1' '-DWATCHDOG_MODS'
+pro20: CFLAGS += '-DLED_START_FLASHES=3' '-DSOFT_UART' '-DBAUD_RATE=230400'
 pro20: AVR_FREQ = 20000000L
 pro20: $(PROGRAM)_pro_20mhz.hex
 pro20: $(PROGRAM)_pro_20mhz.lst
@@ -129,7 +129,7 @@ pro20_isp: EFUSE = 02
 pro20_isp: isp
 
 diecimila: TARGET = diecimila
-diecimila: CFLAGS += '-DMAX_TIME_COUNT=F_CPU>>4' '-DNUM_LED_FLASHES=1'
+diecimila: CFLAGS += '-DLED_START_FLASHES=3' '-DSOFT_UART' '-DBAUD_RATE=230400'
 diecimila: AVR_FREQ = 16000000L 
 diecimila: $(PROGRAM)_diecimila.hex
 diecimila: $(PROGRAM)_diecimila.lst
@@ -142,7 +142,7 @@ diecimila_isp: EFUSE = 02
 diecimila_isp: isp
 
 ng: TARGET = ng
-ng: CFLAGS += '-DMAX_TIME_COUNT=F_CPU>>1' '-DNUM_LED_FLASHES=3'
+ng: CFLAGS += '-DLED_START_FLASHES=3' '-DSOFT_UART' '-DBAUD_RATE=230400'
 ng: AVR_FREQ = 16000000L
 ng: $(PROGRAM)_ng.hex
 ng: $(PROGRAM)_ng.lst
@@ -156,7 +156,7 @@ ng_isp: isp
 
 atmega328: TARGET = atmega328
 atmega328: MCU_TARGET = atmega328p
-atmega328: CFLAGS += '-DMAX_TIME_COUNT=F_CPU>>4' '-DNUM_LED_FLASHES=3' '-DBAUD_RATE=115200'
+atmega328: CFLAGS += '-DLED_START_FLASHES=3' '-DSOFT_UART' '-DBAUD_RATE=230400'
 atmega328: AVR_FREQ = 16000000L
 atmega328: LDSECTION  = --section-start=.text=0x7e00
 atmega328: $(PROGRAM)_atmega328.hex
@@ -172,7 +172,7 @@ atmega328_isp: isp
 
 atmega328_pro8: TARGET = atmega328_pro_8MHz
 atmega328_pro8: MCU_TARGET = atmega328p
-atmega328_pro8: CFLAGS += '-DMAX_TIME_COUNT=F_CPU>>4' '-DNUM_LED_FLASHES=1' '-DBAUD_RATE=57600'
+atmega328_pro8: CFLAGS += '-DLED_START_FLASHES=3' '-DSOFT_UART' '-DBAUD_RATE=115200'
 atmega328_pro8: AVR_FREQ = 8000000L
 atmega328_pro8: LDSECTION  = --section-start=.text=0x7e00
 atmega328_pro8: $(PROGRAM)_atmega328_pro_8MHz.hex
@@ -186,6 +186,14 @@ atmega328_pro8_isp: LFUSE = FF
 atmega328_pro8_isp: EFUSE = 05
 atmega328_pro8_isp: isp
 
+luminet: TARGET = luminet
+luminet: MCU_TARGET = attiny84
+luminet: CFLAGS += '-DLED_START_FLASHES=3' '-DSOFT_UART' '-DBAUD_RATE=115200'
+luminet: AVR_FREQ = 1000000L
+luminet: LDSECTION  = --section-start=.text=0x1e00
+luminet: $(PROGRAM)_luminet.hex
+luminet: $(PROGRAM)_luminet.lst
+
 isp: $(TARGET)
 	$(ISPFUSES)
 	$(ISPFLASH)

+ 151 - 68
optiboot/bootloaders/optiboot/optiboot.c

@@ -40,6 +40,7 @@
 /*   Spiff's 1K bootloader http://spiffie.org/know/arduino_1k_bootloader/bootloader.shtml */
 /*   avr-libc project      http://nongnu.org/avr-libc     */
 /*   Adaboot               http://www.ladyada.net/library/arduino/bootloader.html */
+/*   AVR305                Atmel Application Note         */
 /*                                                        */
 /* This program is free software; you can redistribute it */
 /* and/or modify it under the terms of the GNU General    */
@@ -63,13 +64,16 @@
 /*                                                        */
 /**********************************************************/
 
-
 #include <inttypes.h>
 #include <avr/io.h>
 #include <avr/pgmspace.h>
 #include <avr/boot.h>
 
-#define NOWAIT
+//#define LED_DATA_FLASH
+
+#ifndef LED_START_FLASHES
+#define LED_START_FLASHES 0
+#endif
 
 /* Build-time variables */
 /* BAUD_RATE       Programming baud rate */
@@ -82,11 +86,21 @@
 #define BAUD_RATE   19200
 #endif
 
+
 /* Onboard LED is connected to pin PB5 in Arduino NG, Diecimila, and Duemilanove */ 
-#define LED_DDR  DDRB
-#define LED_PORT PORTB
-#define LED_PIN  PINB
-#define LED      PINB5
+#define LED_DDR     DDRB
+#define LED_PORT    PORTB
+#define LED_PIN     PINB
+#define LED         PINB5
+
+/* Ports for soft UART */
+#ifdef SOFT_UART
+#define UART_PORT   PORTD
+#define UART_PIN    PIND
+#define UART_DDR    DDRD
+#define UART_TX_BIT 1
+#define UART_RX_BIT 0
+#endif
 
 /* STK500 constants list, from AVRDUDE */
 #define STK_OK              0x10
@@ -138,8 +152,12 @@ uint8_t getch(void);
 static inline void getNch(uint8_t); /* "static inline" is a compiler hint to reduce code size */
 void verifySpace();
 static inline void flash_led(uint8_t);
-void setTimer(uint16_t counts);
 uint8_t getLen();
+static inline void watchdogReset();
+void watchdogConfig(uint8_t x);
+#ifdef SOFT_UART
+void uartDelay() __attribute__ ((naked));
+#endif
 void appStart() __attribute__ ((naked));
 
 /* C zero initialises all global variables. However, that requires */
@@ -165,46 +183,11 @@ int main(void) {
 
   uint8_t ch;
 
-#if 0
-  // The compiler normally generates sts instructions for setting
-  // up I/O space registers. But that takes 6 bytes per register.
-  // This code can do it in 2, with an overhead of 20 bytes.
-  // This starts to pay off when initialising 6 or more registers
-  __asm__ volatile (
-    "ldi r30,lo8(init_table)\n"
-    "ldi r31,hi8(init_table)\n"
-    "ldi r29,0\n"
-    "init_loop:lpm r28,Z+\n"
-    "lpm r0,Z+\n"
-    "tst r28\n"
-    "breq init_exit+2\n"
-    "st Y,r0\n"
-    "rjmp init_loop\n"
-    "init_table:\n"
-    ".byte %[addr1]\n"
-    ".byte %[val1]\n"
-    ".byte %[addr2]\n"
-    ".byte %[val2]\n"
-    ".byte %[addr3]\n"
-    ".byte %[val3]\n"
-    ".byte %[addr4]\n"
-    ".byte %[val4]\n"
-    ".byte %[addr5]\n"
-    ".byte %[val5]\n"
-    "init_exit:.word 0\n"
-    // Clobbers R0,R28,R29,R30,R31
-    // But that is fine so we won't tell the compiler
-    // otherwise it will generate useless extra code
-    ::
-    [addr1]"i"(_SFR_MEM_ADDR(TCCR1B)), [val1]"i"(_BV(CS12) | _BV(CS10)),
-    [addr2]"i"(_SFR_MEM_ADDR(UCSR0A)), [val2]"i"(_BV(U2X0)),
-    [addr3]"i"(_SFR_MEM_ADDR(UCSR0B)), [val3]"i"(_BV(RXEN0) | _BV(TXEN0)),
-    [addr4]"i"(_SFR_MEM_ADDR(UCSR0C)), [val4]"i"(_BV(UCSZ00) | _BV(UCSZ01)),
-    [addr5]"i"(_SFR_MEM_ADDR(UBRR0L)), [val5]"i"((F_CPU + BAUD_RATE * 4L) / (BAUD_RATE * 8L) - 1)
-  );
-#else
+#if LED_START_FLASHES > 0
   // Set up Timer 1 for timeout counter
   TCCR1B = _BV(CS12) | _BV(CS10); // div 1024
+#endif
+#ifndef SOFT_UART
   UCSR0A = _BV(U2X0); //Double speed mode USART0
   UCSR0B = _BV(RXEN0) | _BV(TXEN0);
   UCSR0C = _BV(UCSZ00) | _BV(UCSZ01);
@@ -214,17 +197,25 @@ int main(void) {
   // Adaboot no-wait mod
   ch = MCUSR;
   MCUSR = 0;
-  WDTCSR = _BV(WDCE) | _BV(WDE);
-  WDTCSR = 0;
   if (!(ch & _BV(EXTRF))) appStart();
 
-  /* set LED pin as output */
+  // Set up watchdog to trigger after 500ms
+  watchdogConfig(_BV(WDP2)|_BV(WDP0)|_BV(WDE));
+
+  /* Set LED pin as output */
   LED_DDR |= _BV(LED);
 
-  /* flash onboard LED to signal entering of bootloader */
-  flash_led(NUM_LED_FLASHES * 2);
+#ifdef SOFT_UART
+  /* Set TX pin as output */
+  UART_DDR |= _BV(UART_TX_BIT);
+#endif
+
+#if LED_START_FLASHES > 0
+  /* Flash onboard LED to signal entering of bootloader */
+  flash_led(LED_START_FLASHES * 2);
+#endif
 
-  /* forever loop */
+  /* Forever loop */
   for (;;) {
     /* get character from UART */
     ch = getch();
@@ -259,9 +250,9 @@ int main(void) {
       // PROGRAM PAGE - we support flash programming only, not EEPROM
       uint8_t *bufPtr;
       uint16_t addrPtr;
-      
-      if (getLen() != 'F') appStart(); // Abort is not flash programming
-  
+
+      getLen();
+
       // Immediately start page erase - this will 4.5ms
       boot_page_erase((uint16_t)(void*)address);
 
@@ -270,13 +261,13 @@ int main(void) {
       do *bufPtr++ = getch();
       while (--length);
 
+      // Read command terminator, start reply
+      verifySpace();
+      
       // If only a partial page is to be programmed, the erase might not be complete.
       // So check that here
       boot_spm_busy_wait();
 
-      // Read command terminator, start reply
-      verifySpace();
-      
       // Copy buffer into programming buffer
       bufPtr = buff;
       addrPtr = (uint16_t)(void*)address;
@@ -315,7 +306,7 @@ int main(void) {
     }
     else if (ch == 'Q') {
       // Adaboot no-wait mod
-      WDTCSR = _BV(WDE);
+      watchdogConfig(_BV(WDE));
       verifySpace();
     }
     else {
@@ -327,22 +318,97 @@ int main(void) {
 }
 
 void putch(char ch) {
+#ifndef SOFT_UART
   while (!(UCSR0A & _BV(UDRE0)));
   UDR0 = ch;
+#else
+  __asm__ __volatile__ (
+    "   com %[ch]\n" // ones complement, carry set
+    "   sec\n"
+    "1: brcc 2f\n"
+    "   cbi %[uartPort],%[uartBit]\n"
+    "   rjmp 3f\n"
+    "2: sbi %[uartPort],%[uartBit]\n"
+    "   nop\n"
+    "3: rcall uartDelay\n"
+    "   rcall uartDelay\n"
+    "   lsr %[ch]\n"
+    "   dec %[bitcnt]\n"
+    "   brne 1b\n"
+    :
+    :
+      [bitcnt] "d" (10),
+      [ch] "r" (ch),
+      [uartPort] "I" (_SFR_IO_ADDR(UART_PORT)),
+      [uartBit] "I" (UART_TX_BIT)
+    :
+      "r25"
+  );
+#endif
 }
 
-void setTimer(uint16_t counts) {
-  TCNT1 = counts;
-  TIFR1 = _BV(TOV1);
+uint8_t getch(void) {
+  uint8_t ch;
+
+  watchdogReset();
+
+#ifdef LED_DATA_FLASH
+  LED_PIN |= _BV(LED);
+#endif
+
+#ifdef SOFT_UART
+  __asm__ __volatile__ (
+    "1: sbic  %[uartPin],%[uartBit]\n"  // Wait for start edge
+    "   rjmp  1b\n"
+    "   rcall uartDelay\n"          // Get to middle of start bit
+    "2: rcall uartDelay\n"              // Wait 1 bit period
+    "   rcall uartDelay\n"              // Wait 1 bit period
+    "   clc\n"
+    "   sbic  %[uartPin],%[uartBit]\n"
+    "   sec\n"                          
+    "   dec   %[bitCnt]\n"
+    "   breq  3f\n"
+    "   ror   %[ch]\n"
+    "   rjmp  2b\n"
+    "3:\n"
+    :
+      [ch] "=r" (ch)
+    :
+      [bitCnt] "d" (9),
+      [uartPin] "I" (_SFR_IO_ADDR(UART_PIN)),
+      [uartBit] "I" (UART_RX_BIT)
+    :
+      "r25"
+);
+#else
+  while(!(UCSR0A & _BV(RXC0)));
+  ch = UDR0;
+#endif
+
+#ifdef LED_DATA_FLASH
+  LED_PIN |= _BV(LED);
+#endif
+
+  return ch;
 }
 
-uint8_t getch(void) {
-  LED_PORT &= ~_BV(LED);
-  setTimer(-(F_CPU/(1024*2))); // 500ms
-  while(!(UCSR0A & _BV(RXC0))) if (TIFR1 & _BV(TOV1)) appStart();
-  LED_PORT |= _BV(LED);
-  return UDR0;
+#ifdef SOFT_UART
+//#define UART_B_VALUE (((F_CPU/BAUD_RATE)-23)/6)
+#define UART_B_VALUE (((F_CPU/BAUD_RATE)-20)/6)
+#if UART_B_VALUE > 255
+#error Baud rate too slow for soft UART
+#endif
+
+void uartDelay() {
+  __asm__ __volatile__ (
+    "ldi r25,%[count]\n"
+    "1:dec r25\n"
+    "brne 1b\n"
+    "ret\n"
+    ::[count] "M" (UART_B_VALUE)
+  );
 }
+#endif
 
 void getNch(uint8_t count) {
   do getch(); while (--count);
@@ -354,13 +420,17 @@ void verifySpace() {
   putch(STK_INSYNC);
 }
 
+#if LED_START_FLASHES > 0
 void flash_led(uint8_t count) {
   do {
-    setTimer(-(F_CPU/(1024*16))); // 62ms
+    TCNT1 = -(F_CPU/(1024*16));
+    TIFR1 = _BV(TOV1);
     while(!(TIFR1 & _BV(TOV1)));
     LED_PIN |= _BV(LED);
+    watchdogReset();
   } while (--count);
 }
+#endif
 
 uint8_t getLen() {
   getch();
@@ -368,7 +438,20 @@ uint8_t getLen() {
   return getch();
 }
 
+// Watchdog functions. These are only safe with interrupts turned off.
+void watchdogReset() {
+  __asm__ __volatile__ (
+    "wdr\n"
+  );
+}
+
+void watchdogConfig(uint8_t x) {
+  WDTCSR = _BV(WDCE) | _BV(WDE);
+  WDTCSR = x;
+}
+
 void appStart() {
+  watchdogConfig(0);
   __asm__ __volatile__ (
     "clr r30\n"
     "clr r31\n"

+ 32 - 32
optiboot/bootloaders/optiboot/optiboot_atmega328.hex

@@ -1,34 +1,34 @@
-:107E000085E08093810082E08093C00098E19093A8
-:107E1000C10086E08093C20080E18093C40084B7F3
-:107E200014BE909360001092600081FFC1D0259A2B
-:107E300006E080E39CEFB5D0B09BFECF1D9A0150C9
-:107E4000C1F7DD24D394B8E0CB2EA5E0EA2EF1E112
-:107E5000FF2EB1D0813421F481E0C7D083E024C06B
-:107E6000823411F484E103C0853419F485E0BDD077
-:107E70008DC08535A1F49FD0082F10E0109301022A
-:107E80000093000298D090E0982F8827802B912BA8
-:107E9000880F991F909301028093000276C0863567
-:107EA00029F484E0A2D080E074D070C0843609F058
-:107EB00046C090D0863409F07BD0E0910002F0916A
-:107EC000010283E080935700E895C0E0D1E073D0D1
-:107ED0008993809102028150809302028823B9F72E
-:107EE00007B600FCFDCF7BD040910002509101020B
-:107EF000A0E0B1E02C9130E011968C91119790E0C8
-:107F0000982F8827822B932B1296FA010C01D0927E
-:107F10005700E89511244E5F5F4FF1E0A038BF078E
-:107F200049F7E0910002F0910102E0925700E895D4
-:107F300007B600FCFDCFF0925700E89527C08437C4
-:107F4000B9F448D04CD0E0910002F0910102319692
-:107F5000F0930102E09300023197E4918E2F19D043
-:107F600080910202815080930202882361F70EC043
-:107F7000853739F434D08EE10CD085E90AD08FE012
-:107F800093CF813511F4C092600029D080E101D0F7
-:107F900060CF982F8091C00085FFFCCF9093C600E2
-:107FA0000895909385008093840081E086BB0895B6
-:107FB000EE27FF2709942D988CE791EEF2DF02C09F
-:107FC000B099F6DF8091C00087FFFACF2D9A80919B
-:107FD000C6000895F0DFEFDF80930202ECCFEBDF05
-:107FE000803209F0E5DF84E1D4CF1F93182FE3DF5F
-:0A7FF0001150E9F7F4DF1F91089526
+:107E000085E08093810084B714BE81FFE4D08DE0CB
+:107E1000DCD0259A519A86E020E33CEF91E0309344
+:107E200085002093840096BBB09BFECF1D9AA89539
+:107E30008150A9F7DD24D394A5E0EA2EF1E1FF2ECD
+:107E4000ABD0813421F481E0D1D083E024C08234EE
+:107E500011F484E103C0853419F485E0C7D08AC0E9
+:107E60008535A1F499D0082F10E0109301020093FA
+:107E7000000292D090E0982F8827802B912B880FBA
+:107E8000991F909301028093000273C0863529F4F4
+:107E900084E0ACD080E071D06DC0843609F043C07E
+:107EA0008FD0E0910002F091010283E080935700AF
+:107EB000E895C0E0D1E070D08993809102028150B2
+:107EC000809302028823B9F78BD007B600FCFDCF60
+:107ED0004091000250910102A0E0B1E02C9130E00D
+:107EE00011968C91119790E0982F8827822B932BD5
+:107EF0001296FA010C01D0925700E89511244E5FBA
+:107F00005F4FF1E0A038BF0749F7E0910002F09120
+:107F10000102E0925700E89507B600FCFDCFF09211
+:107F20005700E89527C08437B9F44AD059D0E0917A
+:107F30000002F09101023196F0930102E0930002F9
+:107F40003197E4918E2F19D0809102028150809355
+:107F50000202882361F70EC0853739F441D08EE1E3
+:107F60000CD085E90AD08FE096CF813511F488E0F6
+:107F70002CD036D080E101D063CF2AE030E080956C
+:107F8000089410F4599802C0599A000015D014D0E2
+:107F900086952A95B1F70895A89529E030E048998B
+:107FA000FECF0AD009D008D08894489908942A9521
+:107FB00011F08795F7CF089598E09A95F1F7089515
+:107FC000EBDFEADF80930202E7CFE0E6F0E098E142
+:107FD00090838083089580E0F8DFEE27FF270994DF
+:107FE000DBDF803209F0F7DF84E1C7CF1F93182F62
+:0C7FF000D3DF1150E9F7F4DF1F91089572
 :0400000300007E007B
 :00000001FF

+ 320 - 282
optiboot/bootloaders/optiboot/optiboot_atmega328.lst

@@ -3,25 +3,25 @@ optiboot_atmega328.elf:     file format elf32-avr
 
 Sections:
 Idx Name          Size      VMA       LMA       File off  Algn
-  0 .text         000001fa  00007e00  00007e00  00000054  2**1
+  0 .text         000001fc  00007e00  00007e00  00000054  2**1
                   CONTENTS, ALLOC, LOAD, READONLY, CODE
-  1 .debug_aranges 00000028  00000000  00000000  0000024e  2**0
+  1 .debug_aranges 00000028  00000000  00000000  00000250  2**0
                   CONTENTS, READONLY, DEBUGGING
-  2 .debug_pubnames 00000064  00000000  00000000  00000276  2**0
+  2 .debug_pubnames 00000078  00000000  00000000  00000278  2**0
                   CONTENTS, READONLY, DEBUGGING
-  3 .debug_info   0000022f  00000000  00000000  000002da  2**0
+  3 .debug_info   00000275  00000000  00000000  000002f0  2**0
                   CONTENTS, READONLY, DEBUGGING
-  4 .debug_abbrev 00000164  00000000  00000000  00000509  2**0
+  4 .debug_abbrev 000001a3  00000000  00000000  00000565  2**0
                   CONTENTS, READONLY, DEBUGGING
-  5 .debug_line   000003c8  00000000  00000000  0000066d  2**0
+  5 .debug_line   000003b8  00000000  00000000  00000708  2**0
                   CONTENTS, READONLY, DEBUGGING
-  6 .debug_frame  00000090  00000000  00000000  00000a38  2**2
+  6 .debug_frame  000000a0  00000000  00000000  00000ac0  2**2
                   CONTENTS, READONLY, DEBUGGING
-  7 .debug_str    0000011c  00000000  00000000  00000ac8  2**0
+  7 .debug_str    00000133  00000000  00000000  00000b60  2**0
                   CONTENTS, READONLY, DEBUGGING
-  8 .debug_loc    000001d6  00000000  00000000  00000be4  2**0
+  8 .debug_loc    000001a0  00000000  00000000  00000c93  2**0
                   CONTENTS, READONLY, DEBUGGING
-  9 .debug_ranges 00000068  00000000  00000000  00000dba  2**0
+  9 .debug_ranges 00000070  00000000  00000000  00000e33  2**0
                   CONTENTS, READONLY, DEBUGGING
 
 Disassembly of section .text:
@@ -35,449 +35,487 @@ Disassembly of section .text:
 int main(void) {
     7e00:	85 e0       	ldi	r24, 0x05	; 5
     7e02:	80 93 81 00 	sts	0x0081, r24
-    [addr5]"i"(_SFR_MEM_ADDR(UBRR0L)), [val5]"i"((F_CPU + BAUD_RATE * 4L) / (BAUD_RATE * 8L) - 1)
-  );
-#else
-  // Set up Timer 1 for timeout counter
-  TCCR1B = _BV(CS12) | _BV(CS10); // div 1024
-  UCSR0A = _BV(U2X0); //Double speed mode USART0
-    7e06:	82 e0       	ldi	r24, 0x02	; 2
-    7e08:	80 93 c0 00 	sts	0x00C0, r24
-  UCSR0B = _BV(RXEN0) | _BV(TXEN0);
-    7e0c:	98 e1       	ldi	r25, 0x18	; 24
-    7e0e:	90 93 c1 00 	sts	0x00C1, r25
   UCSR0C = _BV(UCSZ00) | _BV(UCSZ01);
-    7e12:	86 e0       	ldi	r24, 0x06	; 6
-    7e14:	80 93 c2 00 	sts	0x00C2, r24
   UBRR0L = (uint8_t)( (F_CPU + BAUD_RATE * 4L) / (BAUD_RATE * 8L) - 1 );
-    7e18:	80 e1       	ldi	r24, 0x10	; 16
-    7e1a:	80 93 c4 00 	sts	0x00C4, r24
 #endif
 
   // Adaboot no-wait mod
   ch = MCUSR;
-    7e1e:	84 b7       	in	r24, 0x34	; 52
+    7e06:	84 b7       	in	r24, 0x34	; 52
   MCUSR = 0;
-    7e20:	14 be       	out	0x34, r1	; 52
-  WDTCSR = _BV(WDCE) | _BV(WDE);
-    7e22:	90 93 60 00 	sts	0x0060, r25
-  WDTCSR = 0;
-    7e26:	10 92 60 00 	sts	0x0060, r1
+    7e08:	14 be       	out	0x34, r1	; 52
   if (!(ch & _BV(EXTRF))) appStart();
-    7e2a:	81 ff       	sbrs	r24, 1
-    7e2c:	c1 d0       	rcall	.+386    	; 0x7fb0 <appStart>
+    7e0a:	81 ff       	sbrs	r24, 1
+    7e0c:	e4 d0       	rcall	.+456    	; 0x7fd6 <appStart>
+
+  // Set up watchdog to trigger after 500ms
+  watchdogConfig(_BV(WDP2)|_BV(WDP0)|_BV(WDE));
+    7e0e:	8d e0       	ldi	r24, 0x0D	; 13
+    7e10:	dc d0       	rcall	.+440    	; 0x7fca <watchdogConfig>
 
-  /* set LED pin as output */
+  /* Set LED pin as output */
   LED_DDR |= _BV(LED);
-    7e2e:	25 9a       	sbi	0x04, 5	; 4
-    7e30:	06 e0       	ldi	r16, 0x06	; 6
-  putch(STK_INSYNC);
+    7e12:	25 9a       	sbi	0x04, 5	; 4
+
+#ifdef SOFT_UART
+  /* Set TX pin as output */
+  UART_DDR |= _BV(UART_TX_BIT);
+    7e14:	51 9a       	sbi	0x0a, 1	; 10
+    7e16:	86 e0       	ldi	r24, 0x06	; 6
+}
+
+#if LED_START_FLASHES > 0
+void flash_led(uint8_t count) {
+  do {
+    TCNT1 = -(F_CPU/(1024*16));
+    7e18:	20 e3       	ldi	r18, 0x30	; 48
+    7e1a:	3c ef       	ldi	r19, 0xFC	; 252
+    TIFR1 = _BV(TOV1);
+    7e1c:	91 e0       	ldi	r25, 0x01	; 1
 }
 
+#if LED_START_FLASHES > 0
 void flash_led(uint8_t count) {
   do {
-    setTimer(-(F_CPU/(1024*16))); // 62ms
-    7e32:	80 e3       	ldi	r24, 0x30	; 48
-    7e34:	9c ef       	ldi	r25, 0xFC	; 252
-    7e36:	b5 d0       	rcall	.+362    	; 0x7fa2 <setTimer>
+    TCNT1 = -(F_CPU/(1024*16));
+    7e1e:	30 93 85 00 	sts	0x0085, r19
+    7e22:	20 93 84 00 	sts	0x0084, r18
+    TIFR1 = _BV(TOV1);
+    7e26:	96 bb       	out	0x16, r25	; 22
+    while(!(TIFR1 & _BV(TOV1)));
+    7e28:	b0 9b       	sbis	0x16, 0	; 22
+    7e2a:	fe cf       	rjmp	.-4      	; 0x7e28 <main+0x28>
+    LED_PIN |= _BV(LED);
+    7e2c:	1d 9a       	sbi	0x03, 5	; 3
+  return getch();
+}
+
+// Watchdog functions. These are only safe with interrupts turned off.
+void watchdogReset() {
+  __asm__ __volatile__ (
+    7e2e:	a8 95       	wdr
+    TCNT1 = -(F_CPU/(1024*16));
+    TIFR1 = _BV(TOV1);
     while(!(TIFR1 & _BV(TOV1)));
-    7e38:	b0 9b       	sbis	0x16, 0	; 22
-    7e3a:	fe cf       	rjmp	.-4      	; 0x7e38 <main+0x38>
     LED_PIN |= _BV(LED);
-    7e3c:	1d 9a       	sbi	0x03, 5	; 3
+    watchdogReset();
   } while (--count);
-    7e3e:	01 50       	subi	r16, 0x01	; 1
-    7e40:	c1 f7       	brne	.-16     	; 0x7e32 <main+0x32>
+    7e30:	81 50       	subi	r24, 0x01	; 1
+    7e32:	a9 f7       	brne	.-22     	; 0x7e1e <main+0x1e>
     /* get character from UART */
     ch = getch();
 
     if(ch == STK_GET_PARAMETER) {
       // GET PARAMETER returns a generic 0x03 reply - enough to keep Avrdude happy
       getNch(1);
-    7e42:	dd 24       	eor	r13, r13
-    7e44:	d3 94       	inc	r13
-      putch(SIGNATURE_1);
-      putch(SIGNATURE_2);
-    }
-    else if (ch == 'Q') {
-      // Adaboot no-wait mod
-      WDTCSR = _BV(WDE);
-    7e46:	b8 e0       	ldi	r27, 0x08	; 8
-    7e48:	cb 2e       	mov	r12, r27
+    7e34:	dd 24       	eor	r13, r13
+    7e36:	d3 94       	inc	r13
         boot_page_fill((uint16_t)(void*)addrPtr,a);
         addrPtr += 2;
       } while (--ch);
       
       // Write from programming buffer
       boot_page_write((uint16_t)(void*)address);
-    7e4a:	a5 e0       	ldi	r26, 0x05	; 5
-    7e4c:	ea 2e       	mov	r14, r26
+    7e38:	a5 e0       	ldi	r26, 0x05	; 5
+    7e3a:	ea 2e       	mov	r14, r26
       boot_spm_busy_wait();
 
       // Reenable read access to flash
       boot_rww_enable();
-    7e4e:	f1 e1       	ldi	r31, 0x11	; 17
-    7e50:	ff 2e       	mov	r15, r31
-  flash_led(NUM_LED_FLASHES * 2);
+    7e3c:	f1 e1       	ldi	r31, 0x11	; 17
+    7e3e:	ff 2e       	mov	r15, r31
+#endif
 
-  /* forever loop */
+  /* Forever loop */
   for (;;) {
     /* get character from UART */
     ch = getch();
-    7e52:	b1 d0       	rcall	.+354    	; 0x7fb6 <getch>
+    7e40:	ab d0       	rcall	.+342    	; 0x7f98 <getch>
 
     if(ch == STK_GET_PARAMETER) {
-    7e54:	81 34       	cpi	r24, 0x41	; 65
-    7e56:	21 f4       	brne	.+8      	; 0x7e60 <main+0x60>
+    7e42:	81 34       	cpi	r24, 0x41	; 65
+    7e44:	21 f4       	brne	.+8      	; 0x7e4e <main+0x4e>
       // GET PARAMETER returns a generic 0x03 reply - enough to keep Avrdude happy
       getNch(1);
-    7e58:	81 e0       	ldi	r24, 0x01	; 1
-    7e5a:	c7 d0       	rcall	.+398    	; 0x7fea <verifySpace+0xc>
+    7e46:	81 e0       	ldi	r24, 0x01	; 1
+    7e48:	d1 d0       	rcall	.+418    	; 0x7fec <verifySpace+0xc>
       putch(0x03);
-    7e5c:	83 e0       	ldi	r24, 0x03	; 3
-    7e5e:	24 c0       	rjmp	.+72     	; 0x7ea8 <main+0xa8>
+    7e4a:	83 e0       	ldi	r24, 0x03	; 3
+    7e4c:	24 c0       	rjmp	.+72     	; 0x7e96 <main+0x96>
     }
     else if(ch == STK_SET_DEVICE) {
-    7e60:	82 34       	cpi	r24, 0x42	; 66
-    7e62:	11 f4       	brne	.+4      	; 0x7e68 <main+0x68>
+    7e4e:	82 34       	cpi	r24, 0x42	; 66
+    7e50:	11 f4       	brne	.+4      	; 0x7e56 <main+0x56>
       // SET DEVICE is ignored
       getNch(20);
-    7e64:	84 e1       	ldi	r24, 0x14	; 20
-    7e66:	03 c0       	rjmp	.+6      	; 0x7e6e <main+0x6e>
+    7e52:	84 e1       	ldi	r24, 0x14	; 20
+    7e54:	03 c0       	rjmp	.+6      	; 0x7e5c <main+0x5c>
     }
     else if(ch == STK_SET_DEVICE_EXT) {
-    7e68:	85 34       	cpi	r24, 0x45	; 69
-    7e6a:	19 f4       	brne	.+6      	; 0x7e72 <main+0x72>
+    7e56:	85 34       	cpi	r24, 0x45	; 69
+    7e58:	19 f4       	brne	.+6      	; 0x7e60 <main+0x60>
       // SET DEVICE EXT is ignored
       getNch(5);
-    7e6c:	85 e0       	ldi	r24, 0x05	; 5
-    7e6e:	bd d0       	rcall	.+378    	; 0x7fea <verifySpace+0xc>
-    7e70:	8d c0       	rjmp	.+282    	; 0x7f8c <main+0x18c>
+    7e5a:	85 e0       	ldi	r24, 0x05	; 5
+    7e5c:	c7 d0       	rcall	.+398    	; 0x7fec <verifySpace+0xc>
+    7e5e:	8a c0       	rjmp	.+276    	; 0x7f74 <main+0x174>
     }
     else if(ch == STK_LOAD_ADDRESS) {
-    7e72:	85 35       	cpi	r24, 0x55	; 85
-    7e74:	a1 f4       	brne	.+40     	; 0x7e9e <main+0x9e>
+    7e60:	85 35       	cpi	r24, 0x55	; 85
+    7e62:	a1 f4       	brne	.+40     	; 0x7e8c <main+0x8c>
       // LOAD ADDRESS
       address = getch();
-    7e76:	9f d0       	rcall	.+318    	; 0x7fb6 <getch>
-    7e78:	08 2f       	mov	r16, r24
-    7e7a:	10 e0       	ldi	r17, 0x00	; 0
-    7e7c:	10 93 01 02 	sts	0x0201, r17
-    7e80:	00 93 00 02 	sts	0x0200, r16
+    7e64:	99 d0       	rcall	.+306    	; 0x7f98 <getch>
+    7e66:	08 2f       	mov	r16, r24
+    7e68:	10 e0       	ldi	r17, 0x00	; 0
+    7e6a:	10 93 01 02 	sts	0x0201, r17
+    7e6e:	00 93 00 02 	sts	0x0200, r16
       address = (address & 0xff) | (getch() << 8);
-    7e84:	98 d0       	rcall	.+304    	; 0x7fb6 <getch>
-    7e86:	90 e0       	ldi	r25, 0x00	; 0
-    7e88:	98 2f       	mov	r25, r24
-    7e8a:	88 27       	eor	r24, r24
-    7e8c:	80 2b       	or	r24, r16
-    7e8e:	91 2b       	or	r25, r17
+    7e72:	92 d0       	rcall	.+292    	; 0x7f98 <getch>
+    7e74:	90 e0       	ldi	r25, 0x00	; 0
+    7e76:	98 2f       	mov	r25, r24
+    7e78:	88 27       	eor	r24, r24
+    7e7a:	80 2b       	or	r24, r16
+    7e7c:	91 2b       	or	r25, r17
       address += address; // Convert from word address to byte address
-    7e90:	88 0f       	add	r24, r24
-    7e92:	99 1f       	adc	r25, r25
-    7e94:	90 93 01 02 	sts	0x0201, r25
-    7e98:	80 93 00 02 	sts	0x0200, r24
-    7e9c:	76 c0       	rjmp	.+236    	; 0x7f8a <main+0x18a>
+    7e7e:	88 0f       	add	r24, r24
+    7e80:	99 1f       	adc	r25, r25
+    7e82:	90 93 01 02 	sts	0x0201, r25
+    7e86:	80 93 00 02 	sts	0x0200, r24
+    7e8a:	73 c0       	rjmp	.+230    	; 0x7f72 <main+0x172>
       verifySpace();
     }
     else if(ch == STK_UNIVERSAL) {
-    7e9e:	86 35       	cpi	r24, 0x56	; 86
-    7ea0:	29 f4       	brne	.+10     	; 0x7eac <main+0xac>
+    7e8c:	86 35       	cpi	r24, 0x56	; 86
+    7e8e:	29 f4       	brne	.+10     	; 0x7e9a <main+0x9a>
       // UNIVERSAL command is ignored
       getNch(4);
-    7ea2:	84 e0       	ldi	r24, 0x04	; 4
-    7ea4:	a2 d0       	rcall	.+324    	; 0x7fea <verifySpace+0xc>
+    7e90:	84 e0       	ldi	r24, 0x04	; 4
+    7e92:	ac d0       	rcall	.+344    	; 0x7fec <verifySpace+0xc>
       putch(0x00);
-    7ea6:	80 e0       	ldi	r24, 0x00	; 0
-    7ea8:	74 d0       	rcall	.+232    	; 0x7f92 <putch>
-    7eaa:	70 c0       	rjmp	.+224    	; 0x7f8c <main+0x18c>
+    7e94:	80 e0       	ldi	r24, 0x00	; 0
+    7e96:	71 d0       	rcall	.+226    	; 0x7f7a <putch>
+    7e98:	6d c0       	rjmp	.+218    	; 0x7f74 <main+0x174>
     }
     /* Write memory, length is big endian and is in bytes  */
     else if(ch == STK_PROG_PAGE) {
-    7eac:	84 36       	cpi	r24, 0x64	; 100
-    7eae:	09 f0       	breq	.+2      	; 0x7eb2 <main+0xb2>
-    7eb0:	46 c0       	rjmp	.+140    	; 0x7f3e <main+0x13e>
+    7e9a:	84 36       	cpi	r24, 0x64	; 100
+    7e9c:	09 f0       	breq	.+2      	; 0x7ea0 <main+0xa0>
+    7e9e:	43 c0       	rjmp	.+134    	; 0x7f26 <main+0x126>
       // PROGRAM PAGE - we support flash programming only, not EEPROM
       uint8_t *bufPtr;
       uint16_t addrPtr;
-      
-      if (getLen() != 'F') appStart(); // Abort is not flash programming
-    7eb2:	90 d0       	rcall	.+288    	; 0x7fd4 <getLen>
-    7eb4:	86 34       	cpi	r24, 0x46	; 70
-    7eb6:	09 f0       	breq	.+2      	; 0x7eba <main+0xba>
-    7eb8:	7b d0       	rcall	.+246    	; 0x7fb0 <appStart>
-  
+
+      getLen();
+    7ea0:	8f d0       	rcall	.+286    	; 0x7fc0 <getLen>
+
       // Immediately start page erase - this will 4.5ms
       boot_page_erase((uint16_t)(void*)address);
-    7eba:	e0 91 00 02 	lds	r30, 0x0200
-    7ebe:	f0 91 01 02 	lds	r31, 0x0201
-    7ec2:	83 e0       	ldi	r24, 0x03	; 3
-    7ec4:	80 93 57 00 	sts	0x0057, r24
-    7ec8:	e8 95       	spm
-    7eca:	c0 e0       	ldi	r28, 0x00	; 0
-    7ecc:	d1 e0       	ldi	r29, 0x01	; 1
+    7ea2:	e0 91 00 02 	lds	r30, 0x0200
+    7ea6:	f0 91 01 02 	lds	r31, 0x0201
+    7eaa:	83 e0       	ldi	r24, 0x03	; 3
+    7eac:	80 93 57 00 	sts	0x0057, r24
+    7eb0:	e8 95       	spm
+    7eb2:	c0 e0       	ldi	r28, 0x00	; 0
+    7eb4:	d1 e0       	ldi	r29, 0x01	; 1
 
       // While that is going on, read in page contents
       bufPtr = buff;
       do *bufPtr++ = getch();
-    7ece:	73 d0       	rcall	.+230    	; 0x7fb6 <getch>
-    7ed0:	89 93       	st	Y+, r24
+    7eb6:	70 d0       	rcall	.+224    	; 0x7f98 <getch>
+    7eb8:	89 93       	st	Y+, r24
       while (--length);
-    7ed2:	80 91 02 02 	lds	r24, 0x0202
-    7ed6:	81 50       	subi	r24, 0x01	; 1
-    7ed8:	80 93 02 02 	sts	0x0202, r24
-    7edc:	88 23       	and	r24, r24
-    7ede:	b9 f7       	brne	.-18     	; 0x7ece <main+0xce>
+    7eba:	80 91 02 02 	lds	r24, 0x0202
+    7ebe:	81 50       	subi	r24, 0x01	; 1
+    7ec0:	80 93 02 02 	sts	0x0202, r24
+    7ec4:	88 23       	and	r24, r24
+    7ec6:	b9 f7       	brne	.-18     	; 0x7eb6 <main+0xb6>
 
+      // Read command terminator, start reply
+      verifySpace();
+    7ec8:	8b d0       	rcall	.+278    	; 0x7fe0 <verifySpace>
+      
       // If only a partial page is to be programmed, the erase might not be complete.
       // So check that here
       boot_spm_busy_wait();
-    7ee0:	07 b6       	in	r0, 0x37	; 55
-    7ee2:	00 fc       	sbrc	r0, 0
-    7ee4:	fd cf       	rjmp	.-6      	; 0x7ee0 <main+0xe0>
+    7eca:	07 b6       	in	r0, 0x37	; 55
+    7ecc:	00 fc       	sbrc	r0, 0
+    7ece:	fd cf       	rjmp	.-6      	; 0x7eca <main+0xca>
 
-      // Read command terminator, start reply
-      verifySpace();
-    7ee6:	7b d0       	rcall	.+246    	; 0x7fde <verifySpace>
-      
       // Copy buffer into programming buffer
       bufPtr = buff;
       addrPtr = (uint16_t)(void*)address;
-    7ee8:	40 91 00 02 	lds	r20, 0x0200
-    7eec:	50 91 01 02 	lds	r21, 0x0201
-    7ef0:	a0 e0       	ldi	r26, 0x00	; 0
-    7ef2:	b1 e0       	ldi	r27, 0x01	; 1
+    7ed0:	40 91 00 02 	lds	r20, 0x0200
+    7ed4:	50 91 01 02 	lds	r21, 0x0201
+    7ed8:	a0 e0       	ldi	r26, 0x00	; 0
+    7eda:	b1 e0       	ldi	r27, 0x01	; 1
       ch = SPM_PAGESIZE / 2;
       do {
         uint16_t a;
         a = *bufPtr++;
-    7ef4:	2c 91       	ld	r18, X
-    7ef6:	30 e0       	ldi	r19, 0x00	; 0
+    7edc:	2c 91       	ld	r18, X
+    7ede:	30 e0       	ldi	r19, 0x00	; 0
         a |= (*bufPtr++) << 8;
-    7ef8:	11 96       	adiw	r26, 0x01	; 1
-    7efa:	8c 91       	ld	r24, X
-    7efc:	11 97       	sbiw	r26, 0x01	; 1
-    7efe:	90 e0       	ldi	r25, 0x00	; 0
-    7f00:	98 2f       	mov	r25, r24
-    7f02:	88 27       	eor	r24, r24
-    7f04:	82 2b       	or	r24, r18
-    7f06:	93 2b       	or	r25, r19
+    7ee0:	11 96       	adiw	r26, 0x01	; 1
+    7ee2:	8c 91       	ld	r24, X
+    7ee4:	11 97       	sbiw	r26, 0x01	; 1
+    7ee6:	90 e0       	ldi	r25, 0x00	; 0
+    7ee8:	98 2f       	mov	r25, r24
+    7eea:	88 27       	eor	r24, r24
+    7eec:	82 2b       	or	r24, r18
+    7eee:	93 2b       	or	r25, r19
 #define buff    ((uint8_t*)(0x100))
 #define address (*(uint16_t*)(0x200))
 #define length  (*(uint8_t*)(0x202))
 
 /* main program starts here */
 int main(void) {
-    7f08:	12 96       	adiw	r26, 0x02	; 2
+    7ef0:	12 96       	adiw	r26, 0x02	; 2
       ch = SPM_PAGESIZE / 2;
       do {
         uint16_t a;
         a = *bufPtr++;
         a |= (*bufPtr++) << 8;
         boot_page_fill((uint16_t)(void*)addrPtr,a);
-    7f0a:	fa 01       	movw	r30, r20
-    7f0c:	0c 01       	movw	r0, r24
-    7f0e:	d0 92 57 00 	sts	0x0057, r13
-    7f12:	e8 95       	spm
-    7f14:	11 24       	eor	r1, r1
+    7ef2:	fa 01       	movw	r30, r20
+    7ef4:	0c 01       	movw	r0, r24
+    7ef6:	d0 92 57 00 	sts	0x0057, r13
+    7efa:	e8 95       	spm
+    7efc:	11 24       	eor	r1, r1
         addrPtr += 2;
-    7f16:	4e 5f       	subi	r20, 0xFE	; 254
-    7f18:	5f 4f       	sbci	r21, 0xFF	; 255
+    7efe:	4e 5f       	subi	r20, 0xFE	; 254
+    7f00:	5f 4f       	sbci	r21, 0xFF	; 255
       } while (--ch);
-    7f1a:	f1 e0       	ldi	r31, 0x01	; 1
-    7f1c:	a0 38       	cpi	r26, 0x80	; 128
-    7f1e:	bf 07       	cpc	r27, r31
-    7f20:	49 f7       	brne	.-46     	; 0x7ef4 <main+0xf4>
+    7f02:	f1 e0       	ldi	r31, 0x01	; 1
+    7f04:	a0 38       	cpi	r26, 0x80	; 128
+    7f06:	bf 07       	cpc	r27, r31
+    7f08:	49 f7       	brne	.-46     	; 0x7edc <main+0xdc>
       
       // Write from programming buffer
       boot_page_write((uint16_t)(void*)address);
-    7f22:	e0 91 00 02 	lds	r30, 0x0200
-    7f26:	f0 91 01 02 	lds	r31, 0x0201
-    7f2a:	e0 92 57 00 	sts	0x0057, r14
-    7f2e:	e8 95       	spm
+    7f0a:	e0 91 00 02 	lds	r30, 0x0200
+    7f0e:	f0 91 01 02 	lds	r31, 0x0201
+    7f12:	e0 92 57 00 	sts	0x0057, r14
+    7f16:	e8 95       	spm
       boot_spm_busy_wait();
-    7f30:	07 b6       	in	r0, 0x37	; 55
-    7f32:	00 fc       	sbrc	r0, 0
-    7f34:	fd cf       	rjmp	.-6      	; 0x7f30 <main+0x130>
+    7f18:	07 b6       	in	r0, 0x37	; 55
+    7f1a:	00 fc       	sbrc	r0, 0
+    7f1c:	fd cf       	rjmp	.-6      	; 0x7f18 <main+0x118>
 
       // Reenable read access to flash
       boot_rww_enable();
-    7f36:	f0 92 57 00 	sts	0x0057, r15
-    7f3a:	e8 95       	spm
-    7f3c:	27 c0       	rjmp	.+78     	; 0x7f8c <main+0x18c>
+    7f1e:	f0 92 57 00 	sts	0x0057, r15
+    7f22:	e8 95       	spm
+    7f24:	27 c0       	rjmp	.+78     	; 0x7f74 <main+0x174>
     }
     /* Read memory block mode, length is big endian.  */
     else if(ch == STK_READ_PAGE) {
-    7f3e:	84 37       	cpi	r24, 0x74	; 116
-    7f40:	b9 f4       	brne	.+46     	; 0x7f70 <main+0x170>
+    7f26:	84 37       	cpi	r24, 0x74	; 116
+    7f28:	b9 f4       	brne	.+46     	; 0x7f58 <main+0x158>
       // READ PAGE - we only read flash
       getLen();
-    7f42:	48 d0       	rcall	.+144    	; 0x7fd4 <getLen>
+    7f2a:	4a d0       	rcall	.+148    	; 0x7fc0 <getLen>
       verifySpace();
-    7f44:	4c d0       	rcall	.+152    	; 0x7fde <verifySpace>
+    7f2c:	59 d0       	rcall	.+178    	; 0x7fe0 <verifySpace>
       do putch(pgm_read_byte_near(address++));
-    7f46:	e0 91 00 02 	lds	r30, 0x0200
-    7f4a:	f0 91 01 02 	lds	r31, 0x0201
-    7f4e:	31 96       	adiw	r30, 0x01	; 1
-    7f50:	f0 93 01 02 	sts	0x0201, r31
-    7f54:	e0 93 00 02 	sts	0x0200, r30
-    7f58:	31 97       	sbiw	r30, 0x01	; 1
-    7f5a:	e4 91       	lpm	r30, Z+
-    7f5c:	8e 2f       	mov	r24, r30
-    7f5e:	19 d0       	rcall	.+50     	; 0x7f92 <putch>
+    7f2e:	e0 91 00 02 	lds	r30, 0x0200
+    7f32:	f0 91 01 02 	lds	r31, 0x0201
+    7f36:	31 96       	adiw	r30, 0x01	; 1
+    7f38:	f0 93 01 02 	sts	0x0201, r31
+    7f3c:	e0 93 00 02 	sts	0x0200, r30
+    7f40:	31 97       	sbiw	r30, 0x01	; 1
+    7f42:	e4 91       	lpm	r30, Z+
+    7f44:	8e 2f       	mov	r24, r30
+    7f46:	19 d0       	rcall	.+50     	; 0x7f7a <putch>
       while (--length);
-    7f60:	80 91 02 02 	lds	r24, 0x0202
-    7f64:	81 50       	subi	r24, 0x01	; 1
-    7f66:	80 93 02 02 	sts	0x0202, r24
-    7f6a:	88 23       	and	r24, r24
-    7f6c:	61 f7       	brne	.-40     	; 0x7f46 <main+0x146>
-    7f6e:	0e c0       	rjmp	.+28     	; 0x7f8c <main+0x18c>
+    7f48:	80 91 02 02 	lds	r24, 0x0202
+    7f4c:	81 50       	subi	r24, 0x01	; 1
+    7f4e:	80 93 02 02 	sts	0x0202, r24
+    7f52:	88 23       	and	r24, r24
+    7f54:	61 f7       	brne	.-40     	; 0x7f2e <main+0x12e>
+    7f56:	0e c0       	rjmp	.+28     	; 0x7f74 <main+0x174>
     }
 
     /* Get device signature bytes  */
     else if(ch == STK_READ_SIGN) {
-    7f70:	85 37       	cpi	r24, 0x75	; 117
-    7f72:	39 f4       	brne	.+14     	; 0x7f82 <main+0x182>
+    7f58:	85 37       	cpi	r24, 0x75	; 117
+    7f5a:	39 f4       	brne	.+14     	; 0x7f6a <main+0x16a>
       // READ SIGN - return what Avrdude wants to hear
       verifySpace();
-    7f74:	34 d0       	rcall	.+104    	; 0x7fde <verifySpace>
+    7f5c:	41 d0       	rcall	.+130    	; 0x7fe0 <verifySpace>
       putch(SIGNATURE_0);
-    7f76:	8e e1       	ldi	r24, 0x1E	; 30
-    7f78:	0c d0       	rcall	.+24     	; 0x7f92 <putch>
+    7f5e:	8e e1       	ldi	r24, 0x1E	; 30
+    7f60:	0c d0       	rcall	.+24     	; 0x7f7a <putch>
       putch(SIGNATURE_1);
-    7f7a:	85 e9       	ldi	r24, 0x95	; 149
-    7f7c:	0a d0       	rcall	.+20     	; 0x7f92 <putch>
+    7f62:	85 e9       	ldi	r24, 0x95	; 149
+    7f64:	0a d0       	rcall	.+20     	; 0x7f7a <putch>
       putch(SIGNATURE_2);
-    7f7e:	8f e0       	ldi	r24, 0x0F	; 15
-    7f80:	93 cf       	rjmp	.-218    	; 0x7ea8 <main+0xa8>
+    7f66:	8f e0       	ldi	r24, 0x0F	; 15
+    7f68:	96 cf       	rjmp	.-212    	; 0x7e96 <main+0x96>
     }
     else if (ch == 'Q') {
-    7f82:	81 35       	cpi	r24, 0x51	; 81
-    7f84:	11 f4       	brne	.+4      	; 0x7f8a <main+0x18a>
+    7f6a:	81 35       	cpi	r24, 0x51	; 81
+    7f6c:	11 f4       	brne	.+4      	; 0x7f72 <main+0x172>
       // Adaboot no-wait mod
-      WDTCSR = _BV(WDE);
-    7f86:	c0 92 60 00 	sts	0x0060, r12
+      watchdogConfig(_BV(WDE));
+    7f6e:	88 e0       	ldi	r24, 0x08	; 8
+    7f70:	2c d0       	rcall	.+88     	; 0x7fca <watchdogConfig>
       verifySpace();
     }
     else {
       // This covers the response to commands like STK_ENTER_PROGMODE
       verifySpace();
-    7f8a:	29 d0       	rcall	.+82     	; 0x7fde <verifySpace>
+    7f72:	36 d0       	rcall	.+108    	; 0x7fe0 <verifySpace>
     }
     putch(STK_OK);
-    7f8c:	80 e1       	ldi	r24, 0x10	; 16
-    7f8e:	01 d0       	rcall	.+2      	; 0x7f92 <putch>
-    7f90:	60 cf       	rjmp	.-320    	; 0x7e52 <main+0x52>
-
-00007f92 <putch>:
-  }
-}
+    7f74:	80 e1       	ldi	r24, 0x10	; 16
+    7f76:	01 d0       	rcall	.+2      	; 0x7f7a <putch>
+    7f78:	63 cf       	rjmp	.-314    	; 0x7e40 <main+0x40>
 
+00007f7a <putch>:
 void putch(char ch) {
-    7f92:	98 2f       	mov	r25, r24
+#ifndef SOFT_UART
   while (!(UCSR0A & _BV(UDRE0)));
-    7f94:	80 91 c0 00 	lds	r24, 0x00C0
-    7f98:	85 ff       	sbrs	r24, 5
-    7f9a:	fc cf       	rjmp	.-8      	; 0x7f94 <putch+0x2>
   UDR0 = ch;
-    7f9c:	90 93 c6 00 	sts	0x00C6, r25
-}
-    7fa0:	08 95       	ret
-
-00007fa2 <setTimer>:
-
-void setTimer(uint16_t counts) {
-  TCNT1 = counts;
-    7fa2:	90 93 85 00 	sts	0x0085, r25
-    7fa6:	80 93 84 00 	sts	0x0084, r24
-  TIFR1 = _BV(TOV1);
-    7faa:	81 e0       	ldi	r24, 0x01	; 1
-    7fac:	86 bb       	out	0x16, r24	; 22
+#else
+  __asm__ __volatile__ (
+    7f7a:	2a e0       	ldi	r18, 0x0A	; 10
+    7f7c:	30 e0       	ldi	r19, 0x00	; 0
+    7f7e:	80 95       	com	r24
+    7f80:	08 94       	sec
+    7f82:	10 f4       	brcc	.+4      	; 0x7f88 <putch+0xe>
+    7f84:	59 98       	cbi	0x0b, 1	; 11
+    7f86:	02 c0       	rjmp	.+4      	; 0x7f8c <putch+0x12>
+    7f88:	59 9a       	sbi	0x0b, 1	; 11
+    7f8a:	00 00       	nop
+    7f8c:	15 d0       	rcall	.+42     	; 0x7fb8 <uartDelay>
+    7f8e:	14 d0       	rcall	.+40     	; 0x7fb8 <uartDelay>
+    7f90:	86 95       	lsr	r24
+    7f92:	2a 95       	dec	r18
+    7f94:	b1 f7       	brne	.-20     	; 0x7f82 <putch+0x8>
+      [uartBit] "I" (UART_TX_BIT)
+    :
+      "r25"
+  );
+#endif
 }
-    7fae:	08 95       	ret
+    7f96:	08 95       	ret
 
-00007fb0 <appStart>:
-  length = getch();
+00007f98 <getch>:
   return getch();
 }
 
-void appStart() {
+// Watchdog functions. These are only safe with interrupts turned off.
+void watchdogReset() {
   __asm__ __volatile__ (
-    7fb0:	ee 27       	eor	r30, r30
-    7fb2:	ff 27       	eor	r31, r31
-    7fb4:	09 94       	ijmp
+    7f98:	a8 95       	wdr
+#ifdef LED_DATA_FLASH
+  LED_PIN |= _BV(LED);
+#endif
 
-00007fb6 <getch>:
-  TCNT1 = counts;
-  TIFR1 = _BV(TOV1);
+  return ch;
 }
+    7f9a:	29 e0       	ldi	r18, 0x09	; 9
+    7f9c:	30 e0       	ldi	r19, 0x00	; 0
+    7f9e:	48 99       	sbic	0x09, 0	; 9
+    7fa0:	fe cf       	rjmp	.-4      	; 0x7f9e <getch+0x6>
+    7fa2:	0a d0       	rcall	.+20     	; 0x7fb8 <uartDelay>
+    7fa4:	09 d0       	rcall	.+18     	; 0x7fb8 <uartDelay>
+    7fa6:	08 d0       	rcall	.+16     	; 0x7fb8 <uartDelay>
+    7fa8:	88 94       	clc
+    7faa:	48 99       	sbic	0x09, 0	; 9
+    7fac:	08 94       	sec
+    7fae:	2a 95       	dec	r18
+    7fb0:	11 f0       	breq	.+4      	; 0x7fb6 <getch+0x1e>
+    7fb2:	87 95       	ror	r24
+    7fb4:	f7 cf       	rjmp	.-18     	; 0x7fa4 <getch+0xc>
+    7fb6:	08 95       	ret
+
+00007fb8 <uartDelay>:
+#if UART_B_VALUE > 255
+#error Baud rate too slow for soft UART
+#endif
 
-uint8_t getch(void) {
-  LED_PORT &= ~_BV(LED);
-    7fb6:	2d 98       	cbi	0x05, 5	; 5
-  setTimer(-(F_CPU/(1024*2))); // 500ms
-    7fb8:	8c e7       	ldi	r24, 0x7C	; 124
-    7fba:	91 ee       	ldi	r25, 0xE1	; 225
-    7fbc:	f2 df       	rcall	.-28     	; 0x7fa2 <setTimer>
-    7fbe:	02 c0       	rjmp	.+4      	; 0x7fc4 <getch+0xe>
-  while(!(UCSR0A & _BV(RXC0))) if (TIFR1 & _BV(TOV1)) appStart();
-    7fc0:	b0 99       	sbic	0x16, 0	; 22
-    7fc2:	f6 df       	rcall	.-20     	; 0x7fb0 <appStart>
-    7fc4:	80 91 c0 00 	lds	r24, 0x00C0
-    7fc8:	87 ff       	sbrs	r24, 7
-    7fca:	fa cf       	rjmp	.-12     	; 0x7fc0 <getch+0xa>
-  LED_PORT |= _BV(LED);
-    7fcc:	2d 9a       	sbi	0x05, 5	; 5
-  return UDR0;
-    7fce:	80 91 c6 00 	lds	r24, 0x00C6
-}
-    7fd2:	08 95       	ret
+void uartDelay() {
+  __asm__ __volatile__ (
+    7fb8:	98 e0       	ldi	r25, 0x08	; 8
+    7fba:	9a 95       	dec	r25
+    7fbc:	f1 f7       	brne	.-4      	; 0x7fba <uartDelay+0x2>
+    7fbe:	08 95       	ret
 
-00007fd4 <getLen>:
-    LED_PIN |= _BV(LED);
+00007fc0 <getLen>:
   } while (--count);
 }
+#endif
 
 uint8_t getLen() {
   getch();
-    7fd4:	f0 df       	rcall	.-32     	; 0x7fb6 <getch>
+    7fc0:	eb df       	rcall	.-42     	; 0x7f98 <getch>
   length = getch();
-    7fd6:	ef df       	rcall	.-34     	; 0x7fb6 <getch>
-    7fd8:	80 93 02 02 	sts	0x0202, r24
+    7fc2:	ea df       	rcall	.-44     	; 0x7f98 <getch>
+    7fc4:	80 93 02 02 	sts	0x0202, r24
   return getch();
 }
-    7fdc:	ec cf       	rjmp	.-40     	; 0x7fb6 <getch>
+    7fc8:	e7 cf       	rjmp	.-50     	; 0x7f98 <getch>
+
+00007fca <watchdogConfig>:
+    "wdr\n"
+  );
+}
 
-00007fde <verifySpace>:
+void watchdogConfig(uint8_t x) {
+  WDTCSR = _BV(WDCE) | _BV(WDE);
+    7fca:	e0 e6       	ldi	r30, 0x60	; 96
+    7fcc:	f0 e0       	ldi	r31, 0x00	; 0
+    7fce:	98 e1       	ldi	r25, 0x18	; 24
+    7fd0:	90 83       	st	Z, r25
+  WDTCSR = x;
+    7fd2:	80 83       	st	Z, r24
+}
+    7fd4:	08 95       	ret
+
+00007fd6 <appStart>:
+
+void appStart() {
+  watchdogConfig(0);
+    7fd6:	80 e0       	ldi	r24, 0x00	; 0
+    7fd8:	f8 df       	rcall	.-16     	; 0x7fca <watchdogConfig>
+  __asm__ __volatile__ (
+    7fda:	ee 27       	eor	r30, r30
+    7fdc:	ff 27       	eor	r31, r31
+    7fde:	09 94       	ijmp
+
+00007fe0 <verifySpace>:
   do getch(); while (--count);
   verifySpace();
 }
 
 void verifySpace() {
   if (getch() != CRC_EOP) appStart();
-    7fde:	eb df       	rcall	.-42     	; 0x7fb6 <getch>
-    7fe0:	80 32       	cpi	r24, 0x20	; 32
-    7fe2:	09 f0       	breq	.+2      	; 0x7fe6 <verifySpace+0x8>
-    7fe4:	e5 df       	rcall	.-54     	; 0x7fb0 <appStart>
+    7fe0:	db df       	rcall	.-74     	; 0x7f98 <getch>
+    7fe2:	80 32       	cpi	r24, 0x20	; 32
+    7fe4:	09 f0       	breq	.+2      	; 0x7fe8 <verifySpace+0x8>
+    7fe6:	f7 df       	rcall	.-18     	; 0x7fd6 <appStart>
   putch(STK_INSYNC);
-    7fe6:	84 e1       	ldi	r24, 0x14	; 20
+    7fe8:	84 e1       	ldi	r24, 0x14	; 20
 }
-    7fe8:	d4 cf       	rjmp	.-88     	; 0x7f92 <putch>
-  while(!(UCSR0A & _BV(RXC0))) if (TIFR1 & _BV(TOV1)) appStart();
-  LED_PORT |= _BV(LED);
-  return UDR0;
+    7fea:	c7 cf       	rjmp	.-114    	; 0x7f7a <putch>
+    ::[count] "M" (UART_B_VALUE)
+  );
 }
+#endif
 
 void getNch(uint8_t count) {
-    7fea:	1f 93       	push	r17
-    7fec:	18 2f       	mov	r17, r24
+    7fec:	1f 93       	push	r17
+    7fee:	18 2f       	mov	r17, r24
 
-00007fee <getNch>:
+00007ff0 <getNch>:
   do getch(); while (--count);
-    7fee:	e3 df       	rcall	.-58     	; 0x7fb6 <getch>
-    7ff0:	11 50       	subi	r17, 0x01	; 1
-    7ff2:	e9 f7       	brne	.-6      	; 0x7fee <getNch>
+    7ff0:	d3 df       	rcall	.-90     	; 0x7f98 <getch>
+    7ff2:	11 50       	subi	r17, 0x01	; 1
+    7ff4:	e9 f7       	brne	.-6      	; 0x7ff0 <getNch>
   verifySpace();
-    7ff4:	f4 df       	rcall	.-24     	; 0x7fde <verifySpace>
+    7ff6:	f4 df       	rcall	.-24     	; 0x7fe0 <verifySpace>
 }
-    7ff6:	1f 91       	pop	r17
-    7ff8:	08 95       	ret
+    7ff8:	1f 91       	pop	r17
+    7ffa:	08 95       	ret

+ 32 - 32
optiboot/bootloaders/optiboot/optiboot_atmega328_pro_8MHz.hex

@@ -1,34 +1,34 @@
-:107E000085E08093810082E08093C00098E19093A8
-:107E1000C10086E08093C20080E18093C40084B7F3
-:107E200014BE909360001092600081FFC1D0259A2B
-:107E300002E088E19EEFB5D0B09BFECF1D9A0150C5
-:107E4000C1F7DD24D394B8E0CB2EA5E0EA2EF1E112
-:107E5000FF2EB1D0813421F481E0C7D083E024C06B
-:107E6000823411F484E103C0853419F485E0BDD077
-:107E70008DC08535A1F49FD0082F10E0109301022A
-:107E80000093000298D090E0982F8827802B912BA8
-:107E9000880F991F909301028093000276C0863567
-:107EA00029F484E0A2D080E074D070C0843609F058
-:107EB00046C090D0863409F07BD0E0910002F0916A
-:107EC000010283E080935700E895C0E0D1E073D0D1
-:107ED0008993809102028150809302028823B9F72E
-:107EE00007B600FCFDCF7BD040910002509101020B
-:107EF000A0E0B1E02C9130E011968C91119790E0C8
-:107F0000982F8827822B932B1296FA010C01D0927E
-:107F10005700E89511244E5F5F4FF1E0A038BF078E
-:107F200049F7E0910002F0910102E0925700E895D4
-:107F300007B600FCFDCFF0925700E89527C08437C4
-:107F4000B9F448D04CD0E0910002F0910102319692
-:107F5000F0930102E09300023197E4918E2F19D043
-:107F600080910202815080930202882361F70EC043
-:107F7000853739F434D08EE10CD085E90AD08FE012
-:107F800093CF813511F4C092600029D080E101D0F7
-:107F900060CF982F8091C00085FFFCCF9093C600E2
-:107FA0000895909385008093840081E086BB0895B6
-:107FB000EE27FF2709942D988EEB90EFF2DF02C099
-:107FC000B099F6DF8091C00087FFFACF2D9A80919B
-:107FD000C6000895F0DFEFDF80930202ECCFEBDF05
-:107FE000803209F0E5DF84E1D4CF1F93182FE3DF5F
-:0A7FF0001150E9F7F4DF1F91089526
+:107E000085E08093810084B714BE81FFE4D08DE0CB
+:107E1000DCD0259A519A86E028E13EEF91E030933C
+:107E200085002093840096BBB09BFECF1D9AA89539
+:107E30008150A9F7DD24D394A5E0EA2EF1E1FF2ECD
+:107E4000ABD0813421F481E0D1D083E024C08234EE
+:107E500011F484E103C0853419F485E0C7D08AC0E9
+:107E60008535A1F499D0082F10E0109301020093FA
+:107E7000000292D090E0982F8827802B912B880FBA
+:107E8000991F909301028093000273C0863529F4F4
+:107E900084E0ACD080E071D06DC0843609F043C07E
+:107EA0008FD0E0910002F091010283E080935700AF
+:107EB000E895C0E0D1E070D08993809102028150B2
+:107EC000809302028823B9F78BD007B600FCFDCF60
+:107ED0004091000250910102A0E0B1E02C9130E00D
+:107EE00011968C91119790E0982F8827822B932BD5
+:107EF0001296FA010C01D0925700E89511244E5FBA
+:107F00005F4FF1E0A038BF0749F7E0910002F09120
+:107F10000102E0925700E89507B600FCFDCFF09211
+:107F20005700E89527C08437B9F44AD059D0E0917A
+:107F30000002F09101023196F0930102E0930002F9
+:107F40003197E4918E2F19D0809102028150809355
+:107F50000202882361F70EC0853739F441D08EE1E3
+:107F60000CD085E90AD08FE096CF813511F488E0F6
+:107F70002CD036D080E101D063CF2AE030E080956C
+:107F8000089410F4599802C0599A000015D014D0E2
+:107F900086952A95B1F70895A89529E030E048998B
+:107FA000FECF0AD009D008D08894489908942A9521
+:107FB00011F08795F7CF089598E09A95F1F7089515
+:107FC000EBDFEADF80930202E7CFE0E6F0E098E142
+:107FD00090838083089580E0F8DFEE27FF270994DF
+:107FE000DBDF803209F0F7DF84E1C7CF1F93182F62
+:0C7FF000D3DF1150E9F7F4DF1F91089572
 :0400000300007E007B
 :00000001FF

+ 320 - 282
optiboot/bootloaders/optiboot/optiboot_atmega328_pro_8MHz.lst

@@ -3,25 +3,25 @@ optiboot_atmega328_pro_8MHz.elf:     file format elf32-avr
 
 Sections:
 Idx Name          Size      VMA       LMA       File off  Algn
-  0 .text         000001fa  00007e00  00007e00  00000054  2**1
+  0 .text         000001fc  00007e00  00007e00  00000054  2**1
                   CONTENTS, ALLOC, LOAD, READONLY, CODE
-  1 .debug_aranges 00000028  00000000  00000000  0000024e  2**0
+  1 .debug_aranges 00000028  00000000  00000000  00000250  2**0
                   CONTENTS, READONLY, DEBUGGING
-  2 .debug_pubnames 00000064  00000000  00000000  00000276  2**0
+  2 .debug_pubnames 00000078  00000000  00000000  00000278  2**0
                   CONTENTS, READONLY, DEBUGGING
-  3 .debug_info   0000022f  00000000  00000000  000002da  2**0
+  3 .debug_info   00000275  00000000  00000000  000002f0  2**0
                   CONTENTS, READONLY, DEBUGGING
-  4 .debug_abbrev 00000164  00000000  00000000  00000509  2**0
+  4 .debug_abbrev 000001a3  00000000  00000000  00000565  2**0
                   CONTENTS, READONLY, DEBUGGING
-  5 .debug_line   000003c8  00000000  00000000  0000066d  2**0
+  5 .debug_line   000003b8  00000000  00000000  00000708  2**0
                   CONTENTS, READONLY, DEBUGGING
-  6 .debug_frame  00000090  00000000  00000000  00000a38  2**2
+  6 .debug_frame  000000a0  00000000  00000000  00000ac0  2**2
                   CONTENTS, READONLY, DEBUGGING
-  7 .debug_str    0000011c  00000000  00000000  00000ac8  2**0
+  7 .debug_str    00000133  00000000  00000000  00000b60  2**0
                   CONTENTS, READONLY, DEBUGGING
-  8 .debug_loc    000001d6  00000000  00000000  00000be4  2**0
+  8 .debug_loc    000001a0  00000000  00000000  00000c93  2**0
                   CONTENTS, READONLY, DEBUGGING
-  9 .debug_ranges 00000068  00000000  00000000  00000dba  2**0
+  9 .debug_ranges 00000070  00000000  00000000  00000e33  2**0
                   CONTENTS, READONLY, DEBUGGING
 
 Disassembly of section .text:
@@ -35,449 +35,487 @@ Disassembly of section .text:
 int main(void) {
     7e00:	85 e0       	ldi	r24, 0x05	; 5
     7e02:	80 93 81 00 	sts	0x0081, r24
-    [addr5]"i"(_SFR_MEM_ADDR(UBRR0L)), [val5]"i"((F_CPU + BAUD_RATE * 4L) / (BAUD_RATE * 8L) - 1)
-  );
-#else
-  // Set up Timer 1 for timeout counter
-  TCCR1B = _BV(CS12) | _BV(CS10); // div 1024
-  UCSR0A = _BV(U2X0); //Double speed mode USART0
-    7e06:	82 e0       	ldi	r24, 0x02	; 2
-    7e08:	80 93 c0 00 	sts	0x00C0, r24
-  UCSR0B = _BV(RXEN0) | _BV(TXEN0);
-    7e0c:	98 e1       	ldi	r25, 0x18	; 24
-    7e0e:	90 93 c1 00 	sts	0x00C1, r25
   UCSR0C = _BV(UCSZ00) | _BV(UCSZ01);
-    7e12:	86 e0       	ldi	r24, 0x06	; 6
-    7e14:	80 93 c2 00 	sts	0x00C2, r24
   UBRR0L = (uint8_t)( (F_CPU + BAUD_RATE * 4L) / (BAUD_RATE * 8L) - 1 );
-    7e18:	80 e1       	ldi	r24, 0x10	; 16
-    7e1a:	80 93 c4 00 	sts	0x00C4, r24
 #endif
 
   // Adaboot no-wait mod
   ch = MCUSR;
-    7e1e:	84 b7       	in	r24, 0x34	; 52
+    7e06:	84 b7       	in	r24, 0x34	; 52
   MCUSR = 0;
-    7e20:	14 be       	out	0x34, r1	; 52
-  WDTCSR = _BV(WDCE) | _BV(WDE);
-    7e22:	90 93 60 00 	sts	0x0060, r25
-  WDTCSR = 0;
-    7e26:	10 92 60 00 	sts	0x0060, r1
+    7e08:	14 be       	out	0x34, r1	; 52
   if (!(ch & _BV(EXTRF))) appStart();
-    7e2a:	81 ff       	sbrs	r24, 1
-    7e2c:	c1 d0       	rcall	.+386    	; 0x7fb0 <appStart>
+    7e0a:	81 ff       	sbrs	r24, 1
+    7e0c:	e4 d0       	rcall	.+456    	; 0x7fd6 <appStart>
+
+  // Set up watchdog to trigger after 500ms
+  watchdogConfig(_BV(WDP2)|_BV(WDP0)|_BV(WDE));
+    7e0e:	8d e0       	ldi	r24, 0x0D	; 13
+    7e10:	dc d0       	rcall	.+440    	; 0x7fca <watchdogConfig>
 
-  /* set LED pin as output */
+  /* Set LED pin as output */
   LED_DDR |= _BV(LED);
-    7e2e:	25 9a       	sbi	0x04, 5	; 4
-    7e30:	02 e0       	ldi	r16, 0x02	; 2
-  putch(STK_INSYNC);
+    7e12:	25 9a       	sbi	0x04, 5	; 4
+
+#ifdef SOFT_UART
+  /* Set TX pin as output */
+  UART_DDR |= _BV(UART_TX_BIT);
+    7e14:	51 9a       	sbi	0x0a, 1	; 10
+    7e16:	86 e0       	ldi	r24, 0x06	; 6
+}
+
+#if LED_START_FLASHES > 0
+void flash_led(uint8_t count) {
+  do {
+    TCNT1 = -(F_CPU/(1024*16));
+    7e18:	28 e1       	ldi	r18, 0x18	; 24
+    7e1a:	3e ef       	ldi	r19, 0xFE	; 254
+    TIFR1 = _BV(TOV1);
+    7e1c:	91 e0       	ldi	r25, 0x01	; 1
 }
 
+#if LED_START_FLASHES > 0
 void flash_led(uint8_t count) {
   do {
-    setTimer(-(F_CPU/(1024*16))); // 62ms
-    7e32:	88 e1       	ldi	r24, 0x18	; 24
-    7e34:	9e ef       	ldi	r25, 0xFE	; 254
-    7e36:	b5 d0       	rcall	.+362    	; 0x7fa2 <setTimer>
+    TCNT1 = -(F_CPU/(1024*16));
+    7e1e:	30 93 85 00 	sts	0x0085, r19
+    7e22:	20 93 84 00 	sts	0x0084, r18
+    TIFR1 = _BV(TOV1);
+    7e26:	96 bb       	out	0x16, r25	; 22
+    while(!(TIFR1 & _BV(TOV1)));
+    7e28:	b0 9b       	sbis	0x16, 0	; 22
+    7e2a:	fe cf       	rjmp	.-4      	; 0x7e28 <main+0x28>
+    LED_PIN |= _BV(LED);
+    7e2c:	1d 9a       	sbi	0x03, 5	; 3
+  return getch();
+}
+
+// Watchdog functions. These are only safe with interrupts turned off.
+void watchdogReset() {
+  __asm__ __volatile__ (
+    7e2e:	a8 95       	wdr
+    TCNT1 = -(F_CPU/(1024*16));
+    TIFR1 = _BV(TOV1);
     while(!(TIFR1 & _BV(TOV1)));
-    7e38:	b0 9b       	sbis	0x16, 0	; 22
-    7e3a:	fe cf       	rjmp	.-4      	; 0x7e38 <main+0x38>
     LED_PIN |= _BV(LED);
-    7e3c:	1d 9a       	sbi	0x03, 5	; 3
+    watchdogReset();
   } while (--count);
-    7e3e:	01 50       	subi	r16, 0x01	; 1
-    7e40:	c1 f7       	brne	.-16     	; 0x7e32 <main+0x32>
+    7e30:	81 50       	subi	r24, 0x01	; 1
+    7e32:	a9 f7       	brne	.-22     	; 0x7e1e <main+0x1e>
     /* get character from UART */
     ch = getch();
 
     if(ch == STK_GET_PARAMETER) {
       // GET PARAMETER returns a generic 0x03 reply - enough to keep Avrdude happy
       getNch(1);
-    7e42:	dd 24       	eor	r13, r13
-    7e44:	d3 94       	inc	r13
-      putch(SIGNATURE_1);
-      putch(SIGNATURE_2);
-    }
-    else if (ch == 'Q') {
-      // Adaboot no-wait mod
-      WDTCSR = _BV(WDE);
-    7e46:	b8 e0       	ldi	r27, 0x08	; 8
-    7e48:	cb 2e       	mov	r12, r27
+    7e34:	dd 24       	eor	r13, r13
+    7e36:	d3 94       	inc	r13
         boot_page_fill((uint16_t)(void*)addrPtr,a);
         addrPtr += 2;
       } while (--ch);
       
       // Write from programming buffer
       boot_page_write((uint16_t)(void*)address);
-    7e4a:	a5 e0       	ldi	r26, 0x05	; 5
-    7e4c:	ea 2e       	mov	r14, r26
+    7e38:	a5 e0       	ldi	r26, 0x05	; 5
+    7e3a:	ea 2e       	mov	r14, r26
       boot_spm_busy_wait();
 
       // Reenable read access to flash
       boot_rww_enable();
-    7e4e:	f1 e1       	ldi	r31, 0x11	; 17
-    7e50:	ff 2e       	mov	r15, r31
-  flash_led(NUM_LED_FLASHES * 2);
+    7e3c:	f1 e1       	ldi	r31, 0x11	; 17
+    7e3e:	ff 2e       	mov	r15, r31
+#endif
 
-  /* forever loop */
+  /* Forever loop */
   for (;;) {
     /* get character from UART */
     ch = getch();
-    7e52:	b1 d0       	rcall	.+354    	; 0x7fb6 <getch>
+    7e40:	ab d0       	rcall	.+342    	; 0x7f98 <getch>
 
     if(ch == STK_GET_PARAMETER) {
-    7e54:	81 34       	cpi	r24, 0x41	; 65
-    7e56:	21 f4       	brne	.+8      	; 0x7e60 <main+0x60>
+    7e42:	81 34       	cpi	r24, 0x41	; 65
+    7e44:	21 f4       	brne	.+8      	; 0x7e4e <main+0x4e>
       // GET PARAMETER returns a generic 0x03 reply - enough to keep Avrdude happy
       getNch(1);
-    7e58:	81 e0       	ldi	r24, 0x01	; 1
-    7e5a:	c7 d0       	rcall	.+398    	; 0x7fea <verifySpace+0xc>
+    7e46:	81 e0       	ldi	r24, 0x01	; 1
+    7e48:	d1 d0       	rcall	.+418    	; 0x7fec <verifySpace+0xc>
       putch(0x03);
-    7e5c:	83 e0       	ldi	r24, 0x03	; 3
-    7e5e:	24 c0       	rjmp	.+72     	; 0x7ea8 <main+0xa8>
+    7e4a:	83 e0       	ldi	r24, 0x03	; 3
+    7e4c:	24 c0       	rjmp	.+72     	; 0x7e96 <main+0x96>
     }
     else if(ch == STK_SET_DEVICE) {
-    7e60:	82 34       	cpi	r24, 0x42	; 66
-    7e62:	11 f4       	brne	.+4      	; 0x7e68 <main+0x68>
+    7e4e:	82 34       	cpi	r24, 0x42	; 66
+    7e50:	11 f4       	brne	.+4      	; 0x7e56 <main+0x56>
       // SET DEVICE is ignored
       getNch(20);
-    7e64:	84 e1       	ldi	r24, 0x14	; 20
-    7e66:	03 c0       	rjmp	.+6      	; 0x7e6e <main+0x6e>
+    7e52:	84 e1       	ldi	r24, 0x14	; 20
+    7e54:	03 c0       	rjmp	.+6      	; 0x7e5c <main+0x5c>
     }
     else if(ch == STK_SET_DEVICE_EXT) {
-    7e68:	85 34       	cpi	r24, 0x45	; 69
-    7e6a:	19 f4       	brne	.+6      	; 0x7e72 <main+0x72>
+    7e56:	85 34       	cpi	r24, 0x45	; 69
+    7e58:	19 f4       	brne	.+6      	; 0x7e60 <main+0x60>
       // SET DEVICE EXT is ignored
       getNch(5);
-    7e6c:	85 e0       	ldi	r24, 0x05	; 5
-    7e6e:	bd d0       	rcall	.+378    	; 0x7fea <verifySpace+0xc>
-    7e70:	8d c0       	rjmp	.+282    	; 0x7f8c <main+0x18c>
+    7e5a:	85 e0       	ldi	r24, 0x05	; 5
+    7e5c:	c7 d0       	rcall	.+398    	; 0x7fec <verifySpace+0xc>
+    7e5e:	8a c0       	rjmp	.+276    	; 0x7f74 <main+0x174>
     }
     else if(ch == STK_LOAD_ADDRESS) {
-    7e72:	85 35       	cpi	r24, 0x55	; 85
-    7e74:	a1 f4       	brne	.+40     	; 0x7e9e <main+0x9e>
+    7e60:	85 35       	cpi	r24, 0x55	; 85
+    7e62:	a1 f4       	brne	.+40     	; 0x7e8c <main+0x8c>
       // LOAD ADDRESS
       address = getch();
-    7e76:	9f d0       	rcall	.+318    	; 0x7fb6 <getch>
-    7e78:	08 2f       	mov	r16, r24
-    7e7a:	10 e0       	ldi	r17, 0x00	; 0
-    7e7c:	10 93 01 02 	sts	0x0201, r17
-    7e80:	00 93 00 02 	sts	0x0200, r16
+    7e64:	99 d0       	rcall	.+306    	; 0x7f98 <getch>
+    7e66:	08 2f       	mov	r16, r24
+    7e68:	10 e0       	ldi	r17, 0x00	; 0
+    7e6a:	10 93 01 02 	sts	0x0201, r17
+    7e6e:	00 93 00 02 	sts	0x0200, r16
       address = (address & 0xff) | (getch() << 8);
-    7e84:	98 d0       	rcall	.+304    	; 0x7fb6 <getch>
-    7e86:	90 e0       	ldi	r25, 0x00	; 0
-    7e88:	98 2f       	mov	r25, r24
-    7e8a:	88 27       	eor	r24, r24
-    7e8c:	80 2b       	or	r24, r16
-    7e8e:	91 2b       	or	r25, r17
+    7e72:	92 d0       	rcall	.+292    	; 0x7f98 <getch>
+    7e74:	90 e0       	ldi	r25, 0x00	; 0
+    7e76:	98 2f       	mov	r25, r24
+    7e78:	88 27       	eor	r24, r24
+    7e7a:	80 2b       	or	r24, r16
+    7e7c:	91 2b       	or	r25, r17
       address += address; // Convert from word address to byte address
-    7e90:	88 0f       	add	r24, r24
-    7e92:	99 1f       	adc	r25, r25
-    7e94:	90 93 01 02 	sts	0x0201, r25
-    7e98:	80 93 00 02 	sts	0x0200, r24
-    7e9c:	76 c0       	rjmp	.+236    	; 0x7f8a <main+0x18a>
+    7e7e:	88 0f       	add	r24, r24
+    7e80:	99 1f       	adc	r25, r25
+    7e82:	90 93 01 02 	sts	0x0201, r25
+    7e86:	80 93 00 02 	sts	0x0200, r24
+    7e8a:	73 c0       	rjmp	.+230    	; 0x7f72 <main+0x172>
       verifySpace();
     }
     else if(ch == STK_UNIVERSAL) {
-    7e9e:	86 35       	cpi	r24, 0x56	; 86
-    7ea0:	29 f4       	brne	.+10     	; 0x7eac <main+0xac>
+    7e8c:	86 35       	cpi	r24, 0x56	; 86
+    7e8e:	29 f4       	brne	.+10     	; 0x7e9a <main+0x9a>
       // UNIVERSAL command is ignored
       getNch(4);
-    7ea2:	84 e0       	ldi	r24, 0x04	; 4
-    7ea4:	a2 d0       	rcall	.+324    	; 0x7fea <verifySpace+0xc>
+    7e90:	84 e0       	ldi	r24, 0x04	; 4
+    7e92:	ac d0       	rcall	.+344    	; 0x7fec <verifySpace+0xc>
       putch(0x00);
-    7ea6:	80 e0       	ldi	r24, 0x00	; 0
-    7ea8:	74 d0       	rcall	.+232    	; 0x7f92 <putch>
-    7eaa:	70 c0       	rjmp	.+224    	; 0x7f8c <main+0x18c>
+    7e94:	80 e0       	ldi	r24, 0x00	; 0
+    7e96:	71 d0       	rcall	.+226    	; 0x7f7a <putch>
+    7e98:	6d c0       	rjmp	.+218    	; 0x7f74 <main+0x174>
     }
     /* Write memory, length is big endian and is in bytes  */
     else if(ch == STK_PROG_PAGE) {
-    7eac:	84 36       	cpi	r24, 0x64	; 100
-    7eae:	09 f0       	breq	.+2      	; 0x7eb2 <main+0xb2>
-    7eb0:	46 c0       	rjmp	.+140    	; 0x7f3e <main+0x13e>
+    7e9a:	84 36       	cpi	r24, 0x64	; 100
+    7e9c:	09 f0       	breq	.+2      	; 0x7ea0 <main+0xa0>
+    7e9e:	43 c0       	rjmp	.+134    	; 0x7f26 <main+0x126>
       // PROGRAM PAGE - we support flash programming only, not EEPROM
       uint8_t *bufPtr;
       uint16_t addrPtr;
-      
-      if (getLen() != 'F') appStart(); // Abort is not flash programming
-    7eb2:	90 d0       	rcall	.+288    	; 0x7fd4 <getLen>
-    7eb4:	86 34       	cpi	r24, 0x46	; 70
-    7eb6:	09 f0       	breq	.+2      	; 0x7eba <main+0xba>
-    7eb8:	7b d0       	rcall	.+246    	; 0x7fb0 <appStart>
-  
+
+      getLen();
+    7ea0:	8f d0       	rcall	.+286    	; 0x7fc0 <getLen>
+
       // Immediately start page erase - this will 4.5ms
       boot_page_erase((uint16_t)(void*)address);
-    7eba:	e0 91 00 02 	lds	r30, 0x0200
-    7ebe:	f0 91 01 02 	lds	r31, 0x0201
-    7ec2:	83 e0       	ldi	r24, 0x03	; 3
-    7ec4:	80 93 57 00 	sts	0x0057, r24
-    7ec8:	e8 95       	spm
-    7eca:	c0 e0       	ldi	r28, 0x00	; 0
-    7ecc:	d1 e0       	ldi	r29, 0x01	; 1
+    7ea2:	e0 91 00 02 	lds	r30, 0x0200
+    7ea6:	f0 91 01 02 	lds	r31, 0x0201
+    7eaa:	83 e0       	ldi	r24, 0x03	; 3
+    7eac:	80 93 57 00 	sts	0x0057, r24
+    7eb0:	e8 95       	spm
+    7eb2:	c0 e0       	ldi	r28, 0x00	; 0
+    7eb4:	d1 e0       	ldi	r29, 0x01	; 1
 
       // While that is going on, read in page contents
       bufPtr = buff;
       do *bufPtr++ = getch();
-    7ece:	73 d0       	rcall	.+230    	; 0x7fb6 <getch>
-    7ed0:	89 93       	st	Y+, r24
+    7eb6:	70 d0       	rcall	.+224    	; 0x7f98 <getch>
+    7eb8:	89 93       	st	Y+, r24
       while (--length);
-    7ed2:	80 91 02 02 	lds	r24, 0x0202
-    7ed6:	81 50       	subi	r24, 0x01	; 1
-    7ed8:	80 93 02 02 	sts	0x0202, r24
-    7edc:	88 23       	and	r24, r24
-    7ede:	b9 f7       	brne	.-18     	; 0x7ece <main+0xce>
+    7eba:	80 91 02 02 	lds	r24, 0x0202
+    7ebe:	81 50       	subi	r24, 0x01	; 1
+    7ec0:	80 93 02 02 	sts	0x0202, r24
+    7ec4:	88 23       	and	r24, r24
+    7ec6:	b9 f7       	brne	.-18     	; 0x7eb6 <main+0xb6>
 
+      // Read command terminator, start reply
+      verifySpace();
+    7ec8:	8b d0       	rcall	.+278    	; 0x7fe0 <verifySpace>
+      
       // If only a partial page is to be programmed, the erase might not be complete.
       // So check that here
       boot_spm_busy_wait();
-    7ee0:	07 b6       	in	r0, 0x37	; 55
-    7ee2:	00 fc       	sbrc	r0, 0
-    7ee4:	fd cf       	rjmp	.-6      	; 0x7ee0 <main+0xe0>
+    7eca:	07 b6       	in	r0, 0x37	; 55
+    7ecc:	00 fc       	sbrc	r0, 0
+    7ece:	fd cf       	rjmp	.-6      	; 0x7eca <main+0xca>
 
-      // Read command terminator, start reply
-      verifySpace();
-    7ee6:	7b d0       	rcall	.+246    	; 0x7fde <verifySpace>
-      
       // Copy buffer into programming buffer
       bufPtr = buff;
       addrPtr = (uint16_t)(void*)address;
-    7ee8:	40 91 00 02 	lds	r20, 0x0200
-    7eec:	50 91 01 02 	lds	r21, 0x0201
-    7ef0:	a0 e0       	ldi	r26, 0x00	; 0
-    7ef2:	b1 e0       	ldi	r27, 0x01	; 1
+    7ed0:	40 91 00 02 	lds	r20, 0x0200
+    7ed4:	50 91 01 02 	lds	r21, 0x0201
+    7ed8:	a0 e0       	ldi	r26, 0x00	; 0
+    7eda:	b1 e0       	ldi	r27, 0x01	; 1
       ch = SPM_PAGESIZE / 2;
       do {
         uint16_t a;
         a = *bufPtr++;
-    7ef4:	2c 91       	ld	r18, X
-    7ef6:	30 e0       	ldi	r19, 0x00	; 0
+    7edc:	2c 91       	ld	r18, X
+    7ede:	30 e0       	ldi	r19, 0x00	; 0
         a |= (*bufPtr++) << 8;
-    7ef8:	11 96       	adiw	r26, 0x01	; 1
-    7efa:	8c 91       	ld	r24, X
-    7efc:	11 97       	sbiw	r26, 0x01	; 1
-    7efe:	90 e0       	ldi	r25, 0x00	; 0
-    7f00:	98 2f       	mov	r25, r24
-    7f02:	88 27       	eor	r24, r24
-    7f04:	82 2b       	or	r24, r18
-    7f06:	93 2b       	or	r25, r19
+    7ee0:	11 96       	adiw	r26, 0x01	; 1
+    7ee2:	8c 91       	ld	r24, X
+    7ee4:	11 97       	sbiw	r26, 0x01	; 1
+    7ee6:	90 e0       	ldi	r25, 0x00	; 0
+    7ee8:	98 2f       	mov	r25, r24
+    7eea:	88 27       	eor	r24, r24
+    7eec:	82 2b       	or	r24, r18
+    7eee:	93 2b       	or	r25, r19
 #define buff    ((uint8_t*)(0x100))
 #define address (*(uint16_t*)(0x200))
 #define length  (*(uint8_t*)(0x202))
 
 /* main program starts here */
 int main(void) {
-    7f08:	12 96       	adiw	r26, 0x02	; 2
+    7ef0:	12 96       	adiw	r26, 0x02	; 2
       ch = SPM_PAGESIZE / 2;
       do {
         uint16_t a;
         a = *bufPtr++;
         a |= (*bufPtr++) << 8;
         boot_page_fill((uint16_t)(void*)addrPtr,a);
-    7f0a:	fa 01       	movw	r30, r20
-    7f0c:	0c 01       	movw	r0, r24
-    7f0e:	d0 92 57 00 	sts	0x0057, r13
-    7f12:	e8 95       	spm
-    7f14:	11 24       	eor	r1, r1
+    7ef2:	fa 01       	movw	r30, r20
+    7ef4:	0c 01       	movw	r0, r24
+    7ef6:	d0 92 57 00 	sts	0x0057, r13
+    7efa:	e8 95       	spm
+    7efc:	11 24       	eor	r1, r1
         addrPtr += 2;
-    7f16:	4e 5f       	subi	r20, 0xFE	; 254
-    7f18:	5f 4f       	sbci	r21, 0xFF	; 255
+    7efe:	4e 5f       	subi	r20, 0xFE	; 254
+    7f00:	5f 4f       	sbci	r21, 0xFF	; 255
       } while (--ch);
-    7f1a:	f1 e0       	ldi	r31, 0x01	; 1
-    7f1c:	a0 38       	cpi	r26, 0x80	; 128
-    7f1e:	bf 07       	cpc	r27, r31
-    7f20:	49 f7       	brne	.-46     	; 0x7ef4 <main+0xf4>
+    7f02:	f1 e0       	ldi	r31, 0x01	; 1
+    7f04:	a0 38       	cpi	r26, 0x80	; 128
+    7f06:	bf 07       	cpc	r27, r31
+    7f08:	49 f7       	brne	.-46     	; 0x7edc <main+0xdc>
       
       // Write from programming buffer
       boot_page_write((uint16_t)(void*)address);
-    7f22:	e0 91 00 02 	lds	r30, 0x0200
-    7f26:	f0 91 01 02 	lds	r31, 0x0201
-    7f2a:	e0 92 57 00 	sts	0x0057, r14
-    7f2e:	e8 95       	spm
+    7f0a:	e0 91 00 02 	lds	r30, 0x0200
+    7f0e:	f0 91 01 02 	lds	r31, 0x0201
+    7f12:	e0 92 57 00 	sts	0x0057, r14
+    7f16:	e8 95       	spm
       boot_spm_busy_wait();
-    7f30:	07 b6       	in	r0, 0x37	; 55
-    7f32:	00 fc       	sbrc	r0, 0
-    7f34:	fd cf       	rjmp	.-6      	; 0x7f30 <main+0x130>
+    7f18:	07 b6       	in	r0, 0x37	; 55
+    7f1a:	00 fc       	sbrc	r0, 0
+    7f1c:	fd cf       	rjmp	.-6      	; 0x7f18 <main+0x118>
 
       // Reenable read access to flash
       boot_rww_enable();
-    7f36:	f0 92 57 00 	sts	0x0057, r15
-    7f3a:	e8 95       	spm
-    7f3c:	27 c0       	rjmp	.+78     	; 0x7f8c <main+0x18c>
+    7f1e:	f0 92 57 00 	sts	0x0057, r15
+    7f22:	e8 95       	spm
+    7f24:	27 c0       	rjmp	.+78     	; 0x7f74 <main+0x174>
     }
     /* Read memory block mode, length is big endian.  */
     else if(ch == STK_READ_PAGE) {
-    7f3e:	84 37       	cpi	r24, 0x74	; 116
-    7f40:	b9 f4       	brne	.+46     	; 0x7f70 <main+0x170>
+    7f26:	84 37       	cpi	r24, 0x74	; 116
+    7f28:	b9 f4       	brne	.+46     	; 0x7f58 <main+0x158>
       // READ PAGE - we only read flash
       getLen();
-    7f42:	48 d0       	rcall	.+144    	; 0x7fd4 <getLen>
+    7f2a:	4a d0       	rcall	.+148    	; 0x7fc0 <getLen>
       verifySpace();
-    7f44:	4c d0       	rcall	.+152    	; 0x7fde <verifySpace>
+    7f2c:	59 d0       	rcall	.+178    	; 0x7fe0 <verifySpace>
       do putch(pgm_read_byte_near(address++));
-    7f46:	e0 91 00 02 	lds	r30, 0x0200
-    7f4a:	f0 91 01 02 	lds	r31, 0x0201
-    7f4e:	31 96       	adiw	r30, 0x01	; 1
-    7f50:	f0 93 01 02 	sts	0x0201, r31
-    7f54:	e0 93 00 02 	sts	0x0200, r30
-    7f58:	31 97       	sbiw	r30, 0x01	; 1
-    7f5a:	e4 91       	lpm	r30, Z+
-    7f5c:	8e 2f       	mov	r24, r30
-    7f5e:	19 d0       	rcall	.+50     	; 0x7f92 <putch>
+    7f2e:	e0 91 00 02 	lds	r30, 0x0200
+    7f32:	f0 91 01 02 	lds	r31, 0x0201
+    7f36:	31 96       	adiw	r30, 0x01	; 1
+    7f38:	f0 93 01 02 	sts	0x0201, r31
+    7f3c:	e0 93 00 02 	sts	0x0200, r30
+    7f40:	31 97       	sbiw	r30, 0x01	; 1
+    7f42:	e4 91       	lpm	r30, Z+
+    7f44:	8e 2f       	mov	r24, r30
+    7f46:	19 d0       	rcall	.+50     	; 0x7f7a <putch>
       while (--length);
-    7f60:	80 91 02 02 	lds	r24, 0x0202
-    7f64:	81 50       	subi	r24, 0x01	; 1
-    7f66:	80 93 02 02 	sts	0x0202, r24
-    7f6a:	88 23       	and	r24, r24
-    7f6c:	61 f7       	brne	.-40     	; 0x7f46 <main+0x146>
-    7f6e:	0e c0       	rjmp	.+28     	; 0x7f8c <main+0x18c>
+    7f48:	80 91 02 02 	lds	r24, 0x0202
+    7f4c:	81 50       	subi	r24, 0x01	; 1
+    7f4e:	80 93 02 02 	sts	0x0202, r24
+    7f52:	88 23       	and	r24, r24
+    7f54:	61 f7       	brne	.-40     	; 0x7f2e <main+0x12e>
+    7f56:	0e c0       	rjmp	.+28     	; 0x7f74 <main+0x174>
     }
 
     /* Get device signature bytes  */
     else if(ch == STK_READ_SIGN) {
-    7f70:	85 37       	cpi	r24, 0x75	; 117
-    7f72:	39 f4       	brne	.+14     	; 0x7f82 <main+0x182>
+    7f58:	85 37       	cpi	r24, 0x75	; 117
+    7f5a:	39 f4       	brne	.+14     	; 0x7f6a <main+0x16a>
       // READ SIGN - return what Avrdude wants to hear
       verifySpace();
-    7f74:	34 d0       	rcall	.+104    	; 0x7fde <verifySpace>
+    7f5c:	41 d0       	rcall	.+130    	; 0x7fe0 <verifySpace>
       putch(SIGNATURE_0);
-    7f76:	8e e1       	ldi	r24, 0x1E	; 30
-    7f78:	0c d0       	rcall	.+24     	; 0x7f92 <putch>
+    7f5e:	8e e1       	ldi	r24, 0x1E	; 30
+    7f60:	0c d0       	rcall	.+24     	; 0x7f7a <putch>
       putch(SIGNATURE_1);
-    7f7a:	85 e9       	ldi	r24, 0x95	; 149
-    7f7c:	0a d0       	rcall	.+20     	; 0x7f92 <putch>
+    7f62:	85 e9       	ldi	r24, 0x95	; 149
+    7f64:	0a d0       	rcall	.+20     	; 0x7f7a <putch>
       putch(SIGNATURE_2);
-    7f7e:	8f e0       	ldi	r24, 0x0F	; 15
-    7f80:	93 cf       	rjmp	.-218    	; 0x7ea8 <main+0xa8>
+    7f66:	8f e0       	ldi	r24, 0x0F	; 15
+    7f68:	96 cf       	rjmp	.-212    	; 0x7e96 <main+0x96>
     }
     else if (ch == 'Q') {
-    7f82:	81 35       	cpi	r24, 0x51	; 81
-    7f84:	11 f4       	brne	.+4      	; 0x7f8a <main+0x18a>
+    7f6a:	81 35       	cpi	r24, 0x51	; 81
+    7f6c:	11 f4       	brne	.+4      	; 0x7f72 <main+0x172>
       // Adaboot no-wait mod
-      WDTCSR = _BV(WDE);
-    7f86:	c0 92 60 00 	sts	0x0060, r12
+      watchdogConfig(_BV(WDE));
+    7f6e:	88 e0       	ldi	r24, 0x08	; 8
+    7f70:	2c d0       	rcall	.+88     	; 0x7fca <watchdogConfig>
       verifySpace();
     }
     else {
       // This covers the response to commands like STK_ENTER_PROGMODE
       verifySpace();
-    7f8a:	29 d0       	rcall	.+82     	; 0x7fde <verifySpace>
+    7f72:	36 d0       	rcall	.+108    	; 0x7fe0 <verifySpace>
     }
     putch(STK_OK);
-    7f8c:	80 e1       	ldi	r24, 0x10	; 16
-    7f8e:	01 d0       	rcall	.+2      	; 0x7f92 <putch>
-    7f90:	60 cf       	rjmp	.-320    	; 0x7e52 <main+0x52>
-
-00007f92 <putch>:
-  }
-}
+    7f74:	80 e1       	ldi	r24, 0x10	; 16
+    7f76:	01 d0       	rcall	.+2      	; 0x7f7a <putch>
+    7f78:	63 cf       	rjmp	.-314    	; 0x7e40 <main+0x40>
 
+00007f7a <putch>:
 void putch(char ch) {
-    7f92:	98 2f       	mov	r25, r24
+#ifndef SOFT_UART
   while (!(UCSR0A & _BV(UDRE0)));
-    7f94:	80 91 c0 00 	lds	r24, 0x00C0
-    7f98:	85 ff       	sbrs	r24, 5
-    7f9a:	fc cf       	rjmp	.-8      	; 0x7f94 <putch+0x2>
   UDR0 = ch;
-    7f9c:	90 93 c6 00 	sts	0x00C6, r25
-}
-    7fa0:	08 95       	ret
-
-00007fa2 <setTimer>:
-
-void setTimer(uint16_t counts) {
-  TCNT1 = counts;
-    7fa2:	90 93 85 00 	sts	0x0085, r25
-    7fa6:	80 93 84 00 	sts	0x0084, r24
-  TIFR1 = _BV(TOV1);
-    7faa:	81 e0       	ldi	r24, 0x01	; 1
-    7fac:	86 bb       	out	0x16, r24	; 22
+#else
+  __asm__ __volatile__ (
+    7f7a:	2a e0       	ldi	r18, 0x0A	; 10
+    7f7c:	30 e0       	ldi	r19, 0x00	; 0
+    7f7e:	80 95       	com	r24
+    7f80:	08 94       	sec
+    7f82:	10 f4       	brcc	.+4      	; 0x7f88 <putch+0xe>
+    7f84:	59 98       	cbi	0x0b, 1	; 11
+    7f86:	02 c0       	rjmp	.+4      	; 0x7f8c <putch+0x12>
+    7f88:	59 9a       	sbi	0x0b, 1	; 11
+    7f8a:	00 00       	nop
+    7f8c:	15 d0       	rcall	.+42     	; 0x7fb8 <uartDelay>
+    7f8e:	14 d0       	rcall	.+40     	; 0x7fb8 <uartDelay>
+    7f90:	86 95       	lsr	r24
+    7f92:	2a 95       	dec	r18
+    7f94:	b1 f7       	brne	.-20     	; 0x7f82 <putch+0x8>
+      [uartBit] "I" (UART_TX_BIT)
+    :
+      "r25"
+  );
+#endif
 }
-    7fae:	08 95       	ret
+    7f96:	08 95       	ret
 
-00007fb0 <appStart>:
-  length = getch();
+00007f98 <getch>:
   return getch();
 }
 
-void appStart() {
+// Watchdog functions. These are only safe with interrupts turned off.
+void watchdogReset() {
   __asm__ __volatile__ (
-    7fb0:	ee 27       	eor	r30, r30
-    7fb2:	ff 27       	eor	r31, r31
-    7fb4:	09 94       	ijmp
+    7f98:	a8 95       	wdr
+#ifdef LED_DATA_FLASH
+  LED_PIN |= _BV(LED);
+#endif
 
-00007fb6 <getch>:
-  TCNT1 = counts;
-  TIFR1 = _BV(TOV1);
+  return ch;
 }
+    7f9a:	29 e0       	ldi	r18, 0x09	; 9
+    7f9c:	30 e0       	ldi	r19, 0x00	; 0
+    7f9e:	48 99       	sbic	0x09, 0	; 9
+    7fa0:	fe cf       	rjmp	.-4      	; 0x7f9e <getch+0x6>
+    7fa2:	0a d0       	rcall	.+20     	; 0x7fb8 <uartDelay>
+    7fa4:	09 d0       	rcall	.+18     	; 0x7fb8 <uartDelay>
+    7fa6:	08 d0       	rcall	.+16     	; 0x7fb8 <uartDelay>
+    7fa8:	88 94       	clc
+    7faa:	48 99       	sbic	0x09, 0	; 9
+    7fac:	08 94       	sec
+    7fae:	2a 95       	dec	r18
+    7fb0:	11 f0       	breq	.+4      	; 0x7fb6 <getch+0x1e>
+    7fb2:	87 95       	ror	r24
+    7fb4:	f7 cf       	rjmp	.-18     	; 0x7fa4 <getch+0xc>
+    7fb6:	08 95       	ret
+
+00007fb8 <uartDelay>:
+#if UART_B_VALUE > 255
+#error Baud rate too slow for soft UART
+#endif
 
-uint8_t getch(void) {
-  LED_PORT &= ~_BV(LED);
-    7fb6:	2d 98       	cbi	0x05, 5	; 5
-  setTimer(-(F_CPU/(1024*2))); // 500ms
-    7fb8:	8e eb       	ldi	r24, 0xBE	; 190
-    7fba:	90 ef       	ldi	r25, 0xF0	; 240
-    7fbc:	f2 df       	rcall	.-28     	; 0x7fa2 <setTimer>
-    7fbe:	02 c0       	rjmp	.+4      	; 0x7fc4 <getch+0xe>
-  while(!(UCSR0A & _BV(RXC0))) if (TIFR1 & _BV(TOV1)) appStart();
-    7fc0:	b0 99       	sbic	0x16, 0	; 22
-    7fc2:	f6 df       	rcall	.-20     	; 0x7fb0 <appStart>
-    7fc4:	80 91 c0 00 	lds	r24, 0x00C0
-    7fc8:	87 ff       	sbrs	r24, 7
-    7fca:	fa cf       	rjmp	.-12     	; 0x7fc0 <getch+0xa>
-  LED_PORT |= _BV(LED);
-    7fcc:	2d 9a       	sbi	0x05, 5	; 5
-  return UDR0;
-    7fce:	80 91 c6 00 	lds	r24, 0x00C6
-}
-    7fd2:	08 95       	ret
+void uartDelay() {
+  __asm__ __volatile__ (
+    7fb8:	98 e0       	ldi	r25, 0x08	; 8
+    7fba:	9a 95       	dec	r25
+    7fbc:	f1 f7       	brne	.-4      	; 0x7fba <uartDelay+0x2>
+    7fbe:	08 95       	ret
 
-00007fd4 <getLen>:
-    LED_PIN |= _BV(LED);
+00007fc0 <getLen>:
   } while (--count);
 }
+#endif
 
 uint8_t getLen() {
   getch();
-    7fd4:	f0 df       	rcall	.-32     	; 0x7fb6 <getch>
+    7fc0:	eb df       	rcall	.-42     	; 0x7f98 <getch>
   length = getch();
-    7fd6:	ef df       	rcall	.-34     	; 0x7fb6 <getch>
-    7fd8:	80 93 02 02 	sts	0x0202, r24
+    7fc2:	ea df       	rcall	.-44     	; 0x7f98 <getch>
+    7fc4:	80 93 02 02 	sts	0x0202, r24
   return getch();
 }
-    7fdc:	ec cf       	rjmp	.-40     	; 0x7fb6 <getch>
+    7fc8:	e7 cf       	rjmp	.-50     	; 0x7f98 <getch>
+
+00007fca <watchdogConfig>:
+    "wdr\n"
+  );
+}
 
-00007fde <verifySpace>:
+void watchdogConfig(uint8_t x) {
+  WDTCSR = _BV(WDCE) | _BV(WDE);
+    7fca:	e0 e6       	ldi	r30, 0x60	; 96
+    7fcc:	f0 e0       	ldi	r31, 0x00	; 0
+    7fce:	98 e1       	ldi	r25, 0x18	; 24
+    7fd0:	90 83       	st	Z, r25
+  WDTCSR = x;
+    7fd2:	80 83       	st	Z, r24
+}
+    7fd4:	08 95       	ret
+
+00007fd6 <appStart>:
+
+void appStart() {
+  watchdogConfig(0);
+    7fd6:	80 e0       	ldi	r24, 0x00	; 0
+    7fd8:	f8 df       	rcall	.-16     	; 0x7fca <watchdogConfig>
+  __asm__ __volatile__ (
+    7fda:	ee 27       	eor	r30, r30
+    7fdc:	ff 27       	eor	r31, r31
+    7fde:	09 94       	ijmp
+
+00007fe0 <verifySpace>:
   do getch(); while (--count);
   verifySpace();
 }
 
 void verifySpace() {
   if (getch() != CRC_EOP) appStart();
-    7fde:	eb df       	rcall	.-42     	; 0x7fb6 <getch>
-    7fe0:	80 32       	cpi	r24, 0x20	; 32
-    7fe2:	09 f0       	breq	.+2      	; 0x7fe6 <verifySpace+0x8>
-    7fe4:	e5 df       	rcall	.-54     	; 0x7fb0 <appStart>
+    7fe0:	db df       	rcall	.-74     	; 0x7f98 <getch>
+    7fe2:	80 32       	cpi	r24, 0x20	; 32
+    7fe4:	09 f0       	breq	.+2      	; 0x7fe8 <verifySpace+0x8>
+    7fe6:	f7 df       	rcall	.-18     	; 0x7fd6 <appStart>
   putch(STK_INSYNC);
-    7fe6:	84 e1       	ldi	r24, 0x14	; 20
+    7fe8:	84 e1       	ldi	r24, 0x14	; 20
 }
-    7fe8:	d4 cf       	rjmp	.-88     	; 0x7f92 <putch>
-  while(!(UCSR0A & _BV(RXC0))) if (TIFR1 & _BV(TOV1)) appStart();
-  LED_PORT |= _BV(LED);
-  return UDR0;
+    7fea:	c7 cf       	rjmp	.-114    	; 0x7f7a <putch>
+    ::[count] "M" (UART_B_VALUE)
+  );
 }
+#endif
 
 void getNch(uint8_t count) {
-    7fea:	1f 93       	push	r17
-    7fec:	18 2f       	mov	r17, r24
+    7fec:	1f 93       	push	r17
+    7fee:	18 2f       	mov	r17, r24
 
-00007fee <getNch>:
+00007ff0 <getNch>:
   do getch(); while (--count);
-    7fee:	e3 df       	rcall	.-58     	; 0x7fb6 <getch>
-    7ff0:	11 50       	subi	r17, 0x01	; 1
-    7ff2:	e9 f7       	brne	.-6      	; 0x7fee <getNch>
+    7ff0:	d3 df       	rcall	.-90     	; 0x7f98 <getch>
+    7ff2:	11 50       	subi	r17, 0x01	; 1
+    7ff4:	e9 f7       	brne	.-6      	; 0x7ff0 <getNch>
   verifySpace();
-    7ff4:	f4 df       	rcall	.-24     	; 0x7fde <verifySpace>
+    7ff6:	f4 df       	rcall	.-24     	; 0x7fe0 <verifySpace>
 }
-    7ff6:	1f 91       	pop	r17
-    7ff8:	08 95       	ret
+    7ff8:	1f 91       	pop	r17
+    7ffa:	08 95       	ret

+ 32 - 32
optiboot/bootloaders/optiboot/optiboot_diecimila.hex

@@ -1,34 +1,34 @@
-:103E000085E08093810082E08093C00098E19093E8
-:103E1000C10086E08093C20087E68093C40084B727
-:103E200014BE909360001092600081FFC1D0259A6B
-:103E300002E080E39CEFB5D0B09BFECF1D9A01500D
-:103E4000C1F7DD24D394B8E0CB2EA5E0EA2EF1E152
-:103E5000FF2EB1D0813421F481E0C7D083E024C0AB
-:103E6000823411F484E103C0853419F485E0BDD0B7
-:103E70008DC08535A1F49FD0082F10E0109301026A
-:103E80000093000298D090E0982F8827802B912BE8
-:103E9000880F991F909301028093000276C08635A7
-:103EA00029F484E0A2D080E074D070C0843609F098
-:103EB00046C090D0863409F07BD0E0910002F091AA
-:103EC000010283E080935700E895C0E0D1E073D011
-:103ED0008993809102028150809302028823B9F76E
-:103EE00007B600FCFDCF7BD040910002509101024B
-:103EF000A0E0B1E02C9130E011968C91119790E008
-:103F0000982F8827822B932B1296FA010C01D092BE
-:103F10005700E89511244E5F5F4FF1E0A038BF07CE
-:103F200049F7E0910002F0910102E0925700E89514
-:103F300007B600FCFDCFF0925700E89527C0843704
-:103F4000B9F448D04CD0E0910002F09101023196D2
-:103F5000F0930102E09300023197E4918E2F19D083
-:103F600080910202815080930202882361F70EC083
-:103F7000853739F434D08EE10CD084E90AD086E05C
-:103F800093CF813511F4C092600029D080E101D037
-:103F900060CF982F8091C00085FFFCCF9093C60022
-:103FA0000895909385008093840081E086BB0895F6
-:103FB000EE27FF2709942D988CE791EEF2DF02C0DF
-:103FC000B099F6DF8091C00087FFFACF2D9A8091DB
-:103FD000C6000895F0DFEFDF80930202ECCFEBDF45
-:103FE000803209F0E5DF84E1D4CF1F93182FE3DF9F
-:0A3FF0001150E9F7F4DF1F91089566
+:103E000085E08093810084B714BE81FFE4D08DE00B
+:103E1000DCD0259A519A86E020E33CEF91E0309384
+:103E200085002093840096BBB09BFECF1D9AA89579
+:103E30008150A9F7DD24D394A5E0EA2EF1E1FF2E0D
+:103E4000ABD0813421F481E0D1D083E024C082342E
+:103E500011F484E103C0853419F485E0C7D08AC029
+:103E60008535A1F499D0082F10E01093010200933A
+:103E7000000292D090E0982F8827802B912B880FFA
+:103E8000991F909301028093000273C0863529F434
+:103E900084E0ACD080E071D06DC0843609F043C0BE
+:103EA0008FD0E0910002F091010283E080935700EF
+:103EB000E895C0E0D1E070D08993809102028150F2
+:103EC000809302028823B9F78BD007B600FCFDCFA0
+:103ED0004091000250910102A0E0B1E02C9130E04D
+:103EE00011968C91119790E0982F8827822B932B15
+:103EF0001296FA010C01D0925700E89511244E5FFA
+:103F00005F4FF1E0A038BF0749F7E0910002F09160
+:103F10000102E0925700E89507B600FCFDCFF09251
+:103F20005700E89527C08437B9F44AD059D0E091BA
+:103F30000002F09101023196F0930102E093000239
+:103F40003197E4918E2F19D0809102028150809395
+:103F50000202882361F70EC0853739F441D08EE123
+:103F60000CD084E90AD086E096CF813511F488E040
+:103F70002CD036D080E101D063CF2AE030E08095AC
+:103F8000089410F4599802C0599A000015D014D022
+:103F900086952A95B1F70895A89529E030E04899CB
+:103FA000FECF0AD009D008D08894489908942A9561
+:103FB00011F08795F7CF089598E09A95F1F7089555
+:103FC000EBDFEADF80930202E7CFE0E6F0E098E182
+:103FD00090838083089580E0F8DFEE27FF2709941F
+:103FE000DBDF803209F0F7DF84E1C7CF1F93182FA2
+:0C3FF000D3DF1150E9F7F4DF1F910895B2
 :0400000300003E00BB
 :00000001FF

+ 320 - 282
optiboot/bootloaders/optiboot/optiboot_diecimila.lst

@@ -3,25 +3,25 @@ optiboot_diecimila.elf:     file format elf32-avr
 
 Sections:
 Idx Name          Size      VMA       LMA       File off  Algn
-  0 .text         000001fa  00003e00  00003e00  00000054  2**1
+  0 .text         000001fc  00003e00  00003e00  00000054  2**1
                   CONTENTS, ALLOC, LOAD, READONLY, CODE
-  1 .debug_aranges 00000028  00000000  00000000  0000024e  2**0
+  1 .debug_aranges 00000028  00000000  00000000  00000250  2**0
                   CONTENTS, READONLY, DEBUGGING
-  2 .debug_pubnames 00000064  00000000  00000000  00000276  2**0
+  2 .debug_pubnames 00000078  00000000  00000000  00000278  2**0
                   CONTENTS, READONLY, DEBUGGING
-  3 .debug_info   0000022f  00000000  00000000  000002da  2**0
+  3 .debug_info   00000275  00000000  00000000  000002f0  2**0
                   CONTENTS, READONLY, DEBUGGING
-  4 .debug_abbrev 00000164  00000000  00000000  00000509  2**0
+  4 .debug_abbrev 000001a3  00000000  00000000  00000565  2**0
                   CONTENTS, READONLY, DEBUGGING
-  5 .debug_line   000003c8  00000000  00000000  0000066d  2**0
+  5 .debug_line   000003b8  00000000  00000000  00000708  2**0
                   CONTENTS, READONLY, DEBUGGING
-  6 .debug_frame  00000090  00000000  00000000  00000a38  2**2
+  6 .debug_frame  000000a0  00000000  00000000  00000ac0  2**2
                   CONTENTS, READONLY, DEBUGGING
-  7 .debug_str    0000011c  00000000  00000000  00000ac8  2**0
+  7 .debug_str    00000133  00000000  00000000  00000b60  2**0
                   CONTENTS, READONLY, DEBUGGING
-  8 .debug_loc    000001d6  00000000  00000000  00000be4  2**0
+  8 .debug_loc    000001a0  00000000  00000000  00000c93  2**0
                   CONTENTS, READONLY, DEBUGGING
-  9 .debug_ranges 00000068  00000000  00000000  00000dba  2**0
+  9 .debug_ranges 00000070  00000000  00000000  00000e33  2**0
                   CONTENTS, READONLY, DEBUGGING
 
 Disassembly of section .text:
@@ -35,449 +35,487 @@ Disassembly of section .text:
 int main(void) {
     3e00:	85 e0       	ldi	r24, 0x05	; 5
     3e02:	80 93 81 00 	sts	0x0081, r24
-    [addr5]"i"(_SFR_MEM_ADDR(UBRR0L)), [val5]"i"((F_CPU + BAUD_RATE * 4L) / (BAUD_RATE * 8L) - 1)
-  );
-#else
-  // Set up Timer 1 for timeout counter
-  TCCR1B = _BV(CS12) | _BV(CS10); // div 1024
-  UCSR0A = _BV(U2X0); //Double speed mode USART0
-    3e06:	82 e0       	ldi	r24, 0x02	; 2
-    3e08:	80 93 c0 00 	sts	0x00C0, r24
-  UCSR0B = _BV(RXEN0) | _BV(TXEN0);
-    3e0c:	98 e1       	ldi	r25, 0x18	; 24
-    3e0e:	90 93 c1 00 	sts	0x00C1, r25
   UCSR0C = _BV(UCSZ00) | _BV(UCSZ01);
-    3e12:	86 e0       	ldi	r24, 0x06	; 6
-    3e14:	80 93 c2 00 	sts	0x00C2, r24
   UBRR0L = (uint8_t)( (F_CPU + BAUD_RATE * 4L) / (BAUD_RATE * 8L) - 1 );
-    3e18:	87 e6       	ldi	r24, 0x67	; 103
-    3e1a:	80 93 c4 00 	sts	0x00C4, r24
 #endif
 
   // Adaboot no-wait mod
   ch = MCUSR;
-    3e1e:	84 b7       	in	r24, 0x34	; 52
+    3e06:	84 b7       	in	r24, 0x34	; 52
   MCUSR = 0;
-    3e20:	14 be       	out	0x34, r1	; 52
-  WDTCSR = _BV(WDCE) | _BV(WDE);
-    3e22:	90 93 60 00 	sts	0x0060, r25
-  WDTCSR = 0;
-    3e26:	10 92 60 00 	sts	0x0060, r1
+    3e08:	14 be       	out	0x34, r1	; 52
   if (!(ch & _BV(EXTRF))) appStart();
-    3e2a:	81 ff       	sbrs	r24, 1
-    3e2c:	c1 d0       	rcall	.+386    	; 0x3fb0 <appStart>
+    3e0a:	81 ff       	sbrs	r24, 1
+    3e0c:	e4 d0       	rcall	.+456    	; 0x3fd6 <appStart>
+
+  // Set up watchdog to trigger after 500ms
+  watchdogConfig(_BV(WDP2)|_BV(WDP0)|_BV(WDE));
+    3e0e:	8d e0       	ldi	r24, 0x0D	; 13
+    3e10:	dc d0       	rcall	.+440    	; 0x3fca <watchdogConfig>
 
-  /* set LED pin as output */
+  /* Set LED pin as output */
   LED_DDR |= _BV(LED);
-    3e2e:	25 9a       	sbi	0x04, 5	; 4
-    3e30:	02 e0       	ldi	r16, 0x02	; 2
-  putch(STK_INSYNC);
+    3e12:	25 9a       	sbi	0x04, 5	; 4
+
+#ifdef SOFT_UART
+  /* Set TX pin as output */
+  UART_DDR |= _BV(UART_TX_BIT);
+    3e14:	51 9a       	sbi	0x0a, 1	; 10
+    3e16:	86 e0       	ldi	r24, 0x06	; 6
+}
+
+#if LED_START_FLASHES > 0
+void flash_led(uint8_t count) {
+  do {
+    TCNT1 = -(F_CPU/(1024*16));
+    3e18:	20 e3       	ldi	r18, 0x30	; 48
+    3e1a:	3c ef       	ldi	r19, 0xFC	; 252
+    TIFR1 = _BV(TOV1);
+    3e1c:	91 e0       	ldi	r25, 0x01	; 1
 }
 
+#if LED_START_FLASHES > 0
 void flash_led(uint8_t count) {
   do {
-    setTimer(-(F_CPU/(1024*16))); // 62ms
-    3e32:	80 e3       	ldi	r24, 0x30	; 48
-    3e34:	9c ef       	ldi	r25, 0xFC	; 252
-    3e36:	b5 d0       	rcall	.+362    	; 0x3fa2 <setTimer>
+    TCNT1 = -(F_CPU/(1024*16));
+    3e1e:	30 93 85 00 	sts	0x0085, r19
+    3e22:	20 93 84 00 	sts	0x0084, r18
+    TIFR1 = _BV(TOV1);
+    3e26:	96 bb       	out	0x16, r25	; 22
+    while(!(TIFR1 & _BV(TOV1)));
+    3e28:	b0 9b       	sbis	0x16, 0	; 22
+    3e2a:	fe cf       	rjmp	.-4      	; 0x3e28 <main+0x28>
+    LED_PIN |= _BV(LED);
+    3e2c:	1d 9a       	sbi	0x03, 5	; 3
+  return getch();
+}
+
+// Watchdog functions. These are only safe with interrupts turned off.
+void watchdogReset() {
+  __asm__ __volatile__ (
+    3e2e:	a8 95       	wdr
+    TCNT1 = -(F_CPU/(1024*16));
+    TIFR1 = _BV(TOV1);
     while(!(TIFR1 & _BV(TOV1)));
-    3e38:	b0 9b       	sbis	0x16, 0	; 22
-    3e3a:	fe cf       	rjmp	.-4      	; 0x3e38 <main+0x38>
     LED_PIN |= _BV(LED);
-    3e3c:	1d 9a       	sbi	0x03, 5	; 3
+    watchdogReset();
   } while (--count);
-    3e3e:	01 50       	subi	r16, 0x01	; 1
-    3e40:	c1 f7       	brne	.-16     	; 0x3e32 <main+0x32>
+    3e30:	81 50       	subi	r24, 0x01	; 1
+    3e32:	a9 f7       	brne	.-22     	; 0x3e1e <main+0x1e>
     /* get character from UART */
     ch = getch();
 
     if(ch == STK_GET_PARAMETER) {
       // GET PARAMETER returns a generic 0x03 reply - enough to keep Avrdude happy
       getNch(1);
-    3e42:	dd 24       	eor	r13, r13
-    3e44:	d3 94       	inc	r13
-      putch(SIGNATURE_1);
-      putch(SIGNATURE_2);
-    }
-    else if (ch == 'Q') {
-      // Adaboot no-wait mod
-      WDTCSR = _BV(WDE);
-    3e46:	b8 e0       	ldi	r27, 0x08	; 8
-    3e48:	cb 2e       	mov	r12, r27
+    3e34:	dd 24       	eor	r13, r13
+    3e36:	d3 94       	inc	r13
         boot_page_fill((uint16_t)(void*)addrPtr,a);
         addrPtr += 2;
       } while (--ch);
       
       // Write from programming buffer
       boot_page_write((uint16_t)(void*)address);
-    3e4a:	a5 e0       	ldi	r26, 0x05	; 5
-    3e4c:	ea 2e       	mov	r14, r26
+    3e38:	a5 e0       	ldi	r26, 0x05	; 5
+    3e3a:	ea 2e       	mov	r14, r26
       boot_spm_busy_wait();
 
       // Reenable read access to flash
       boot_rww_enable();
-    3e4e:	f1 e1       	ldi	r31, 0x11	; 17
-    3e50:	ff 2e       	mov	r15, r31
-  flash_led(NUM_LED_FLASHES * 2);
+    3e3c:	f1 e1       	ldi	r31, 0x11	; 17
+    3e3e:	ff 2e       	mov	r15, r31
+#endif
 
-  /* forever loop */
+  /* Forever loop */
   for (;;) {
     /* get character from UART */
     ch = getch();
-    3e52:	b1 d0       	rcall	.+354    	; 0x3fb6 <getch>
+    3e40:	ab d0       	rcall	.+342    	; 0x3f98 <getch>
 
     if(ch == STK_GET_PARAMETER) {
-    3e54:	81 34       	cpi	r24, 0x41	; 65
-    3e56:	21 f4       	brne	.+8      	; 0x3e60 <main+0x60>
+    3e42:	81 34       	cpi	r24, 0x41	; 65
+    3e44:	21 f4       	brne	.+8      	; 0x3e4e <main+0x4e>
       // GET PARAMETER returns a generic 0x03 reply - enough to keep Avrdude happy
       getNch(1);
-    3e58:	81 e0       	ldi	r24, 0x01	; 1
-    3e5a:	c7 d0       	rcall	.+398    	; 0x3fea <verifySpace+0xc>
+    3e46:	81 e0       	ldi	r24, 0x01	; 1
+    3e48:	d1 d0       	rcall	.+418    	; 0x3fec <verifySpace+0xc>
       putch(0x03);
-    3e5c:	83 e0       	ldi	r24, 0x03	; 3
-    3e5e:	24 c0       	rjmp	.+72     	; 0x3ea8 <main+0xa8>
+    3e4a:	83 e0       	ldi	r24, 0x03	; 3
+    3e4c:	24 c0       	rjmp	.+72     	; 0x3e96 <main+0x96>
     }
     else if(ch == STK_SET_DEVICE) {
-    3e60:	82 34       	cpi	r24, 0x42	; 66
-    3e62:	11 f4       	brne	.+4      	; 0x3e68 <main+0x68>
+    3e4e:	82 34       	cpi	r24, 0x42	; 66
+    3e50:	11 f4       	brne	.+4      	; 0x3e56 <main+0x56>
       // SET DEVICE is ignored
       getNch(20);
-    3e64:	84 e1       	ldi	r24, 0x14	; 20
-    3e66:	03 c0       	rjmp	.+6      	; 0x3e6e <main+0x6e>
+    3e52:	84 e1       	ldi	r24, 0x14	; 20
+    3e54:	03 c0       	rjmp	.+6      	; 0x3e5c <main+0x5c>
     }
     else if(ch == STK_SET_DEVICE_EXT) {
-    3e68:	85 34       	cpi	r24, 0x45	; 69
-    3e6a:	19 f4       	brne	.+6      	; 0x3e72 <main+0x72>
+    3e56:	85 34       	cpi	r24, 0x45	; 69
+    3e58:	19 f4       	brne	.+6      	; 0x3e60 <main+0x60>
       // SET DEVICE EXT is ignored
       getNch(5);
-    3e6c:	85 e0       	ldi	r24, 0x05	; 5
-    3e6e:	bd d0       	rcall	.+378    	; 0x3fea <verifySpace+0xc>
-    3e70:	8d c0       	rjmp	.+282    	; 0x3f8c <main+0x18c>
+    3e5a:	85 e0       	ldi	r24, 0x05	; 5
+    3e5c:	c7 d0       	rcall	.+398    	; 0x3fec <verifySpace+0xc>
+    3e5e:	8a c0       	rjmp	.+276    	; 0x3f74 <main+0x174>
     }
     else if(ch == STK_LOAD_ADDRESS) {
-    3e72:	85 35       	cpi	r24, 0x55	; 85
-    3e74:	a1 f4       	brne	.+40     	; 0x3e9e <main+0x9e>
+    3e60:	85 35       	cpi	r24, 0x55	; 85
+    3e62:	a1 f4       	brne	.+40     	; 0x3e8c <main+0x8c>
       // LOAD ADDRESS
       address = getch();
-    3e76:	9f d0       	rcall	.+318    	; 0x3fb6 <getch>
-    3e78:	08 2f       	mov	r16, r24
-    3e7a:	10 e0       	ldi	r17, 0x00	; 0
-    3e7c:	10 93 01 02 	sts	0x0201, r17
-    3e80:	00 93 00 02 	sts	0x0200, r16
+    3e64:	99 d0       	rcall	.+306    	; 0x3f98 <getch>
+    3e66:	08 2f       	mov	r16, r24
+    3e68:	10 e0       	ldi	r17, 0x00	; 0
+    3e6a:	10 93 01 02 	sts	0x0201, r17
+    3e6e:	00 93 00 02 	sts	0x0200, r16
       address = (address & 0xff) | (getch() << 8);
-    3e84:	98 d0       	rcall	.+304    	; 0x3fb6 <getch>
-    3e86:	90 e0       	ldi	r25, 0x00	; 0
-    3e88:	98 2f       	mov	r25, r24
-    3e8a:	88 27       	eor	r24, r24
-    3e8c:	80 2b       	or	r24, r16
-    3e8e:	91 2b       	or	r25, r17
+    3e72:	92 d0       	rcall	.+292    	; 0x3f98 <getch>
+    3e74:	90 e0       	ldi	r25, 0x00	; 0
+    3e76:	98 2f       	mov	r25, r24
+    3e78:	88 27       	eor	r24, r24
+    3e7a:	80 2b       	or	r24, r16
+    3e7c:	91 2b       	or	r25, r17
       address += address; // Convert from word address to byte address
-    3e90:	88 0f       	add	r24, r24
-    3e92:	99 1f       	adc	r25, r25
-    3e94:	90 93 01 02 	sts	0x0201, r25
-    3e98:	80 93 00 02 	sts	0x0200, r24
-    3e9c:	76 c0       	rjmp	.+236    	; 0x3f8a <main+0x18a>
+    3e7e:	88 0f       	add	r24, r24
+    3e80:	99 1f       	adc	r25, r25
+    3e82:	90 93 01 02 	sts	0x0201, r25
+    3e86:	80 93 00 02 	sts	0x0200, r24
+    3e8a:	73 c0       	rjmp	.+230    	; 0x3f72 <main+0x172>
       verifySpace();
     }
     else if(ch == STK_UNIVERSAL) {
-    3e9e:	86 35       	cpi	r24, 0x56	; 86
-    3ea0:	29 f4       	brne	.+10     	; 0x3eac <main+0xac>
+    3e8c:	86 35       	cpi	r24, 0x56	; 86
+    3e8e:	29 f4       	brne	.+10     	; 0x3e9a <main+0x9a>
       // UNIVERSAL command is ignored
       getNch(4);
-    3ea2:	84 e0       	ldi	r24, 0x04	; 4
-    3ea4:	a2 d0       	rcall	.+324    	; 0x3fea <verifySpace+0xc>
+    3e90:	84 e0       	ldi	r24, 0x04	; 4
+    3e92:	ac d0       	rcall	.+344    	; 0x3fec <verifySpace+0xc>
       putch(0x00);
-    3ea6:	80 e0       	ldi	r24, 0x00	; 0
-    3ea8:	74 d0       	rcall	.+232    	; 0x3f92 <putch>
-    3eaa:	70 c0       	rjmp	.+224    	; 0x3f8c <main+0x18c>
+    3e94:	80 e0       	ldi	r24, 0x00	; 0
+    3e96:	71 d0       	rcall	.+226    	; 0x3f7a <putch>
+    3e98:	6d c0       	rjmp	.+218    	; 0x3f74 <main+0x174>
     }
     /* Write memory, length is big endian and is in bytes  */
     else if(ch == STK_PROG_PAGE) {
-    3eac:	84 36       	cpi	r24, 0x64	; 100
-    3eae:	09 f0       	breq	.+2      	; 0x3eb2 <main+0xb2>
-    3eb0:	46 c0       	rjmp	.+140    	; 0x3f3e <main+0x13e>
+    3e9a:	84 36       	cpi	r24, 0x64	; 100
+    3e9c:	09 f0       	breq	.+2      	; 0x3ea0 <main+0xa0>
+    3e9e:	43 c0       	rjmp	.+134    	; 0x3f26 <main+0x126>
       // PROGRAM PAGE - we support flash programming only, not EEPROM
       uint8_t *bufPtr;
       uint16_t addrPtr;
-      
-      if (getLen() != 'F') appStart(); // Abort is not flash programming
-    3eb2:	90 d0       	rcall	.+288    	; 0x3fd4 <getLen>
-    3eb4:	86 34       	cpi	r24, 0x46	; 70
-    3eb6:	09 f0       	breq	.+2      	; 0x3eba <main+0xba>
-    3eb8:	7b d0       	rcall	.+246    	; 0x3fb0 <appStart>
-  
+
+      getLen();
+    3ea0:	8f d0       	rcall	.+286    	; 0x3fc0 <getLen>
+
       // Immediately start page erase - this will 4.5ms
       boot_page_erase((uint16_t)(void*)address);
-    3eba:	e0 91 00 02 	lds	r30, 0x0200
-    3ebe:	f0 91 01 02 	lds	r31, 0x0201
-    3ec2:	83 e0       	ldi	r24, 0x03	; 3
-    3ec4:	80 93 57 00 	sts	0x0057, r24
-    3ec8:	e8 95       	spm
-    3eca:	c0 e0       	ldi	r28, 0x00	; 0
-    3ecc:	d1 e0       	ldi	r29, 0x01	; 1
+    3ea2:	e0 91 00 02 	lds	r30, 0x0200
+    3ea6:	f0 91 01 02 	lds	r31, 0x0201
+    3eaa:	83 e0       	ldi	r24, 0x03	; 3
+    3eac:	80 93 57 00 	sts	0x0057, r24
+    3eb0:	e8 95       	spm
+    3eb2:	c0 e0       	ldi	r28, 0x00	; 0
+    3eb4:	d1 e0       	ldi	r29, 0x01	; 1
 
       // While that is going on, read in page contents
       bufPtr = buff;
       do *bufPtr++ = getch();
-    3ece:	73 d0       	rcall	.+230    	; 0x3fb6 <getch>
-    3ed0:	89 93       	st	Y+, r24
+    3eb6:	70 d0       	rcall	.+224    	; 0x3f98 <getch>
+    3eb8:	89 93       	st	Y+, r24
       while (--length);
-    3ed2:	80 91 02 02 	lds	r24, 0x0202
-    3ed6:	81 50       	subi	r24, 0x01	; 1
-    3ed8:	80 93 02 02 	sts	0x0202, r24
-    3edc:	88 23       	and	r24, r24
-    3ede:	b9 f7       	brne	.-18     	; 0x3ece <main+0xce>
+    3eba:	80 91 02 02 	lds	r24, 0x0202
+    3ebe:	81 50       	subi	r24, 0x01	; 1
+    3ec0:	80 93 02 02 	sts	0x0202, r24
+    3ec4:	88 23       	and	r24, r24
+    3ec6:	b9 f7       	brne	.-18     	; 0x3eb6 <main+0xb6>
 
+      // Read command terminator, start reply
+      verifySpace();
+    3ec8:	8b d0       	rcall	.+278    	; 0x3fe0 <verifySpace>
+      
       // If only a partial page is to be programmed, the erase might not be complete.
       // So check that here
       boot_spm_busy_wait();
-    3ee0:	07 b6       	in	r0, 0x37	; 55
-    3ee2:	00 fc       	sbrc	r0, 0
-    3ee4:	fd cf       	rjmp	.-6      	; 0x3ee0 <main+0xe0>
+    3eca:	07 b6       	in	r0, 0x37	; 55
+    3ecc:	00 fc       	sbrc	r0, 0
+    3ece:	fd cf       	rjmp	.-6      	; 0x3eca <main+0xca>
 
-      // Read command terminator, start reply
-      verifySpace();
-    3ee6:	7b d0       	rcall	.+246    	; 0x3fde <verifySpace>
-      
       // Copy buffer into programming buffer
       bufPtr = buff;
       addrPtr = (uint16_t)(void*)address;
-    3ee8:	40 91 00 02 	lds	r20, 0x0200
-    3eec:	50 91 01 02 	lds	r21, 0x0201
-    3ef0:	a0 e0       	ldi	r26, 0x00	; 0
-    3ef2:	b1 e0       	ldi	r27, 0x01	; 1
+    3ed0:	40 91 00 02 	lds	r20, 0x0200
+    3ed4:	50 91 01 02 	lds	r21, 0x0201
+    3ed8:	a0 e0       	ldi	r26, 0x00	; 0
+    3eda:	b1 e0       	ldi	r27, 0x01	; 1
       ch = SPM_PAGESIZE / 2;
       do {
         uint16_t a;
         a = *bufPtr++;
-    3ef4:	2c 91       	ld	r18, X
-    3ef6:	30 e0       	ldi	r19, 0x00	; 0
+    3edc:	2c 91       	ld	r18, X
+    3ede:	30 e0       	ldi	r19, 0x00	; 0
         a |= (*bufPtr++) << 8;
-    3ef8:	11 96       	adiw	r26, 0x01	; 1
-    3efa:	8c 91       	ld	r24, X
-    3efc:	11 97       	sbiw	r26, 0x01	; 1
-    3efe:	90 e0       	ldi	r25, 0x00	; 0
-    3f00:	98 2f       	mov	r25, r24
-    3f02:	88 27       	eor	r24, r24
-    3f04:	82 2b       	or	r24, r18
-    3f06:	93 2b       	or	r25, r19
+    3ee0:	11 96       	adiw	r26, 0x01	; 1
+    3ee2:	8c 91       	ld	r24, X
+    3ee4:	11 97       	sbiw	r26, 0x01	; 1
+    3ee6:	90 e0       	ldi	r25, 0x00	; 0
+    3ee8:	98 2f       	mov	r25, r24
+    3eea:	88 27       	eor	r24, r24
+    3eec:	82 2b       	or	r24, r18
+    3eee:	93 2b       	or	r25, r19
 #define buff    ((uint8_t*)(0x100))
 #define address (*(uint16_t*)(0x200))
 #define length  (*(uint8_t*)(0x202))
 
 /* main program starts here */
 int main(void) {
-    3f08:	12 96       	adiw	r26, 0x02	; 2
+    3ef0:	12 96       	adiw	r26, 0x02	; 2
       ch = SPM_PAGESIZE / 2;
       do {
         uint16_t a;
         a = *bufPtr++;
         a |= (*bufPtr++) << 8;
         boot_page_fill((uint16_t)(void*)addrPtr,a);
-    3f0a:	fa 01       	movw	r30, r20
-    3f0c:	0c 01       	movw	r0, r24
-    3f0e:	d0 92 57 00 	sts	0x0057, r13
-    3f12:	e8 95       	spm
-    3f14:	11 24       	eor	r1, r1
+    3ef2:	fa 01       	movw	r30, r20
+    3ef4:	0c 01       	movw	r0, r24
+    3ef6:	d0 92 57 00 	sts	0x0057, r13
+    3efa:	e8 95       	spm
+    3efc:	11 24       	eor	r1, r1
         addrPtr += 2;
-    3f16:	4e 5f       	subi	r20, 0xFE	; 254
-    3f18:	5f 4f       	sbci	r21, 0xFF	; 255
+    3efe:	4e 5f       	subi	r20, 0xFE	; 254
+    3f00:	5f 4f       	sbci	r21, 0xFF	; 255
       } while (--ch);
-    3f1a:	f1 e0       	ldi	r31, 0x01	; 1
-    3f1c:	a0 38       	cpi	r26, 0x80	; 128
-    3f1e:	bf 07       	cpc	r27, r31
-    3f20:	49 f7       	brne	.-46     	; 0x3ef4 <main+0xf4>
+    3f02:	f1 e0       	ldi	r31, 0x01	; 1
+    3f04:	a0 38       	cpi	r26, 0x80	; 128
+    3f06:	bf 07       	cpc	r27, r31
+    3f08:	49 f7       	brne	.-46     	; 0x3edc <main+0xdc>
       
       // Write from programming buffer
       boot_page_write((uint16_t)(void*)address);
-    3f22:	e0 91 00 02 	lds	r30, 0x0200
-    3f26:	f0 91 01 02 	lds	r31, 0x0201
-    3f2a:	e0 92 57 00 	sts	0x0057, r14
-    3f2e:	e8 95       	spm
+    3f0a:	e0 91 00 02 	lds	r30, 0x0200
+    3f0e:	f0 91 01 02 	lds	r31, 0x0201
+    3f12:	e0 92 57 00 	sts	0x0057, r14
+    3f16:	e8 95       	spm
       boot_spm_busy_wait();
-    3f30:	07 b6       	in	r0, 0x37	; 55
-    3f32:	00 fc       	sbrc	r0, 0
-    3f34:	fd cf       	rjmp	.-6      	; 0x3f30 <main+0x130>
+    3f18:	07 b6       	in	r0, 0x37	; 55
+    3f1a:	00 fc       	sbrc	r0, 0
+    3f1c:	fd cf       	rjmp	.-6      	; 0x3f18 <main+0x118>
 
       // Reenable read access to flash
       boot_rww_enable();
-    3f36:	f0 92 57 00 	sts	0x0057, r15
-    3f3a:	e8 95       	spm
-    3f3c:	27 c0       	rjmp	.+78     	; 0x3f8c <main+0x18c>
+    3f1e:	f0 92 57 00 	sts	0x0057, r15
+    3f22:	e8 95       	spm
+    3f24:	27 c0       	rjmp	.+78     	; 0x3f74 <main+0x174>
     }
     /* Read memory block mode, length is big endian.  */
     else if(ch == STK_READ_PAGE) {
-    3f3e:	84 37       	cpi	r24, 0x74	; 116
-    3f40:	b9 f4       	brne	.+46     	; 0x3f70 <main+0x170>
+    3f26:	84 37       	cpi	r24, 0x74	; 116
+    3f28:	b9 f4       	brne	.+46     	; 0x3f58 <main+0x158>
       // READ PAGE - we only read flash
       getLen();
-    3f42:	48 d0       	rcall	.+144    	; 0x3fd4 <getLen>
+    3f2a:	4a d0       	rcall	.+148    	; 0x3fc0 <getLen>
       verifySpace();
-    3f44:	4c d0       	rcall	.+152    	; 0x3fde <verifySpace>
+    3f2c:	59 d0       	rcall	.+178    	; 0x3fe0 <verifySpace>
       do putch(pgm_read_byte_near(address++));
-    3f46:	e0 91 00 02 	lds	r30, 0x0200
-    3f4a:	f0 91 01 02 	lds	r31, 0x0201
-    3f4e:	31 96       	adiw	r30, 0x01	; 1
-    3f50:	f0 93 01 02 	sts	0x0201, r31
-    3f54:	e0 93 00 02 	sts	0x0200, r30
-    3f58:	31 97       	sbiw	r30, 0x01	; 1
-    3f5a:	e4 91       	lpm	r30, Z+
-    3f5c:	8e 2f       	mov	r24, r30
-    3f5e:	19 d0       	rcall	.+50     	; 0x3f92 <putch>
+    3f2e:	e0 91 00 02 	lds	r30, 0x0200
+    3f32:	f0 91 01 02 	lds	r31, 0x0201
+    3f36:	31 96       	adiw	r30, 0x01	; 1
+    3f38:	f0 93 01 02 	sts	0x0201, r31
+    3f3c:	e0 93 00 02 	sts	0x0200, r30
+    3f40:	31 97       	sbiw	r30, 0x01	; 1
+    3f42:	e4 91       	lpm	r30, Z+
+    3f44:	8e 2f       	mov	r24, r30
+    3f46:	19 d0       	rcall	.+50     	; 0x3f7a <putch>
       while (--length);
-    3f60:	80 91 02 02 	lds	r24, 0x0202
-    3f64:	81 50       	subi	r24, 0x01	; 1
-    3f66:	80 93 02 02 	sts	0x0202, r24
-    3f6a:	88 23       	and	r24, r24
-    3f6c:	61 f7       	brne	.-40     	; 0x3f46 <main+0x146>
-    3f6e:	0e c0       	rjmp	.+28     	; 0x3f8c <main+0x18c>
+    3f48:	80 91 02 02 	lds	r24, 0x0202
+    3f4c:	81 50       	subi	r24, 0x01	; 1
+    3f4e:	80 93 02 02 	sts	0x0202, r24
+    3f52:	88 23       	and	r24, r24
+    3f54:	61 f7       	brne	.-40     	; 0x3f2e <main+0x12e>
+    3f56:	0e c0       	rjmp	.+28     	; 0x3f74 <main+0x174>
     }
 
     /* Get device signature bytes  */
     else if(ch == STK_READ_SIGN) {
-    3f70:	85 37       	cpi	r24, 0x75	; 117
-    3f72:	39 f4       	brne	.+14     	; 0x3f82 <main+0x182>
+    3f58:	85 37       	cpi	r24, 0x75	; 117
+    3f5a:	39 f4       	brne	.+14     	; 0x3f6a <main+0x16a>
       // READ SIGN - return what Avrdude wants to hear
       verifySpace();
-    3f74:	34 d0       	rcall	.+104    	; 0x3fde <verifySpace>
+    3f5c:	41 d0       	rcall	.+130    	; 0x3fe0 <verifySpace>
       putch(SIGNATURE_0);
-    3f76:	8e e1       	ldi	r24, 0x1E	; 30
-    3f78:	0c d0       	rcall	.+24     	; 0x3f92 <putch>
+    3f5e:	8e e1       	ldi	r24, 0x1E	; 30
+    3f60:	0c d0       	rcall	.+24     	; 0x3f7a <putch>
       putch(SIGNATURE_1);
-    3f7a:	84 e9       	ldi	r24, 0x94	; 148
-    3f7c:	0a d0       	rcall	.+20     	; 0x3f92 <putch>
+    3f62:	84 e9       	ldi	r24, 0x94	; 148
+    3f64:	0a d0       	rcall	.+20     	; 0x3f7a <putch>
       putch(SIGNATURE_2);
-    3f7e:	86 e0       	ldi	r24, 0x06	; 6
-    3f80:	93 cf       	rjmp	.-218    	; 0x3ea8 <main+0xa8>
+    3f66:	86 e0       	ldi	r24, 0x06	; 6
+    3f68:	96 cf       	rjmp	.-212    	; 0x3e96 <main+0x96>
     }
     else if (ch == 'Q') {
-    3f82:	81 35       	cpi	r24, 0x51	; 81
-    3f84:	11 f4       	brne	.+4      	; 0x3f8a <main+0x18a>
+    3f6a:	81 35       	cpi	r24, 0x51	; 81
+    3f6c:	11 f4       	brne	.+4      	; 0x3f72 <main+0x172>
       // Adaboot no-wait mod
-      WDTCSR = _BV(WDE);
-    3f86:	c0 92 60 00 	sts	0x0060, r12
+      watchdogConfig(_BV(WDE));
+    3f6e:	88 e0       	ldi	r24, 0x08	; 8
+    3f70:	2c d0       	rcall	.+88     	; 0x3fca <watchdogConfig>
       verifySpace();
     }
     else {
       // This covers the response to commands like STK_ENTER_PROGMODE
       verifySpace();
-    3f8a:	29 d0       	rcall	.+82     	; 0x3fde <verifySpace>
+    3f72:	36 d0       	rcall	.+108    	; 0x3fe0 <verifySpace>
     }
     putch(STK_OK);
-    3f8c:	80 e1       	ldi	r24, 0x10	; 16
-    3f8e:	01 d0       	rcall	.+2      	; 0x3f92 <putch>
-    3f90:	60 cf       	rjmp	.-320    	; 0x3e52 <main+0x52>
-
-00003f92 <putch>:
-  }
-}
+    3f74:	80 e1       	ldi	r24, 0x10	; 16
+    3f76:	01 d0       	rcall	.+2      	; 0x3f7a <putch>
+    3f78:	63 cf       	rjmp	.-314    	; 0x3e40 <main+0x40>
 
+00003f7a <putch>:
 void putch(char ch) {
-    3f92:	98 2f       	mov	r25, r24
+#ifndef SOFT_UART
   while (!(UCSR0A & _BV(UDRE0)));
-    3f94:	80 91 c0 00 	lds	r24, 0x00C0
-    3f98:	85 ff       	sbrs	r24, 5
-    3f9a:	fc cf       	rjmp	.-8      	; 0x3f94 <putch+0x2>
   UDR0 = ch;
-    3f9c:	90 93 c6 00 	sts	0x00C6, r25
-}
-    3fa0:	08 95       	ret
-
-00003fa2 <setTimer>:
-
-void setTimer(uint16_t counts) {
-  TCNT1 = counts;
-    3fa2:	90 93 85 00 	sts	0x0085, r25
-    3fa6:	80 93 84 00 	sts	0x0084, r24
-  TIFR1 = _BV(TOV1);
-    3faa:	81 e0       	ldi	r24, 0x01	; 1
-    3fac:	86 bb       	out	0x16, r24	; 22
+#else
+  __asm__ __volatile__ (
+    3f7a:	2a e0       	ldi	r18, 0x0A	; 10
+    3f7c:	30 e0       	ldi	r19, 0x00	; 0
+    3f7e:	80 95       	com	r24
+    3f80:	08 94       	sec
+    3f82:	10 f4       	brcc	.+4      	; 0x3f88 <putch+0xe>
+    3f84:	59 98       	cbi	0x0b, 1	; 11
+    3f86:	02 c0       	rjmp	.+4      	; 0x3f8c <putch+0x12>
+    3f88:	59 9a       	sbi	0x0b, 1	; 11
+    3f8a:	00 00       	nop
+    3f8c:	15 d0       	rcall	.+42     	; 0x3fb8 <uartDelay>
+    3f8e:	14 d0       	rcall	.+40     	; 0x3fb8 <uartDelay>
+    3f90:	86 95       	lsr	r24
+    3f92:	2a 95       	dec	r18
+    3f94:	b1 f7       	brne	.-20     	; 0x3f82 <putch+0x8>
+      [uartBit] "I" (UART_TX_BIT)
+    :
+      "r25"
+  );
+#endif
 }
-    3fae:	08 95       	ret
+    3f96:	08 95       	ret
 
-00003fb0 <appStart>:
-  length = getch();
+00003f98 <getch>:
   return getch();
 }
 
-void appStart() {
+// Watchdog functions. These are only safe with interrupts turned off.
+void watchdogReset() {
   __asm__ __volatile__ (
-    3fb0:	ee 27       	eor	r30, r30
-    3fb2:	ff 27       	eor	r31, r31
-    3fb4:	09 94       	ijmp
+    3f98:	a8 95       	wdr
+#ifdef LED_DATA_FLASH
+  LED_PIN |= _BV(LED);
+#endif
 
-00003fb6 <getch>:
-  TCNT1 = counts;
-  TIFR1 = _BV(TOV1);
+  return ch;
 }
+    3f9a:	29 e0       	ldi	r18, 0x09	; 9
+    3f9c:	30 e0       	ldi	r19, 0x00	; 0
+    3f9e:	48 99       	sbic	0x09, 0	; 9
+    3fa0:	fe cf       	rjmp	.-4      	; 0x3f9e <getch+0x6>
+    3fa2:	0a d0       	rcall	.+20     	; 0x3fb8 <uartDelay>
+    3fa4:	09 d0       	rcall	.+18     	; 0x3fb8 <uartDelay>
+    3fa6:	08 d0       	rcall	.+16     	; 0x3fb8 <uartDelay>
+    3fa8:	88 94       	clc
+    3faa:	48 99       	sbic	0x09, 0	; 9
+    3fac:	08 94       	sec
+    3fae:	2a 95       	dec	r18
+    3fb0:	11 f0       	breq	.+4      	; 0x3fb6 <getch+0x1e>
+    3fb2:	87 95       	ror	r24
+    3fb4:	f7 cf       	rjmp	.-18     	; 0x3fa4 <getch+0xc>
+    3fb6:	08 95       	ret
+
+00003fb8 <uartDelay>:
+#if UART_B_VALUE > 255
+#error Baud rate too slow for soft UART
+#endif
 
-uint8_t getch(void) {
-  LED_PORT &= ~_BV(LED);
-    3fb6:	2d 98       	cbi	0x05, 5	; 5
-  setTimer(-(F_CPU/(1024*2))); // 500ms
-    3fb8:	8c e7       	ldi	r24, 0x7C	; 124
-    3fba:	91 ee       	ldi	r25, 0xE1	; 225
-    3fbc:	f2 df       	rcall	.-28     	; 0x3fa2 <setTimer>
-    3fbe:	02 c0       	rjmp	.+4      	; 0x3fc4 <getch+0xe>
-  while(!(UCSR0A & _BV(RXC0))) if (TIFR1 & _BV(TOV1)) appStart();
-    3fc0:	b0 99       	sbic	0x16, 0	; 22
-    3fc2:	f6 df       	rcall	.-20     	; 0x3fb0 <appStart>
-    3fc4:	80 91 c0 00 	lds	r24, 0x00C0
-    3fc8:	87 ff       	sbrs	r24, 7
-    3fca:	fa cf       	rjmp	.-12     	; 0x3fc0 <getch+0xa>
-  LED_PORT |= _BV(LED);
-    3fcc:	2d 9a       	sbi	0x05, 5	; 5
-  return UDR0;
-    3fce:	80 91 c6 00 	lds	r24, 0x00C6
-}
-    3fd2:	08 95       	ret
+void uartDelay() {
+  __asm__ __volatile__ (
+    3fb8:	98 e0       	ldi	r25, 0x08	; 8
+    3fba:	9a 95       	dec	r25
+    3fbc:	f1 f7       	brne	.-4      	; 0x3fba <uartDelay+0x2>
+    3fbe:	08 95       	ret
 
-00003fd4 <getLen>:
-    LED_PIN |= _BV(LED);
+00003fc0 <getLen>:
   } while (--count);
 }
+#endif
 
 uint8_t getLen() {
   getch();
-    3fd4:	f0 df       	rcall	.-32     	; 0x3fb6 <getch>
+    3fc0:	eb df       	rcall	.-42     	; 0x3f98 <getch>
   length = getch();
-    3fd6:	ef df       	rcall	.-34     	; 0x3fb6 <getch>
-    3fd8:	80 93 02 02 	sts	0x0202, r24
+    3fc2:	ea df       	rcall	.-44     	; 0x3f98 <getch>
+    3fc4:	80 93 02 02 	sts	0x0202, r24
   return getch();
 }
-    3fdc:	ec cf       	rjmp	.-40     	; 0x3fb6 <getch>
+    3fc8:	e7 cf       	rjmp	.-50     	; 0x3f98 <getch>
+
+00003fca <watchdogConfig>:
+    "wdr\n"
+  );
+}
 
-00003fde <verifySpace>:
+void watchdogConfig(uint8_t x) {
+  WDTCSR = _BV(WDCE) | _BV(WDE);
+    3fca:	e0 e6       	ldi	r30, 0x60	; 96
+    3fcc:	f0 e0       	ldi	r31, 0x00	; 0
+    3fce:	98 e1       	ldi	r25, 0x18	; 24
+    3fd0:	90 83       	st	Z, r25
+  WDTCSR = x;
+    3fd2:	80 83       	st	Z, r24
+}
+    3fd4:	08 95       	ret
+
+00003fd6 <appStart>:
+
+void appStart() {
+  watchdogConfig(0);
+    3fd6:	80 e0       	ldi	r24, 0x00	; 0
+    3fd8:	f8 df       	rcall	.-16     	; 0x3fca <watchdogConfig>
+  __asm__ __volatile__ (
+    3fda:	ee 27       	eor	r30, r30
+    3fdc:	ff 27       	eor	r31, r31
+    3fde:	09 94       	ijmp
+
+00003fe0 <verifySpace>:
   do getch(); while (--count);
   verifySpace();
 }
 
 void verifySpace() {
   if (getch() != CRC_EOP) appStart();
-    3fde:	eb df       	rcall	.-42     	; 0x3fb6 <getch>
-    3fe0:	80 32       	cpi	r24, 0x20	; 32
-    3fe2:	09 f0       	breq	.+2      	; 0x3fe6 <verifySpace+0x8>
-    3fe4:	e5 df       	rcall	.-54     	; 0x3fb0 <appStart>
+    3fe0:	db df       	rcall	.-74     	; 0x3f98 <getch>
+    3fe2:	80 32       	cpi	r24, 0x20	; 32
+    3fe4:	09 f0       	breq	.+2      	; 0x3fe8 <verifySpace+0x8>
+    3fe6:	f7 df       	rcall	.-18     	; 0x3fd6 <appStart>
   putch(STK_INSYNC);
-    3fe6:	84 e1       	ldi	r24, 0x14	; 20
+    3fe8:	84 e1       	ldi	r24, 0x14	; 20
 }
-    3fe8:	d4 cf       	rjmp	.-88     	; 0x3f92 <putch>
-  while(!(UCSR0A & _BV(RXC0))) if (TIFR1 & _BV(TOV1)) appStart();
-  LED_PORT |= _BV(LED);
-  return UDR0;
+    3fea:	c7 cf       	rjmp	.-114    	; 0x3f7a <putch>
+    ::[count] "M" (UART_B_VALUE)
+  );
 }
+#endif
 
 void getNch(uint8_t count) {
-    3fea:	1f 93       	push	r17
-    3fec:	18 2f       	mov	r17, r24
+    3fec:	1f 93       	push	r17
+    3fee:	18 2f       	mov	r17, r24
 
-00003fee <getNch>:
+00003ff0 <getNch>:
   do getch(); while (--count);
-    3fee:	e3 df       	rcall	.-58     	; 0x3fb6 <getch>
-    3ff0:	11 50       	subi	r17, 0x01	; 1
-    3ff2:	e9 f7       	brne	.-6      	; 0x3fee <getNch>
+    3ff0:	d3 df       	rcall	.-90     	; 0x3f98 <getch>
+    3ff2:	11 50       	subi	r17, 0x01	; 1
+    3ff4:	e9 f7       	brne	.-6      	; 0x3ff0 <getNch>
   verifySpace();
-    3ff4:	f4 df       	rcall	.-24     	; 0x3fde <verifySpace>
+    3ff6:	f4 df       	rcall	.-24     	; 0x3fe0 <verifySpace>
 }
-    3ff6:	1f 91       	pop	r17
-    3ff8:	08 95       	ret
+    3ff8:	1f 91       	pop	r17
+    3ffa:	08 95       	ret

+ 32 - 32
optiboot/bootloaders/optiboot/optiboot_lilypad.hex

@@ -1,34 +1,34 @@
-:103E000085E08093810082E08093C00098E19093E8
-:103E1000C10086E08093C20083E38093C40084B72E
-:103E200014BE909360001092600081FFC1D0259A6B
-:103E300006E088E19EEFB5D0B09BFECF1D9A015001
-:103E4000C1F7DD24D394B8E0CB2EA5E0EA2EF1E152
-:103E5000FF2EB1D0813421F481E0C7D083E024C0AB
-:103E6000823411F484E103C0853419F485E0BDD0B7
-:103E70008DC08535A1F49FD0082F10E0109301026A
-:103E80000093000298D090E0982F8827802B912BE8
-:103E9000880F991F909301028093000276C08635A7
-:103EA00029F484E0A2D080E074D070C0843609F098
-:103EB00046C090D0863409F07BD0E0910002F091AA
-:103EC000010283E080935700E895C0E0D1E073D011
-:103ED0008993809102028150809302028823B9F76E
-:103EE00007B600FCFDCF7BD040910002509101024B
-:103EF000A0E0B1E02C9130E011968C91119790E008
-:103F0000982F8827822B932B1296FA010C01D092BE
-:103F10005700E89511244E5F5F4FF1E0A038BF07CE
-:103F200049F7E0910002F0910102E0925700E89514
-:103F300007B600FCFDCFF0925700E89527C0843704
-:103F4000B9F448D04CD0E0910002F09101023196D2
-:103F5000F0930102E09300023197E4918E2F19D083
-:103F600080910202815080930202882361F70EC083
-:103F7000853739F434D08EE10CD084E90AD086E05C
-:103F800093CF813511F4C092600029D080E101D037
-:103F900060CF982F8091C00085FFFCCF9093C60022
-:103FA0000895909385008093840081E086BB0895F6
-:103FB000EE27FF2709942D988EEB90EFF2DF02C0D9
-:103FC000B099F6DF8091C00087FFFACF2D9A8091DB
-:103FD000C6000895F0DFEFDF80930202ECCFEBDF45
-:103FE000803209F0E5DF84E1D4CF1F93182FE3DF9F
-:0A3FF0001150E9F7F4DF1F91089566
+:103E000085E08093810084B714BE81FFE4D08DE00B
+:103E1000DCD0259A519A86E028E13EEF91E030937C
+:103E200085002093840096BBB09BFECF1D9AA89579
+:103E30008150A9F7DD24D394A5E0EA2EF1E1FF2E0D
+:103E4000ABD0813421F481E0D1D083E024C082342E
+:103E500011F484E103C0853419F485E0C7D08AC029
+:103E60008535A1F499D0082F10E01093010200933A
+:103E7000000292D090E0982F8827802B912B880FFA
+:103E8000991F909301028093000273C0863529F434
+:103E900084E0ACD080E071D06DC0843609F043C0BE
+:103EA0008FD0E0910002F091010283E080935700EF
+:103EB000E895C0E0D1E070D08993809102028150F2
+:103EC000809302028823B9F78BD007B600FCFDCFA0
+:103ED0004091000250910102A0E0B1E02C9130E04D
+:103EE00011968C91119790E0982F8827822B932B15
+:103EF0001296FA010C01D0925700E89511244E5FFA
+:103F00005F4FF1E0A038BF0749F7E0910002F09160
+:103F10000102E0925700E89507B600FCFDCFF09251
+:103F20005700E89527C08437B9F44AD059D0E091BA
+:103F30000002F09101023196F0930102E093000239
+:103F40003197E4918E2F19D0809102028150809395
+:103F50000202882361F70EC0853739F441D08EE123
+:103F60000CD084E90AD086E096CF813511F488E040
+:103F70002CD036D080E101D063CF2AE030E08095AC
+:103F8000089410F4599802C0599A000015D014D022
+:103F900086952A95B1F70895A89529E030E04899CB
+:103FA000FECF0AD009D008D08894489908942A9561
+:103FB00011F08795F7CF089598E09A95F1F7089555
+:103FC000EBDFEADF80930202E7CFE0E6F0E098E182
+:103FD00090838083089580E0F8DFEE27FF2709941F
+:103FE000DBDF803209F0F7DF84E1C7CF1F93182FA2
+:0C3FF000D3DF1150E9F7F4DF1F910895B2
 :0400000300003E00BB
 :00000001FF

+ 320 - 282
optiboot/bootloaders/optiboot/optiboot_lilypad.lst

@@ -3,25 +3,25 @@ optiboot_lilypad.elf:     file format elf32-avr
 
 Sections:
 Idx Name          Size      VMA       LMA       File off  Algn
-  0 .text         000001fa  00003e00  00003e00  00000054  2**1
+  0 .text         000001fc  00003e00  00003e00  00000054  2**1
                   CONTENTS, ALLOC, LOAD, READONLY, CODE
-  1 .debug_aranges 00000028  00000000  00000000  0000024e  2**0
+  1 .debug_aranges 00000028  00000000  00000000  00000250  2**0
                   CONTENTS, READONLY, DEBUGGING
-  2 .debug_pubnames 00000064  00000000  00000000  00000276  2**0
+  2 .debug_pubnames 00000078  00000000  00000000  00000278  2**0
                   CONTENTS, READONLY, DEBUGGING
-  3 .debug_info   0000022f  00000000  00000000  000002da  2**0
+  3 .debug_info   00000275  00000000  00000000  000002f0  2**0
                   CONTENTS, READONLY, DEBUGGING
-  4 .debug_abbrev 00000164  00000000  00000000  00000509  2**0
+  4 .debug_abbrev 000001a3  00000000  00000000  00000565  2**0
                   CONTENTS, READONLY, DEBUGGING
-  5 .debug_line   000003c8  00000000  00000000  0000066d  2**0
+  5 .debug_line   000003b8  00000000  00000000  00000708  2**0
                   CONTENTS, READONLY, DEBUGGING
-  6 .debug_frame  00000090  00000000  00000000  00000a38  2**2
+  6 .debug_frame  000000a0  00000000  00000000  00000ac0  2**2
                   CONTENTS, READONLY, DEBUGGING
-  7 .debug_str    0000011c  00000000  00000000  00000ac8  2**0
+  7 .debug_str    00000133  00000000  00000000  00000b60  2**0
                   CONTENTS, READONLY, DEBUGGING
-  8 .debug_loc    000001d6  00000000  00000000  00000be4  2**0
+  8 .debug_loc    000001a0  00000000  00000000  00000c93  2**0
                   CONTENTS, READONLY, DEBUGGING
-  9 .debug_ranges 00000068  00000000  00000000  00000dba  2**0
+  9 .debug_ranges 00000070  00000000  00000000  00000e33  2**0
                   CONTENTS, READONLY, DEBUGGING
 
 Disassembly of section .text:
@@ -35,449 +35,487 @@ Disassembly of section .text:
 int main(void) {
     3e00:	85 e0       	ldi	r24, 0x05	; 5
     3e02:	80 93 81 00 	sts	0x0081, r24
-    [addr5]"i"(_SFR_MEM_ADDR(UBRR0L)), [val5]"i"((F_CPU + BAUD_RATE * 4L) / (BAUD_RATE * 8L) - 1)
-  );
-#else
-  // Set up Timer 1 for timeout counter
-  TCCR1B = _BV(CS12) | _BV(CS10); // div 1024
-  UCSR0A = _BV(U2X0); //Double speed mode USART0
-    3e06:	82 e0       	ldi	r24, 0x02	; 2
-    3e08:	80 93 c0 00 	sts	0x00C0, r24
-  UCSR0B = _BV(RXEN0) | _BV(TXEN0);
-    3e0c:	98 e1       	ldi	r25, 0x18	; 24
-    3e0e:	90 93 c1 00 	sts	0x00C1, r25
   UCSR0C = _BV(UCSZ00) | _BV(UCSZ01);
-    3e12:	86 e0       	ldi	r24, 0x06	; 6
-    3e14:	80 93 c2 00 	sts	0x00C2, r24
   UBRR0L = (uint8_t)( (F_CPU + BAUD_RATE * 4L) / (BAUD_RATE * 8L) - 1 );
-    3e18:	83 e3       	ldi	r24, 0x33	; 51
-    3e1a:	80 93 c4 00 	sts	0x00C4, r24
 #endif
 
   // Adaboot no-wait mod
   ch = MCUSR;
-    3e1e:	84 b7       	in	r24, 0x34	; 52
+    3e06:	84 b7       	in	r24, 0x34	; 52
   MCUSR = 0;
-    3e20:	14 be       	out	0x34, r1	; 52
-  WDTCSR = _BV(WDCE) | _BV(WDE);
-    3e22:	90 93 60 00 	sts	0x0060, r25
-  WDTCSR = 0;
-    3e26:	10 92 60 00 	sts	0x0060, r1
+    3e08:	14 be       	out	0x34, r1	; 52
   if (!(ch & _BV(EXTRF))) appStart();
-    3e2a:	81 ff       	sbrs	r24, 1
-    3e2c:	c1 d0       	rcall	.+386    	; 0x3fb0 <appStart>
+    3e0a:	81 ff       	sbrs	r24, 1
+    3e0c:	e4 d0       	rcall	.+456    	; 0x3fd6 <appStart>
+
+  // Set up watchdog to trigger after 500ms
+  watchdogConfig(_BV(WDP2)|_BV(WDP0)|_BV(WDE));
+    3e0e:	8d e0       	ldi	r24, 0x0D	; 13
+    3e10:	dc d0       	rcall	.+440    	; 0x3fca <watchdogConfig>
 
-  /* set LED pin as output */
+  /* Set LED pin as output */
   LED_DDR |= _BV(LED);
-    3e2e:	25 9a       	sbi	0x04, 5	; 4
-    3e30:	06 e0       	ldi	r16, 0x06	; 6
-  putch(STK_INSYNC);
+    3e12:	25 9a       	sbi	0x04, 5	; 4
+
+#ifdef SOFT_UART
+  /* Set TX pin as output */
+  UART_DDR |= _BV(UART_TX_BIT);
+    3e14:	51 9a       	sbi	0x0a, 1	; 10
+    3e16:	86 e0       	ldi	r24, 0x06	; 6
+}
+
+#if LED_START_FLASHES > 0
+void flash_led(uint8_t count) {
+  do {
+    TCNT1 = -(F_CPU/(1024*16));
+    3e18:	28 e1       	ldi	r18, 0x18	; 24
+    3e1a:	3e ef       	ldi	r19, 0xFE	; 254
+    TIFR1 = _BV(TOV1);
+    3e1c:	91 e0       	ldi	r25, 0x01	; 1
 }
 
+#if LED_START_FLASHES > 0
 void flash_led(uint8_t count) {
   do {
-    setTimer(-(F_CPU/(1024*16))); // 62ms
-    3e32:	88 e1       	ldi	r24, 0x18	; 24
-    3e34:	9e ef       	ldi	r25, 0xFE	; 254
-    3e36:	b5 d0       	rcall	.+362    	; 0x3fa2 <setTimer>
+    TCNT1 = -(F_CPU/(1024*16));
+    3e1e:	30 93 85 00 	sts	0x0085, r19
+    3e22:	20 93 84 00 	sts	0x0084, r18
+    TIFR1 = _BV(TOV1);
+    3e26:	96 bb       	out	0x16, r25	; 22
+    while(!(TIFR1 & _BV(TOV1)));
+    3e28:	b0 9b       	sbis	0x16, 0	; 22
+    3e2a:	fe cf       	rjmp	.-4      	; 0x3e28 <main+0x28>
+    LED_PIN |= _BV(LED);
+    3e2c:	1d 9a       	sbi	0x03, 5	; 3
+  return getch();
+}
+
+// Watchdog functions. These are only safe with interrupts turned off.
+void watchdogReset() {
+  __asm__ __volatile__ (
+    3e2e:	a8 95       	wdr
+    TCNT1 = -(F_CPU/(1024*16));
+    TIFR1 = _BV(TOV1);
     while(!(TIFR1 & _BV(TOV1)));
-    3e38:	b0 9b       	sbis	0x16, 0	; 22
-    3e3a:	fe cf       	rjmp	.-4      	; 0x3e38 <main+0x38>
     LED_PIN |= _BV(LED);
-    3e3c:	1d 9a       	sbi	0x03, 5	; 3
+    watchdogReset();
   } while (--count);
-    3e3e:	01 50       	subi	r16, 0x01	; 1
-    3e40:	c1 f7       	brne	.-16     	; 0x3e32 <main+0x32>
+    3e30:	81 50       	subi	r24, 0x01	; 1
+    3e32:	a9 f7       	brne	.-22     	; 0x3e1e <main+0x1e>
     /* get character from UART */
     ch = getch();
 
     if(ch == STK_GET_PARAMETER) {
       // GET PARAMETER returns a generic 0x03 reply - enough to keep Avrdude happy
       getNch(1);
-    3e42:	dd 24       	eor	r13, r13
-    3e44:	d3 94       	inc	r13
-      putch(SIGNATURE_1);
-      putch(SIGNATURE_2);
-    }
-    else if (ch == 'Q') {
-      // Adaboot no-wait mod
-      WDTCSR = _BV(WDE);
-    3e46:	b8 e0       	ldi	r27, 0x08	; 8
-    3e48:	cb 2e       	mov	r12, r27
+    3e34:	dd 24       	eor	r13, r13
+    3e36:	d3 94       	inc	r13
         boot_page_fill((uint16_t)(void*)addrPtr,a);
         addrPtr += 2;
       } while (--ch);
       
       // Write from programming buffer
       boot_page_write((uint16_t)(void*)address);
-    3e4a:	a5 e0       	ldi	r26, 0x05	; 5
-    3e4c:	ea 2e       	mov	r14, r26
+    3e38:	a5 e0       	ldi	r26, 0x05	; 5
+    3e3a:	ea 2e       	mov	r14, r26
       boot_spm_busy_wait();
 
       // Reenable read access to flash
       boot_rww_enable();
-    3e4e:	f1 e1       	ldi	r31, 0x11	; 17
-    3e50:	ff 2e       	mov	r15, r31
-  flash_led(NUM_LED_FLASHES * 2);
+    3e3c:	f1 e1       	ldi	r31, 0x11	; 17
+    3e3e:	ff 2e       	mov	r15, r31
+#endif
 
-  /* forever loop */
+  /* Forever loop */
   for (;;) {
     /* get character from UART */
     ch = getch();
-    3e52:	b1 d0       	rcall	.+354    	; 0x3fb6 <getch>
+    3e40:	ab d0       	rcall	.+342    	; 0x3f98 <getch>
 
     if(ch == STK_GET_PARAMETER) {
-    3e54:	81 34       	cpi	r24, 0x41	; 65
-    3e56:	21 f4       	brne	.+8      	; 0x3e60 <main+0x60>
+    3e42:	81 34       	cpi	r24, 0x41	; 65
+    3e44:	21 f4       	brne	.+8      	; 0x3e4e <main+0x4e>
       // GET PARAMETER returns a generic 0x03 reply - enough to keep Avrdude happy
       getNch(1);
-    3e58:	81 e0       	ldi	r24, 0x01	; 1
-    3e5a:	c7 d0       	rcall	.+398    	; 0x3fea <verifySpace+0xc>
+    3e46:	81 e0       	ldi	r24, 0x01	; 1
+    3e48:	d1 d0       	rcall	.+418    	; 0x3fec <verifySpace+0xc>
       putch(0x03);
-    3e5c:	83 e0       	ldi	r24, 0x03	; 3
-    3e5e:	24 c0       	rjmp	.+72     	; 0x3ea8 <main+0xa8>
+    3e4a:	83 e0       	ldi	r24, 0x03	; 3
+    3e4c:	24 c0       	rjmp	.+72     	; 0x3e96 <main+0x96>
     }
     else if(ch == STK_SET_DEVICE) {
-    3e60:	82 34       	cpi	r24, 0x42	; 66
-    3e62:	11 f4       	brne	.+4      	; 0x3e68 <main+0x68>
+    3e4e:	82 34       	cpi	r24, 0x42	; 66
+    3e50:	11 f4       	brne	.+4      	; 0x3e56 <main+0x56>
       // SET DEVICE is ignored
       getNch(20);
-    3e64:	84 e1       	ldi	r24, 0x14	; 20
-    3e66:	03 c0       	rjmp	.+6      	; 0x3e6e <main+0x6e>
+    3e52:	84 e1       	ldi	r24, 0x14	; 20
+    3e54:	03 c0       	rjmp	.+6      	; 0x3e5c <main+0x5c>
     }
     else if(ch == STK_SET_DEVICE_EXT) {
-    3e68:	85 34       	cpi	r24, 0x45	; 69
-    3e6a:	19 f4       	brne	.+6      	; 0x3e72 <main+0x72>
+    3e56:	85 34       	cpi	r24, 0x45	; 69
+    3e58:	19 f4       	brne	.+6      	; 0x3e60 <main+0x60>
       // SET DEVICE EXT is ignored
       getNch(5);
-    3e6c:	85 e0       	ldi	r24, 0x05	; 5
-    3e6e:	bd d0       	rcall	.+378    	; 0x3fea <verifySpace+0xc>
-    3e70:	8d c0       	rjmp	.+282    	; 0x3f8c <main+0x18c>
+    3e5a:	85 e0       	ldi	r24, 0x05	; 5
+    3e5c:	c7 d0       	rcall	.+398    	; 0x3fec <verifySpace+0xc>
+    3e5e:	8a c0       	rjmp	.+276    	; 0x3f74 <main+0x174>
     }
     else if(ch == STK_LOAD_ADDRESS) {
-    3e72:	85 35       	cpi	r24, 0x55	; 85
-    3e74:	a1 f4       	brne	.+40     	; 0x3e9e <main+0x9e>
+    3e60:	85 35       	cpi	r24, 0x55	; 85
+    3e62:	a1 f4       	brne	.+40     	; 0x3e8c <main+0x8c>
       // LOAD ADDRESS
       address = getch();
-    3e76:	9f d0       	rcall	.+318    	; 0x3fb6 <getch>
-    3e78:	08 2f       	mov	r16, r24
-    3e7a:	10 e0       	ldi	r17, 0x00	; 0
-    3e7c:	10 93 01 02 	sts	0x0201, r17
-    3e80:	00 93 00 02 	sts	0x0200, r16
+    3e64:	99 d0       	rcall	.+306    	; 0x3f98 <getch>
+    3e66:	08 2f       	mov	r16, r24
+    3e68:	10 e0       	ldi	r17, 0x00	; 0
+    3e6a:	10 93 01 02 	sts	0x0201, r17
+    3e6e:	00 93 00 02 	sts	0x0200, r16
       address = (address & 0xff) | (getch() << 8);
-    3e84:	98 d0       	rcall	.+304    	; 0x3fb6 <getch>
-    3e86:	90 e0       	ldi	r25, 0x00	; 0
-    3e88:	98 2f       	mov	r25, r24
-    3e8a:	88 27       	eor	r24, r24
-    3e8c:	80 2b       	or	r24, r16
-    3e8e:	91 2b       	or	r25, r17
+    3e72:	92 d0       	rcall	.+292    	; 0x3f98 <getch>
+    3e74:	90 e0       	ldi	r25, 0x00	; 0
+    3e76:	98 2f       	mov	r25, r24
+    3e78:	88 27       	eor	r24, r24
+    3e7a:	80 2b       	or	r24, r16
+    3e7c:	91 2b       	or	r25, r17
       address += address; // Convert from word address to byte address
-    3e90:	88 0f       	add	r24, r24
-    3e92:	99 1f       	adc	r25, r25
-    3e94:	90 93 01 02 	sts	0x0201, r25
-    3e98:	80 93 00 02 	sts	0x0200, r24
-    3e9c:	76 c0       	rjmp	.+236    	; 0x3f8a <main+0x18a>
+    3e7e:	88 0f       	add	r24, r24
+    3e80:	99 1f       	adc	r25, r25
+    3e82:	90 93 01 02 	sts	0x0201, r25
+    3e86:	80 93 00 02 	sts	0x0200, r24
+    3e8a:	73 c0       	rjmp	.+230    	; 0x3f72 <main+0x172>
       verifySpace();
     }
     else if(ch == STK_UNIVERSAL) {
-    3e9e:	86 35       	cpi	r24, 0x56	; 86
-    3ea0:	29 f4       	brne	.+10     	; 0x3eac <main+0xac>
+    3e8c:	86 35       	cpi	r24, 0x56	; 86
+    3e8e:	29 f4       	brne	.+10     	; 0x3e9a <main+0x9a>
       // UNIVERSAL command is ignored
       getNch(4);
-    3ea2:	84 e0       	ldi	r24, 0x04	; 4
-    3ea4:	a2 d0       	rcall	.+324    	; 0x3fea <verifySpace+0xc>
+    3e90:	84 e0       	ldi	r24, 0x04	; 4
+    3e92:	ac d0       	rcall	.+344    	; 0x3fec <verifySpace+0xc>
       putch(0x00);
-    3ea6:	80 e0       	ldi	r24, 0x00	; 0
-    3ea8:	74 d0       	rcall	.+232    	; 0x3f92 <putch>
-    3eaa:	70 c0       	rjmp	.+224    	; 0x3f8c <main+0x18c>
+    3e94:	80 e0       	ldi	r24, 0x00	; 0
+    3e96:	71 d0       	rcall	.+226    	; 0x3f7a <putch>
+    3e98:	6d c0       	rjmp	.+218    	; 0x3f74 <main+0x174>
     }
     /* Write memory, length is big endian and is in bytes  */
     else if(ch == STK_PROG_PAGE) {
-    3eac:	84 36       	cpi	r24, 0x64	; 100
-    3eae:	09 f0       	breq	.+2      	; 0x3eb2 <main+0xb2>
-    3eb0:	46 c0       	rjmp	.+140    	; 0x3f3e <main+0x13e>
+    3e9a:	84 36       	cpi	r24, 0x64	; 100
+    3e9c:	09 f0       	breq	.+2      	; 0x3ea0 <main+0xa0>
+    3e9e:	43 c0       	rjmp	.+134    	; 0x3f26 <main+0x126>
       // PROGRAM PAGE - we support flash programming only, not EEPROM
       uint8_t *bufPtr;
       uint16_t addrPtr;
-      
-      if (getLen() != 'F') appStart(); // Abort is not flash programming
-    3eb2:	90 d0       	rcall	.+288    	; 0x3fd4 <getLen>
-    3eb4:	86 34       	cpi	r24, 0x46	; 70
-    3eb6:	09 f0       	breq	.+2      	; 0x3eba <main+0xba>
-    3eb8:	7b d0       	rcall	.+246    	; 0x3fb0 <appStart>
-  
+
+      getLen();
+    3ea0:	8f d0       	rcall	.+286    	; 0x3fc0 <getLen>
+
       // Immediately start page erase - this will 4.5ms
       boot_page_erase((uint16_t)(void*)address);
-    3eba:	e0 91 00 02 	lds	r30, 0x0200
-    3ebe:	f0 91 01 02 	lds	r31, 0x0201
-    3ec2:	83 e0       	ldi	r24, 0x03	; 3
-    3ec4:	80 93 57 00 	sts	0x0057, r24
-    3ec8:	e8 95       	spm
-    3eca:	c0 e0       	ldi	r28, 0x00	; 0
-    3ecc:	d1 e0       	ldi	r29, 0x01	; 1
+    3ea2:	e0 91 00 02 	lds	r30, 0x0200
+    3ea6:	f0 91 01 02 	lds	r31, 0x0201
+    3eaa:	83 e0       	ldi	r24, 0x03	; 3
+    3eac:	80 93 57 00 	sts	0x0057, r24
+    3eb0:	e8 95       	spm
+    3eb2:	c0 e0       	ldi	r28, 0x00	; 0
+    3eb4:	d1 e0       	ldi	r29, 0x01	; 1
 
       // While that is going on, read in page contents
       bufPtr = buff;
       do *bufPtr++ = getch();
-    3ece:	73 d0       	rcall	.+230    	; 0x3fb6 <getch>
-    3ed0:	89 93       	st	Y+, r24
+    3eb6:	70 d0       	rcall	.+224    	; 0x3f98 <getch>
+    3eb8:	89 93       	st	Y+, r24
       while (--length);
-    3ed2:	80 91 02 02 	lds	r24, 0x0202
-    3ed6:	81 50       	subi	r24, 0x01	; 1
-    3ed8:	80 93 02 02 	sts	0x0202, r24
-    3edc:	88 23       	and	r24, r24
-    3ede:	b9 f7       	brne	.-18     	; 0x3ece <main+0xce>
+    3eba:	80 91 02 02 	lds	r24, 0x0202
+    3ebe:	81 50       	subi	r24, 0x01	; 1
+    3ec0:	80 93 02 02 	sts	0x0202, r24
+    3ec4:	88 23       	and	r24, r24
+    3ec6:	b9 f7       	brne	.-18     	; 0x3eb6 <main+0xb6>
 
+      // Read command terminator, start reply
+      verifySpace();
+    3ec8:	8b d0       	rcall	.+278    	; 0x3fe0 <verifySpace>
+      
       // If only a partial page is to be programmed, the erase might not be complete.
       // So check that here
       boot_spm_busy_wait();
-    3ee0:	07 b6       	in	r0, 0x37	; 55
-    3ee2:	00 fc       	sbrc	r0, 0
-    3ee4:	fd cf       	rjmp	.-6      	; 0x3ee0 <main+0xe0>
+    3eca:	07 b6       	in	r0, 0x37	; 55
+    3ecc:	00 fc       	sbrc	r0, 0
+    3ece:	fd cf       	rjmp	.-6      	; 0x3eca <main+0xca>
 
-      // Read command terminator, start reply
-      verifySpace();
-    3ee6:	7b d0       	rcall	.+246    	; 0x3fde <verifySpace>
-      
       // Copy buffer into programming buffer
       bufPtr = buff;
       addrPtr = (uint16_t)(void*)address;
-    3ee8:	40 91 00 02 	lds	r20, 0x0200
-    3eec:	50 91 01 02 	lds	r21, 0x0201
-    3ef0:	a0 e0       	ldi	r26, 0x00	; 0
-    3ef2:	b1 e0       	ldi	r27, 0x01	; 1
+    3ed0:	40 91 00 02 	lds	r20, 0x0200
+    3ed4:	50 91 01 02 	lds	r21, 0x0201
+    3ed8:	a0 e0       	ldi	r26, 0x00	; 0
+    3eda:	b1 e0       	ldi	r27, 0x01	; 1
       ch = SPM_PAGESIZE / 2;
       do {
         uint16_t a;
         a = *bufPtr++;
-    3ef4:	2c 91       	ld	r18, X
-    3ef6:	30 e0       	ldi	r19, 0x00	; 0
+    3edc:	2c 91       	ld	r18, X
+    3ede:	30 e0       	ldi	r19, 0x00	; 0
         a |= (*bufPtr++) << 8;
-    3ef8:	11 96       	adiw	r26, 0x01	; 1
-    3efa:	8c 91       	ld	r24, X
-    3efc:	11 97       	sbiw	r26, 0x01	; 1
-    3efe:	90 e0       	ldi	r25, 0x00	; 0
-    3f00:	98 2f       	mov	r25, r24
-    3f02:	88 27       	eor	r24, r24
-    3f04:	82 2b       	or	r24, r18
-    3f06:	93 2b       	or	r25, r19
+    3ee0:	11 96       	adiw	r26, 0x01	; 1
+    3ee2:	8c 91       	ld	r24, X
+    3ee4:	11 97       	sbiw	r26, 0x01	; 1
+    3ee6:	90 e0       	ldi	r25, 0x00	; 0
+    3ee8:	98 2f       	mov	r25, r24
+    3eea:	88 27       	eor	r24, r24
+    3eec:	82 2b       	or	r24, r18
+    3eee:	93 2b       	or	r25, r19
 #define buff    ((uint8_t*)(0x100))
 #define address (*(uint16_t*)(0x200))
 #define length  (*(uint8_t*)(0x202))
 
 /* main program starts here */
 int main(void) {
-    3f08:	12 96       	adiw	r26, 0x02	; 2
+    3ef0:	12 96       	adiw	r26, 0x02	; 2
       ch = SPM_PAGESIZE / 2;
       do {
         uint16_t a;
         a = *bufPtr++;
         a |= (*bufPtr++) << 8;
         boot_page_fill((uint16_t)(void*)addrPtr,a);
-    3f0a:	fa 01       	movw	r30, r20
-    3f0c:	0c 01       	movw	r0, r24
-    3f0e:	d0 92 57 00 	sts	0x0057, r13
-    3f12:	e8 95       	spm
-    3f14:	11 24       	eor	r1, r1
+    3ef2:	fa 01       	movw	r30, r20
+    3ef4:	0c 01       	movw	r0, r24
+    3ef6:	d0 92 57 00 	sts	0x0057, r13
+    3efa:	e8 95       	spm
+    3efc:	11 24       	eor	r1, r1
         addrPtr += 2;
-    3f16:	4e 5f       	subi	r20, 0xFE	; 254
-    3f18:	5f 4f       	sbci	r21, 0xFF	; 255
+    3efe:	4e 5f       	subi	r20, 0xFE	; 254
+    3f00:	5f 4f       	sbci	r21, 0xFF	; 255
       } while (--ch);
-    3f1a:	f1 e0       	ldi	r31, 0x01	; 1
-    3f1c:	a0 38       	cpi	r26, 0x80	; 128
-    3f1e:	bf 07       	cpc	r27, r31
-    3f20:	49 f7       	brne	.-46     	; 0x3ef4 <main+0xf4>
+    3f02:	f1 e0       	ldi	r31, 0x01	; 1
+    3f04:	a0 38       	cpi	r26, 0x80	; 128
+    3f06:	bf 07       	cpc	r27, r31
+    3f08:	49 f7       	brne	.-46     	; 0x3edc <main+0xdc>
       
       // Write from programming buffer
       boot_page_write((uint16_t)(void*)address);
-    3f22:	e0 91 00 02 	lds	r30, 0x0200
-    3f26:	f0 91 01 02 	lds	r31, 0x0201
-    3f2a:	e0 92 57 00 	sts	0x0057, r14
-    3f2e:	e8 95       	spm
+    3f0a:	e0 91 00 02 	lds	r30, 0x0200
+    3f0e:	f0 91 01 02 	lds	r31, 0x0201
+    3f12:	e0 92 57 00 	sts	0x0057, r14
+    3f16:	e8 95       	spm
       boot_spm_busy_wait();
-    3f30:	07 b6       	in	r0, 0x37	; 55
-    3f32:	00 fc       	sbrc	r0, 0
-    3f34:	fd cf       	rjmp	.-6      	; 0x3f30 <main+0x130>
+    3f18:	07 b6       	in	r0, 0x37	; 55
+    3f1a:	00 fc       	sbrc	r0, 0
+    3f1c:	fd cf       	rjmp	.-6      	; 0x3f18 <main+0x118>
 
       // Reenable read access to flash
       boot_rww_enable();
-    3f36:	f0 92 57 00 	sts	0x0057, r15
-    3f3a:	e8 95       	spm
-    3f3c:	27 c0       	rjmp	.+78     	; 0x3f8c <main+0x18c>
+    3f1e:	f0 92 57 00 	sts	0x0057, r15
+    3f22:	e8 95       	spm
+    3f24:	27 c0       	rjmp	.+78     	; 0x3f74 <main+0x174>
     }
     /* Read memory block mode, length is big endian.  */
     else if(ch == STK_READ_PAGE) {
-    3f3e:	84 37       	cpi	r24, 0x74	; 116
-    3f40:	b9 f4       	brne	.+46     	; 0x3f70 <main+0x170>
+    3f26:	84 37       	cpi	r24, 0x74	; 116
+    3f28:	b9 f4       	brne	.+46     	; 0x3f58 <main+0x158>
       // READ PAGE - we only read flash
       getLen();
-    3f42:	48 d0       	rcall	.+144    	; 0x3fd4 <getLen>
+    3f2a:	4a d0       	rcall	.+148    	; 0x3fc0 <getLen>
       verifySpace();
-    3f44:	4c d0       	rcall	.+152    	; 0x3fde <verifySpace>
+    3f2c:	59 d0       	rcall	.+178    	; 0x3fe0 <verifySpace>
       do putch(pgm_read_byte_near(address++));
-    3f46:	e0 91 00 02 	lds	r30, 0x0200
-    3f4a:	f0 91 01 02 	lds	r31, 0x0201
-    3f4e:	31 96       	adiw	r30, 0x01	; 1
-    3f50:	f0 93 01 02 	sts	0x0201, r31
-    3f54:	e0 93 00 02 	sts	0x0200, r30
-    3f58:	31 97       	sbiw	r30, 0x01	; 1
-    3f5a:	e4 91       	lpm	r30, Z+
-    3f5c:	8e 2f       	mov	r24, r30
-    3f5e:	19 d0       	rcall	.+50     	; 0x3f92 <putch>
+    3f2e:	e0 91 00 02 	lds	r30, 0x0200
+    3f32:	f0 91 01 02 	lds	r31, 0x0201
+    3f36:	31 96       	adiw	r30, 0x01	; 1
+    3f38:	f0 93 01 02 	sts	0x0201, r31
+    3f3c:	e0 93 00 02 	sts	0x0200, r30
+    3f40:	31 97       	sbiw	r30, 0x01	; 1
+    3f42:	e4 91       	lpm	r30, Z+
+    3f44:	8e 2f       	mov	r24, r30
+    3f46:	19 d0       	rcall	.+50     	; 0x3f7a <putch>
       while (--length);
-    3f60:	80 91 02 02 	lds	r24, 0x0202
-    3f64:	81 50       	subi	r24, 0x01	; 1
-    3f66:	80 93 02 02 	sts	0x0202, r24
-    3f6a:	88 23       	and	r24, r24
-    3f6c:	61 f7       	brne	.-40     	; 0x3f46 <main+0x146>
-    3f6e:	0e c0       	rjmp	.+28     	; 0x3f8c <main+0x18c>
+    3f48:	80 91 02 02 	lds	r24, 0x0202
+    3f4c:	81 50       	subi	r24, 0x01	; 1
+    3f4e:	80 93 02 02 	sts	0x0202, r24
+    3f52:	88 23       	and	r24, r24
+    3f54:	61 f7       	brne	.-40     	; 0x3f2e <main+0x12e>
+    3f56:	0e c0       	rjmp	.+28     	; 0x3f74 <main+0x174>
     }
 
     /* Get device signature bytes  */
     else if(ch == STK_READ_SIGN) {
-    3f70:	85 37       	cpi	r24, 0x75	; 117
-    3f72:	39 f4       	brne	.+14     	; 0x3f82 <main+0x182>
+    3f58:	85 37       	cpi	r24, 0x75	; 117
+    3f5a:	39 f4       	brne	.+14     	; 0x3f6a <main+0x16a>
       // READ SIGN - return what Avrdude wants to hear
       verifySpace();
-    3f74:	34 d0       	rcall	.+104    	; 0x3fde <verifySpace>
+    3f5c:	41 d0       	rcall	.+130    	; 0x3fe0 <verifySpace>
       putch(SIGNATURE_0);
-    3f76:	8e e1       	ldi	r24, 0x1E	; 30
-    3f78:	0c d0       	rcall	.+24     	; 0x3f92 <putch>
+    3f5e:	8e e1       	ldi	r24, 0x1E	; 30
+    3f60:	0c d0       	rcall	.+24     	; 0x3f7a <putch>
       putch(SIGNATURE_1);
-    3f7a:	84 e9       	ldi	r24, 0x94	; 148
-    3f7c:	0a d0       	rcall	.+20     	; 0x3f92 <putch>
+    3f62:	84 e9       	ldi	r24, 0x94	; 148
+    3f64:	0a d0       	rcall	.+20     	; 0x3f7a <putch>
       putch(SIGNATURE_2);
-    3f7e:	86 e0       	ldi	r24, 0x06	; 6
-    3f80:	93 cf       	rjmp	.-218    	; 0x3ea8 <main+0xa8>
+    3f66:	86 e0       	ldi	r24, 0x06	; 6
+    3f68:	96 cf       	rjmp	.-212    	; 0x3e96 <main+0x96>
     }
     else if (ch == 'Q') {
-    3f82:	81 35       	cpi	r24, 0x51	; 81
-    3f84:	11 f4       	brne	.+4      	; 0x3f8a <main+0x18a>
+    3f6a:	81 35       	cpi	r24, 0x51	; 81
+    3f6c:	11 f4       	brne	.+4      	; 0x3f72 <main+0x172>
       // Adaboot no-wait mod
-      WDTCSR = _BV(WDE);
-    3f86:	c0 92 60 00 	sts	0x0060, r12
+      watchdogConfig(_BV(WDE));
+    3f6e:	88 e0       	ldi	r24, 0x08	; 8
+    3f70:	2c d0       	rcall	.+88     	; 0x3fca <watchdogConfig>
       verifySpace();
     }
     else {
       // This covers the response to commands like STK_ENTER_PROGMODE
       verifySpace();
-    3f8a:	29 d0       	rcall	.+82     	; 0x3fde <verifySpace>
+    3f72:	36 d0       	rcall	.+108    	; 0x3fe0 <verifySpace>
     }
     putch(STK_OK);
-    3f8c:	80 e1       	ldi	r24, 0x10	; 16
-    3f8e:	01 d0       	rcall	.+2      	; 0x3f92 <putch>
-    3f90:	60 cf       	rjmp	.-320    	; 0x3e52 <main+0x52>
-
-00003f92 <putch>:
-  }
-}
+    3f74:	80 e1       	ldi	r24, 0x10	; 16
+    3f76:	01 d0       	rcall	.+2      	; 0x3f7a <putch>
+    3f78:	63 cf       	rjmp	.-314    	; 0x3e40 <main+0x40>
 
+00003f7a <putch>:
 void putch(char ch) {
-    3f92:	98 2f       	mov	r25, r24
+#ifndef SOFT_UART
   while (!(UCSR0A & _BV(UDRE0)));
-    3f94:	80 91 c0 00 	lds	r24, 0x00C0
-    3f98:	85 ff       	sbrs	r24, 5
-    3f9a:	fc cf       	rjmp	.-8      	; 0x3f94 <putch+0x2>
   UDR0 = ch;
-    3f9c:	90 93 c6 00 	sts	0x00C6, r25
-}
-    3fa0:	08 95       	ret
-
-00003fa2 <setTimer>:
-
-void setTimer(uint16_t counts) {
-  TCNT1 = counts;
-    3fa2:	90 93 85 00 	sts	0x0085, r25
-    3fa6:	80 93 84 00 	sts	0x0084, r24
-  TIFR1 = _BV(TOV1);
-    3faa:	81 e0       	ldi	r24, 0x01	; 1
-    3fac:	86 bb       	out	0x16, r24	; 22
+#else
+  __asm__ __volatile__ (
+    3f7a:	2a e0       	ldi	r18, 0x0A	; 10
+    3f7c:	30 e0       	ldi	r19, 0x00	; 0
+    3f7e:	80 95       	com	r24
+    3f80:	08 94       	sec
+    3f82:	10 f4       	brcc	.+4      	; 0x3f88 <putch+0xe>
+    3f84:	59 98       	cbi	0x0b, 1	; 11
+    3f86:	02 c0       	rjmp	.+4      	; 0x3f8c <putch+0x12>
+    3f88:	59 9a       	sbi	0x0b, 1	; 11
+    3f8a:	00 00       	nop
+    3f8c:	15 d0       	rcall	.+42     	; 0x3fb8 <uartDelay>
+    3f8e:	14 d0       	rcall	.+40     	; 0x3fb8 <uartDelay>
+    3f90:	86 95       	lsr	r24
+    3f92:	2a 95       	dec	r18
+    3f94:	b1 f7       	brne	.-20     	; 0x3f82 <putch+0x8>
+      [uartBit] "I" (UART_TX_BIT)
+    :
+      "r25"
+  );
+#endif
 }
-    3fae:	08 95       	ret
+    3f96:	08 95       	ret
 
-00003fb0 <appStart>:
-  length = getch();
+00003f98 <getch>:
   return getch();
 }
 
-void appStart() {
+// Watchdog functions. These are only safe with interrupts turned off.
+void watchdogReset() {
   __asm__ __volatile__ (
-    3fb0:	ee 27       	eor	r30, r30
-    3fb2:	ff 27       	eor	r31, r31
-    3fb4:	09 94       	ijmp
+    3f98:	a8 95       	wdr
+#ifdef LED_DATA_FLASH
+  LED_PIN |= _BV(LED);
+#endif
 
-00003fb6 <getch>:
-  TCNT1 = counts;
-  TIFR1 = _BV(TOV1);
+  return ch;
 }
+    3f9a:	29 e0       	ldi	r18, 0x09	; 9
+    3f9c:	30 e0       	ldi	r19, 0x00	; 0
+    3f9e:	48 99       	sbic	0x09, 0	; 9
+    3fa0:	fe cf       	rjmp	.-4      	; 0x3f9e <getch+0x6>
+    3fa2:	0a d0       	rcall	.+20     	; 0x3fb8 <uartDelay>
+    3fa4:	09 d0       	rcall	.+18     	; 0x3fb8 <uartDelay>
+    3fa6:	08 d0       	rcall	.+16     	; 0x3fb8 <uartDelay>
+    3fa8:	88 94       	clc
+    3faa:	48 99       	sbic	0x09, 0	; 9
+    3fac:	08 94       	sec
+    3fae:	2a 95       	dec	r18
+    3fb0:	11 f0       	breq	.+4      	; 0x3fb6 <getch+0x1e>
+    3fb2:	87 95       	ror	r24
+    3fb4:	f7 cf       	rjmp	.-18     	; 0x3fa4 <getch+0xc>
+    3fb6:	08 95       	ret
+
+00003fb8 <uartDelay>:
+#if UART_B_VALUE > 255
+#error Baud rate too slow for soft UART
+#endif
 
-uint8_t getch(void) {
-  LED_PORT &= ~_BV(LED);
-    3fb6:	2d 98       	cbi	0x05, 5	; 5
-  setTimer(-(F_CPU/(1024*2))); // 500ms
-    3fb8:	8e eb       	ldi	r24, 0xBE	; 190
-    3fba:	90 ef       	ldi	r25, 0xF0	; 240
-    3fbc:	f2 df       	rcall	.-28     	; 0x3fa2 <setTimer>
-    3fbe:	02 c0       	rjmp	.+4      	; 0x3fc4 <getch+0xe>
-  while(!(UCSR0A & _BV(RXC0))) if (TIFR1 & _BV(TOV1)) appStart();
-    3fc0:	b0 99       	sbic	0x16, 0	; 22
-    3fc2:	f6 df       	rcall	.-20     	; 0x3fb0 <appStart>
-    3fc4:	80 91 c0 00 	lds	r24, 0x00C0
-    3fc8:	87 ff       	sbrs	r24, 7
-    3fca:	fa cf       	rjmp	.-12     	; 0x3fc0 <getch+0xa>
-  LED_PORT |= _BV(LED);
-    3fcc:	2d 9a       	sbi	0x05, 5	; 5
-  return UDR0;
-    3fce:	80 91 c6 00 	lds	r24, 0x00C6
-}
-    3fd2:	08 95       	ret
+void uartDelay() {
+  __asm__ __volatile__ (
+    3fb8:	98 e0       	ldi	r25, 0x08	; 8
+    3fba:	9a 95       	dec	r25
+    3fbc:	f1 f7       	brne	.-4      	; 0x3fba <uartDelay+0x2>
+    3fbe:	08 95       	ret
 
-00003fd4 <getLen>:
-    LED_PIN |= _BV(LED);
+00003fc0 <getLen>:
   } while (--count);
 }
+#endif
 
 uint8_t getLen() {
   getch();
-    3fd4:	f0 df       	rcall	.-32     	; 0x3fb6 <getch>
+    3fc0:	eb df       	rcall	.-42     	; 0x3f98 <getch>
   length = getch();
-    3fd6:	ef df       	rcall	.-34     	; 0x3fb6 <getch>
-    3fd8:	80 93 02 02 	sts	0x0202, r24
+    3fc2:	ea df       	rcall	.-44     	; 0x3f98 <getch>
+    3fc4:	80 93 02 02 	sts	0x0202, r24
   return getch();
 }
-    3fdc:	ec cf       	rjmp	.-40     	; 0x3fb6 <getch>
+    3fc8:	e7 cf       	rjmp	.-50     	; 0x3f98 <getch>
+
+00003fca <watchdogConfig>:
+    "wdr\n"
+  );
+}
 
-00003fde <verifySpace>:
+void watchdogConfig(uint8_t x) {
+  WDTCSR = _BV(WDCE) | _BV(WDE);
+    3fca:	e0 e6       	ldi	r30, 0x60	; 96
+    3fcc:	f0 e0       	ldi	r31, 0x00	; 0
+    3fce:	98 e1       	ldi	r25, 0x18	; 24
+    3fd0:	90 83       	st	Z, r25
+  WDTCSR = x;
+    3fd2:	80 83       	st	Z, r24
+}
+    3fd4:	08 95       	ret
+
+00003fd6 <appStart>:
+
+void appStart() {
+  watchdogConfig(0);
+    3fd6:	80 e0       	ldi	r24, 0x00	; 0
+    3fd8:	f8 df       	rcall	.-16     	; 0x3fca <watchdogConfig>
+  __asm__ __volatile__ (
+    3fda:	ee 27       	eor	r30, r30
+    3fdc:	ff 27       	eor	r31, r31
+    3fde:	09 94       	ijmp
+
+00003fe0 <verifySpace>:
   do getch(); while (--count);
   verifySpace();
 }
 
 void verifySpace() {
   if (getch() != CRC_EOP) appStart();
-    3fde:	eb df       	rcall	.-42     	; 0x3fb6 <getch>
-    3fe0:	80 32       	cpi	r24, 0x20	; 32
-    3fe2:	09 f0       	breq	.+2      	; 0x3fe6 <verifySpace+0x8>
-    3fe4:	e5 df       	rcall	.-54     	; 0x3fb0 <appStart>
+    3fe0:	db df       	rcall	.-74     	; 0x3f98 <getch>
+    3fe2:	80 32       	cpi	r24, 0x20	; 32
+    3fe4:	09 f0       	breq	.+2      	; 0x3fe8 <verifySpace+0x8>
+    3fe6:	f7 df       	rcall	.-18     	; 0x3fd6 <appStart>
   putch(STK_INSYNC);
-    3fe6:	84 e1       	ldi	r24, 0x14	; 20
+    3fe8:	84 e1       	ldi	r24, 0x14	; 20
 }
-    3fe8:	d4 cf       	rjmp	.-88     	; 0x3f92 <putch>
-  while(!(UCSR0A & _BV(RXC0))) if (TIFR1 & _BV(TOV1)) appStart();
-  LED_PORT |= _BV(LED);
-  return UDR0;
+    3fea:	c7 cf       	rjmp	.-114    	; 0x3f7a <putch>
+    ::[count] "M" (UART_B_VALUE)
+  );
 }
+#endif
 
 void getNch(uint8_t count) {
-    3fea:	1f 93       	push	r17
-    3fec:	18 2f       	mov	r17, r24
+    3fec:	1f 93       	push	r17
+    3fee:	18 2f       	mov	r17, r24
 
-00003fee <getNch>:
+00003ff0 <getNch>:
   do getch(); while (--count);
-    3fee:	e3 df       	rcall	.-58     	; 0x3fb6 <getch>
-    3ff0:	11 50       	subi	r17, 0x01	; 1
-    3ff2:	e9 f7       	brne	.-6      	; 0x3fee <getNch>
+    3ff0:	d3 df       	rcall	.-90     	; 0x3f98 <getch>
+    3ff2:	11 50       	subi	r17, 0x01	; 1
+    3ff4:	e9 f7       	brne	.-6      	; 0x3ff0 <getNch>
   verifySpace();
-    3ff4:	f4 df       	rcall	.-24     	; 0x3fde <verifySpace>
+    3ff6:	f4 df       	rcall	.-24     	; 0x3fe0 <verifySpace>
 }
-    3ff6:	1f 91       	pop	r17
-    3ff8:	08 95       	ret
+    3ff8:	1f 91       	pop	r17
+    3ffa:	08 95       	ret

+ 32 - 32
optiboot/bootloaders/optiboot/optiboot_lilypad_resonator.hex

@@ -1,34 +1,34 @@
-:103E000085E08093810082E08093C00098E19093E8
-:103E1000C10086E08093C20083E38093C40084B72E
-:103E200014BE909360001092600081FFC1D0259A6B
-:103E300006E088E19EEFB5D0B09BFECF1D9A015001
-:103E4000C1F7DD24D394B8E0CB2EA5E0EA2EF1E152
-:103E5000FF2EB1D0813421F481E0C7D083E024C0AB
-:103E6000823411F484E103C0853419F485E0BDD0B7
-:103E70008DC08535A1F49FD0082F10E0109301026A
-:103E80000093000298D090E0982F8827802B912BE8
-:103E9000880F991F909301028093000276C08635A7
-:103EA00029F484E0A2D080E074D070C0843609F098
-:103EB00046C090D0863409F07BD0E0910002F091AA
-:103EC000010283E080935700E895C0E0D1E073D011
-:103ED0008993809102028150809302028823B9F76E
-:103EE00007B600FCFDCF7BD040910002509101024B
-:103EF000A0E0B1E02C9130E011968C91119790E008
-:103F0000982F8827822B932B1296FA010C01D092BE
-:103F10005700E89511244E5F5F4FF1E0A038BF07CE
-:103F200049F7E0910002F0910102E0925700E89514
-:103F300007B600FCFDCFF0925700E89527C0843704
-:103F4000B9F448D04CD0E0910002F09101023196D2
-:103F5000F0930102E09300023197E4918E2F19D083
-:103F600080910202815080930202882361F70EC083
-:103F7000853739F434D08EE10CD084E90AD086E05C
-:103F800093CF813511F4C092600029D080E101D037
-:103F900060CF982F8091C00085FFFCCF9093C60022
-:103FA0000895909385008093840081E086BB0895F6
-:103FB000EE27FF2709942D988EEB90EFF2DF02C0D9
-:103FC000B099F6DF8091C00087FFFACF2D9A8091DB
-:103FD000C6000895F0DFEFDF80930202ECCFEBDF45
-:103FE000803209F0E5DF84E1D4CF1F93182FE3DF9F
-:0A3FF0001150E9F7F4DF1F91089566
+:103E000085E08093810084B714BE81FFE4D08DE00B
+:103E1000DCD0259A519A86E028E13EEF91E030937C
+:103E200085002093840096BBB09BFECF1D9AA89579
+:103E30008150A9F7DD24D394A5E0EA2EF1E1FF2E0D
+:103E4000ABD0813421F481E0D1D083E024C082342E
+:103E500011F484E103C0853419F485E0C7D08AC029
+:103E60008535A1F499D0082F10E01093010200933A
+:103E7000000292D090E0982F8827802B912B880FFA
+:103E8000991F909301028093000273C0863529F434
+:103E900084E0ACD080E071D06DC0843609F043C0BE
+:103EA0008FD0E0910002F091010283E080935700EF
+:103EB000E895C0E0D1E070D08993809102028150F2
+:103EC000809302028823B9F78BD007B600FCFDCFA0
+:103ED0004091000250910102A0E0B1E02C9130E04D
+:103EE00011968C91119790E0982F8827822B932B15
+:103EF0001296FA010C01D0925700E89511244E5FFA
+:103F00005F4FF1E0A038BF0749F7E0910002F09160
+:103F10000102E0925700E89507B600FCFDCFF09251
+:103F20005700E89527C08437B9F44AD059D0E091BA
+:103F30000002F09101023196F0930102E093000239
+:103F40003197E4918E2F19D0809102028150809395
+:103F50000202882361F70EC0853739F441D08EE123
+:103F60000CD084E90AD086E096CF813511F488E040
+:103F70002CD036D080E101D063CF2AE030E08095AC
+:103F8000089410F4599802C0599A000015D014D022
+:103F900086952A95B1F70895A89529E030E04899CB
+:103FA000FECF0AD009D008D08894489908942A9561
+:103FB00011F08795F7CF089598E09A95F1F7089555
+:103FC000EBDFEADF80930202E7CFE0E6F0E098E182
+:103FD00090838083089580E0F8DFEE27FF2709941F
+:103FE000DBDF803209F0F7DF84E1C7CF1F93182FA2
+:0C3FF000D3DF1150E9F7F4DF1F910895B2
 :0400000300003E00BB
 :00000001FF

+ 320 - 282
optiboot/bootloaders/optiboot/optiboot_lilypad_resonator.lst

@@ -3,25 +3,25 @@ optiboot_lilypad_resonator.elf:     file format elf32-avr
 
 Sections:
 Idx Name          Size      VMA       LMA       File off  Algn
-  0 .text         000001fa  00003e00  00003e00  00000054  2**1
+  0 .text         000001fc  00003e00  00003e00  00000054  2**1
                   CONTENTS, ALLOC, LOAD, READONLY, CODE
-  1 .debug_aranges 00000028  00000000  00000000  0000024e  2**0
+  1 .debug_aranges 00000028  00000000  00000000  00000250  2**0
                   CONTENTS, READONLY, DEBUGGING
-  2 .debug_pubnames 00000064  00000000  00000000  00000276  2**0
+  2 .debug_pubnames 00000078  00000000  00000000  00000278  2**0
                   CONTENTS, READONLY, DEBUGGING
-  3 .debug_info   0000022f  00000000  00000000  000002da  2**0
+  3 .debug_info   00000275  00000000  00000000  000002f0  2**0
                   CONTENTS, READONLY, DEBUGGING
-  4 .debug_abbrev 00000164  00000000  00000000  00000509  2**0
+  4 .debug_abbrev 000001a3  00000000  00000000  00000565  2**0
                   CONTENTS, READONLY, DEBUGGING
-  5 .debug_line   000003c8  00000000  00000000  0000066d  2**0
+  5 .debug_line   000003b8  00000000  00000000  00000708  2**0
                   CONTENTS, READONLY, DEBUGGING
-  6 .debug_frame  00000090  00000000  00000000  00000a38  2**2
+  6 .debug_frame  000000a0  00000000  00000000  00000ac0  2**2
                   CONTENTS, READONLY, DEBUGGING
-  7 .debug_str    0000011c  00000000  00000000  00000ac8  2**0
+  7 .debug_str    00000133  00000000  00000000  00000b60  2**0
                   CONTENTS, READONLY, DEBUGGING
-  8 .debug_loc    000001d6  00000000  00000000  00000be4  2**0
+  8 .debug_loc    000001a0  00000000  00000000  00000c93  2**0
                   CONTENTS, READONLY, DEBUGGING
-  9 .debug_ranges 00000068  00000000  00000000  00000dba  2**0
+  9 .debug_ranges 00000070  00000000  00000000  00000e33  2**0
                   CONTENTS, READONLY, DEBUGGING
 
 Disassembly of section .text:
@@ -35,449 +35,487 @@ Disassembly of section .text:
 int main(void) {
     3e00:	85 e0       	ldi	r24, 0x05	; 5
     3e02:	80 93 81 00 	sts	0x0081, r24
-    [addr5]"i"(_SFR_MEM_ADDR(UBRR0L)), [val5]"i"((F_CPU + BAUD_RATE * 4L) / (BAUD_RATE * 8L) - 1)
-  );
-#else
-  // Set up Timer 1 for timeout counter
-  TCCR1B = _BV(CS12) | _BV(CS10); // div 1024
-  UCSR0A = _BV(U2X0); //Double speed mode USART0
-    3e06:	82 e0       	ldi	r24, 0x02	; 2
-    3e08:	80 93 c0 00 	sts	0x00C0, r24
-  UCSR0B = _BV(RXEN0) | _BV(TXEN0);
-    3e0c:	98 e1       	ldi	r25, 0x18	; 24
-    3e0e:	90 93 c1 00 	sts	0x00C1, r25
   UCSR0C = _BV(UCSZ00) | _BV(UCSZ01);
-    3e12:	86 e0       	ldi	r24, 0x06	; 6
-    3e14:	80 93 c2 00 	sts	0x00C2, r24
   UBRR0L = (uint8_t)( (F_CPU + BAUD_RATE * 4L) / (BAUD_RATE * 8L) - 1 );
-    3e18:	83 e3       	ldi	r24, 0x33	; 51
-    3e1a:	80 93 c4 00 	sts	0x00C4, r24
 #endif
 
   // Adaboot no-wait mod
   ch = MCUSR;
-    3e1e:	84 b7       	in	r24, 0x34	; 52
+    3e06:	84 b7       	in	r24, 0x34	; 52
   MCUSR = 0;
-    3e20:	14 be       	out	0x34, r1	; 52
-  WDTCSR = _BV(WDCE) | _BV(WDE);
-    3e22:	90 93 60 00 	sts	0x0060, r25
-  WDTCSR = 0;
-    3e26:	10 92 60 00 	sts	0x0060, r1
+    3e08:	14 be       	out	0x34, r1	; 52
   if (!(ch & _BV(EXTRF))) appStart();
-    3e2a:	81 ff       	sbrs	r24, 1
-    3e2c:	c1 d0       	rcall	.+386    	; 0x3fb0 <appStart>
+    3e0a:	81 ff       	sbrs	r24, 1
+    3e0c:	e4 d0       	rcall	.+456    	; 0x3fd6 <appStart>
+
+  // Set up watchdog to trigger after 500ms
+  watchdogConfig(_BV(WDP2)|_BV(WDP0)|_BV(WDE));
+    3e0e:	8d e0       	ldi	r24, 0x0D	; 13
+    3e10:	dc d0       	rcall	.+440    	; 0x3fca <watchdogConfig>
 
-  /* set LED pin as output */
+  /* Set LED pin as output */
   LED_DDR |= _BV(LED);
-    3e2e:	25 9a       	sbi	0x04, 5	; 4
-    3e30:	06 e0       	ldi	r16, 0x06	; 6
-  putch(STK_INSYNC);
+    3e12:	25 9a       	sbi	0x04, 5	; 4
+
+#ifdef SOFT_UART
+  /* Set TX pin as output */
+  UART_DDR |= _BV(UART_TX_BIT);
+    3e14:	51 9a       	sbi	0x0a, 1	; 10
+    3e16:	86 e0       	ldi	r24, 0x06	; 6
+}
+
+#if LED_START_FLASHES > 0
+void flash_led(uint8_t count) {
+  do {
+    TCNT1 = -(F_CPU/(1024*16));
+    3e18:	28 e1       	ldi	r18, 0x18	; 24
+    3e1a:	3e ef       	ldi	r19, 0xFE	; 254
+    TIFR1 = _BV(TOV1);
+    3e1c:	91 e0       	ldi	r25, 0x01	; 1
 }
 
+#if LED_START_FLASHES > 0
 void flash_led(uint8_t count) {
   do {
-    setTimer(-(F_CPU/(1024*16))); // 62ms
-    3e32:	88 e1       	ldi	r24, 0x18	; 24
-    3e34:	9e ef       	ldi	r25, 0xFE	; 254
-    3e36:	b5 d0       	rcall	.+362    	; 0x3fa2 <setTimer>
+    TCNT1 = -(F_CPU/(1024*16));
+    3e1e:	30 93 85 00 	sts	0x0085, r19
+    3e22:	20 93 84 00 	sts	0x0084, r18
+    TIFR1 = _BV(TOV1);
+    3e26:	96 bb       	out	0x16, r25	; 22
+    while(!(TIFR1 & _BV(TOV1)));
+    3e28:	b0 9b       	sbis	0x16, 0	; 22
+    3e2a:	fe cf       	rjmp	.-4      	; 0x3e28 <main+0x28>
+    LED_PIN |= _BV(LED);
+    3e2c:	1d 9a       	sbi	0x03, 5	; 3
+  return getch();
+}
+
+// Watchdog functions. These are only safe with interrupts turned off.
+void watchdogReset() {
+  __asm__ __volatile__ (
+    3e2e:	a8 95       	wdr
+    TCNT1 = -(F_CPU/(1024*16));
+    TIFR1 = _BV(TOV1);
     while(!(TIFR1 & _BV(TOV1)));
-    3e38:	b0 9b       	sbis	0x16, 0	; 22
-    3e3a:	fe cf       	rjmp	.-4      	; 0x3e38 <main+0x38>
     LED_PIN |= _BV(LED);
-    3e3c:	1d 9a       	sbi	0x03, 5	; 3
+    watchdogReset();
   } while (--count);
-    3e3e:	01 50       	subi	r16, 0x01	; 1
-    3e40:	c1 f7       	brne	.-16     	; 0x3e32 <main+0x32>
+    3e30:	81 50       	subi	r24, 0x01	; 1
+    3e32:	a9 f7       	brne	.-22     	; 0x3e1e <main+0x1e>
     /* get character from UART */
     ch = getch();
 
     if(ch == STK_GET_PARAMETER) {
       // GET PARAMETER returns a generic 0x03 reply - enough to keep Avrdude happy
       getNch(1);
-    3e42:	dd 24       	eor	r13, r13
-    3e44:	d3 94       	inc	r13
-      putch(SIGNATURE_1);
-      putch(SIGNATURE_2);
-    }
-    else if (ch == 'Q') {
-      // Adaboot no-wait mod
-      WDTCSR = _BV(WDE);
-    3e46:	b8 e0       	ldi	r27, 0x08	; 8
-    3e48:	cb 2e       	mov	r12, r27
+    3e34:	dd 24       	eor	r13, r13
+    3e36:	d3 94       	inc	r13
         boot_page_fill((uint16_t)(void*)addrPtr,a);
         addrPtr += 2;
       } while (--ch);
       
       // Write from programming buffer
       boot_page_write((uint16_t)(void*)address);
-    3e4a:	a5 e0       	ldi	r26, 0x05	; 5
-    3e4c:	ea 2e       	mov	r14, r26
+    3e38:	a5 e0       	ldi	r26, 0x05	; 5
+    3e3a:	ea 2e       	mov	r14, r26
       boot_spm_busy_wait();
 
       // Reenable read access to flash
       boot_rww_enable();
-    3e4e:	f1 e1       	ldi	r31, 0x11	; 17
-    3e50:	ff 2e       	mov	r15, r31
-  flash_led(NUM_LED_FLASHES * 2);
+    3e3c:	f1 e1       	ldi	r31, 0x11	; 17
+    3e3e:	ff 2e       	mov	r15, r31
+#endif
 
-  /* forever loop */
+  /* Forever loop */
   for (;;) {
     /* get character from UART */
     ch = getch();
-    3e52:	b1 d0       	rcall	.+354    	; 0x3fb6 <getch>
+    3e40:	ab d0       	rcall	.+342    	; 0x3f98 <getch>
 
     if(ch == STK_GET_PARAMETER) {
-    3e54:	81 34       	cpi	r24, 0x41	; 65
-    3e56:	21 f4       	brne	.+8      	; 0x3e60 <main+0x60>
+    3e42:	81 34       	cpi	r24, 0x41	; 65
+    3e44:	21 f4       	brne	.+8      	; 0x3e4e <main+0x4e>
       // GET PARAMETER returns a generic 0x03 reply - enough to keep Avrdude happy
       getNch(1);
-    3e58:	81 e0       	ldi	r24, 0x01	; 1
-    3e5a:	c7 d0       	rcall	.+398    	; 0x3fea <verifySpace+0xc>
+    3e46:	81 e0       	ldi	r24, 0x01	; 1
+    3e48:	d1 d0       	rcall	.+418    	; 0x3fec <verifySpace+0xc>
       putch(0x03);
-    3e5c:	83 e0       	ldi	r24, 0x03	; 3
-    3e5e:	24 c0       	rjmp	.+72     	; 0x3ea8 <main+0xa8>
+    3e4a:	83 e0       	ldi	r24, 0x03	; 3
+    3e4c:	24 c0       	rjmp	.+72     	; 0x3e96 <main+0x96>
     }
     else if(ch == STK_SET_DEVICE) {
-    3e60:	82 34       	cpi	r24, 0x42	; 66
-    3e62:	11 f4       	brne	.+4      	; 0x3e68 <main+0x68>
+    3e4e:	82 34       	cpi	r24, 0x42	; 66
+    3e50:	11 f4       	brne	.+4      	; 0x3e56 <main+0x56>
       // SET DEVICE is ignored
       getNch(20);
-    3e64:	84 e1       	ldi	r24, 0x14	; 20
-    3e66:	03 c0       	rjmp	.+6      	; 0x3e6e <main+0x6e>
+    3e52:	84 e1       	ldi	r24, 0x14	; 20
+    3e54:	03 c0       	rjmp	.+6      	; 0x3e5c <main+0x5c>
     }
     else if(ch == STK_SET_DEVICE_EXT) {
-    3e68:	85 34       	cpi	r24, 0x45	; 69
-    3e6a:	19 f4       	brne	.+6      	; 0x3e72 <main+0x72>
+    3e56:	85 34       	cpi	r24, 0x45	; 69
+    3e58:	19 f4       	brne	.+6      	; 0x3e60 <main+0x60>
       // SET DEVICE EXT is ignored
       getNch(5);
-    3e6c:	85 e0       	ldi	r24, 0x05	; 5
-    3e6e:	bd d0       	rcall	.+378    	; 0x3fea <verifySpace+0xc>
-    3e70:	8d c0       	rjmp	.+282    	; 0x3f8c <main+0x18c>
+    3e5a:	85 e0       	ldi	r24, 0x05	; 5
+    3e5c:	c7 d0       	rcall	.+398    	; 0x3fec <verifySpace+0xc>
+    3e5e:	8a c0       	rjmp	.+276    	; 0x3f74 <main+0x174>
     }
     else if(ch == STK_LOAD_ADDRESS) {
-    3e72:	85 35       	cpi	r24, 0x55	; 85
-    3e74:	a1 f4       	brne	.+40     	; 0x3e9e <main+0x9e>
+    3e60:	85 35       	cpi	r24, 0x55	; 85
+    3e62:	a1 f4       	brne	.+40     	; 0x3e8c <main+0x8c>
       // LOAD ADDRESS
       address = getch();
-    3e76:	9f d0       	rcall	.+318    	; 0x3fb6 <getch>
-    3e78:	08 2f       	mov	r16, r24
-    3e7a:	10 e0       	ldi	r17, 0x00	; 0
-    3e7c:	10 93 01 02 	sts	0x0201, r17
-    3e80:	00 93 00 02 	sts	0x0200, r16
+    3e64:	99 d0       	rcall	.+306    	; 0x3f98 <getch>
+    3e66:	08 2f       	mov	r16, r24
+    3e68:	10 e0       	ldi	r17, 0x00	; 0
+    3e6a:	10 93 01 02 	sts	0x0201, r17
+    3e6e:	00 93 00 02 	sts	0x0200, r16
       address = (address & 0xff) | (getch() << 8);
-    3e84:	98 d0       	rcall	.+304    	; 0x3fb6 <getch>
-    3e86:	90 e0       	ldi	r25, 0x00	; 0
-    3e88:	98 2f       	mov	r25, r24
-    3e8a:	88 27       	eor	r24, r24
-    3e8c:	80 2b       	or	r24, r16
-    3e8e:	91 2b       	or	r25, r17
+    3e72:	92 d0       	rcall	.+292    	; 0x3f98 <getch>
+    3e74:	90 e0       	ldi	r25, 0x00	; 0
+    3e76:	98 2f       	mov	r25, r24
+    3e78:	88 27       	eor	r24, r24
+    3e7a:	80 2b       	or	r24, r16
+    3e7c:	91 2b       	or	r25, r17
       address += address; // Convert from word address to byte address
-    3e90:	88 0f       	add	r24, r24
-    3e92:	99 1f       	adc	r25, r25
-    3e94:	90 93 01 02 	sts	0x0201, r25
-    3e98:	80 93 00 02 	sts	0x0200, r24
-    3e9c:	76 c0       	rjmp	.+236    	; 0x3f8a <main+0x18a>
+    3e7e:	88 0f       	add	r24, r24
+    3e80:	99 1f       	adc	r25, r25
+    3e82:	90 93 01 02 	sts	0x0201, r25
+    3e86:	80 93 00 02 	sts	0x0200, r24
+    3e8a:	73 c0       	rjmp	.+230    	; 0x3f72 <main+0x172>
       verifySpace();
     }
     else if(ch == STK_UNIVERSAL) {
-    3e9e:	86 35       	cpi	r24, 0x56	; 86
-    3ea0:	29 f4       	brne	.+10     	; 0x3eac <main+0xac>
+    3e8c:	86 35       	cpi	r24, 0x56	; 86
+    3e8e:	29 f4       	brne	.+10     	; 0x3e9a <main+0x9a>
       // UNIVERSAL command is ignored
       getNch(4);
-    3ea2:	84 e0       	ldi	r24, 0x04	; 4
-    3ea4:	a2 d0       	rcall	.+324    	; 0x3fea <verifySpace+0xc>
+    3e90:	84 e0       	ldi	r24, 0x04	; 4
+    3e92:	ac d0       	rcall	.+344    	; 0x3fec <verifySpace+0xc>
       putch(0x00);
-    3ea6:	80 e0       	ldi	r24, 0x00	; 0
-    3ea8:	74 d0       	rcall	.+232    	; 0x3f92 <putch>
-    3eaa:	70 c0       	rjmp	.+224    	; 0x3f8c <main+0x18c>
+    3e94:	80 e0       	ldi	r24, 0x00	; 0
+    3e96:	71 d0       	rcall	.+226    	; 0x3f7a <putch>
+    3e98:	6d c0       	rjmp	.+218    	; 0x3f74 <main+0x174>
     }
     /* Write memory, length is big endian and is in bytes  */
     else if(ch == STK_PROG_PAGE) {
-    3eac:	84 36       	cpi	r24, 0x64	; 100
-    3eae:	09 f0       	breq	.+2      	; 0x3eb2 <main+0xb2>
-    3eb0:	46 c0       	rjmp	.+140    	; 0x3f3e <main+0x13e>
+    3e9a:	84 36       	cpi	r24, 0x64	; 100
+    3e9c:	09 f0       	breq	.+2      	; 0x3ea0 <main+0xa0>
+    3e9e:	43 c0       	rjmp	.+134    	; 0x3f26 <main+0x126>
       // PROGRAM PAGE - we support flash programming only, not EEPROM
       uint8_t *bufPtr;
       uint16_t addrPtr;
-      
-      if (getLen() != 'F') appStart(); // Abort is not flash programming
-    3eb2:	90 d0       	rcall	.+288    	; 0x3fd4 <getLen>
-    3eb4:	86 34       	cpi	r24, 0x46	; 70
-    3eb6:	09 f0       	breq	.+2      	; 0x3eba <main+0xba>
-    3eb8:	7b d0       	rcall	.+246    	; 0x3fb0 <appStart>
-  
+
+      getLen();
+    3ea0:	8f d0       	rcall	.+286    	; 0x3fc0 <getLen>
+
       // Immediately start page erase - this will 4.5ms
       boot_page_erase((uint16_t)(void*)address);
-    3eba:	e0 91 00 02 	lds	r30, 0x0200
-    3ebe:	f0 91 01 02 	lds	r31, 0x0201
-    3ec2:	83 e0       	ldi	r24, 0x03	; 3
-    3ec4:	80 93 57 00 	sts	0x0057, r24
-    3ec8:	e8 95       	spm
-    3eca:	c0 e0       	ldi	r28, 0x00	; 0
-    3ecc:	d1 e0       	ldi	r29, 0x01	; 1
+    3ea2:	e0 91 00 02 	lds	r30, 0x0200
+    3ea6:	f0 91 01 02 	lds	r31, 0x0201
+    3eaa:	83 e0       	ldi	r24, 0x03	; 3
+    3eac:	80 93 57 00 	sts	0x0057, r24
+    3eb0:	e8 95       	spm
+    3eb2:	c0 e0       	ldi	r28, 0x00	; 0
+    3eb4:	d1 e0       	ldi	r29, 0x01	; 1
 
       // While that is going on, read in page contents
       bufPtr = buff;
       do *bufPtr++ = getch();
-    3ece:	73 d0       	rcall	.+230    	; 0x3fb6 <getch>
-    3ed0:	89 93       	st	Y+, r24
+    3eb6:	70 d0       	rcall	.+224    	; 0x3f98 <getch>
+    3eb8:	89 93       	st	Y+, r24
       while (--length);
-    3ed2:	80 91 02 02 	lds	r24, 0x0202
-    3ed6:	81 50       	subi	r24, 0x01	; 1
-    3ed8:	80 93 02 02 	sts	0x0202, r24
-    3edc:	88 23       	and	r24, r24
-    3ede:	b9 f7       	brne	.-18     	; 0x3ece <main+0xce>
+    3eba:	80 91 02 02 	lds	r24, 0x0202
+    3ebe:	81 50       	subi	r24, 0x01	; 1
+    3ec0:	80 93 02 02 	sts	0x0202, r24
+    3ec4:	88 23       	and	r24, r24
+    3ec6:	b9 f7       	brne	.-18     	; 0x3eb6 <main+0xb6>
 
+      // Read command terminator, start reply
+      verifySpace();
+    3ec8:	8b d0       	rcall	.+278    	; 0x3fe0 <verifySpace>
+      
       // If only a partial page is to be programmed, the erase might not be complete.
       // So check that here
       boot_spm_busy_wait();
-    3ee0:	07 b6       	in	r0, 0x37	; 55
-    3ee2:	00 fc       	sbrc	r0, 0
-    3ee4:	fd cf       	rjmp	.-6      	; 0x3ee0 <main+0xe0>
+    3eca:	07 b6       	in	r0, 0x37	; 55
+    3ecc:	00 fc       	sbrc	r0, 0
+    3ece:	fd cf       	rjmp	.-6      	; 0x3eca <main+0xca>
 
-      // Read command terminator, start reply
-      verifySpace();
-    3ee6:	7b d0       	rcall	.+246    	; 0x3fde <verifySpace>
-      
       // Copy buffer into programming buffer
       bufPtr = buff;
       addrPtr = (uint16_t)(void*)address;
-    3ee8:	40 91 00 02 	lds	r20, 0x0200
-    3eec:	50 91 01 02 	lds	r21, 0x0201
-    3ef0:	a0 e0       	ldi	r26, 0x00	; 0
-    3ef2:	b1 e0       	ldi	r27, 0x01	; 1
+    3ed0:	40 91 00 02 	lds	r20, 0x0200
+    3ed4:	50 91 01 02 	lds	r21, 0x0201
+    3ed8:	a0 e0       	ldi	r26, 0x00	; 0
+    3eda:	b1 e0       	ldi	r27, 0x01	; 1
       ch = SPM_PAGESIZE / 2;
       do {
         uint16_t a;
         a = *bufPtr++;
-    3ef4:	2c 91       	ld	r18, X
-    3ef6:	30 e0       	ldi	r19, 0x00	; 0
+    3edc:	2c 91       	ld	r18, X
+    3ede:	30 e0       	ldi	r19, 0x00	; 0
         a |= (*bufPtr++) << 8;
-    3ef8:	11 96       	adiw	r26, 0x01	; 1
-    3efa:	8c 91       	ld	r24, X
-    3efc:	11 97       	sbiw	r26, 0x01	; 1
-    3efe:	90 e0       	ldi	r25, 0x00	; 0
-    3f00:	98 2f       	mov	r25, r24
-    3f02:	88 27       	eor	r24, r24
-    3f04:	82 2b       	or	r24, r18
-    3f06:	93 2b       	or	r25, r19
+    3ee0:	11 96       	adiw	r26, 0x01	; 1
+    3ee2:	8c 91       	ld	r24, X
+    3ee4:	11 97       	sbiw	r26, 0x01	; 1
+    3ee6:	90 e0       	ldi	r25, 0x00	; 0
+    3ee8:	98 2f       	mov	r25, r24
+    3eea:	88 27       	eor	r24, r24
+    3eec:	82 2b       	or	r24, r18
+    3eee:	93 2b       	or	r25, r19
 #define buff    ((uint8_t*)(0x100))
 #define address (*(uint16_t*)(0x200))
 #define length  (*(uint8_t*)(0x202))
 
 /* main program starts here */
 int main(void) {
-    3f08:	12 96       	adiw	r26, 0x02	; 2
+    3ef0:	12 96       	adiw	r26, 0x02	; 2
       ch = SPM_PAGESIZE / 2;
       do {
         uint16_t a;
         a = *bufPtr++;
         a |= (*bufPtr++) << 8;
         boot_page_fill((uint16_t)(void*)addrPtr,a);
-    3f0a:	fa 01       	movw	r30, r20
-    3f0c:	0c 01       	movw	r0, r24
-    3f0e:	d0 92 57 00 	sts	0x0057, r13
-    3f12:	e8 95       	spm
-    3f14:	11 24       	eor	r1, r1
+    3ef2:	fa 01       	movw	r30, r20
+    3ef4:	0c 01       	movw	r0, r24
+    3ef6:	d0 92 57 00 	sts	0x0057, r13
+    3efa:	e8 95       	spm
+    3efc:	11 24       	eor	r1, r1
         addrPtr += 2;
-    3f16:	4e 5f       	subi	r20, 0xFE	; 254
-    3f18:	5f 4f       	sbci	r21, 0xFF	; 255
+    3efe:	4e 5f       	subi	r20, 0xFE	; 254
+    3f00:	5f 4f       	sbci	r21, 0xFF	; 255
       } while (--ch);
-    3f1a:	f1 e0       	ldi	r31, 0x01	; 1
-    3f1c:	a0 38       	cpi	r26, 0x80	; 128
-    3f1e:	bf 07       	cpc	r27, r31
-    3f20:	49 f7       	brne	.-46     	; 0x3ef4 <main+0xf4>
+    3f02:	f1 e0       	ldi	r31, 0x01	; 1
+    3f04:	a0 38       	cpi	r26, 0x80	; 128
+    3f06:	bf 07       	cpc	r27, r31
+    3f08:	49 f7       	brne	.-46     	; 0x3edc <main+0xdc>
       
       // Write from programming buffer
       boot_page_write((uint16_t)(void*)address);
-    3f22:	e0 91 00 02 	lds	r30, 0x0200
-    3f26:	f0 91 01 02 	lds	r31, 0x0201
-    3f2a:	e0 92 57 00 	sts	0x0057, r14
-    3f2e:	e8 95       	spm
+    3f0a:	e0 91 00 02 	lds	r30, 0x0200
+    3f0e:	f0 91 01 02 	lds	r31, 0x0201
+    3f12:	e0 92 57 00 	sts	0x0057, r14
+    3f16:	e8 95       	spm
       boot_spm_busy_wait();
-    3f30:	07 b6       	in	r0, 0x37	; 55
-    3f32:	00 fc       	sbrc	r0, 0
-    3f34:	fd cf       	rjmp	.-6      	; 0x3f30 <main+0x130>
+    3f18:	07 b6       	in	r0, 0x37	; 55
+    3f1a:	00 fc       	sbrc	r0, 0
+    3f1c:	fd cf       	rjmp	.-6      	; 0x3f18 <main+0x118>
 
       // Reenable read access to flash
       boot_rww_enable();
-    3f36:	f0 92 57 00 	sts	0x0057, r15
-    3f3a:	e8 95       	spm
-    3f3c:	27 c0       	rjmp	.+78     	; 0x3f8c <main+0x18c>
+    3f1e:	f0 92 57 00 	sts	0x0057, r15
+    3f22:	e8 95       	spm
+    3f24:	27 c0       	rjmp	.+78     	; 0x3f74 <main+0x174>
     }
     /* Read memory block mode, length is big endian.  */
     else if(ch == STK_READ_PAGE) {
-    3f3e:	84 37       	cpi	r24, 0x74	; 116
-    3f40:	b9 f4       	brne	.+46     	; 0x3f70 <main+0x170>
+    3f26:	84 37       	cpi	r24, 0x74	; 116
+    3f28:	b9 f4       	brne	.+46     	; 0x3f58 <main+0x158>
       // READ PAGE - we only read flash
       getLen();
-    3f42:	48 d0       	rcall	.+144    	; 0x3fd4 <getLen>
+    3f2a:	4a d0       	rcall	.+148    	; 0x3fc0 <getLen>
       verifySpace();
-    3f44:	4c d0       	rcall	.+152    	; 0x3fde <verifySpace>
+    3f2c:	59 d0       	rcall	.+178    	; 0x3fe0 <verifySpace>
       do putch(pgm_read_byte_near(address++));
-    3f46:	e0 91 00 02 	lds	r30, 0x0200
-    3f4a:	f0 91 01 02 	lds	r31, 0x0201
-    3f4e:	31 96       	adiw	r30, 0x01	; 1
-    3f50:	f0 93 01 02 	sts	0x0201, r31
-    3f54:	e0 93 00 02 	sts	0x0200, r30
-    3f58:	31 97       	sbiw	r30, 0x01	; 1
-    3f5a:	e4 91       	lpm	r30, Z+
-    3f5c:	8e 2f       	mov	r24, r30
-    3f5e:	19 d0       	rcall	.+50     	; 0x3f92 <putch>
+    3f2e:	e0 91 00 02 	lds	r30, 0x0200
+    3f32:	f0 91 01 02 	lds	r31, 0x0201
+    3f36:	31 96       	adiw	r30, 0x01	; 1
+    3f38:	f0 93 01 02 	sts	0x0201, r31
+    3f3c:	e0 93 00 02 	sts	0x0200, r30
+    3f40:	31 97       	sbiw	r30, 0x01	; 1
+    3f42:	e4 91       	lpm	r30, Z+
+    3f44:	8e 2f       	mov	r24, r30
+    3f46:	19 d0       	rcall	.+50     	; 0x3f7a <putch>
       while (--length);
-    3f60:	80 91 02 02 	lds	r24, 0x0202
-    3f64:	81 50       	subi	r24, 0x01	; 1
-    3f66:	80 93 02 02 	sts	0x0202, r24
-    3f6a:	88 23       	and	r24, r24
-    3f6c:	61 f7       	brne	.-40     	; 0x3f46 <main+0x146>
-    3f6e:	0e c0       	rjmp	.+28     	; 0x3f8c <main+0x18c>
+    3f48:	80 91 02 02 	lds	r24, 0x0202
+    3f4c:	81 50       	subi	r24, 0x01	; 1
+    3f4e:	80 93 02 02 	sts	0x0202, r24
+    3f52:	88 23       	and	r24, r24
+    3f54:	61 f7       	brne	.-40     	; 0x3f2e <main+0x12e>
+    3f56:	0e c0       	rjmp	.+28     	; 0x3f74 <main+0x174>
     }
 
     /* Get device signature bytes  */
     else if(ch == STK_READ_SIGN) {
-    3f70:	85 37       	cpi	r24, 0x75	; 117
-    3f72:	39 f4       	brne	.+14     	; 0x3f82 <main+0x182>
+    3f58:	85 37       	cpi	r24, 0x75	; 117
+    3f5a:	39 f4       	brne	.+14     	; 0x3f6a <main+0x16a>
       // READ SIGN - return what Avrdude wants to hear
       verifySpace();
-    3f74:	34 d0       	rcall	.+104    	; 0x3fde <verifySpace>
+    3f5c:	41 d0       	rcall	.+130    	; 0x3fe0 <verifySpace>
       putch(SIGNATURE_0);
-    3f76:	8e e1       	ldi	r24, 0x1E	; 30
-    3f78:	0c d0       	rcall	.+24     	; 0x3f92 <putch>
+    3f5e:	8e e1       	ldi	r24, 0x1E	; 30
+    3f60:	0c d0       	rcall	.+24     	; 0x3f7a <putch>
       putch(SIGNATURE_1);
-    3f7a:	84 e9       	ldi	r24, 0x94	; 148
-    3f7c:	0a d0       	rcall	.+20     	; 0x3f92 <putch>
+    3f62:	84 e9       	ldi	r24, 0x94	; 148
+    3f64:	0a d0       	rcall	.+20     	; 0x3f7a <putch>
       putch(SIGNATURE_2);
-    3f7e:	86 e0       	ldi	r24, 0x06	; 6
-    3f80:	93 cf       	rjmp	.-218    	; 0x3ea8 <main+0xa8>
+    3f66:	86 e0       	ldi	r24, 0x06	; 6
+    3f68:	96 cf       	rjmp	.-212    	; 0x3e96 <main+0x96>
     }
     else if (ch == 'Q') {
-    3f82:	81 35       	cpi	r24, 0x51	; 81
-    3f84:	11 f4       	brne	.+4      	; 0x3f8a <main+0x18a>
+    3f6a:	81 35       	cpi	r24, 0x51	; 81
+    3f6c:	11 f4       	brne	.+4      	; 0x3f72 <main+0x172>
       // Adaboot no-wait mod
-      WDTCSR = _BV(WDE);
-    3f86:	c0 92 60 00 	sts	0x0060, r12
+      watchdogConfig(_BV(WDE));
+    3f6e:	88 e0       	ldi	r24, 0x08	; 8
+    3f70:	2c d0       	rcall	.+88     	; 0x3fca <watchdogConfig>
       verifySpace();
     }
     else {
       // This covers the response to commands like STK_ENTER_PROGMODE
       verifySpace();
-    3f8a:	29 d0       	rcall	.+82     	; 0x3fde <verifySpace>
+    3f72:	36 d0       	rcall	.+108    	; 0x3fe0 <verifySpace>
     }
     putch(STK_OK);
-    3f8c:	80 e1       	ldi	r24, 0x10	; 16
-    3f8e:	01 d0       	rcall	.+2      	; 0x3f92 <putch>
-    3f90:	60 cf       	rjmp	.-320    	; 0x3e52 <main+0x52>
-
-00003f92 <putch>:
-  }
-}
+    3f74:	80 e1       	ldi	r24, 0x10	; 16
+    3f76:	01 d0       	rcall	.+2      	; 0x3f7a <putch>
+    3f78:	63 cf       	rjmp	.-314    	; 0x3e40 <main+0x40>
 
+00003f7a <putch>:
 void putch(char ch) {
-    3f92:	98 2f       	mov	r25, r24
+#ifndef SOFT_UART
   while (!(UCSR0A & _BV(UDRE0)));
-    3f94:	80 91 c0 00 	lds	r24, 0x00C0
-    3f98:	85 ff       	sbrs	r24, 5
-    3f9a:	fc cf       	rjmp	.-8      	; 0x3f94 <putch+0x2>
   UDR0 = ch;
-    3f9c:	90 93 c6 00 	sts	0x00C6, r25
-}
-    3fa0:	08 95       	ret
-
-00003fa2 <setTimer>:
-
-void setTimer(uint16_t counts) {
-  TCNT1 = counts;
-    3fa2:	90 93 85 00 	sts	0x0085, r25
-    3fa6:	80 93 84 00 	sts	0x0084, r24
-  TIFR1 = _BV(TOV1);
-    3faa:	81 e0       	ldi	r24, 0x01	; 1
-    3fac:	86 bb       	out	0x16, r24	; 22
+#else
+  __asm__ __volatile__ (
+    3f7a:	2a e0       	ldi	r18, 0x0A	; 10
+    3f7c:	30 e0       	ldi	r19, 0x00	; 0
+    3f7e:	80 95       	com	r24
+    3f80:	08 94       	sec
+    3f82:	10 f4       	brcc	.+4      	; 0x3f88 <putch+0xe>
+    3f84:	59 98       	cbi	0x0b, 1	; 11
+    3f86:	02 c0       	rjmp	.+4      	; 0x3f8c <putch+0x12>
+    3f88:	59 9a       	sbi	0x0b, 1	; 11
+    3f8a:	00 00       	nop
+    3f8c:	15 d0       	rcall	.+42     	; 0x3fb8 <uartDelay>
+    3f8e:	14 d0       	rcall	.+40     	; 0x3fb8 <uartDelay>
+    3f90:	86 95       	lsr	r24
+    3f92:	2a 95       	dec	r18
+    3f94:	b1 f7       	brne	.-20     	; 0x3f82 <putch+0x8>
+      [uartBit] "I" (UART_TX_BIT)
+    :
+      "r25"
+  );
+#endif
 }
-    3fae:	08 95       	ret
+    3f96:	08 95       	ret
 
-00003fb0 <appStart>:
-  length = getch();
+00003f98 <getch>:
   return getch();
 }
 
-void appStart() {
+// Watchdog functions. These are only safe with interrupts turned off.
+void watchdogReset() {
   __asm__ __volatile__ (
-    3fb0:	ee 27       	eor	r30, r30
-    3fb2:	ff 27       	eor	r31, r31
-    3fb4:	09 94       	ijmp
+    3f98:	a8 95       	wdr
+#ifdef LED_DATA_FLASH
+  LED_PIN |= _BV(LED);
+#endif
 
-00003fb6 <getch>:
-  TCNT1 = counts;
-  TIFR1 = _BV(TOV1);
+  return ch;
 }
+    3f9a:	29 e0       	ldi	r18, 0x09	; 9
+    3f9c:	30 e0       	ldi	r19, 0x00	; 0
+    3f9e:	48 99       	sbic	0x09, 0	; 9
+    3fa0:	fe cf       	rjmp	.-4      	; 0x3f9e <getch+0x6>
+    3fa2:	0a d0       	rcall	.+20     	; 0x3fb8 <uartDelay>
+    3fa4:	09 d0       	rcall	.+18     	; 0x3fb8 <uartDelay>
+    3fa6:	08 d0       	rcall	.+16     	; 0x3fb8 <uartDelay>
+    3fa8:	88 94       	clc
+    3faa:	48 99       	sbic	0x09, 0	; 9
+    3fac:	08 94       	sec
+    3fae:	2a 95       	dec	r18
+    3fb0:	11 f0       	breq	.+4      	; 0x3fb6 <getch+0x1e>
+    3fb2:	87 95       	ror	r24
+    3fb4:	f7 cf       	rjmp	.-18     	; 0x3fa4 <getch+0xc>
+    3fb6:	08 95       	ret
+
+00003fb8 <uartDelay>:
+#if UART_B_VALUE > 255
+#error Baud rate too slow for soft UART
+#endif
 
-uint8_t getch(void) {
-  LED_PORT &= ~_BV(LED);
-    3fb6:	2d 98       	cbi	0x05, 5	; 5
-  setTimer(-(F_CPU/(1024*2))); // 500ms
-    3fb8:	8e eb       	ldi	r24, 0xBE	; 190
-    3fba:	90 ef       	ldi	r25, 0xF0	; 240
-    3fbc:	f2 df       	rcall	.-28     	; 0x3fa2 <setTimer>
-    3fbe:	02 c0       	rjmp	.+4      	; 0x3fc4 <getch+0xe>
-  while(!(UCSR0A & _BV(RXC0))) if (TIFR1 & _BV(TOV1)) appStart();
-    3fc0:	b0 99       	sbic	0x16, 0	; 22
-    3fc2:	f6 df       	rcall	.-20     	; 0x3fb0 <appStart>
-    3fc4:	80 91 c0 00 	lds	r24, 0x00C0
-    3fc8:	87 ff       	sbrs	r24, 7
-    3fca:	fa cf       	rjmp	.-12     	; 0x3fc0 <getch+0xa>
-  LED_PORT |= _BV(LED);
-    3fcc:	2d 9a       	sbi	0x05, 5	; 5
-  return UDR0;
-    3fce:	80 91 c6 00 	lds	r24, 0x00C6
-}
-    3fd2:	08 95       	ret
+void uartDelay() {
+  __asm__ __volatile__ (
+    3fb8:	98 e0       	ldi	r25, 0x08	; 8
+    3fba:	9a 95       	dec	r25
+    3fbc:	f1 f7       	brne	.-4      	; 0x3fba <uartDelay+0x2>
+    3fbe:	08 95       	ret
 
-00003fd4 <getLen>:
-    LED_PIN |= _BV(LED);
+00003fc0 <getLen>:
   } while (--count);
 }
+#endif
 
 uint8_t getLen() {
   getch();
-    3fd4:	f0 df       	rcall	.-32     	; 0x3fb6 <getch>
+    3fc0:	eb df       	rcall	.-42     	; 0x3f98 <getch>
   length = getch();
-    3fd6:	ef df       	rcall	.-34     	; 0x3fb6 <getch>
-    3fd8:	80 93 02 02 	sts	0x0202, r24
+    3fc2:	ea df       	rcall	.-44     	; 0x3f98 <getch>
+    3fc4:	80 93 02 02 	sts	0x0202, r24
   return getch();
 }
-    3fdc:	ec cf       	rjmp	.-40     	; 0x3fb6 <getch>
+    3fc8:	e7 cf       	rjmp	.-50     	; 0x3f98 <getch>
+
+00003fca <watchdogConfig>:
+    "wdr\n"
+  );
+}
 
-00003fde <verifySpace>:
+void watchdogConfig(uint8_t x) {
+  WDTCSR = _BV(WDCE) | _BV(WDE);
+    3fca:	e0 e6       	ldi	r30, 0x60	; 96
+    3fcc:	f0 e0       	ldi	r31, 0x00	; 0
+    3fce:	98 e1       	ldi	r25, 0x18	; 24
+    3fd0:	90 83       	st	Z, r25
+  WDTCSR = x;
+    3fd2:	80 83       	st	Z, r24
+}
+    3fd4:	08 95       	ret
+
+00003fd6 <appStart>:
+
+void appStart() {
+  watchdogConfig(0);
+    3fd6:	80 e0       	ldi	r24, 0x00	; 0
+    3fd8:	f8 df       	rcall	.-16     	; 0x3fca <watchdogConfig>
+  __asm__ __volatile__ (
+    3fda:	ee 27       	eor	r30, r30
+    3fdc:	ff 27       	eor	r31, r31
+    3fde:	09 94       	ijmp
+
+00003fe0 <verifySpace>:
   do getch(); while (--count);
   verifySpace();
 }
 
 void verifySpace() {
   if (getch() != CRC_EOP) appStart();
-    3fde:	eb df       	rcall	.-42     	; 0x3fb6 <getch>
-    3fe0:	80 32       	cpi	r24, 0x20	; 32
-    3fe2:	09 f0       	breq	.+2      	; 0x3fe6 <verifySpace+0x8>
-    3fe4:	e5 df       	rcall	.-54     	; 0x3fb0 <appStart>
+    3fe0:	db df       	rcall	.-74     	; 0x3f98 <getch>
+    3fe2:	80 32       	cpi	r24, 0x20	; 32
+    3fe4:	09 f0       	breq	.+2      	; 0x3fe8 <verifySpace+0x8>
+    3fe6:	f7 df       	rcall	.-18     	; 0x3fd6 <appStart>
   putch(STK_INSYNC);
-    3fe6:	84 e1       	ldi	r24, 0x14	; 20
+    3fe8:	84 e1       	ldi	r24, 0x14	; 20
 }
-    3fe8:	d4 cf       	rjmp	.-88     	; 0x3f92 <putch>
-  while(!(UCSR0A & _BV(RXC0))) if (TIFR1 & _BV(TOV1)) appStart();
-  LED_PORT |= _BV(LED);
-  return UDR0;
+    3fea:	c7 cf       	rjmp	.-114    	; 0x3f7a <putch>
+    ::[count] "M" (UART_B_VALUE)
+  );
 }
+#endif
 
 void getNch(uint8_t count) {
-    3fea:	1f 93       	push	r17
-    3fec:	18 2f       	mov	r17, r24
+    3fec:	1f 93       	push	r17
+    3fee:	18 2f       	mov	r17, r24
 
-00003fee <getNch>:
+00003ff0 <getNch>:
   do getch(); while (--count);
-    3fee:	e3 df       	rcall	.-58     	; 0x3fb6 <getch>
-    3ff0:	11 50       	subi	r17, 0x01	; 1
-    3ff2:	e9 f7       	brne	.-6      	; 0x3fee <getNch>
+    3ff0:	d3 df       	rcall	.-90     	; 0x3f98 <getch>
+    3ff2:	11 50       	subi	r17, 0x01	; 1
+    3ff4:	e9 f7       	brne	.-6      	; 0x3ff0 <getNch>
   verifySpace();
-    3ff4:	f4 df       	rcall	.-24     	; 0x3fde <verifySpace>
+    3ff6:	f4 df       	rcall	.-24     	; 0x3fe0 <verifySpace>
 }
-    3ff6:	1f 91       	pop	r17
-    3ff8:	08 95       	ret
+    3ff8:	1f 91       	pop	r17
+    3ffa:	08 95       	ret

+ 32 - 32
optiboot/bootloaders/optiboot/optiboot_ng.hex

@@ -1,34 +1,34 @@
-:103E000085E08093810082E08093C00098E19093E8
-:103E1000C10086E08093C20087E68093C40084B727
-:103E200014BE909360001092600081FFC1D0259A6B
-:103E300006E080E39CEFB5D0B09BFECF1D9A015009
-:103E4000C1F7DD24D394B8E0CB2EA5E0EA2EF1E152
-:103E5000FF2EB1D0813421F481E0C7D083E024C0AB
-:103E6000823411F484E103C0853419F485E0BDD0B7
-:103E70008DC08535A1F49FD0082F10E0109301026A
-:103E80000093000298D090E0982F8827802B912BE8
-:103E9000880F991F909301028093000276C08635A7
-:103EA00029F484E0A2D080E074D070C0843609F098
-:103EB00046C090D0863409F07BD0E0910002F091AA
-:103EC000010283E080935700E895C0E0D1E073D011
-:103ED0008993809102028150809302028823B9F76E
-:103EE00007B600FCFDCF7BD040910002509101024B
-:103EF000A0E0B1E02C9130E011968C91119790E008
-:103F0000982F8827822B932B1296FA010C01D092BE
-:103F10005700E89511244E5F5F4FF1E0A038BF07CE
-:103F200049F7E0910002F0910102E0925700E89514
-:103F300007B600FCFDCFF0925700E89527C0843704
-:103F4000B9F448D04CD0E0910002F09101023196D2
-:103F5000F0930102E09300023197E4918E2F19D083
-:103F600080910202815080930202882361F70EC083
-:103F7000853739F434D08EE10CD084E90AD086E05C
-:103F800093CF813511F4C092600029D080E101D037
-:103F900060CF982F8091C00085FFFCCF9093C60022
-:103FA0000895909385008093840081E086BB0895F6
-:103FB000EE27FF2709942D988CE791EEF2DF02C0DF
-:103FC000B099F6DF8091C00087FFFACF2D9A8091DB
-:103FD000C6000895F0DFEFDF80930202ECCFEBDF45
-:103FE000803209F0E5DF84E1D4CF1F93182FE3DF9F
-:0A3FF0001150E9F7F4DF1F91089566
+:103E000085E08093810084B714BE81FFE4D08DE00B
+:103E1000DCD0259A519A86E020E33CEF91E0309384
+:103E200085002093840096BBB09BFECF1D9AA89579
+:103E30008150A9F7DD24D394A5E0EA2EF1E1FF2E0D
+:103E4000ABD0813421F481E0D1D083E024C082342E
+:103E500011F484E103C0853419F485E0C7D08AC029
+:103E60008535A1F499D0082F10E01093010200933A
+:103E7000000292D090E0982F8827802B912B880FFA
+:103E8000991F909301028093000273C0863529F434
+:103E900084E0ACD080E071D06DC0843609F043C0BE
+:103EA0008FD0E0910002F091010283E080935700EF
+:103EB000E895C0E0D1E070D08993809102028150F2
+:103EC000809302028823B9F78BD007B600FCFDCFA0
+:103ED0004091000250910102A0E0B1E02C9130E04D
+:103EE00011968C91119790E0982F8827822B932B15
+:103EF0001296FA010C01D0925700E89511244E5FFA
+:103F00005F4FF1E0A038BF0749F7E0910002F09160
+:103F10000102E0925700E89507B600FCFDCFF09251
+:103F20005700E89527C08437B9F44AD059D0E091BA
+:103F30000002F09101023196F0930102E093000239
+:103F40003197E4918E2F19D0809102028150809395
+:103F50000202882361F70EC0853739F441D08EE123
+:103F60000CD084E90AD086E096CF813511F488E040
+:103F70002CD036D080E101D063CF2AE030E08095AC
+:103F8000089410F4599802C0599A000015D014D022
+:103F900086952A95B1F70895A89529E030E04899CB
+:103FA000FECF0AD009D008D08894489908942A9561
+:103FB00011F08795F7CF089598E09A95F1F7089555
+:103FC000EBDFEADF80930202E7CFE0E6F0E098E182
+:103FD00090838083089580E0F8DFEE27FF2709941F
+:103FE000DBDF803209F0F7DF84E1C7CF1F93182FA2
+:0C3FF000D3DF1150E9F7F4DF1F910895B2
 :0400000300003E00BB
 :00000001FF

+ 320 - 282
optiboot/bootloaders/optiboot/optiboot_ng.lst

@@ -3,25 +3,25 @@ optiboot_ng.elf:     file format elf32-avr
 
 Sections:
 Idx Name          Size      VMA       LMA       File off  Algn
-  0 .text         000001fa  00003e00  00003e00  00000054  2**1
+  0 .text         000001fc  00003e00  00003e00  00000054  2**1
                   CONTENTS, ALLOC, LOAD, READONLY, CODE
-  1 .debug_aranges 00000028  00000000  00000000  0000024e  2**0
+  1 .debug_aranges 00000028  00000000  00000000  00000250  2**0
                   CONTENTS, READONLY, DEBUGGING
-  2 .debug_pubnames 00000064  00000000  00000000  00000276  2**0
+  2 .debug_pubnames 00000078  00000000  00000000  00000278  2**0
                   CONTENTS, READONLY, DEBUGGING
-  3 .debug_info   0000022f  00000000  00000000  000002da  2**0
+  3 .debug_info   00000275  00000000  00000000  000002f0  2**0
                   CONTENTS, READONLY, DEBUGGING
-  4 .debug_abbrev 00000164  00000000  00000000  00000509  2**0
+  4 .debug_abbrev 000001a3  00000000  00000000  00000565  2**0
                   CONTENTS, READONLY, DEBUGGING
-  5 .debug_line   000003c8  00000000  00000000  0000066d  2**0
+  5 .debug_line   000003b8  00000000  00000000  00000708  2**0
                   CONTENTS, READONLY, DEBUGGING
-  6 .debug_frame  00000090  00000000  00000000  00000a38  2**2
+  6 .debug_frame  000000a0  00000000  00000000  00000ac0  2**2
                   CONTENTS, READONLY, DEBUGGING
-  7 .debug_str    0000011c  00000000  00000000  00000ac8  2**0
+  7 .debug_str    00000133  00000000  00000000  00000b60  2**0
                   CONTENTS, READONLY, DEBUGGING
-  8 .debug_loc    000001d6  00000000  00000000  00000be4  2**0
+  8 .debug_loc    000001a0  00000000  00000000  00000c93  2**0
                   CONTENTS, READONLY, DEBUGGING
-  9 .debug_ranges 00000068  00000000  00000000  00000dba  2**0
+  9 .debug_ranges 00000070  00000000  00000000  00000e33  2**0
                   CONTENTS, READONLY, DEBUGGING
 
 Disassembly of section .text:
@@ -35,449 +35,487 @@ Disassembly of section .text:
 int main(void) {
     3e00:	85 e0       	ldi	r24, 0x05	; 5
     3e02:	80 93 81 00 	sts	0x0081, r24
-    [addr5]"i"(_SFR_MEM_ADDR(UBRR0L)), [val5]"i"((F_CPU + BAUD_RATE * 4L) / (BAUD_RATE * 8L) - 1)
-  );
-#else
-  // Set up Timer 1 for timeout counter
-  TCCR1B = _BV(CS12) | _BV(CS10); // div 1024
-  UCSR0A = _BV(U2X0); //Double speed mode USART0
-    3e06:	82 e0       	ldi	r24, 0x02	; 2
-    3e08:	80 93 c0 00 	sts	0x00C0, r24
-  UCSR0B = _BV(RXEN0) | _BV(TXEN0);
-    3e0c:	98 e1       	ldi	r25, 0x18	; 24
-    3e0e:	90 93 c1 00 	sts	0x00C1, r25
   UCSR0C = _BV(UCSZ00) | _BV(UCSZ01);
-    3e12:	86 e0       	ldi	r24, 0x06	; 6
-    3e14:	80 93 c2 00 	sts	0x00C2, r24
   UBRR0L = (uint8_t)( (F_CPU + BAUD_RATE * 4L) / (BAUD_RATE * 8L) - 1 );
-    3e18:	87 e6       	ldi	r24, 0x67	; 103
-    3e1a:	80 93 c4 00 	sts	0x00C4, r24
 #endif
 
   // Adaboot no-wait mod
   ch = MCUSR;
-    3e1e:	84 b7       	in	r24, 0x34	; 52
+    3e06:	84 b7       	in	r24, 0x34	; 52
   MCUSR = 0;
-    3e20:	14 be       	out	0x34, r1	; 52
-  WDTCSR = _BV(WDCE) | _BV(WDE);
-    3e22:	90 93 60 00 	sts	0x0060, r25
-  WDTCSR = 0;
-    3e26:	10 92 60 00 	sts	0x0060, r1
+    3e08:	14 be       	out	0x34, r1	; 52
   if (!(ch & _BV(EXTRF))) appStart();
-    3e2a:	81 ff       	sbrs	r24, 1
-    3e2c:	c1 d0       	rcall	.+386    	; 0x3fb0 <appStart>
+    3e0a:	81 ff       	sbrs	r24, 1
+    3e0c:	e4 d0       	rcall	.+456    	; 0x3fd6 <appStart>
+
+  // Set up watchdog to trigger after 500ms
+  watchdogConfig(_BV(WDP2)|_BV(WDP0)|_BV(WDE));
+    3e0e:	8d e0       	ldi	r24, 0x0D	; 13
+    3e10:	dc d0       	rcall	.+440    	; 0x3fca <watchdogConfig>
 
-  /* set LED pin as output */
+  /* Set LED pin as output */
   LED_DDR |= _BV(LED);
-    3e2e:	25 9a       	sbi	0x04, 5	; 4
-    3e30:	06 e0       	ldi	r16, 0x06	; 6
-  putch(STK_INSYNC);
+    3e12:	25 9a       	sbi	0x04, 5	; 4
+
+#ifdef SOFT_UART
+  /* Set TX pin as output */
+  UART_DDR |= _BV(UART_TX_BIT);
+    3e14:	51 9a       	sbi	0x0a, 1	; 10
+    3e16:	86 e0       	ldi	r24, 0x06	; 6
+}
+
+#if LED_START_FLASHES > 0
+void flash_led(uint8_t count) {
+  do {
+    TCNT1 = -(F_CPU/(1024*16));
+    3e18:	20 e3       	ldi	r18, 0x30	; 48
+    3e1a:	3c ef       	ldi	r19, 0xFC	; 252
+    TIFR1 = _BV(TOV1);
+    3e1c:	91 e0       	ldi	r25, 0x01	; 1
 }
 
+#if LED_START_FLASHES > 0
 void flash_led(uint8_t count) {
   do {
-    setTimer(-(F_CPU/(1024*16))); // 62ms
-    3e32:	80 e3       	ldi	r24, 0x30	; 48
-    3e34:	9c ef       	ldi	r25, 0xFC	; 252
-    3e36:	b5 d0       	rcall	.+362    	; 0x3fa2 <setTimer>
+    TCNT1 = -(F_CPU/(1024*16));
+    3e1e:	30 93 85 00 	sts	0x0085, r19
+    3e22:	20 93 84 00 	sts	0x0084, r18
+    TIFR1 = _BV(TOV1);
+    3e26:	96 bb       	out	0x16, r25	; 22
+    while(!(TIFR1 & _BV(TOV1)));
+    3e28:	b0 9b       	sbis	0x16, 0	; 22
+    3e2a:	fe cf       	rjmp	.-4      	; 0x3e28 <main+0x28>
+    LED_PIN |= _BV(LED);
+    3e2c:	1d 9a       	sbi	0x03, 5	; 3
+  return getch();
+}
+
+// Watchdog functions. These are only safe with interrupts turned off.
+void watchdogReset() {
+  __asm__ __volatile__ (
+    3e2e:	a8 95       	wdr
+    TCNT1 = -(F_CPU/(1024*16));
+    TIFR1 = _BV(TOV1);
     while(!(TIFR1 & _BV(TOV1)));
-    3e38:	b0 9b       	sbis	0x16, 0	; 22
-    3e3a:	fe cf       	rjmp	.-4      	; 0x3e38 <main+0x38>
     LED_PIN |= _BV(LED);
-    3e3c:	1d 9a       	sbi	0x03, 5	; 3
+    watchdogReset();
   } while (--count);
-    3e3e:	01 50       	subi	r16, 0x01	; 1
-    3e40:	c1 f7       	brne	.-16     	; 0x3e32 <main+0x32>
+    3e30:	81 50       	subi	r24, 0x01	; 1
+    3e32:	a9 f7       	brne	.-22     	; 0x3e1e <main+0x1e>
     /* get character from UART */
     ch = getch();
 
     if(ch == STK_GET_PARAMETER) {
       // GET PARAMETER returns a generic 0x03 reply - enough to keep Avrdude happy
       getNch(1);
-    3e42:	dd 24       	eor	r13, r13
-    3e44:	d3 94       	inc	r13
-      putch(SIGNATURE_1);
-      putch(SIGNATURE_2);
-    }
-    else if (ch == 'Q') {
-      // Adaboot no-wait mod
-      WDTCSR = _BV(WDE);
-    3e46:	b8 e0       	ldi	r27, 0x08	; 8
-    3e48:	cb 2e       	mov	r12, r27
+    3e34:	dd 24       	eor	r13, r13
+    3e36:	d3 94       	inc	r13
         boot_page_fill((uint16_t)(void*)addrPtr,a);
         addrPtr += 2;
       } while (--ch);
       
       // Write from programming buffer
       boot_page_write((uint16_t)(void*)address);
-    3e4a:	a5 e0       	ldi	r26, 0x05	; 5
-    3e4c:	ea 2e       	mov	r14, r26
+    3e38:	a5 e0       	ldi	r26, 0x05	; 5
+    3e3a:	ea 2e       	mov	r14, r26
       boot_spm_busy_wait();
 
       // Reenable read access to flash
       boot_rww_enable();
-    3e4e:	f1 e1       	ldi	r31, 0x11	; 17
-    3e50:	ff 2e       	mov	r15, r31
-  flash_led(NUM_LED_FLASHES * 2);
+    3e3c:	f1 e1       	ldi	r31, 0x11	; 17
+    3e3e:	ff 2e       	mov	r15, r31
+#endif
 
-  /* forever loop */
+  /* Forever loop */
   for (;;) {
     /* get character from UART */
     ch = getch();
-    3e52:	b1 d0       	rcall	.+354    	; 0x3fb6 <getch>
+    3e40:	ab d0       	rcall	.+342    	; 0x3f98 <getch>
 
     if(ch == STK_GET_PARAMETER) {
-    3e54:	81 34       	cpi	r24, 0x41	; 65
-    3e56:	21 f4       	brne	.+8      	; 0x3e60 <main+0x60>
+    3e42:	81 34       	cpi	r24, 0x41	; 65
+    3e44:	21 f4       	brne	.+8      	; 0x3e4e <main+0x4e>
       // GET PARAMETER returns a generic 0x03 reply - enough to keep Avrdude happy
       getNch(1);
-    3e58:	81 e0       	ldi	r24, 0x01	; 1
-    3e5a:	c7 d0       	rcall	.+398    	; 0x3fea <verifySpace+0xc>
+    3e46:	81 e0       	ldi	r24, 0x01	; 1
+    3e48:	d1 d0       	rcall	.+418    	; 0x3fec <verifySpace+0xc>
       putch(0x03);
-    3e5c:	83 e0       	ldi	r24, 0x03	; 3
-    3e5e:	24 c0       	rjmp	.+72     	; 0x3ea8 <main+0xa8>
+    3e4a:	83 e0       	ldi	r24, 0x03	; 3
+    3e4c:	24 c0       	rjmp	.+72     	; 0x3e96 <main+0x96>
     }
     else if(ch == STK_SET_DEVICE) {
-    3e60:	82 34       	cpi	r24, 0x42	; 66
-    3e62:	11 f4       	brne	.+4      	; 0x3e68 <main+0x68>
+    3e4e:	82 34       	cpi	r24, 0x42	; 66
+    3e50:	11 f4       	brne	.+4      	; 0x3e56 <main+0x56>
       // SET DEVICE is ignored
       getNch(20);
-    3e64:	84 e1       	ldi	r24, 0x14	; 20
-    3e66:	03 c0       	rjmp	.+6      	; 0x3e6e <main+0x6e>
+    3e52:	84 e1       	ldi	r24, 0x14	; 20
+    3e54:	03 c0       	rjmp	.+6      	; 0x3e5c <main+0x5c>
     }
     else if(ch == STK_SET_DEVICE_EXT) {
-    3e68:	85 34       	cpi	r24, 0x45	; 69
-    3e6a:	19 f4       	brne	.+6      	; 0x3e72 <main+0x72>
+    3e56:	85 34       	cpi	r24, 0x45	; 69
+    3e58:	19 f4       	brne	.+6      	; 0x3e60 <main+0x60>
       // SET DEVICE EXT is ignored
       getNch(5);
-    3e6c:	85 e0       	ldi	r24, 0x05	; 5
-    3e6e:	bd d0       	rcall	.+378    	; 0x3fea <verifySpace+0xc>
-    3e70:	8d c0       	rjmp	.+282    	; 0x3f8c <main+0x18c>
+    3e5a:	85 e0       	ldi	r24, 0x05	; 5
+    3e5c:	c7 d0       	rcall	.+398    	; 0x3fec <verifySpace+0xc>
+    3e5e:	8a c0       	rjmp	.+276    	; 0x3f74 <main+0x174>
     }
     else if(ch == STK_LOAD_ADDRESS) {
-    3e72:	85 35       	cpi	r24, 0x55	; 85
-    3e74:	a1 f4       	brne	.+40     	; 0x3e9e <main+0x9e>
+    3e60:	85 35       	cpi	r24, 0x55	; 85
+    3e62:	a1 f4       	brne	.+40     	; 0x3e8c <main+0x8c>
       // LOAD ADDRESS
       address = getch();
-    3e76:	9f d0       	rcall	.+318    	; 0x3fb6 <getch>
-    3e78:	08 2f       	mov	r16, r24
-    3e7a:	10 e0       	ldi	r17, 0x00	; 0
-    3e7c:	10 93 01 02 	sts	0x0201, r17
-    3e80:	00 93 00 02 	sts	0x0200, r16
+    3e64:	99 d0       	rcall	.+306    	; 0x3f98 <getch>
+    3e66:	08 2f       	mov	r16, r24
+    3e68:	10 e0       	ldi	r17, 0x00	; 0
+    3e6a:	10 93 01 02 	sts	0x0201, r17
+    3e6e:	00 93 00 02 	sts	0x0200, r16
       address = (address & 0xff) | (getch() << 8);
-    3e84:	98 d0       	rcall	.+304    	; 0x3fb6 <getch>
-    3e86:	90 e0       	ldi	r25, 0x00	; 0
-    3e88:	98 2f       	mov	r25, r24
-    3e8a:	88 27       	eor	r24, r24
-    3e8c:	80 2b       	or	r24, r16
-    3e8e:	91 2b       	or	r25, r17
+    3e72:	92 d0       	rcall	.+292    	; 0x3f98 <getch>
+    3e74:	90 e0       	ldi	r25, 0x00	; 0
+    3e76:	98 2f       	mov	r25, r24
+    3e78:	88 27       	eor	r24, r24
+    3e7a:	80 2b       	or	r24, r16
+    3e7c:	91 2b       	or	r25, r17
       address += address; // Convert from word address to byte address
-    3e90:	88 0f       	add	r24, r24
-    3e92:	99 1f       	adc	r25, r25
-    3e94:	90 93 01 02 	sts	0x0201, r25
-    3e98:	80 93 00 02 	sts	0x0200, r24
-    3e9c:	76 c0       	rjmp	.+236    	; 0x3f8a <main+0x18a>
+    3e7e:	88 0f       	add	r24, r24
+    3e80:	99 1f       	adc	r25, r25
+    3e82:	90 93 01 02 	sts	0x0201, r25
+    3e86:	80 93 00 02 	sts	0x0200, r24
+    3e8a:	73 c0       	rjmp	.+230    	; 0x3f72 <main+0x172>
       verifySpace();
     }
     else if(ch == STK_UNIVERSAL) {
-    3e9e:	86 35       	cpi	r24, 0x56	; 86
-    3ea0:	29 f4       	brne	.+10     	; 0x3eac <main+0xac>
+    3e8c:	86 35       	cpi	r24, 0x56	; 86
+    3e8e:	29 f4       	brne	.+10     	; 0x3e9a <main+0x9a>
       // UNIVERSAL command is ignored
       getNch(4);
-    3ea2:	84 e0       	ldi	r24, 0x04	; 4
-    3ea4:	a2 d0       	rcall	.+324    	; 0x3fea <verifySpace+0xc>
+    3e90:	84 e0       	ldi	r24, 0x04	; 4
+    3e92:	ac d0       	rcall	.+344    	; 0x3fec <verifySpace+0xc>
       putch(0x00);
-    3ea6:	80 e0       	ldi	r24, 0x00	; 0
-    3ea8:	74 d0       	rcall	.+232    	; 0x3f92 <putch>
-    3eaa:	70 c0       	rjmp	.+224    	; 0x3f8c <main+0x18c>
+    3e94:	80 e0       	ldi	r24, 0x00	; 0
+    3e96:	71 d0       	rcall	.+226    	; 0x3f7a <putch>
+    3e98:	6d c0       	rjmp	.+218    	; 0x3f74 <main+0x174>
     }
     /* Write memory, length is big endian and is in bytes  */
     else if(ch == STK_PROG_PAGE) {
-    3eac:	84 36       	cpi	r24, 0x64	; 100
-    3eae:	09 f0       	breq	.+2      	; 0x3eb2 <main+0xb2>
-    3eb0:	46 c0       	rjmp	.+140    	; 0x3f3e <main+0x13e>
+    3e9a:	84 36       	cpi	r24, 0x64	; 100
+    3e9c:	09 f0       	breq	.+2      	; 0x3ea0 <main+0xa0>
+    3e9e:	43 c0       	rjmp	.+134    	; 0x3f26 <main+0x126>
       // PROGRAM PAGE - we support flash programming only, not EEPROM
       uint8_t *bufPtr;
       uint16_t addrPtr;
-      
-      if (getLen() != 'F') appStart(); // Abort is not flash programming
-    3eb2:	90 d0       	rcall	.+288    	; 0x3fd4 <getLen>
-    3eb4:	86 34       	cpi	r24, 0x46	; 70
-    3eb6:	09 f0       	breq	.+2      	; 0x3eba <main+0xba>
-    3eb8:	7b d0       	rcall	.+246    	; 0x3fb0 <appStart>
-  
+
+      getLen();
+    3ea0:	8f d0       	rcall	.+286    	; 0x3fc0 <getLen>
+
       // Immediately start page erase - this will 4.5ms
       boot_page_erase((uint16_t)(void*)address);
-    3eba:	e0 91 00 02 	lds	r30, 0x0200
-    3ebe:	f0 91 01 02 	lds	r31, 0x0201
-    3ec2:	83 e0       	ldi	r24, 0x03	; 3
-    3ec4:	80 93 57 00 	sts	0x0057, r24
-    3ec8:	e8 95       	spm
-    3eca:	c0 e0       	ldi	r28, 0x00	; 0
-    3ecc:	d1 e0       	ldi	r29, 0x01	; 1
+    3ea2:	e0 91 00 02 	lds	r30, 0x0200
+    3ea6:	f0 91 01 02 	lds	r31, 0x0201
+    3eaa:	83 e0       	ldi	r24, 0x03	; 3
+    3eac:	80 93 57 00 	sts	0x0057, r24
+    3eb0:	e8 95       	spm
+    3eb2:	c0 e0       	ldi	r28, 0x00	; 0
+    3eb4:	d1 e0       	ldi	r29, 0x01	; 1
 
       // While that is going on, read in page contents
       bufPtr = buff;
       do *bufPtr++ = getch();
-    3ece:	73 d0       	rcall	.+230    	; 0x3fb6 <getch>
-    3ed0:	89 93       	st	Y+, r24
+    3eb6:	70 d0       	rcall	.+224    	; 0x3f98 <getch>
+    3eb8:	89 93       	st	Y+, r24
       while (--length);
-    3ed2:	80 91 02 02 	lds	r24, 0x0202
-    3ed6:	81 50       	subi	r24, 0x01	; 1
-    3ed8:	80 93 02 02 	sts	0x0202, r24
-    3edc:	88 23       	and	r24, r24
-    3ede:	b9 f7       	brne	.-18     	; 0x3ece <main+0xce>
+    3eba:	80 91 02 02 	lds	r24, 0x0202
+    3ebe:	81 50       	subi	r24, 0x01	; 1
+    3ec0:	80 93 02 02 	sts	0x0202, r24
+    3ec4:	88 23       	and	r24, r24
+    3ec6:	b9 f7       	brne	.-18     	; 0x3eb6 <main+0xb6>
 
+      // Read command terminator, start reply
+      verifySpace();
+    3ec8:	8b d0       	rcall	.+278    	; 0x3fe0 <verifySpace>
+      
       // If only a partial page is to be programmed, the erase might not be complete.
       // So check that here
       boot_spm_busy_wait();
-    3ee0:	07 b6       	in	r0, 0x37	; 55
-    3ee2:	00 fc       	sbrc	r0, 0
-    3ee4:	fd cf       	rjmp	.-6      	; 0x3ee0 <main+0xe0>
+    3eca:	07 b6       	in	r0, 0x37	; 55
+    3ecc:	00 fc       	sbrc	r0, 0
+    3ece:	fd cf       	rjmp	.-6      	; 0x3eca <main+0xca>
 
-      // Read command terminator, start reply
-      verifySpace();
-    3ee6:	7b d0       	rcall	.+246    	; 0x3fde <verifySpace>
-      
       // Copy buffer into programming buffer
       bufPtr = buff;
       addrPtr = (uint16_t)(void*)address;
-    3ee8:	40 91 00 02 	lds	r20, 0x0200
-    3eec:	50 91 01 02 	lds	r21, 0x0201
-    3ef0:	a0 e0       	ldi	r26, 0x00	; 0
-    3ef2:	b1 e0       	ldi	r27, 0x01	; 1
+    3ed0:	40 91 00 02 	lds	r20, 0x0200
+    3ed4:	50 91 01 02 	lds	r21, 0x0201
+    3ed8:	a0 e0       	ldi	r26, 0x00	; 0
+    3eda:	b1 e0       	ldi	r27, 0x01	; 1
       ch = SPM_PAGESIZE / 2;
       do {
         uint16_t a;
         a = *bufPtr++;
-    3ef4:	2c 91       	ld	r18, X
-    3ef6:	30 e0       	ldi	r19, 0x00	; 0
+    3edc:	2c 91       	ld	r18, X
+    3ede:	30 e0       	ldi	r19, 0x00	; 0
         a |= (*bufPtr++) << 8;
-    3ef8:	11 96       	adiw	r26, 0x01	; 1
-    3efa:	8c 91       	ld	r24, X
-    3efc:	11 97       	sbiw	r26, 0x01	; 1
-    3efe:	90 e0       	ldi	r25, 0x00	; 0
-    3f00:	98 2f       	mov	r25, r24
-    3f02:	88 27       	eor	r24, r24
-    3f04:	82 2b       	or	r24, r18
-    3f06:	93 2b       	or	r25, r19
+    3ee0:	11 96       	adiw	r26, 0x01	; 1
+    3ee2:	8c 91       	ld	r24, X
+    3ee4:	11 97       	sbiw	r26, 0x01	; 1
+    3ee6:	90 e0       	ldi	r25, 0x00	; 0
+    3ee8:	98 2f       	mov	r25, r24
+    3eea:	88 27       	eor	r24, r24
+    3eec:	82 2b       	or	r24, r18
+    3eee:	93 2b       	or	r25, r19
 #define buff    ((uint8_t*)(0x100))
 #define address (*(uint16_t*)(0x200))
 #define length  (*(uint8_t*)(0x202))
 
 /* main program starts here */
 int main(void) {
-    3f08:	12 96       	adiw	r26, 0x02	; 2
+    3ef0:	12 96       	adiw	r26, 0x02	; 2
       ch = SPM_PAGESIZE / 2;
       do {
         uint16_t a;
         a = *bufPtr++;
         a |= (*bufPtr++) << 8;
         boot_page_fill((uint16_t)(void*)addrPtr,a);
-    3f0a:	fa 01       	movw	r30, r20
-    3f0c:	0c 01       	movw	r0, r24
-    3f0e:	d0 92 57 00 	sts	0x0057, r13
-    3f12:	e8 95       	spm
-    3f14:	11 24       	eor	r1, r1
+    3ef2:	fa 01       	movw	r30, r20
+    3ef4:	0c 01       	movw	r0, r24
+    3ef6:	d0 92 57 00 	sts	0x0057, r13
+    3efa:	e8 95       	spm
+    3efc:	11 24       	eor	r1, r1
         addrPtr += 2;
-    3f16:	4e 5f       	subi	r20, 0xFE	; 254
-    3f18:	5f 4f       	sbci	r21, 0xFF	; 255
+    3efe:	4e 5f       	subi	r20, 0xFE	; 254
+    3f00:	5f 4f       	sbci	r21, 0xFF	; 255
       } while (--ch);
-    3f1a:	f1 e0       	ldi	r31, 0x01	; 1
-    3f1c:	a0 38       	cpi	r26, 0x80	; 128
-    3f1e:	bf 07       	cpc	r27, r31
-    3f20:	49 f7       	brne	.-46     	; 0x3ef4 <main+0xf4>
+    3f02:	f1 e0       	ldi	r31, 0x01	; 1
+    3f04:	a0 38       	cpi	r26, 0x80	; 128
+    3f06:	bf 07       	cpc	r27, r31
+    3f08:	49 f7       	brne	.-46     	; 0x3edc <main+0xdc>
       
       // Write from programming buffer
       boot_page_write((uint16_t)(void*)address);
-    3f22:	e0 91 00 02 	lds	r30, 0x0200
-    3f26:	f0 91 01 02 	lds	r31, 0x0201
-    3f2a:	e0 92 57 00 	sts	0x0057, r14
-    3f2e:	e8 95       	spm
+    3f0a:	e0 91 00 02 	lds	r30, 0x0200
+    3f0e:	f0 91 01 02 	lds	r31, 0x0201
+    3f12:	e0 92 57 00 	sts	0x0057, r14
+    3f16:	e8 95       	spm
       boot_spm_busy_wait();
-    3f30:	07 b6       	in	r0, 0x37	; 55
-    3f32:	00 fc       	sbrc	r0, 0
-    3f34:	fd cf       	rjmp	.-6      	; 0x3f30 <main+0x130>
+    3f18:	07 b6       	in	r0, 0x37	; 55
+    3f1a:	00 fc       	sbrc	r0, 0
+    3f1c:	fd cf       	rjmp	.-6      	; 0x3f18 <main+0x118>
 
       // Reenable read access to flash
       boot_rww_enable();
-    3f36:	f0 92 57 00 	sts	0x0057, r15
-    3f3a:	e8 95       	spm
-    3f3c:	27 c0       	rjmp	.+78     	; 0x3f8c <main+0x18c>
+    3f1e:	f0 92 57 00 	sts	0x0057, r15
+    3f22:	e8 95       	spm
+    3f24:	27 c0       	rjmp	.+78     	; 0x3f74 <main+0x174>
     }
     /* Read memory block mode, length is big endian.  */
     else if(ch == STK_READ_PAGE) {
-    3f3e:	84 37       	cpi	r24, 0x74	; 116
-    3f40:	b9 f4       	brne	.+46     	; 0x3f70 <main+0x170>
+    3f26:	84 37       	cpi	r24, 0x74	; 116
+    3f28:	b9 f4       	brne	.+46     	; 0x3f58 <main+0x158>
       // READ PAGE - we only read flash
       getLen();
-    3f42:	48 d0       	rcall	.+144    	; 0x3fd4 <getLen>
+    3f2a:	4a d0       	rcall	.+148    	; 0x3fc0 <getLen>
       verifySpace();
-    3f44:	4c d0       	rcall	.+152    	; 0x3fde <verifySpace>
+    3f2c:	59 d0       	rcall	.+178    	; 0x3fe0 <verifySpace>
       do putch(pgm_read_byte_near(address++));
-    3f46:	e0 91 00 02 	lds	r30, 0x0200
-    3f4a:	f0 91 01 02 	lds	r31, 0x0201
-    3f4e:	31 96       	adiw	r30, 0x01	; 1
-    3f50:	f0 93 01 02 	sts	0x0201, r31
-    3f54:	e0 93 00 02 	sts	0x0200, r30
-    3f58:	31 97       	sbiw	r30, 0x01	; 1
-    3f5a:	e4 91       	lpm	r30, Z+
-    3f5c:	8e 2f       	mov	r24, r30
-    3f5e:	19 d0       	rcall	.+50     	; 0x3f92 <putch>
+    3f2e:	e0 91 00 02 	lds	r30, 0x0200
+    3f32:	f0 91 01 02 	lds	r31, 0x0201
+    3f36:	31 96       	adiw	r30, 0x01	; 1
+    3f38:	f0 93 01 02 	sts	0x0201, r31
+    3f3c:	e0 93 00 02 	sts	0x0200, r30
+    3f40:	31 97       	sbiw	r30, 0x01	; 1
+    3f42:	e4 91       	lpm	r30, Z+
+    3f44:	8e 2f       	mov	r24, r30
+    3f46:	19 d0       	rcall	.+50     	; 0x3f7a <putch>
       while (--length);
-    3f60:	80 91 02 02 	lds	r24, 0x0202
-    3f64:	81 50       	subi	r24, 0x01	; 1
-    3f66:	80 93 02 02 	sts	0x0202, r24
-    3f6a:	88 23       	and	r24, r24
-    3f6c:	61 f7       	brne	.-40     	; 0x3f46 <main+0x146>
-    3f6e:	0e c0       	rjmp	.+28     	; 0x3f8c <main+0x18c>
+    3f48:	80 91 02 02 	lds	r24, 0x0202
+    3f4c:	81 50       	subi	r24, 0x01	; 1
+    3f4e:	80 93 02 02 	sts	0x0202, r24
+    3f52:	88 23       	and	r24, r24
+    3f54:	61 f7       	brne	.-40     	; 0x3f2e <main+0x12e>
+    3f56:	0e c0       	rjmp	.+28     	; 0x3f74 <main+0x174>
     }
 
     /* Get device signature bytes  */
     else if(ch == STK_READ_SIGN) {
-    3f70:	85 37       	cpi	r24, 0x75	; 117
-    3f72:	39 f4       	brne	.+14     	; 0x3f82 <main+0x182>
+    3f58:	85 37       	cpi	r24, 0x75	; 117
+    3f5a:	39 f4       	brne	.+14     	; 0x3f6a <main+0x16a>
       // READ SIGN - return what Avrdude wants to hear
       verifySpace();
-    3f74:	34 d0       	rcall	.+104    	; 0x3fde <verifySpace>
+    3f5c:	41 d0       	rcall	.+130    	; 0x3fe0 <verifySpace>
       putch(SIGNATURE_0);
-    3f76:	8e e1       	ldi	r24, 0x1E	; 30
-    3f78:	0c d0       	rcall	.+24     	; 0x3f92 <putch>
+    3f5e:	8e e1       	ldi	r24, 0x1E	; 30
+    3f60:	0c d0       	rcall	.+24     	; 0x3f7a <putch>
       putch(SIGNATURE_1);
-    3f7a:	84 e9       	ldi	r24, 0x94	; 148
-    3f7c:	0a d0       	rcall	.+20     	; 0x3f92 <putch>
+    3f62:	84 e9       	ldi	r24, 0x94	; 148
+    3f64:	0a d0       	rcall	.+20     	; 0x3f7a <putch>
       putch(SIGNATURE_2);
-    3f7e:	86 e0       	ldi	r24, 0x06	; 6
-    3f80:	93 cf       	rjmp	.-218    	; 0x3ea8 <main+0xa8>
+    3f66:	86 e0       	ldi	r24, 0x06	; 6
+    3f68:	96 cf       	rjmp	.-212    	; 0x3e96 <main+0x96>
     }
     else if (ch == 'Q') {
-    3f82:	81 35       	cpi	r24, 0x51	; 81
-    3f84:	11 f4       	brne	.+4      	; 0x3f8a <main+0x18a>
+    3f6a:	81 35       	cpi	r24, 0x51	; 81
+    3f6c:	11 f4       	brne	.+4      	; 0x3f72 <main+0x172>
       // Adaboot no-wait mod
-      WDTCSR = _BV(WDE);
-    3f86:	c0 92 60 00 	sts	0x0060, r12
+      watchdogConfig(_BV(WDE));
+    3f6e:	88 e0       	ldi	r24, 0x08	; 8
+    3f70:	2c d0       	rcall	.+88     	; 0x3fca <watchdogConfig>
       verifySpace();
     }
     else {
       // This covers the response to commands like STK_ENTER_PROGMODE
       verifySpace();
-    3f8a:	29 d0       	rcall	.+82     	; 0x3fde <verifySpace>
+    3f72:	36 d0       	rcall	.+108    	; 0x3fe0 <verifySpace>
     }
     putch(STK_OK);
-    3f8c:	80 e1       	ldi	r24, 0x10	; 16
-    3f8e:	01 d0       	rcall	.+2      	; 0x3f92 <putch>
-    3f90:	60 cf       	rjmp	.-320    	; 0x3e52 <main+0x52>
-
-00003f92 <putch>:
-  }
-}
+    3f74:	80 e1       	ldi	r24, 0x10	; 16
+    3f76:	01 d0       	rcall	.+2      	; 0x3f7a <putch>
+    3f78:	63 cf       	rjmp	.-314    	; 0x3e40 <main+0x40>
 
+00003f7a <putch>:
 void putch(char ch) {
-    3f92:	98 2f       	mov	r25, r24
+#ifndef SOFT_UART
   while (!(UCSR0A & _BV(UDRE0)));
-    3f94:	80 91 c0 00 	lds	r24, 0x00C0
-    3f98:	85 ff       	sbrs	r24, 5
-    3f9a:	fc cf       	rjmp	.-8      	; 0x3f94 <putch+0x2>
   UDR0 = ch;
-    3f9c:	90 93 c6 00 	sts	0x00C6, r25
-}
-    3fa0:	08 95       	ret
-
-00003fa2 <setTimer>:
-
-void setTimer(uint16_t counts) {
-  TCNT1 = counts;
-    3fa2:	90 93 85 00 	sts	0x0085, r25
-    3fa6:	80 93 84 00 	sts	0x0084, r24
-  TIFR1 = _BV(TOV1);
-    3faa:	81 e0       	ldi	r24, 0x01	; 1
-    3fac:	86 bb       	out	0x16, r24	; 22
+#else
+  __asm__ __volatile__ (
+    3f7a:	2a e0       	ldi	r18, 0x0A	; 10
+    3f7c:	30 e0       	ldi	r19, 0x00	; 0
+    3f7e:	80 95       	com	r24
+    3f80:	08 94       	sec
+    3f82:	10 f4       	brcc	.+4      	; 0x3f88 <putch+0xe>
+    3f84:	59 98       	cbi	0x0b, 1	; 11
+    3f86:	02 c0       	rjmp	.+4      	; 0x3f8c <putch+0x12>
+    3f88:	59 9a       	sbi	0x0b, 1	; 11
+    3f8a:	00 00       	nop
+    3f8c:	15 d0       	rcall	.+42     	; 0x3fb8 <uartDelay>
+    3f8e:	14 d0       	rcall	.+40     	; 0x3fb8 <uartDelay>
+    3f90:	86 95       	lsr	r24
+    3f92:	2a 95       	dec	r18
+    3f94:	b1 f7       	brne	.-20     	; 0x3f82 <putch+0x8>
+      [uartBit] "I" (UART_TX_BIT)
+    :
+      "r25"
+  );
+#endif
 }
-    3fae:	08 95       	ret
+    3f96:	08 95       	ret
 
-00003fb0 <appStart>:
-  length = getch();
+00003f98 <getch>:
   return getch();
 }
 
-void appStart() {
+// Watchdog functions. These are only safe with interrupts turned off.
+void watchdogReset() {
   __asm__ __volatile__ (
-    3fb0:	ee 27       	eor	r30, r30
-    3fb2:	ff 27       	eor	r31, r31
-    3fb4:	09 94       	ijmp
+    3f98:	a8 95       	wdr
+#ifdef LED_DATA_FLASH
+  LED_PIN |= _BV(LED);
+#endif
 
-00003fb6 <getch>:
-  TCNT1 = counts;
-  TIFR1 = _BV(TOV1);
+  return ch;
 }
+    3f9a:	29 e0       	ldi	r18, 0x09	; 9
+    3f9c:	30 e0       	ldi	r19, 0x00	; 0
+    3f9e:	48 99       	sbic	0x09, 0	; 9
+    3fa0:	fe cf       	rjmp	.-4      	; 0x3f9e <getch+0x6>
+    3fa2:	0a d0       	rcall	.+20     	; 0x3fb8 <uartDelay>
+    3fa4:	09 d0       	rcall	.+18     	; 0x3fb8 <uartDelay>
+    3fa6:	08 d0       	rcall	.+16     	; 0x3fb8 <uartDelay>
+    3fa8:	88 94       	clc
+    3faa:	48 99       	sbic	0x09, 0	; 9
+    3fac:	08 94       	sec
+    3fae:	2a 95       	dec	r18
+    3fb0:	11 f0       	breq	.+4      	; 0x3fb6 <getch+0x1e>
+    3fb2:	87 95       	ror	r24
+    3fb4:	f7 cf       	rjmp	.-18     	; 0x3fa4 <getch+0xc>
+    3fb6:	08 95       	ret
+
+00003fb8 <uartDelay>:
+#if UART_B_VALUE > 255
+#error Baud rate too slow for soft UART
+#endif
 
-uint8_t getch(void) {
-  LED_PORT &= ~_BV(LED);
-    3fb6:	2d 98       	cbi	0x05, 5	; 5
-  setTimer(-(F_CPU/(1024*2))); // 500ms
-    3fb8:	8c e7       	ldi	r24, 0x7C	; 124
-    3fba:	91 ee       	ldi	r25, 0xE1	; 225
-    3fbc:	f2 df       	rcall	.-28     	; 0x3fa2 <setTimer>
-    3fbe:	02 c0       	rjmp	.+4      	; 0x3fc4 <getch+0xe>
-  while(!(UCSR0A & _BV(RXC0))) if (TIFR1 & _BV(TOV1)) appStart();
-    3fc0:	b0 99       	sbic	0x16, 0	; 22
-    3fc2:	f6 df       	rcall	.-20     	; 0x3fb0 <appStart>
-    3fc4:	80 91 c0 00 	lds	r24, 0x00C0
-    3fc8:	87 ff       	sbrs	r24, 7
-    3fca:	fa cf       	rjmp	.-12     	; 0x3fc0 <getch+0xa>
-  LED_PORT |= _BV(LED);
-    3fcc:	2d 9a       	sbi	0x05, 5	; 5
-  return UDR0;
-    3fce:	80 91 c6 00 	lds	r24, 0x00C6
-}
-    3fd2:	08 95       	ret
+void uartDelay() {
+  __asm__ __volatile__ (
+    3fb8:	98 e0       	ldi	r25, 0x08	; 8
+    3fba:	9a 95       	dec	r25
+    3fbc:	f1 f7       	brne	.-4      	; 0x3fba <uartDelay+0x2>
+    3fbe:	08 95       	ret
 
-00003fd4 <getLen>:
-    LED_PIN |= _BV(LED);
+00003fc0 <getLen>:
   } while (--count);
 }
+#endif
 
 uint8_t getLen() {
   getch();
-    3fd4:	f0 df       	rcall	.-32     	; 0x3fb6 <getch>
+    3fc0:	eb df       	rcall	.-42     	; 0x3f98 <getch>
   length = getch();
-    3fd6:	ef df       	rcall	.-34     	; 0x3fb6 <getch>
-    3fd8:	80 93 02 02 	sts	0x0202, r24
+    3fc2:	ea df       	rcall	.-44     	; 0x3f98 <getch>
+    3fc4:	80 93 02 02 	sts	0x0202, r24
   return getch();
 }
-    3fdc:	ec cf       	rjmp	.-40     	; 0x3fb6 <getch>
+    3fc8:	e7 cf       	rjmp	.-50     	; 0x3f98 <getch>
+
+00003fca <watchdogConfig>:
+    "wdr\n"
+  );
+}
 
-00003fde <verifySpace>:
+void watchdogConfig(uint8_t x) {
+  WDTCSR = _BV(WDCE) | _BV(WDE);
+    3fca:	e0 e6       	ldi	r30, 0x60	; 96
+    3fcc:	f0 e0       	ldi	r31, 0x00	; 0
+    3fce:	98 e1       	ldi	r25, 0x18	; 24
+    3fd0:	90 83       	st	Z, r25
+  WDTCSR = x;
+    3fd2:	80 83       	st	Z, r24
+}
+    3fd4:	08 95       	ret
+
+00003fd6 <appStart>:
+
+void appStart() {
+  watchdogConfig(0);
+    3fd6:	80 e0       	ldi	r24, 0x00	; 0
+    3fd8:	f8 df       	rcall	.-16     	; 0x3fca <watchdogConfig>
+  __asm__ __volatile__ (
+    3fda:	ee 27       	eor	r30, r30
+    3fdc:	ff 27       	eor	r31, r31
+    3fde:	09 94       	ijmp
+
+00003fe0 <verifySpace>:
   do getch(); while (--count);
   verifySpace();
 }
 
 void verifySpace() {
   if (getch() != CRC_EOP) appStart();
-    3fde:	eb df       	rcall	.-42     	; 0x3fb6 <getch>
-    3fe0:	80 32       	cpi	r24, 0x20	; 32
-    3fe2:	09 f0       	breq	.+2      	; 0x3fe6 <verifySpace+0x8>
-    3fe4:	e5 df       	rcall	.-54     	; 0x3fb0 <appStart>
+    3fe0:	db df       	rcall	.-74     	; 0x3f98 <getch>
+    3fe2:	80 32       	cpi	r24, 0x20	; 32
+    3fe4:	09 f0       	breq	.+2      	; 0x3fe8 <verifySpace+0x8>
+    3fe6:	f7 df       	rcall	.-18     	; 0x3fd6 <appStart>
   putch(STK_INSYNC);
-    3fe6:	84 e1       	ldi	r24, 0x14	; 20
+    3fe8:	84 e1       	ldi	r24, 0x14	; 20
 }
-    3fe8:	d4 cf       	rjmp	.-88     	; 0x3f92 <putch>
-  while(!(UCSR0A & _BV(RXC0))) if (TIFR1 & _BV(TOV1)) appStart();
-  LED_PORT |= _BV(LED);
-  return UDR0;
+    3fea:	c7 cf       	rjmp	.-114    	; 0x3f7a <putch>
+    ::[count] "M" (UART_B_VALUE)
+  );
 }
+#endif
 
 void getNch(uint8_t count) {
-    3fea:	1f 93       	push	r17
-    3fec:	18 2f       	mov	r17, r24
+    3fec:	1f 93       	push	r17
+    3fee:	18 2f       	mov	r17, r24
 
-00003fee <getNch>:
+00003ff0 <getNch>:
   do getch(); while (--count);
-    3fee:	e3 df       	rcall	.-58     	; 0x3fb6 <getch>
-    3ff0:	11 50       	subi	r17, 0x01	; 1
-    3ff2:	e9 f7       	brne	.-6      	; 0x3fee <getNch>
+    3ff0:	d3 df       	rcall	.-90     	; 0x3f98 <getch>
+    3ff2:	11 50       	subi	r17, 0x01	; 1
+    3ff4:	e9 f7       	brne	.-6      	; 0x3ff0 <getNch>
   verifySpace();
-    3ff4:	f4 df       	rcall	.-24     	; 0x3fde <verifySpace>
+    3ff6:	f4 df       	rcall	.-24     	; 0x3fe0 <verifySpace>
 }
-    3ff6:	1f 91       	pop	r17
-    3ff8:	08 95       	ret
+    3ff8:	1f 91       	pop	r17
+    3ffa:	08 95       	ret

+ 32 - 32
optiboot/bootloaders/optiboot/optiboot_pro_16MHz.hex

@@ -1,34 +1,34 @@
-:103E000085E08093810082E08093C00098E19093E8
-:103E1000C10086E08093C20087E68093C40084B727
-:103E200014BE909360001092600081FFC1D0259A6B
-:103E300002E080E39CEFB5D0B09BFECF1D9A01500D
-:103E4000C1F7DD24D394B8E0CB2EA5E0EA2EF1E152
-:103E5000FF2EB1D0813421F481E0C7D083E024C0AB
-:103E6000823411F484E103C0853419F485E0BDD0B7
-:103E70008DC08535A1F49FD0082F10E0109301026A
-:103E80000093000298D090E0982F8827802B912BE8
-:103E9000880F991F909301028093000276C08635A7
-:103EA00029F484E0A2D080E074D070C0843609F098
-:103EB00046C090D0863409F07BD0E0910002F091AA
-:103EC000010283E080935700E895C0E0D1E073D011
-:103ED0008993809102028150809302028823B9F76E
-:103EE00007B600FCFDCF7BD040910002509101024B
-:103EF000A0E0B1E02C9130E011968C91119790E008
-:103F0000982F8827822B932B1296FA010C01D092BE
-:103F10005700E89511244E5F5F4FF1E0A038BF07CE
-:103F200049F7E0910002F0910102E0925700E89514
-:103F300007B600FCFDCFF0925700E89527C0843704
-:103F4000B9F448D04CD0E0910002F09101023196D2
-:103F5000F0930102E09300023197E4918E2F19D083
-:103F600080910202815080930202882361F70EC083
-:103F7000853739F434D08EE10CD084E90AD086E05C
-:103F800093CF813511F4C092600029D080E101D037
-:103F900060CF982F8091C00085FFFCCF9093C60022
-:103FA0000895909385008093840081E086BB0895F6
-:103FB000EE27FF2709942D988CE791EEF2DF02C0DF
-:103FC000B099F6DF8091C00087FFFACF2D9A8091DB
-:103FD000C6000895F0DFEFDF80930202ECCFEBDF45
-:103FE000803209F0E5DF84E1D4CF1F93182FE3DF9F
-:0A3FF0001150E9F7F4DF1F91089566
+:103E000085E08093810084B714BE81FFE4D08DE00B
+:103E1000DCD0259A519A86E020E33CEF91E0309384
+:103E200085002093840096BBB09BFECF1D9AA89579
+:103E30008150A9F7DD24D394A5E0EA2EF1E1FF2E0D
+:103E4000ABD0813421F481E0D1D083E024C082342E
+:103E500011F484E103C0853419F485E0C7D08AC029
+:103E60008535A1F499D0082F10E01093010200933A
+:103E7000000292D090E0982F8827802B912B880FFA
+:103E8000991F909301028093000273C0863529F434
+:103E900084E0ACD080E071D06DC0843609F043C0BE
+:103EA0008FD0E0910002F091010283E080935700EF
+:103EB000E895C0E0D1E070D08993809102028150F2
+:103EC000809302028823B9F78BD007B600FCFDCFA0
+:103ED0004091000250910102A0E0B1E02C9130E04D
+:103EE00011968C91119790E0982F8827822B932B15
+:103EF0001296FA010C01D0925700E89511244E5FFA
+:103F00005F4FF1E0A038BF0749F7E0910002F09160
+:103F10000102E0925700E89507B600FCFDCFF09251
+:103F20005700E89527C08437B9F44AD059D0E091BA
+:103F30000002F09101023196F0930102E093000239
+:103F40003197E4918E2F19D0809102028150809395
+:103F50000202882361F70EC0853739F441D08EE123
+:103F60000CD084E90AD086E096CF813511F488E040
+:103F70002CD036D080E101D063CF2AE030E08095AC
+:103F8000089410F4599802C0599A000015D014D022
+:103F900086952A95B1F70895A89529E030E04899CB
+:103FA000FECF0AD009D008D08894489908942A9561
+:103FB00011F08795F7CF089598E09A95F1F7089555
+:103FC000EBDFEADF80930202E7CFE0E6F0E098E182
+:103FD00090838083089580E0F8DFEE27FF2709941F
+:103FE000DBDF803209F0F7DF84E1C7CF1F93182FA2
+:0C3FF000D3DF1150E9F7F4DF1F910895B2
 :0400000300003E00BB
 :00000001FF

+ 320 - 282
optiboot/bootloaders/optiboot/optiboot_pro_16MHz.lst

@@ -3,25 +3,25 @@ optiboot_pro_16MHz.elf:     file format elf32-avr
 
 Sections:
 Idx Name          Size      VMA       LMA       File off  Algn
-  0 .text         000001fa  00003e00  00003e00  00000054  2**1
+  0 .text         000001fc  00003e00  00003e00  00000054  2**1
                   CONTENTS, ALLOC, LOAD, READONLY, CODE
-  1 .debug_aranges 00000028  00000000  00000000  0000024e  2**0
+  1 .debug_aranges 00000028  00000000  00000000  00000250  2**0
                   CONTENTS, READONLY, DEBUGGING
-  2 .debug_pubnames 00000064  00000000  00000000  00000276  2**0
+  2 .debug_pubnames 00000078  00000000  00000000  00000278  2**0
                   CONTENTS, READONLY, DEBUGGING
-  3 .debug_info   0000022f  00000000  00000000  000002da  2**0
+  3 .debug_info   00000275  00000000  00000000  000002f0  2**0
                   CONTENTS, READONLY, DEBUGGING
-  4 .debug_abbrev 00000164  00000000  00000000  00000509  2**0
+  4 .debug_abbrev 000001a3  00000000  00000000  00000565  2**0
                   CONTENTS, READONLY, DEBUGGING
-  5 .debug_line   000003c8  00000000  00000000  0000066d  2**0
+  5 .debug_line   000003b8  00000000  00000000  00000708  2**0
                   CONTENTS, READONLY, DEBUGGING
-  6 .debug_frame  00000090  00000000  00000000  00000a38  2**2
+  6 .debug_frame  000000a0  00000000  00000000  00000ac0  2**2
                   CONTENTS, READONLY, DEBUGGING
-  7 .debug_str    0000011c  00000000  00000000  00000ac8  2**0
+  7 .debug_str    00000133  00000000  00000000  00000b60  2**0
                   CONTENTS, READONLY, DEBUGGING
-  8 .debug_loc    000001d6  00000000  00000000  00000be4  2**0
+  8 .debug_loc    000001a0  00000000  00000000  00000c93  2**0
                   CONTENTS, READONLY, DEBUGGING
-  9 .debug_ranges 00000068  00000000  00000000  00000dba  2**0
+  9 .debug_ranges 00000070  00000000  00000000  00000e33  2**0
                   CONTENTS, READONLY, DEBUGGING
 
 Disassembly of section .text:
@@ -35,449 +35,487 @@ Disassembly of section .text:
 int main(void) {
     3e00:	85 e0       	ldi	r24, 0x05	; 5
     3e02:	80 93 81 00 	sts	0x0081, r24
-    [addr5]"i"(_SFR_MEM_ADDR(UBRR0L)), [val5]"i"((F_CPU + BAUD_RATE * 4L) / (BAUD_RATE * 8L) - 1)
-  );
-#else
-  // Set up Timer 1 for timeout counter
-  TCCR1B = _BV(CS12) | _BV(CS10); // div 1024
-  UCSR0A = _BV(U2X0); //Double speed mode USART0
-    3e06:	82 e0       	ldi	r24, 0x02	; 2
-    3e08:	80 93 c0 00 	sts	0x00C0, r24
-  UCSR0B = _BV(RXEN0) | _BV(TXEN0);
-    3e0c:	98 e1       	ldi	r25, 0x18	; 24
-    3e0e:	90 93 c1 00 	sts	0x00C1, r25
   UCSR0C = _BV(UCSZ00) | _BV(UCSZ01);
-    3e12:	86 e0       	ldi	r24, 0x06	; 6
-    3e14:	80 93 c2 00 	sts	0x00C2, r24
   UBRR0L = (uint8_t)( (F_CPU + BAUD_RATE * 4L) / (BAUD_RATE * 8L) - 1 );
-    3e18:	87 e6       	ldi	r24, 0x67	; 103
-    3e1a:	80 93 c4 00 	sts	0x00C4, r24
 #endif
 
   // Adaboot no-wait mod
   ch = MCUSR;
-    3e1e:	84 b7       	in	r24, 0x34	; 52
+    3e06:	84 b7       	in	r24, 0x34	; 52
   MCUSR = 0;
-    3e20:	14 be       	out	0x34, r1	; 52
-  WDTCSR = _BV(WDCE) | _BV(WDE);
-    3e22:	90 93 60 00 	sts	0x0060, r25
-  WDTCSR = 0;
-    3e26:	10 92 60 00 	sts	0x0060, r1
+    3e08:	14 be       	out	0x34, r1	; 52
   if (!(ch & _BV(EXTRF))) appStart();
-    3e2a:	81 ff       	sbrs	r24, 1
-    3e2c:	c1 d0       	rcall	.+386    	; 0x3fb0 <appStart>
+    3e0a:	81 ff       	sbrs	r24, 1
+    3e0c:	e4 d0       	rcall	.+456    	; 0x3fd6 <appStart>
+
+  // Set up watchdog to trigger after 500ms
+  watchdogConfig(_BV(WDP2)|_BV(WDP0)|_BV(WDE));
+    3e0e:	8d e0       	ldi	r24, 0x0D	; 13
+    3e10:	dc d0       	rcall	.+440    	; 0x3fca <watchdogConfig>
 
-  /* set LED pin as output */
+  /* Set LED pin as output */
   LED_DDR |= _BV(LED);
-    3e2e:	25 9a       	sbi	0x04, 5	; 4
-    3e30:	02 e0       	ldi	r16, 0x02	; 2
-  putch(STK_INSYNC);
+    3e12:	25 9a       	sbi	0x04, 5	; 4
+
+#ifdef SOFT_UART
+  /* Set TX pin as output */
+  UART_DDR |= _BV(UART_TX_BIT);
+    3e14:	51 9a       	sbi	0x0a, 1	; 10
+    3e16:	86 e0       	ldi	r24, 0x06	; 6
+}
+
+#if LED_START_FLASHES > 0
+void flash_led(uint8_t count) {
+  do {
+    TCNT1 = -(F_CPU/(1024*16));
+    3e18:	20 e3       	ldi	r18, 0x30	; 48
+    3e1a:	3c ef       	ldi	r19, 0xFC	; 252
+    TIFR1 = _BV(TOV1);
+    3e1c:	91 e0       	ldi	r25, 0x01	; 1
 }
 
+#if LED_START_FLASHES > 0
 void flash_led(uint8_t count) {
   do {
-    setTimer(-(F_CPU/(1024*16))); // 62ms
-    3e32:	80 e3       	ldi	r24, 0x30	; 48
-    3e34:	9c ef       	ldi	r25, 0xFC	; 252
-    3e36:	b5 d0       	rcall	.+362    	; 0x3fa2 <setTimer>
+    TCNT1 = -(F_CPU/(1024*16));
+    3e1e:	30 93 85 00 	sts	0x0085, r19
+    3e22:	20 93 84 00 	sts	0x0084, r18
+    TIFR1 = _BV(TOV1);
+    3e26:	96 bb       	out	0x16, r25	; 22
+    while(!(TIFR1 & _BV(TOV1)));
+    3e28:	b0 9b       	sbis	0x16, 0	; 22
+    3e2a:	fe cf       	rjmp	.-4      	; 0x3e28 <main+0x28>
+    LED_PIN |= _BV(LED);
+    3e2c:	1d 9a       	sbi	0x03, 5	; 3
+  return getch();
+}
+
+// Watchdog functions. These are only safe with interrupts turned off.
+void watchdogReset() {
+  __asm__ __volatile__ (
+    3e2e:	a8 95       	wdr
+    TCNT1 = -(F_CPU/(1024*16));
+    TIFR1 = _BV(TOV1);
     while(!(TIFR1 & _BV(TOV1)));
-    3e38:	b0 9b       	sbis	0x16, 0	; 22
-    3e3a:	fe cf       	rjmp	.-4      	; 0x3e38 <main+0x38>
     LED_PIN |= _BV(LED);
-    3e3c:	1d 9a       	sbi	0x03, 5	; 3
+    watchdogReset();
   } while (--count);
-    3e3e:	01 50       	subi	r16, 0x01	; 1
-    3e40:	c1 f7       	brne	.-16     	; 0x3e32 <main+0x32>
+    3e30:	81 50       	subi	r24, 0x01	; 1
+    3e32:	a9 f7       	brne	.-22     	; 0x3e1e <main+0x1e>
     /* get character from UART */
     ch = getch();
 
     if(ch == STK_GET_PARAMETER) {
       // GET PARAMETER returns a generic 0x03 reply - enough to keep Avrdude happy
       getNch(1);
-    3e42:	dd 24       	eor	r13, r13
-    3e44:	d3 94       	inc	r13
-      putch(SIGNATURE_1);
-      putch(SIGNATURE_2);
-    }
-    else if (ch == 'Q') {
-      // Adaboot no-wait mod
-      WDTCSR = _BV(WDE);
-    3e46:	b8 e0       	ldi	r27, 0x08	; 8
-    3e48:	cb 2e       	mov	r12, r27
+    3e34:	dd 24       	eor	r13, r13
+    3e36:	d3 94       	inc	r13
         boot_page_fill((uint16_t)(void*)addrPtr,a);
         addrPtr += 2;
       } while (--ch);
       
       // Write from programming buffer
       boot_page_write((uint16_t)(void*)address);
-    3e4a:	a5 e0       	ldi	r26, 0x05	; 5
-    3e4c:	ea 2e       	mov	r14, r26
+    3e38:	a5 e0       	ldi	r26, 0x05	; 5
+    3e3a:	ea 2e       	mov	r14, r26
       boot_spm_busy_wait();
 
       // Reenable read access to flash
       boot_rww_enable();
-    3e4e:	f1 e1       	ldi	r31, 0x11	; 17
-    3e50:	ff 2e       	mov	r15, r31
-  flash_led(NUM_LED_FLASHES * 2);
+    3e3c:	f1 e1       	ldi	r31, 0x11	; 17
+    3e3e:	ff 2e       	mov	r15, r31
+#endif
 
-  /* forever loop */
+  /* Forever loop */
   for (;;) {
     /* get character from UART */
     ch = getch();
-    3e52:	b1 d0       	rcall	.+354    	; 0x3fb6 <getch>
+    3e40:	ab d0       	rcall	.+342    	; 0x3f98 <getch>
 
     if(ch == STK_GET_PARAMETER) {
-    3e54:	81 34       	cpi	r24, 0x41	; 65
-    3e56:	21 f4       	brne	.+8      	; 0x3e60 <main+0x60>
+    3e42:	81 34       	cpi	r24, 0x41	; 65
+    3e44:	21 f4       	brne	.+8      	; 0x3e4e <main+0x4e>
       // GET PARAMETER returns a generic 0x03 reply - enough to keep Avrdude happy
       getNch(1);
-    3e58:	81 e0       	ldi	r24, 0x01	; 1
-    3e5a:	c7 d0       	rcall	.+398    	; 0x3fea <verifySpace+0xc>
+    3e46:	81 e0       	ldi	r24, 0x01	; 1
+    3e48:	d1 d0       	rcall	.+418    	; 0x3fec <verifySpace+0xc>
       putch(0x03);
-    3e5c:	83 e0       	ldi	r24, 0x03	; 3
-    3e5e:	24 c0       	rjmp	.+72     	; 0x3ea8 <main+0xa8>
+    3e4a:	83 e0       	ldi	r24, 0x03	; 3
+    3e4c:	24 c0       	rjmp	.+72     	; 0x3e96 <main+0x96>
     }
     else if(ch == STK_SET_DEVICE) {
-    3e60:	82 34       	cpi	r24, 0x42	; 66
-    3e62:	11 f4       	brne	.+4      	; 0x3e68 <main+0x68>
+    3e4e:	82 34       	cpi	r24, 0x42	; 66
+    3e50:	11 f4       	brne	.+4      	; 0x3e56 <main+0x56>
       // SET DEVICE is ignored
       getNch(20);
-    3e64:	84 e1       	ldi	r24, 0x14	; 20
-    3e66:	03 c0       	rjmp	.+6      	; 0x3e6e <main+0x6e>
+    3e52:	84 e1       	ldi	r24, 0x14	; 20
+    3e54:	03 c0       	rjmp	.+6      	; 0x3e5c <main+0x5c>
     }
     else if(ch == STK_SET_DEVICE_EXT) {
-    3e68:	85 34       	cpi	r24, 0x45	; 69
-    3e6a:	19 f4       	brne	.+6      	; 0x3e72 <main+0x72>
+    3e56:	85 34       	cpi	r24, 0x45	; 69
+    3e58:	19 f4       	brne	.+6      	; 0x3e60 <main+0x60>
       // SET DEVICE EXT is ignored
       getNch(5);
-    3e6c:	85 e0       	ldi	r24, 0x05	; 5
-    3e6e:	bd d0       	rcall	.+378    	; 0x3fea <verifySpace+0xc>
-    3e70:	8d c0       	rjmp	.+282    	; 0x3f8c <main+0x18c>
+    3e5a:	85 e0       	ldi	r24, 0x05	; 5
+    3e5c:	c7 d0       	rcall	.+398    	; 0x3fec <verifySpace+0xc>
+    3e5e:	8a c0       	rjmp	.+276    	; 0x3f74 <main+0x174>
     }
     else if(ch == STK_LOAD_ADDRESS) {
-    3e72:	85 35       	cpi	r24, 0x55	; 85
-    3e74:	a1 f4       	brne	.+40     	; 0x3e9e <main+0x9e>
+    3e60:	85 35       	cpi	r24, 0x55	; 85
+    3e62:	a1 f4       	brne	.+40     	; 0x3e8c <main+0x8c>
       // LOAD ADDRESS
       address = getch();
-    3e76:	9f d0       	rcall	.+318    	; 0x3fb6 <getch>
-    3e78:	08 2f       	mov	r16, r24
-    3e7a:	10 e0       	ldi	r17, 0x00	; 0
-    3e7c:	10 93 01 02 	sts	0x0201, r17
-    3e80:	00 93 00 02 	sts	0x0200, r16
+    3e64:	99 d0       	rcall	.+306    	; 0x3f98 <getch>
+    3e66:	08 2f       	mov	r16, r24
+    3e68:	10 e0       	ldi	r17, 0x00	; 0
+    3e6a:	10 93 01 02 	sts	0x0201, r17
+    3e6e:	00 93 00 02 	sts	0x0200, r16
       address = (address & 0xff) | (getch() << 8);
-    3e84:	98 d0       	rcall	.+304    	; 0x3fb6 <getch>
-    3e86:	90 e0       	ldi	r25, 0x00	; 0
-    3e88:	98 2f       	mov	r25, r24
-    3e8a:	88 27       	eor	r24, r24
-    3e8c:	80 2b       	or	r24, r16
-    3e8e:	91 2b       	or	r25, r17
+    3e72:	92 d0       	rcall	.+292    	; 0x3f98 <getch>
+    3e74:	90 e0       	ldi	r25, 0x00	; 0
+    3e76:	98 2f       	mov	r25, r24
+    3e78:	88 27       	eor	r24, r24
+    3e7a:	80 2b       	or	r24, r16
+    3e7c:	91 2b       	or	r25, r17
       address += address; // Convert from word address to byte address
-    3e90:	88 0f       	add	r24, r24
-    3e92:	99 1f       	adc	r25, r25
-    3e94:	90 93 01 02 	sts	0x0201, r25
-    3e98:	80 93 00 02 	sts	0x0200, r24
-    3e9c:	76 c0       	rjmp	.+236    	; 0x3f8a <main+0x18a>
+    3e7e:	88 0f       	add	r24, r24
+    3e80:	99 1f       	adc	r25, r25
+    3e82:	90 93 01 02 	sts	0x0201, r25
+    3e86:	80 93 00 02 	sts	0x0200, r24
+    3e8a:	73 c0       	rjmp	.+230    	; 0x3f72 <main+0x172>
       verifySpace();
     }
     else if(ch == STK_UNIVERSAL) {
-    3e9e:	86 35       	cpi	r24, 0x56	; 86
-    3ea0:	29 f4       	brne	.+10     	; 0x3eac <main+0xac>
+    3e8c:	86 35       	cpi	r24, 0x56	; 86
+    3e8e:	29 f4       	brne	.+10     	; 0x3e9a <main+0x9a>
       // UNIVERSAL command is ignored
       getNch(4);
-    3ea2:	84 e0       	ldi	r24, 0x04	; 4
-    3ea4:	a2 d0       	rcall	.+324    	; 0x3fea <verifySpace+0xc>
+    3e90:	84 e0       	ldi	r24, 0x04	; 4
+    3e92:	ac d0       	rcall	.+344    	; 0x3fec <verifySpace+0xc>
       putch(0x00);
-    3ea6:	80 e0       	ldi	r24, 0x00	; 0
-    3ea8:	74 d0       	rcall	.+232    	; 0x3f92 <putch>
-    3eaa:	70 c0       	rjmp	.+224    	; 0x3f8c <main+0x18c>
+    3e94:	80 e0       	ldi	r24, 0x00	; 0
+    3e96:	71 d0       	rcall	.+226    	; 0x3f7a <putch>
+    3e98:	6d c0       	rjmp	.+218    	; 0x3f74 <main+0x174>
     }
     /* Write memory, length is big endian and is in bytes  */
     else if(ch == STK_PROG_PAGE) {
-    3eac:	84 36       	cpi	r24, 0x64	; 100
-    3eae:	09 f0       	breq	.+2      	; 0x3eb2 <main+0xb2>
-    3eb0:	46 c0       	rjmp	.+140    	; 0x3f3e <main+0x13e>
+    3e9a:	84 36       	cpi	r24, 0x64	; 100
+    3e9c:	09 f0       	breq	.+2      	; 0x3ea0 <main+0xa0>
+    3e9e:	43 c0       	rjmp	.+134    	; 0x3f26 <main+0x126>
       // PROGRAM PAGE - we support flash programming only, not EEPROM
       uint8_t *bufPtr;
       uint16_t addrPtr;
-      
-      if (getLen() != 'F') appStart(); // Abort is not flash programming
-    3eb2:	90 d0       	rcall	.+288    	; 0x3fd4 <getLen>
-    3eb4:	86 34       	cpi	r24, 0x46	; 70
-    3eb6:	09 f0       	breq	.+2      	; 0x3eba <main+0xba>
-    3eb8:	7b d0       	rcall	.+246    	; 0x3fb0 <appStart>
-  
+
+      getLen();
+    3ea0:	8f d0       	rcall	.+286    	; 0x3fc0 <getLen>
+
       // Immediately start page erase - this will 4.5ms
       boot_page_erase((uint16_t)(void*)address);
-    3eba:	e0 91 00 02 	lds	r30, 0x0200
-    3ebe:	f0 91 01 02 	lds	r31, 0x0201
-    3ec2:	83 e0       	ldi	r24, 0x03	; 3
-    3ec4:	80 93 57 00 	sts	0x0057, r24
-    3ec8:	e8 95       	spm
-    3eca:	c0 e0       	ldi	r28, 0x00	; 0
-    3ecc:	d1 e0       	ldi	r29, 0x01	; 1
+    3ea2:	e0 91 00 02 	lds	r30, 0x0200
+    3ea6:	f0 91 01 02 	lds	r31, 0x0201
+    3eaa:	83 e0       	ldi	r24, 0x03	; 3
+    3eac:	80 93 57 00 	sts	0x0057, r24
+    3eb0:	e8 95       	spm
+    3eb2:	c0 e0       	ldi	r28, 0x00	; 0
+    3eb4:	d1 e0       	ldi	r29, 0x01	; 1
 
       // While that is going on, read in page contents
       bufPtr = buff;
       do *bufPtr++ = getch();
-    3ece:	73 d0       	rcall	.+230    	; 0x3fb6 <getch>
-    3ed0:	89 93       	st	Y+, r24
+    3eb6:	70 d0       	rcall	.+224    	; 0x3f98 <getch>
+    3eb8:	89 93       	st	Y+, r24
       while (--length);
-    3ed2:	80 91 02 02 	lds	r24, 0x0202
-    3ed6:	81 50       	subi	r24, 0x01	; 1
-    3ed8:	80 93 02 02 	sts	0x0202, r24
-    3edc:	88 23       	and	r24, r24
-    3ede:	b9 f7       	brne	.-18     	; 0x3ece <main+0xce>
+    3eba:	80 91 02 02 	lds	r24, 0x0202
+    3ebe:	81 50       	subi	r24, 0x01	; 1
+    3ec0:	80 93 02 02 	sts	0x0202, r24
+    3ec4:	88 23       	and	r24, r24
+    3ec6:	b9 f7       	brne	.-18     	; 0x3eb6 <main+0xb6>
 
+      // Read command terminator, start reply
+      verifySpace();
+    3ec8:	8b d0       	rcall	.+278    	; 0x3fe0 <verifySpace>
+      
       // If only a partial page is to be programmed, the erase might not be complete.
       // So check that here
       boot_spm_busy_wait();
-    3ee0:	07 b6       	in	r0, 0x37	; 55
-    3ee2:	00 fc       	sbrc	r0, 0
-    3ee4:	fd cf       	rjmp	.-6      	; 0x3ee0 <main+0xe0>
+    3eca:	07 b6       	in	r0, 0x37	; 55
+    3ecc:	00 fc       	sbrc	r0, 0
+    3ece:	fd cf       	rjmp	.-6      	; 0x3eca <main+0xca>
 
-      // Read command terminator, start reply
-      verifySpace();
-    3ee6:	7b d0       	rcall	.+246    	; 0x3fde <verifySpace>
-      
       // Copy buffer into programming buffer
       bufPtr = buff;
       addrPtr = (uint16_t)(void*)address;
-    3ee8:	40 91 00 02 	lds	r20, 0x0200
-    3eec:	50 91 01 02 	lds	r21, 0x0201
-    3ef0:	a0 e0       	ldi	r26, 0x00	; 0
-    3ef2:	b1 e0       	ldi	r27, 0x01	; 1
+    3ed0:	40 91 00 02 	lds	r20, 0x0200
+    3ed4:	50 91 01 02 	lds	r21, 0x0201
+    3ed8:	a0 e0       	ldi	r26, 0x00	; 0
+    3eda:	b1 e0       	ldi	r27, 0x01	; 1
       ch = SPM_PAGESIZE / 2;
       do {
         uint16_t a;
         a = *bufPtr++;
-    3ef4:	2c 91       	ld	r18, X
-    3ef6:	30 e0       	ldi	r19, 0x00	; 0
+    3edc:	2c 91       	ld	r18, X
+    3ede:	30 e0       	ldi	r19, 0x00	; 0
         a |= (*bufPtr++) << 8;
-    3ef8:	11 96       	adiw	r26, 0x01	; 1
-    3efa:	8c 91       	ld	r24, X
-    3efc:	11 97       	sbiw	r26, 0x01	; 1
-    3efe:	90 e0       	ldi	r25, 0x00	; 0
-    3f00:	98 2f       	mov	r25, r24
-    3f02:	88 27       	eor	r24, r24
-    3f04:	82 2b       	or	r24, r18
-    3f06:	93 2b       	or	r25, r19
+    3ee0:	11 96       	adiw	r26, 0x01	; 1
+    3ee2:	8c 91       	ld	r24, X
+    3ee4:	11 97       	sbiw	r26, 0x01	; 1
+    3ee6:	90 e0       	ldi	r25, 0x00	; 0
+    3ee8:	98 2f       	mov	r25, r24
+    3eea:	88 27       	eor	r24, r24
+    3eec:	82 2b       	or	r24, r18
+    3eee:	93 2b       	or	r25, r19
 #define buff    ((uint8_t*)(0x100))
 #define address (*(uint16_t*)(0x200))
 #define length  (*(uint8_t*)(0x202))
 
 /* main program starts here */
 int main(void) {
-    3f08:	12 96       	adiw	r26, 0x02	; 2
+    3ef0:	12 96       	adiw	r26, 0x02	; 2
       ch = SPM_PAGESIZE / 2;
       do {
         uint16_t a;
         a = *bufPtr++;
         a |= (*bufPtr++) << 8;
         boot_page_fill((uint16_t)(void*)addrPtr,a);
-    3f0a:	fa 01       	movw	r30, r20
-    3f0c:	0c 01       	movw	r0, r24
-    3f0e:	d0 92 57 00 	sts	0x0057, r13
-    3f12:	e8 95       	spm
-    3f14:	11 24       	eor	r1, r1
+    3ef2:	fa 01       	movw	r30, r20
+    3ef4:	0c 01       	movw	r0, r24
+    3ef6:	d0 92 57 00 	sts	0x0057, r13
+    3efa:	e8 95       	spm
+    3efc:	11 24       	eor	r1, r1
         addrPtr += 2;
-    3f16:	4e 5f       	subi	r20, 0xFE	; 254
-    3f18:	5f 4f       	sbci	r21, 0xFF	; 255
+    3efe:	4e 5f       	subi	r20, 0xFE	; 254
+    3f00:	5f 4f       	sbci	r21, 0xFF	; 255
       } while (--ch);
-    3f1a:	f1 e0       	ldi	r31, 0x01	; 1
-    3f1c:	a0 38       	cpi	r26, 0x80	; 128
-    3f1e:	bf 07       	cpc	r27, r31
-    3f20:	49 f7       	brne	.-46     	; 0x3ef4 <main+0xf4>
+    3f02:	f1 e0       	ldi	r31, 0x01	; 1
+    3f04:	a0 38       	cpi	r26, 0x80	; 128
+    3f06:	bf 07       	cpc	r27, r31
+    3f08:	49 f7       	brne	.-46     	; 0x3edc <main+0xdc>
       
       // Write from programming buffer
       boot_page_write((uint16_t)(void*)address);
-    3f22:	e0 91 00 02 	lds	r30, 0x0200
-    3f26:	f0 91 01 02 	lds	r31, 0x0201
-    3f2a:	e0 92 57 00 	sts	0x0057, r14
-    3f2e:	e8 95       	spm
+    3f0a:	e0 91 00 02 	lds	r30, 0x0200
+    3f0e:	f0 91 01 02 	lds	r31, 0x0201
+    3f12:	e0 92 57 00 	sts	0x0057, r14
+    3f16:	e8 95       	spm
       boot_spm_busy_wait();
-    3f30:	07 b6       	in	r0, 0x37	; 55
-    3f32:	00 fc       	sbrc	r0, 0
-    3f34:	fd cf       	rjmp	.-6      	; 0x3f30 <main+0x130>
+    3f18:	07 b6       	in	r0, 0x37	; 55
+    3f1a:	00 fc       	sbrc	r0, 0
+    3f1c:	fd cf       	rjmp	.-6      	; 0x3f18 <main+0x118>
 
       // Reenable read access to flash
       boot_rww_enable();
-    3f36:	f0 92 57 00 	sts	0x0057, r15
-    3f3a:	e8 95       	spm
-    3f3c:	27 c0       	rjmp	.+78     	; 0x3f8c <main+0x18c>
+    3f1e:	f0 92 57 00 	sts	0x0057, r15
+    3f22:	e8 95       	spm
+    3f24:	27 c0       	rjmp	.+78     	; 0x3f74 <main+0x174>
     }
     /* Read memory block mode, length is big endian.  */
     else if(ch == STK_READ_PAGE) {
-    3f3e:	84 37       	cpi	r24, 0x74	; 116
-    3f40:	b9 f4       	brne	.+46     	; 0x3f70 <main+0x170>
+    3f26:	84 37       	cpi	r24, 0x74	; 116
+    3f28:	b9 f4       	brne	.+46     	; 0x3f58 <main+0x158>
       // READ PAGE - we only read flash
       getLen();
-    3f42:	48 d0       	rcall	.+144    	; 0x3fd4 <getLen>
+    3f2a:	4a d0       	rcall	.+148    	; 0x3fc0 <getLen>
       verifySpace();
-    3f44:	4c d0       	rcall	.+152    	; 0x3fde <verifySpace>
+    3f2c:	59 d0       	rcall	.+178    	; 0x3fe0 <verifySpace>
       do putch(pgm_read_byte_near(address++));
-    3f46:	e0 91 00 02 	lds	r30, 0x0200
-    3f4a:	f0 91 01 02 	lds	r31, 0x0201
-    3f4e:	31 96       	adiw	r30, 0x01	; 1
-    3f50:	f0 93 01 02 	sts	0x0201, r31
-    3f54:	e0 93 00 02 	sts	0x0200, r30
-    3f58:	31 97       	sbiw	r30, 0x01	; 1
-    3f5a:	e4 91       	lpm	r30, Z+
-    3f5c:	8e 2f       	mov	r24, r30
-    3f5e:	19 d0       	rcall	.+50     	; 0x3f92 <putch>
+    3f2e:	e0 91 00 02 	lds	r30, 0x0200
+    3f32:	f0 91 01 02 	lds	r31, 0x0201
+    3f36:	31 96       	adiw	r30, 0x01	; 1
+    3f38:	f0 93 01 02 	sts	0x0201, r31
+    3f3c:	e0 93 00 02 	sts	0x0200, r30
+    3f40:	31 97       	sbiw	r30, 0x01	; 1
+    3f42:	e4 91       	lpm	r30, Z+
+    3f44:	8e 2f       	mov	r24, r30
+    3f46:	19 d0       	rcall	.+50     	; 0x3f7a <putch>
       while (--length);
-    3f60:	80 91 02 02 	lds	r24, 0x0202
-    3f64:	81 50       	subi	r24, 0x01	; 1
-    3f66:	80 93 02 02 	sts	0x0202, r24
-    3f6a:	88 23       	and	r24, r24
-    3f6c:	61 f7       	brne	.-40     	; 0x3f46 <main+0x146>
-    3f6e:	0e c0       	rjmp	.+28     	; 0x3f8c <main+0x18c>
+    3f48:	80 91 02 02 	lds	r24, 0x0202
+    3f4c:	81 50       	subi	r24, 0x01	; 1
+    3f4e:	80 93 02 02 	sts	0x0202, r24
+    3f52:	88 23       	and	r24, r24
+    3f54:	61 f7       	brne	.-40     	; 0x3f2e <main+0x12e>
+    3f56:	0e c0       	rjmp	.+28     	; 0x3f74 <main+0x174>
     }
 
     /* Get device signature bytes  */
     else if(ch == STK_READ_SIGN) {
-    3f70:	85 37       	cpi	r24, 0x75	; 117
-    3f72:	39 f4       	brne	.+14     	; 0x3f82 <main+0x182>
+    3f58:	85 37       	cpi	r24, 0x75	; 117
+    3f5a:	39 f4       	brne	.+14     	; 0x3f6a <main+0x16a>
       // READ SIGN - return what Avrdude wants to hear
       verifySpace();
-    3f74:	34 d0       	rcall	.+104    	; 0x3fde <verifySpace>
+    3f5c:	41 d0       	rcall	.+130    	; 0x3fe0 <verifySpace>
       putch(SIGNATURE_0);
-    3f76:	8e e1       	ldi	r24, 0x1E	; 30
-    3f78:	0c d0       	rcall	.+24     	; 0x3f92 <putch>
+    3f5e:	8e e1       	ldi	r24, 0x1E	; 30
+    3f60:	0c d0       	rcall	.+24     	; 0x3f7a <putch>
       putch(SIGNATURE_1);
-    3f7a:	84 e9       	ldi	r24, 0x94	; 148
-    3f7c:	0a d0       	rcall	.+20     	; 0x3f92 <putch>
+    3f62:	84 e9       	ldi	r24, 0x94	; 148
+    3f64:	0a d0       	rcall	.+20     	; 0x3f7a <putch>
       putch(SIGNATURE_2);
-    3f7e:	86 e0       	ldi	r24, 0x06	; 6
-    3f80:	93 cf       	rjmp	.-218    	; 0x3ea8 <main+0xa8>
+    3f66:	86 e0       	ldi	r24, 0x06	; 6
+    3f68:	96 cf       	rjmp	.-212    	; 0x3e96 <main+0x96>
     }
     else if (ch == 'Q') {
-    3f82:	81 35       	cpi	r24, 0x51	; 81
-    3f84:	11 f4       	brne	.+4      	; 0x3f8a <main+0x18a>
+    3f6a:	81 35       	cpi	r24, 0x51	; 81
+    3f6c:	11 f4       	brne	.+4      	; 0x3f72 <main+0x172>
       // Adaboot no-wait mod
-      WDTCSR = _BV(WDE);
-    3f86:	c0 92 60 00 	sts	0x0060, r12
+      watchdogConfig(_BV(WDE));
+    3f6e:	88 e0       	ldi	r24, 0x08	; 8
+    3f70:	2c d0       	rcall	.+88     	; 0x3fca <watchdogConfig>
       verifySpace();
     }
     else {
       // This covers the response to commands like STK_ENTER_PROGMODE
       verifySpace();
-    3f8a:	29 d0       	rcall	.+82     	; 0x3fde <verifySpace>
+    3f72:	36 d0       	rcall	.+108    	; 0x3fe0 <verifySpace>
     }
     putch(STK_OK);
-    3f8c:	80 e1       	ldi	r24, 0x10	; 16
-    3f8e:	01 d0       	rcall	.+2      	; 0x3f92 <putch>
-    3f90:	60 cf       	rjmp	.-320    	; 0x3e52 <main+0x52>
-
-00003f92 <putch>:
-  }
-}
+    3f74:	80 e1       	ldi	r24, 0x10	; 16
+    3f76:	01 d0       	rcall	.+2      	; 0x3f7a <putch>
+    3f78:	63 cf       	rjmp	.-314    	; 0x3e40 <main+0x40>
 
+00003f7a <putch>:
 void putch(char ch) {
-    3f92:	98 2f       	mov	r25, r24
+#ifndef SOFT_UART
   while (!(UCSR0A & _BV(UDRE0)));
-    3f94:	80 91 c0 00 	lds	r24, 0x00C0
-    3f98:	85 ff       	sbrs	r24, 5
-    3f9a:	fc cf       	rjmp	.-8      	; 0x3f94 <putch+0x2>
   UDR0 = ch;
-    3f9c:	90 93 c6 00 	sts	0x00C6, r25
-}
-    3fa0:	08 95       	ret
-
-00003fa2 <setTimer>:
-
-void setTimer(uint16_t counts) {
-  TCNT1 = counts;
-    3fa2:	90 93 85 00 	sts	0x0085, r25
-    3fa6:	80 93 84 00 	sts	0x0084, r24
-  TIFR1 = _BV(TOV1);
-    3faa:	81 e0       	ldi	r24, 0x01	; 1
-    3fac:	86 bb       	out	0x16, r24	; 22
+#else
+  __asm__ __volatile__ (
+    3f7a:	2a e0       	ldi	r18, 0x0A	; 10
+    3f7c:	30 e0       	ldi	r19, 0x00	; 0
+    3f7e:	80 95       	com	r24
+    3f80:	08 94       	sec
+    3f82:	10 f4       	brcc	.+4      	; 0x3f88 <putch+0xe>
+    3f84:	59 98       	cbi	0x0b, 1	; 11
+    3f86:	02 c0       	rjmp	.+4      	; 0x3f8c <putch+0x12>
+    3f88:	59 9a       	sbi	0x0b, 1	; 11
+    3f8a:	00 00       	nop
+    3f8c:	15 d0       	rcall	.+42     	; 0x3fb8 <uartDelay>
+    3f8e:	14 d0       	rcall	.+40     	; 0x3fb8 <uartDelay>
+    3f90:	86 95       	lsr	r24
+    3f92:	2a 95       	dec	r18
+    3f94:	b1 f7       	brne	.-20     	; 0x3f82 <putch+0x8>
+      [uartBit] "I" (UART_TX_BIT)
+    :
+      "r25"
+  );
+#endif
 }
-    3fae:	08 95       	ret
+    3f96:	08 95       	ret
 
-00003fb0 <appStart>:
-  length = getch();
+00003f98 <getch>:
   return getch();
 }
 
-void appStart() {
+// Watchdog functions. These are only safe with interrupts turned off.
+void watchdogReset() {
   __asm__ __volatile__ (
-    3fb0:	ee 27       	eor	r30, r30
-    3fb2:	ff 27       	eor	r31, r31
-    3fb4:	09 94       	ijmp
+    3f98:	a8 95       	wdr
+#ifdef LED_DATA_FLASH
+  LED_PIN |= _BV(LED);
+#endif
 
-00003fb6 <getch>:
-  TCNT1 = counts;
-  TIFR1 = _BV(TOV1);
+  return ch;
 }
+    3f9a:	29 e0       	ldi	r18, 0x09	; 9
+    3f9c:	30 e0       	ldi	r19, 0x00	; 0
+    3f9e:	48 99       	sbic	0x09, 0	; 9
+    3fa0:	fe cf       	rjmp	.-4      	; 0x3f9e <getch+0x6>
+    3fa2:	0a d0       	rcall	.+20     	; 0x3fb8 <uartDelay>
+    3fa4:	09 d0       	rcall	.+18     	; 0x3fb8 <uartDelay>
+    3fa6:	08 d0       	rcall	.+16     	; 0x3fb8 <uartDelay>
+    3fa8:	88 94       	clc
+    3faa:	48 99       	sbic	0x09, 0	; 9
+    3fac:	08 94       	sec
+    3fae:	2a 95       	dec	r18
+    3fb0:	11 f0       	breq	.+4      	; 0x3fb6 <getch+0x1e>
+    3fb2:	87 95       	ror	r24
+    3fb4:	f7 cf       	rjmp	.-18     	; 0x3fa4 <getch+0xc>
+    3fb6:	08 95       	ret
+
+00003fb8 <uartDelay>:
+#if UART_B_VALUE > 255
+#error Baud rate too slow for soft UART
+#endif
 
-uint8_t getch(void) {
-  LED_PORT &= ~_BV(LED);
-    3fb6:	2d 98       	cbi	0x05, 5	; 5
-  setTimer(-(F_CPU/(1024*2))); // 500ms
-    3fb8:	8c e7       	ldi	r24, 0x7C	; 124
-    3fba:	91 ee       	ldi	r25, 0xE1	; 225
-    3fbc:	f2 df       	rcall	.-28     	; 0x3fa2 <setTimer>
-    3fbe:	02 c0       	rjmp	.+4      	; 0x3fc4 <getch+0xe>
-  while(!(UCSR0A & _BV(RXC0))) if (TIFR1 & _BV(TOV1)) appStart();
-    3fc0:	b0 99       	sbic	0x16, 0	; 22
-    3fc2:	f6 df       	rcall	.-20     	; 0x3fb0 <appStart>
-    3fc4:	80 91 c0 00 	lds	r24, 0x00C0
-    3fc8:	87 ff       	sbrs	r24, 7
-    3fca:	fa cf       	rjmp	.-12     	; 0x3fc0 <getch+0xa>
-  LED_PORT |= _BV(LED);
-    3fcc:	2d 9a       	sbi	0x05, 5	; 5
-  return UDR0;
-    3fce:	80 91 c6 00 	lds	r24, 0x00C6
-}
-    3fd2:	08 95       	ret
+void uartDelay() {
+  __asm__ __volatile__ (
+    3fb8:	98 e0       	ldi	r25, 0x08	; 8
+    3fba:	9a 95       	dec	r25
+    3fbc:	f1 f7       	brne	.-4      	; 0x3fba <uartDelay+0x2>
+    3fbe:	08 95       	ret
 
-00003fd4 <getLen>:
-    LED_PIN |= _BV(LED);
+00003fc0 <getLen>:
   } while (--count);
 }
+#endif
 
 uint8_t getLen() {
   getch();
-    3fd4:	f0 df       	rcall	.-32     	; 0x3fb6 <getch>
+    3fc0:	eb df       	rcall	.-42     	; 0x3f98 <getch>
   length = getch();
-    3fd6:	ef df       	rcall	.-34     	; 0x3fb6 <getch>
-    3fd8:	80 93 02 02 	sts	0x0202, r24
+    3fc2:	ea df       	rcall	.-44     	; 0x3f98 <getch>
+    3fc4:	80 93 02 02 	sts	0x0202, r24
   return getch();
 }
-    3fdc:	ec cf       	rjmp	.-40     	; 0x3fb6 <getch>
+    3fc8:	e7 cf       	rjmp	.-50     	; 0x3f98 <getch>
+
+00003fca <watchdogConfig>:
+    "wdr\n"
+  );
+}
 
-00003fde <verifySpace>:
+void watchdogConfig(uint8_t x) {
+  WDTCSR = _BV(WDCE) | _BV(WDE);
+    3fca:	e0 e6       	ldi	r30, 0x60	; 96
+    3fcc:	f0 e0       	ldi	r31, 0x00	; 0
+    3fce:	98 e1       	ldi	r25, 0x18	; 24
+    3fd0:	90 83       	st	Z, r25
+  WDTCSR = x;
+    3fd2:	80 83       	st	Z, r24
+}
+    3fd4:	08 95       	ret
+
+00003fd6 <appStart>:
+
+void appStart() {
+  watchdogConfig(0);
+    3fd6:	80 e0       	ldi	r24, 0x00	; 0
+    3fd8:	f8 df       	rcall	.-16     	; 0x3fca <watchdogConfig>
+  __asm__ __volatile__ (
+    3fda:	ee 27       	eor	r30, r30
+    3fdc:	ff 27       	eor	r31, r31
+    3fde:	09 94       	ijmp
+
+00003fe0 <verifySpace>:
   do getch(); while (--count);
   verifySpace();
 }
 
 void verifySpace() {
   if (getch() != CRC_EOP) appStart();
-    3fde:	eb df       	rcall	.-42     	; 0x3fb6 <getch>
-    3fe0:	80 32       	cpi	r24, 0x20	; 32
-    3fe2:	09 f0       	breq	.+2      	; 0x3fe6 <verifySpace+0x8>
-    3fe4:	e5 df       	rcall	.-54     	; 0x3fb0 <appStart>
+    3fe0:	db df       	rcall	.-74     	; 0x3f98 <getch>
+    3fe2:	80 32       	cpi	r24, 0x20	; 32
+    3fe4:	09 f0       	breq	.+2      	; 0x3fe8 <verifySpace+0x8>
+    3fe6:	f7 df       	rcall	.-18     	; 0x3fd6 <appStart>
   putch(STK_INSYNC);
-    3fe6:	84 e1       	ldi	r24, 0x14	; 20
+    3fe8:	84 e1       	ldi	r24, 0x14	; 20
 }
-    3fe8:	d4 cf       	rjmp	.-88     	; 0x3f92 <putch>
-  while(!(UCSR0A & _BV(RXC0))) if (TIFR1 & _BV(TOV1)) appStart();
-  LED_PORT |= _BV(LED);
-  return UDR0;
+    3fea:	c7 cf       	rjmp	.-114    	; 0x3f7a <putch>
+    ::[count] "M" (UART_B_VALUE)
+  );
 }
+#endif
 
 void getNch(uint8_t count) {
-    3fea:	1f 93       	push	r17
-    3fec:	18 2f       	mov	r17, r24
+    3fec:	1f 93       	push	r17
+    3fee:	18 2f       	mov	r17, r24
 
-00003fee <getNch>:
+00003ff0 <getNch>:
   do getch(); while (--count);
-    3fee:	e3 df       	rcall	.-58     	; 0x3fb6 <getch>
-    3ff0:	11 50       	subi	r17, 0x01	; 1
-    3ff2:	e9 f7       	brne	.-6      	; 0x3fee <getNch>
+    3ff0:	d3 df       	rcall	.-90     	; 0x3f98 <getch>
+    3ff2:	11 50       	subi	r17, 0x01	; 1
+    3ff4:	e9 f7       	brne	.-6      	; 0x3ff0 <getNch>
   verifySpace();
-    3ff4:	f4 df       	rcall	.-24     	; 0x3fde <verifySpace>
+    3ff6:	f4 df       	rcall	.-24     	; 0x3fe0 <verifySpace>
 }
-    3ff6:	1f 91       	pop	r17
-    3ff8:	08 95       	ret
+    3ff8:	1f 91       	pop	r17
+    3ffa:	08 95       	ret

+ 32 - 32
optiboot/bootloaders/optiboot/optiboot_pro_20mhz.hex

@@ -1,34 +1,34 @@
-:103E000085E08093810082E08093C00098E19093E8
-:103E1000C10086E08093C20081E88093C40084B72B
-:103E200014BE909360001092600081FFC1D0259A6B
-:103E300002E08CE39BEFB5D0B09BFECF1D9A015002
-:103E4000C1F7DD24D394B8E0CB2EA5E0EA2EF1E152
-:103E5000FF2EB1D0813421F481E0C7D083E024C0AB
-:103E6000823411F484E103C0853419F485E0BDD0B7
-:103E70008DC08535A1F49FD0082F10E0109301026A
-:103E80000093000298D090E0982F8827802B912BE8
-:103E9000880F991F909301028093000276C08635A7
-:103EA00029F484E0A2D080E074D070C0843609F098
-:103EB00046C090D0863409F07BD0E0910002F091AA
-:103EC000010283E080935700E895C0E0D1E073D011
-:103ED0008993809102028150809302028823B9F76E
-:103EE00007B600FCFDCF7BD040910002509101024B
-:103EF000A0E0B1E02C9130E011968C91119790E008
-:103F0000982F8827822B932B1296FA010C01D092BE
-:103F10005700E89511244E5F5F4FF1E0A038BF07CE
-:103F200049F7E0910002F0910102E0925700E89514
-:103F300007B600FCFDCFF0925700E89527C0843704
-:103F4000B9F448D04CD0E0910002F09101023196D2
-:103F5000F0930102E09300023197E4918E2F19D083
-:103F600080910202815080930202882361F70EC083
-:103F7000853739F434D08EE10CD084E90AD086E05C
-:103F800093CF813511F4C092600029D080E101D037
-:103F900060CF982F8091C00085FFFCCF9093C60022
-:103FA0000895909385008093840081E086BB0895F6
-:103FB000EE27FF2709942D988BED99EDF2DF02C0D3
-:103FC000B099F6DF8091C00087FFFACF2D9A8091DB
-:103FD000C6000895F0DFEFDF80930202ECCFEBDF45
-:103FE000803209F0E5DF84E1D4CF1F93182FE3DF9F
-:0A3FF0001150E9F7F4DF1F91089566
+:103E000085E08093810084B714BE81FFE4D08DE00B
+:103E1000DCD0259A519A86E02CE33BEF91E0309379
+:103E200085002093840096BBB09BFECF1D9AA89579
+:103E30008150A9F7DD24D394A5E0EA2EF1E1FF2E0D
+:103E4000ABD0813421F481E0D1D083E024C082342E
+:103E500011F484E103C0853419F485E0C7D08AC029
+:103E60008535A1F499D0082F10E01093010200933A
+:103E7000000292D090E0982F8827802B912B880FFA
+:103E8000991F909301028093000273C0863529F434
+:103E900084E0ACD080E071D06DC0843609F043C0BE
+:103EA0008FD0E0910002F091010283E080935700EF
+:103EB000E895C0E0D1E070D08993809102028150F2
+:103EC000809302028823B9F78BD007B600FCFDCFA0
+:103ED0004091000250910102A0E0B1E02C9130E04D
+:103EE00011968C91119790E0982F8827822B932B15
+:103EF0001296FA010C01D0925700E89511244E5FFA
+:103F00005F4FF1E0A038BF0749F7E0910002F09160
+:103F10000102E0925700E89507B600FCFDCFF09251
+:103F20005700E89527C08437B9F44AD059D0E091BA
+:103F30000002F09101023196F0930102E093000239
+:103F40003197E4918E2F19D0809102028150809395
+:103F50000202882361F70EC0853739F441D08EE123
+:103F60000CD084E90AD086E096CF813511F488E040
+:103F70002CD036D080E101D063CF2AE030E08095AC
+:103F8000089410F4599802C0599A000015D014D022
+:103F900086952A95B1F70895A89529E030E04899CB
+:103FA000FECF0AD009D008D08894489908942A9561
+:103FB00011F08795F7CF08959BE09A95F1F7089552
+:103FC000EBDFEADF80930202E7CFE0E6F0E098E182
+:103FD00090838083089580E0F8DFEE27FF2709941F
+:103FE000DBDF803209F0F7DF84E1C7CF1F93182FA2
+:0C3FF000D3DF1150E9F7F4DF1F910895B2
 :0400000300003E00BB
 :00000001FF

+ 320 - 282
optiboot/bootloaders/optiboot/optiboot_pro_20mhz.lst

@@ -3,25 +3,25 @@ optiboot_pro_20mhz.elf:     file format elf32-avr
 
 Sections:
 Idx Name          Size      VMA       LMA       File off  Algn
-  0 .text         000001fa  00003e00  00003e00  00000054  2**1
+  0 .text         000001fc  00003e00  00003e00  00000054  2**1
                   CONTENTS, ALLOC, LOAD, READONLY, CODE
-  1 .debug_aranges 00000028  00000000  00000000  0000024e  2**0
+  1 .debug_aranges 00000028  00000000  00000000  00000250  2**0
                   CONTENTS, READONLY, DEBUGGING
-  2 .debug_pubnames 00000064  00000000  00000000  00000276  2**0
+  2 .debug_pubnames 00000078  00000000  00000000  00000278  2**0
                   CONTENTS, READONLY, DEBUGGING
-  3 .debug_info   0000022f  00000000  00000000  000002da  2**0
+  3 .debug_info   00000275  00000000  00000000  000002f0  2**0
                   CONTENTS, READONLY, DEBUGGING
-  4 .debug_abbrev 00000164  00000000  00000000  00000509  2**0
+  4 .debug_abbrev 000001a3  00000000  00000000  00000565  2**0
                   CONTENTS, READONLY, DEBUGGING
-  5 .debug_line   000003c8  00000000  00000000  0000066d  2**0
+  5 .debug_line   000003b8  00000000  00000000  00000708  2**0
                   CONTENTS, READONLY, DEBUGGING
-  6 .debug_frame  00000090  00000000  00000000  00000a38  2**2
+  6 .debug_frame  000000a0  00000000  00000000  00000ac0  2**2
                   CONTENTS, READONLY, DEBUGGING
-  7 .debug_str    0000011c  00000000  00000000  00000ac8  2**0
+  7 .debug_str    00000133  00000000  00000000  00000b60  2**0
                   CONTENTS, READONLY, DEBUGGING
-  8 .debug_loc    000001d6  00000000  00000000  00000be4  2**0
+  8 .debug_loc    000001a0  00000000  00000000  00000c93  2**0
                   CONTENTS, READONLY, DEBUGGING
-  9 .debug_ranges 00000068  00000000  00000000  00000dba  2**0
+  9 .debug_ranges 00000070  00000000  00000000  00000e33  2**0
                   CONTENTS, READONLY, DEBUGGING
 
 Disassembly of section .text:
@@ -35,449 +35,487 @@ Disassembly of section .text:
 int main(void) {
     3e00:	85 e0       	ldi	r24, 0x05	; 5
     3e02:	80 93 81 00 	sts	0x0081, r24
-    [addr5]"i"(_SFR_MEM_ADDR(UBRR0L)), [val5]"i"((F_CPU + BAUD_RATE * 4L) / (BAUD_RATE * 8L) - 1)
-  );
-#else
-  // Set up Timer 1 for timeout counter
-  TCCR1B = _BV(CS12) | _BV(CS10); // div 1024
-  UCSR0A = _BV(U2X0); //Double speed mode USART0
-    3e06:	82 e0       	ldi	r24, 0x02	; 2
-    3e08:	80 93 c0 00 	sts	0x00C0, r24
-  UCSR0B = _BV(RXEN0) | _BV(TXEN0);
-    3e0c:	98 e1       	ldi	r25, 0x18	; 24
-    3e0e:	90 93 c1 00 	sts	0x00C1, r25
   UCSR0C = _BV(UCSZ00) | _BV(UCSZ01);
-    3e12:	86 e0       	ldi	r24, 0x06	; 6
-    3e14:	80 93 c2 00 	sts	0x00C2, r24
   UBRR0L = (uint8_t)( (F_CPU + BAUD_RATE * 4L) / (BAUD_RATE * 8L) - 1 );
-    3e18:	81 e8       	ldi	r24, 0x81	; 129
-    3e1a:	80 93 c4 00 	sts	0x00C4, r24
 #endif
 
   // Adaboot no-wait mod
   ch = MCUSR;
-    3e1e:	84 b7       	in	r24, 0x34	; 52
+    3e06:	84 b7       	in	r24, 0x34	; 52
   MCUSR = 0;
-    3e20:	14 be       	out	0x34, r1	; 52
-  WDTCSR = _BV(WDCE) | _BV(WDE);
-    3e22:	90 93 60 00 	sts	0x0060, r25
-  WDTCSR = 0;
-    3e26:	10 92 60 00 	sts	0x0060, r1
+    3e08:	14 be       	out	0x34, r1	; 52
   if (!(ch & _BV(EXTRF))) appStart();
-    3e2a:	81 ff       	sbrs	r24, 1
-    3e2c:	c1 d0       	rcall	.+386    	; 0x3fb0 <appStart>
+    3e0a:	81 ff       	sbrs	r24, 1
+    3e0c:	e4 d0       	rcall	.+456    	; 0x3fd6 <appStart>
+
+  // Set up watchdog to trigger after 500ms
+  watchdogConfig(_BV(WDP2)|_BV(WDP0)|_BV(WDE));
+    3e0e:	8d e0       	ldi	r24, 0x0D	; 13
+    3e10:	dc d0       	rcall	.+440    	; 0x3fca <watchdogConfig>
 
-  /* set LED pin as output */
+  /* Set LED pin as output */
   LED_DDR |= _BV(LED);
-    3e2e:	25 9a       	sbi	0x04, 5	; 4
-    3e30:	02 e0       	ldi	r16, 0x02	; 2
-  putch(STK_INSYNC);
+    3e12:	25 9a       	sbi	0x04, 5	; 4
+
+#ifdef SOFT_UART
+  /* Set TX pin as output */
+  UART_DDR |= _BV(UART_TX_BIT);
+    3e14:	51 9a       	sbi	0x0a, 1	; 10
+    3e16:	86 e0       	ldi	r24, 0x06	; 6
+}
+
+#if LED_START_FLASHES > 0
+void flash_led(uint8_t count) {
+  do {
+    TCNT1 = -(F_CPU/(1024*16));
+    3e18:	2c e3       	ldi	r18, 0x3C	; 60
+    3e1a:	3b ef       	ldi	r19, 0xFB	; 251
+    TIFR1 = _BV(TOV1);
+    3e1c:	91 e0       	ldi	r25, 0x01	; 1
 }
 
+#if LED_START_FLASHES > 0
 void flash_led(uint8_t count) {
   do {
-    setTimer(-(F_CPU/(1024*16))); // 62ms
-    3e32:	8c e3       	ldi	r24, 0x3C	; 60
-    3e34:	9b ef       	ldi	r25, 0xFB	; 251
-    3e36:	b5 d0       	rcall	.+362    	; 0x3fa2 <setTimer>
+    TCNT1 = -(F_CPU/(1024*16));
+    3e1e:	30 93 85 00 	sts	0x0085, r19
+    3e22:	20 93 84 00 	sts	0x0084, r18
+    TIFR1 = _BV(TOV1);
+    3e26:	96 bb       	out	0x16, r25	; 22
+    while(!(TIFR1 & _BV(TOV1)));
+    3e28:	b0 9b       	sbis	0x16, 0	; 22
+    3e2a:	fe cf       	rjmp	.-4      	; 0x3e28 <main+0x28>
+    LED_PIN |= _BV(LED);
+    3e2c:	1d 9a       	sbi	0x03, 5	; 3
+  return getch();
+}
+
+// Watchdog functions. These are only safe with interrupts turned off.
+void watchdogReset() {
+  __asm__ __volatile__ (
+    3e2e:	a8 95       	wdr
+    TCNT1 = -(F_CPU/(1024*16));
+    TIFR1 = _BV(TOV1);
     while(!(TIFR1 & _BV(TOV1)));
-    3e38:	b0 9b       	sbis	0x16, 0	; 22
-    3e3a:	fe cf       	rjmp	.-4      	; 0x3e38 <main+0x38>
     LED_PIN |= _BV(LED);
-    3e3c:	1d 9a       	sbi	0x03, 5	; 3
+    watchdogReset();
   } while (--count);
-    3e3e:	01 50       	subi	r16, 0x01	; 1
-    3e40:	c1 f7       	brne	.-16     	; 0x3e32 <main+0x32>
+    3e30:	81 50       	subi	r24, 0x01	; 1
+    3e32:	a9 f7       	brne	.-22     	; 0x3e1e <main+0x1e>
     /* get character from UART */
     ch = getch();
 
     if(ch == STK_GET_PARAMETER) {
       // GET PARAMETER returns a generic 0x03 reply - enough to keep Avrdude happy
       getNch(1);
-    3e42:	dd 24       	eor	r13, r13
-    3e44:	d3 94       	inc	r13
-      putch(SIGNATURE_1);
-      putch(SIGNATURE_2);
-    }
-    else if (ch == 'Q') {
-      // Adaboot no-wait mod
-      WDTCSR = _BV(WDE);
-    3e46:	b8 e0       	ldi	r27, 0x08	; 8
-    3e48:	cb 2e       	mov	r12, r27
+    3e34:	dd 24       	eor	r13, r13
+    3e36:	d3 94       	inc	r13
         boot_page_fill((uint16_t)(void*)addrPtr,a);
         addrPtr += 2;
       } while (--ch);
       
       // Write from programming buffer
       boot_page_write((uint16_t)(void*)address);
-    3e4a:	a5 e0       	ldi	r26, 0x05	; 5
-    3e4c:	ea 2e       	mov	r14, r26
+    3e38:	a5 e0       	ldi	r26, 0x05	; 5
+    3e3a:	ea 2e       	mov	r14, r26
       boot_spm_busy_wait();
 
       // Reenable read access to flash
       boot_rww_enable();
-    3e4e:	f1 e1       	ldi	r31, 0x11	; 17
-    3e50:	ff 2e       	mov	r15, r31
-  flash_led(NUM_LED_FLASHES * 2);
+    3e3c:	f1 e1       	ldi	r31, 0x11	; 17
+    3e3e:	ff 2e       	mov	r15, r31
+#endif
 
-  /* forever loop */
+  /* Forever loop */
   for (;;) {
     /* get character from UART */
     ch = getch();
-    3e52:	b1 d0       	rcall	.+354    	; 0x3fb6 <getch>
+    3e40:	ab d0       	rcall	.+342    	; 0x3f98 <getch>
 
     if(ch == STK_GET_PARAMETER) {
-    3e54:	81 34       	cpi	r24, 0x41	; 65
-    3e56:	21 f4       	brne	.+8      	; 0x3e60 <main+0x60>
+    3e42:	81 34       	cpi	r24, 0x41	; 65
+    3e44:	21 f4       	brne	.+8      	; 0x3e4e <main+0x4e>
       // GET PARAMETER returns a generic 0x03 reply - enough to keep Avrdude happy
       getNch(1);
-    3e58:	81 e0       	ldi	r24, 0x01	; 1
-    3e5a:	c7 d0       	rcall	.+398    	; 0x3fea <verifySpace+0xc>
+    3e46:	81 e0       	ldi	r24, 0x01	; 1
+    3e48:	d1 d0       	rcall	.+418    	; 0x3fec <verifySpace+0xc>
       putch(0x03);
-    3e5c:	83 e0       	ldi	r24, 0x03	; 3
-    3e5e:	24 c0       	rjmp	.+72     	; 0x3ea8 <main+0xa8>
+    3e4a:	83 e0       	ldi	r24, 0x03	; 3
+    3e4c:	24 c0       	rjmp	.+72     	; 0x3e96 <main+0x96>
     }
     else if(ch == STK_SET_DEVICE) {
-    3e60:	82 34       	cpi	r24, 0x42	; 66
-    3e62:	11 f4       	brne	.+4      	; 0x3e68 <main+0x68>
+    3e4e:	82 34       	cpi	r24, 0x42	; 66
+    3e50:	11 f4       	brne	.+4      	; 0x3e56 <main+0x56>
       // SET DEVICE is ignored
       getNch(20);
-    3e64:	84 e1       	ldi	r24, 0x14	; 20
-    3e66:	03 c0       	rjmp	.+6      	; 0x3e6e <main+0x6e>
+    3e52:	84 e1       	ldi	r24, 0x14	; 20
+    3e54:	03 c0       	rjmp	.+6      	; 0x3e5c <main+0x5c>
     }
     else if(ch == STK_SET_DEVICE_EXT) {
-    3e68:	85 34       	cpi	r24, 0x45	; 69
-    3e6a:	19 f4       	brne	.+6      	; 0x3e72 <main+0x72>
+    3e56:	85 34       	cpi	r24, 0x45	; 69
+    3e58:	19 f4       	brne	.+6      	; 0x3e60 <main+0x60>
       // SET DEVICE EXT is ignored
       getNch(5);
-    3e6c:	85 e0       	ldi	r24, 0x05	; 5
-    3e6e:	bd d0       	rcall	.+378    	; 0x3fea <verifySpace+0xc>
-    3e70:	8d c0       	rjmp	.+282    	; 0x3f8c <main+0x18c>
+    3e5a:	85 e0       	ldi	r24, 0x05	; 5
+    3e5c:	c7 d0       	rcall	.+398    	; 0x3fec <verifySpace+0xc>
+    3e5e:	8a c0       	rjmp	.+276    	; 0x3f74 <main+0x174>
     }
     else if(ch == STK_LOAD_ADDRESS) {
-    3e72:	85 35       	cpi	r24, 0x55	; 85
-    3e74:	a1 f4       	brne	.+40     	; 0x3e9e <main+0x9e>
+    3e60:	85 35       	cpi	r24, 0x55	; 85
+    3e62:	a1 f4       	brne	.+40     	; 0x3e8c <main+0x8c>
       // LOAD ADDRESS
       address = getch();
-    3e76:	9f d0       	rcall	.+318    	; 0x3fb6 <getch>
-    3e78:	08 2f       	mov	r16, r24
-    3e7a:	10 e0       	ldi	r17, 0x00	; 0
-    3e7c:	10 93 01 02 	sts	0x0201, r17
-    3e80:	00 93 00 02 	sts	0x0200, r16
+    3e64:	99 d0       	rcall	.+306    	; 0x3f98 <getch>
+    3e66:	08 2f       	mov	r16, r24
+    3e68:	10 e0       	ldi	r17, 0x00	; 0
+    3e6a:	10 93 01 02 	sts	0x0201, r17
+    3e6e:	00 93 00 02 	sts	0x0200, r16
       address = (address & 0xff) | (getch() << 8);
-    3e84:	98 d0       	rcall	.+304    	; 0x3fb6 <getch>
-    3e86:	90 e0       	ldi	r25, 0x00	; 0
-    3e88:	98 2f       	mov	r25, r24
-    3e8a:	88 27       	eor	r24, r24
-    3e8c:	80 2b       	or	r24, r16
-    3e8e:	91 2b       	or	r25, r17
+    3e72:	92 d0       	rcall	.+292    	; 0x3f98 <getch>
+    3e74:	90 e0       	ldi	r25, 0x00	; 0
+    3e76:	98 2f       	mov	r25, r24
+    3e78:	88 27       	eor	r24, r24
+    3e7a:	80 2b       	or	r24, r16
+    3e7c:	91 2b       	or	r25, r17
       address += address; // Convert from word address to byte address
-    3e90:	88 0f       	add	r24, r24
-    3e92:	99 1f       	adc	r25, r25
-    3e94:	90 93 01 02 	sts	0x0201, r25
-    3e98:	80 93 00 02 	sts	0x0200, r24
-    3e9c:	76 c0       	rjmp	.+236    	; 0x3f8a <main+0x18a>
+    3e7e:	88 0f       	add	r24, r24
+    3e80:	99 1f       	adc	r25, r25
+    3e82:	90 93 01 02 	sts	0x0201, r25
+    3e86:	80 93 00 02 	sts	0x0200, r24
+    3e8a:	73 c0       	rjmp	.+230    	; 0x3f72 <main+0x172>
       verifySpace();
     }
     else if(ch == STK_UNIVERSAL) {
-    3e9e:	86 35       	cpi	r24, 0x56	; 86
-    3ea0:	29 f4       	brne	.+10     	; 0x3eac <main+0xac>
+    3e8c:	86 35       	cpi	r24, 0x56	; 86
+    3e8e:	29 f4       	brne	.+10     	; 0x3e9a <main+0x9a>
       // UNIVERSAL command is ignored
       getNch(4);
-    3ea2:	84 e0       	ldi	r24, 0x04	; 4
-    3ea4:	a2 d0       	rcall	.+324    	; 0x3fea <verifySpace+0xc>
+    3e90:	84 e0       	ldi	r24, 0x04	; 4
+    3e92:	ac d0       	rcall	.+344    	; 0x3fec <verifySpace+0xc>
       putch(0x00);
-    3ea6:	80 e0       	ldi	r24, 0x00	; 0
-    3ea8:	74 d0       	rcall	.+232    	; 0x3f92 <putch>
-    3eaa:	70 c0       	rjmp	.+224    	; 0x3f8c <main+0x18c>
+    3e94:	80 e0       	ldi	r24, 0x00	; 0
+    3e96:	71 d0       	rcall	.+226    	; 0x3f7a <putch>
+    3e98:	6d c0       	rjmp	.+218    	; 0x3f74 <main+0x174>
     }
     /* Write memory, length is big endian and is in bytes  */
     else if(ch == STK_PROG_PAGE) {
-    3eac:	84 36       	cpi	r24, 0x64	; 100
-    3eae:	09 f0       	breq	.+2      	; 0x3eb2 <main+0xb2>
-    3eb0:	46 c0       	rjmp	.+140    	; 0x3f3e <main+0x13e>
+    3e9a:	84 36       	cpi	r24, 0x64	; 100
+    3e9c:	09 f0       	breq	.+2      	; 0x3ea0 <main+0xa0>
+    3e9e:	43 c0       	rjmp	.+134    	; 0x3f26 <main+0x126>
       // PROGRAM PAGE - we support flash programming only, not EEPROM
       uint8_t *bufPtr;
       uint16_t addrPtr;
-      
-      if (getLen() != 'F') appStart(); // Abort is not flash programming
-    3eb2:	90 d0       	rcall	.+288    	; 0x3fd4 <getLen>
-    3eb4:	86 34       	cpi	r24, 0x46	; 70
-    3eb6:	09 f0       	breq	.+2      	; 0x3eba <main+0xba>
-    3eb8:	7b d0       	rcall	.+246    	; 0x3fb0 <appStart>
-  
+
+      getLen();
+    3ea0:	8f d0       	rcall	.+286    	; 0x3fc0 <getLen>
+
       // Immediately start page erase - this will 4.5ms
       boot_page_erase((uint16_t)(void*)address);
-    3eba:	e0 91 00 02 	lds	r30, 0x0200
-    3ebe:	f0 91 01 02 	lds	r31, 0x0201
-    3ec2:	83 e0       	ldi	r24, 0x03	; 3
-    3ec4:	80 93 57 00 	sts	0x0057, r24
-    3ec8:	e8 95       	spm
-    3eca:	c0 e0       	ldi	r28, 0x00	; 0
-    3ecc:	d1 e0       	ldi	r29, 0x01	; 1
+    3ea2:	e0 91 00 02 	lds	r30, 0x0200
+    3ea6:	f0 91 01 02 	lds	r31, 0x0201
+    3eaa:	83 e0       	ldi	r24, 0x03	; 3
+    3eac:	80 93 57 00 	sts	0x0057, r24
+    3eb0:	e8 95       	spm
+    3eb2:	c0 e0       	ldi	r28, 0x00	; 0
+    3eb4:	d1 e0       	ldi	r29, 0x01	; 1
 
       // While that is going on, read in page contents
       bufPtr = buff;
       do *bufPtr++ = getch();
-    3ece:	73 d0       	rcall	.+230    	; 0x3fb6 <getch>
-    3ed0:	89 93       	st	Y+, r24
+    3eb6:	70 d0       	rcall	.+224    	; 0x3f98 <getch>
+    3eb8:	89 93       	st	Y+, r24
       while (--length);
-    3ed2:	80 91 02 02 	lds	r24, 0x0202
-    3ed6:	81 50       	subi	r24, 0x01	; 1
-    3ed8:	80 93 02 02 	sts	0x0202, r24
-    3edc:	88 23       	and	r24, r24
-    3ede:	b9 f7       	brne	.-18     	; 0x3ece <main+0xce>
+    3eba:	80 91 02 02 	lds	r24, 0x0202
+    3ebe:	81 50       	subi	r24, 0x01	; 1
+    3ec0:	80 93 02 02 	sts	0x0202, r24
+    3ec4:	88 23       	and	r24, r24
+    3ec6:	b9 f7       	brne	.-18     	; 0x3eb6 <main+0xb6>
 
+      // Read command terminator, start reply
+      verifySpace();
+    3ec8:	8b d0       	rcall	.+278    	; 0x3fe0 <verifySpace>
+      
       // If only a partial page is to be programmed, the erase might not be complete.
       // So check that here
       boot_spm_busy_wait();
-    3ee0:	07 b6       	in	r0, 0x37	; 55
-    3ee2:	00 fc       	sbrc	r0, 0
-    3ee4:	fd cf       	rjmp	.-6      	; 0x3ee0 <main+0xe0>
+    3eca:	07 b6       	in	r0, 0x37	; 55
+    3ecc:	00 fc       	sbrc	r0, 0
+    3ece:	fd cf       	rjmp	.-6      	; 0x3eca <main+0xca>
 
-      // Read command terminator, start reply
-      verifySpace();
-    3ee6:	7b d0       	rcall	.+246    	; 0x3fde <verifySpace>
-      
       // Copy buffer into programming buffer
       bufPtr = buff;
       addrPtr = (uint16_t)(void*)address;
-    3ee8:	40 91 00 02 	lds	r20, 0x0200
-    3eec:	50 91 01 02 	lds	r21, 0x0201
-    3ef0:	a0 e0       	ldi	r26, 0x00	; 0
-    3ef2:	b1 e0       	ldi	r27, 0x01	; 1
+    3ed0:	40 91 00 02 	lds	r20, 0x0200
+    3ed4:	50 91 01 02 	lds	r21, 0x0201
+    3ed8:	a0 e0       	ldi	r26, 0x00	; 0
+    3eda:	b1 e0       	ldi	r27, 0x01	; 1
       ch = SPM_PAGESIZE / 2;
       do {
         uint16_t a;
         a = *bufPtr++;
-    3ef4:	2c 91       	ld	r18, X
-    3ef6:	30 e0       	ldi	r19, 0x00	; 0
+    3edc:	2c 91       	ld	r18, X
+    3ede:	30 e0       	ldi	r19, 0x00	; 0
         a |= (*bufPtr++) << 8;
-    3ef8:	11 96       	adiw	r26, 0x01	; 1
-    3efa:	8c 91       	ld	r24, X
-    3efc:	11 97       	sbiw	r26, 0x01	; 1
-    3efe:	90 e0       	ldi	r25, 0x00	; 0
-    3f00:	98 2f       	mov	r25, r24
-    3f02:	88 27       	eor	r24, r24
-    3f04:	82 2b       	or	r24, r18
-    3f06:	93 2b       	or	r25, r19
+    3ee0:	11 96       	adiw	r26, 0x01	; 1
+    3ee2:	8c 91       	ld	r24, X
+    3ee4:	11 97       	sbiw	r26, 0x01	; 1
+    3ee6:	90 e0       	ldi	r25, 0x00	; 0
+    3ee8:	98 2f       	mov	r25, r24
+    3eea:	88 27       	eor	r24, r24
+    3eec:	82 2b       	or	r24, r18
+    3eee:	93 2b       	or	r25, r19
 #define buff    ((uint8_t*)(0x100))
 #define address (*(uint16_t*)(0x200))
 #define length  (*(uint8_t*)(0x202))
 
 /* main program starts here */
 int main(void) {
-    3f08:	12 96       	adiw	r26, 0x02	; 2
+    3ef0:	12 96       	adiw	r26, 0x02	; 2
       ch = SPM_PAGESIZE / 2;
       do {
         uint16_t a;
         a = *bufPtr++;
         a |= (*bufPtr++) << 8;
         boot_page_fill((uint16_t)(void*)addrPtr,a);
-    3f0a:	fa 01       	movw	r30, r20
-    3f0c:	0c 01       	movw	r0, r24
-    3f0e:	d0 92 57 00 	sts	0x0057, r13
-    3f12:	e8 95       	spm
-    3f14:	11 24       	eor	r1, r1
+    3ef2:	fa 01       	movw	r30, r20
+    3ef4:	0c 01       	movw	r0, r24
+    3ef6:	d0 92 57 00 	sts	0x0057, r13
+    3efa:	e8 95       	spm
+    3efc:	11 24       	eor	r1, r1
         addrPtr += 2;
-    3f16:	4e 5f       	subi	r20, 0xFE	; 254
-    3f18:	5f 4f       	sbci	r21, 0xFF	; 255
+    3efe:	4e 5f       	subi	r20, 0xFE	; 254
+    3f00:	5f 4f       	sbci	r21, 0xFF	; 255
       } while (--ch);
-    3f1a:	f1 e0       	ldi	r31, 0x01	; 1
-    3f1c:	a0 38       	cpi	r26, 0x80	; 128
-    3f1e:	bf 07       	cpc	r27, r31
-    3f20:	49 f7       	brne	.-46     	; 0x3ef4 <main+0xf4>
+    3f02:	f1 e0       	ldi	r31, 0x01	; 1
+    3f04:	a0 38       	cpi	r26, 0x80	; 128
+    3f06:	bf 07       	cpc	r27, r31
+    3f08:	49 f7       	brne	.-46     	; 0x3edc <main+0xdc>
       
       // Write from programming buffer
       boot_page_write((uint16_t)(void*)address);
-    3f22:	e0 91 00 02 	lds	r30, 0x0200
-    3f26:	f0 91 01 02 	lds	r31, 0x0201
-    3f2a:	e0 92 57 00 	sts	0x0057, r14
-    3f2e:	e8 95       	spm
+    3f0a:	e0 91 00 02 	lds	r30, 0x0200
+    3f0e:	f0 91 01 02 	lds	r31, 0x0201
+    3f12:	e0 92 57 00 	sts	0x0057, r14
+    3f16:	e8 95       	spm
       boot_spm_busy_wait();
-    3f30:	07 b6       	in	r0, 0x37	; 55
-    3f32:	00 fc       	sbrc	r0, 0
-    3f34:	fd cf       	rjmp	.-6      	; 0x3f30 <main+0x130>
+    3f18:	07 b6       	in	r0, 0x37	; 55
+    3f1a:	00 fc       	sbrc	r0, 0
+    3f1c:	fd cf       	rjmp	.-6      	; 0x3f18 <main+0x118>
 
       // Reenable read access to flash
       boot_rww_enable();
-    3f36:	f0 92 57 00 	sts	0x0057, r15
-    3f3a:	e8 95       	spm
-    3f3c:	27 c0       	rjmp	.+78     	; 0x3f8c <main+0x18c>
+    3f1e:	f0 92 57 00 	sts	0x0057, r15
+    3f22:	e8 95       	spm
+    3f24:	27 c0       	rjmp	.+78     	; 0x3f74 <main+0x174>
     }
     /* Read memory block mode, length is big endian.  */
     else if(ch == STK_READ_PAGE) {
-    3f3e:	84 37       	cpi	r24, 0x74	; 116
-    3f40:	b9 f4       	brne	.+46     	; 0x3f70 <main+0x170>
+    3f26:	84 37       	cpi	r24, 0x74	; 116
+    3f28:	b9 f4       	brne	.+46     	; 0x3f58 <main+0x158>
       // READ PAGE - we only read flash
       getLen();
-    3f42:	48 d0       	rcall	.+144    	; 0x3fd4 <getLen>
+    3f2a:	4a d0       	rcall	.+148    	; 0x3fc0 <getLen>
       verifySpace();
-    3f44:	4c d0       	rcall	.+152    	; 0x3fde <verifySpace>
+    3f2c:	59 d0       	rcall	.+178    	; 0x3fe0 <verifySpace>
       do putch(pgm_read_byte_near(address++));
-    3f46:	e0 91 00 02 	lds	r30, 0x0200
-    3f4a:	f0 91 01 02 	lds	r31, 0x0201
-    3f4e:	31 96       	adiw	r30, 0x01	; 1
-    3f50:	f0 93 01 02 	sts	0x0201, r31
-    3f54:	e0 93 00 02 	sts	0x0200, r30
-    3f58:	31 97       	sbiw	r30, 0x01	; 1
-    3f5a:	e4 91       	lpm	r30, Z+
-    3f5c:	8e 2f       	mov	r24, r30
-    3f5e:	19 d0       	rcall	.+50     	; 0x3f92 <putch>
+    3f2e:	e0 91 00 02 	lds	r30, 0x0200
+    3f32:	f0 91 01 02 	lds	r31, 0x0201
+    3f36:	31 96       	adiw	r30, 0x01	; 1
+    3f38:	f0 93 01 02 	sts	0x0201, r31
+    3f3c:	e0 93 00 02 	sts	0x0200, r30
+    3f40:	31 97       	sbiw	r30, 0x01	; 1
+    3f42:	e4 91       	lpm	r30, Z+
+    3f44:	8e 2f       	mov	r24, r30
+    3f46:	19 d0       	rcall	.+50     	; 0x3f7a <putch>
       while (--length);
-    3f60:	80 91 02 02 	lds	r24, 0x0202
-    3f64:	81 50       	subi	r24, 0x01	; 1
-    3f66:	80 93 02 02 	sts	0x0202, r24
-    3f6a:	88 23       	and	r24, r24
-    3f6c:	61 f7       	brne	.-40     	; 0x3f46 <main+0x146>
-    3f6e:	0e c0       	rjmp	.+28     	; 0x3f8c <main+0x18c>
+    3f48:	80 91 02 02 	lds	r24, 0x0202
+    3f4c:	81 50       	subi	r24, 0x01	; 1
+    3f4e:	80 93 02 02 	sts	0x0202, r24
+    3f52:	88 23       	and	r24, r24
+    3f54:	61 f7       	brne	.-40     	; 0x3f2e <main+0x12e>
+    3f56:	0e c0       	rjmp	.+28     	; 0x3f74 <main+0x174>
     }
 
     /* Get device signature bytes  */
     else if(ch == STK_READ_SIGN) {
-    3f70:	85 37       	cpi	r24, 0x75	; 117
-    3f72:	39 f4       	brne	.+14     	; 0x3f82 <main+0x182>
+    3f58:	85 37       	cpi	r24, 0x75	; 117
+    3f5a:	39 f4       	brne	.+14     	; 0x3f6a <main+0x16a>
       // READ SIGN - return what Avrdude wants to hear
       verifySpace();
-    3f74:	34 d0       	rcall	.+104    	; 0x3fde <verifySpace>
+    3f5c:	41 d0       	rcall	.+130    	; 0x3fe0 <verifySpace>
       putch(SIGNATURE_0);
-    3f76:	8e e1       	ldi	r24, 0x1E	; 30
-    3f78:	0c d0       	rcall	.+24     	; 0x3f92 <putch>
+    3f5e:	8e e1       	ldi	r24, 0x1E	; 30
+    3f60:	0c d0       	rcall	.+24     	; 0x3f7a <putch>
       putch(SIGNATURE_1);
-    3f7a:	84 e9       	ldi	r24, 0x94	; 148
-    3f7c:	0a d0       	rcall	.+20     	; 0x3f92 <putch>
+    3f62:	84 e9       	ldi	r24, 0x94	; 148
+    3f64:	0a d0       	rcall	.+20     	; 0x3f7a <putch>
       putch(SIGNATURE_2);
-    3f7e:	86 e0       	ldi	r24, 0x06	; 6
-    3f80:	93 cf       	rjmp	.-218    	; 0x3ea8 <main+0xa8>
+    3f66:	86 e0       	ldi	r24, 0x06	; 6
+    3f68:	96 cf       	rjmp	.-212    	; 0x3e96 <main+0x96>
     }
     else if (ch == 'Q') {
-    3f82:	81 35       	cpi	r24, 0x51	; 81
-    3f84:	11 f4       	brne	.+4      	; 0x3f8a <main+0x18a>
+    3f6a:	81 35       	cpi	r24, 0x51	; 81
+    3f6c:	11 f4       	brne	.+4      	; 0x3f72 <main+0x172>
       // Adaboot no-wait mod
-      WDTCSR = _BV(WDE);
-    3f86:	c0 92 60 00 	sts	0x0060, r12
+      watchdogConfig(_BV(WDE));
+    3f6e:	88 e0       	ldi	r24, 0x08	; 8
+    3f70:	2c d0       	rcall	.+88     	; 0x3fca <watchdogConfig>
       verifySpace();
     }
     else {
       // This covers the response to commands like STK_ENTER_PROGMODE
       verifySpace();
-    3f8a:	29 d0       	rcall	.+82     	; 0x3fde <verifySpace>
+    3f72:	36 d0       	rcall	.+108    	; 0x3fe0 <verifySpace>
     }
     putch(STK_OK);
-    3f8c:	80 e1       	ldi	r24, 0x10	; 16
-    3f8e:	01 d0       	rcall	.+2      	; 0x3f92 <putch>
-    3f90:	60 cf       	rjmp	.-320    	; 0x3e52 <main+0x52>
-
-00003f92 <putch>:
-  }
-}
+    3f74:	80 e1       	ldi	r24, 0x10	; 16
+    3f76:	01 d0       	rcall	.+2      	; 0x3f7a <putch>
+    3f78:	63 cf       	rjmp	.-314    	; 0x3e40 <main+0x40>
 
+00003f7a <putch>:
 void putch(char ch) {
-    3f92:	98 2f       	mov	r25, r24
+#ifndef SOFT_UART
   while (!(UCSR0A & _BV(UDRE0)));
-    3f94:	80 91 c0 00 	lds	r24, 0x00C0
-    3f98:	85 ff       	sbrs	r24, 5
-    3f9a:	fc cf       	rjmp	.-8      	; 0x3f94 <putch+0x2>
   UDR0 = ch;
-    3f9c:	90 93 c6 00 	sts	0x00C6, r25
-}
-    3fa0:	08 95       	ret
-
-00003fa2 <setTimer>:
-
-void setTimer(uint16_t counts) {
-  TCNT1 = counts;
-    3fa2:	90 93 85 00 	sts	0x0085, r25
-    3fa6:	80 93 84 00 	sts	0x0084, r24
-  TIFR1 = _BV(TOV1);
-    3faa:	81 e0       	ldi	r24, 0x01	; 1
-    3fac:	86 bb       	out	0x16, r24	; 22
+#else
+  __asm__ __volatile__ (
+    3f7a:	2a e0       	ldi	r18, 0x0A	; 10
+    3f7c:	30 e0       	ldi	r19, 0x00	; 0
+    3f7e:	80 95       	com	r24
+    3f80:	08 94       	sec
+    3f82:	10 f4       	brcc	.+4      	; 0x3f88 <putch+0xe>
+    3f84:	59 98       	cbi	0x0b, 1	; 11
+    3f86:	02 c0       	rjmp	.+4      	; 0x3f8c <putch+0x12>
+    3f88:	59 9a       	sbi	0x0b, 1	; 11
+    3f8a:	00 00       	nop
+    3f8c:	15 d0       	rcall	.+42     	; 0x3fb8 <uartDelay>
+    3f8e:	14 d0       	rcall	.+40     	; 0x3fb8 <uartDelay>
+    3f90:	86 95       	lsr	r24
+    3f92:	2a 95       	dec	r18
+    3f94:	b1 f7       	brne	.-20     	; 0x3f82 <putch+0x8>
+      [uartBit] "I" (UART_TX_BIT)
+    :
+      "r25"
+  );
+#endif
 }
-    3fae:	08 95       	ret
+    3f96:	08 95       	ret
 
-00003fb0 <appStart>:
-  length = getch();
+00003f98 <getch>:
   return getch();
 }
 
-void appStart() {
+// Watchdog functions. These are only safe with interrupts turned off.
+void watchdogReset() {
   __asm__ __volatile__ (
-    3fb0:	ee 27       	eor	r30, r30
-    3fb2:	ff 27       	eor	r31, r31
-    3fb4:	09 94       	ijmp
+    3f98:	a8 95       	wdr
+#ifdef LED_DATA_FLASH
+  LED_PIN |= _BV(LED);
+#endif
 
-00003fb6 <getch>:
-  TCNT1 = counts;
-  TIFR1 = _BV(TOV1);
+  return ch;
 }
+    3f9a:	29 e0       	ldi	r18, 0x09	; 9
+    3f9c:	30 e0       	ldi	r19, 0x00	; 0
+    3f9e:	48 99       	sbic	0x09, 0	; 9
+    3fa0:	fe cf       	rjmp	.-4      	; 0x3f9e <getch+0x6>
+    3fa2:	0a d0       	rcall	.+20     	; 0x3fb8 <uartDelay>
+    3fa4:	09 d0       	rcall	.+18     	; 0x3fb8 <uartDelay>
+    3fa6:	08 d0       	rcall	.+16     	; 0x3fb8 <uartDelay>
+    3fa8:	88 94       	clc
+    3faa:	48 99       	sbic	0x09, 0	; 9
+    3fac:	08 94       	sec
+    3fae:	2a 95       	dec	r18
+    3fb0:	11 f0       	breq	.+4      	; 0x3fb6 <getch+0x1e>
+    3fb2:	87 95       	ror	r24
+    3fb4:	f7 cf       	rjmp	.-18     	; 0x3fa4 <getch+0xc>
+    3fb6:	08 95       	ret
+
+00003fb8 <uartDelay>:
+#if UART_B_VALUE > 255
+#error Baud rate too slow for soft UART
+#endif
 
-uint8_t getch(void) {
-  LED_PORT &= ~_BV(LED);
-    3fb6:	2d 98       	cbi	0x05, 5	; 5
-  setTimer(-(F_CPU/(1024*2))); // 500ms
-    3fb8:	8b ed       	ldi	r24, 0xDB	; 219
-    3fba:	99 ed       	ldi	r25, 0xD9	; 217
-    3fbc:	f2 df       	rcall	.-28     	; 0x3fa2 <setTimer>
-    3fbe:	02 c0       	rjmp	.+4      	; 0x3fc4 <getch+0xe>
-  while(!(UCSR0A & _BV(RXC0))) if (TIFR1 & _BV(TOV1)) appStart();
-    3fc0:	b0 99       	sbic	0x16, 0	; 22
-    3fc2:	f6 df       	rcall	.-20     	; 0x3fb0 <appStart>
-    3fc4:	80 91 c0 00 	lds	r24, 0x00C0
-    3fc8:	87 ff       	sbrs	r24, 7
-    3fca:	fa cf       	rjmp	.-12     	; 0x3fc0 <getch+0xa>
-  LED_PORT |= _BV(LED);
-    3fcc:	2d 9a       	sbi	0x05, 5	; 5
-  return UDR0;
-    3fce:	80 91 c6 00 	lds	r24, 0x00C6
-}
-    3fd2:	08 95       	ret
+void uartDelay() {
+  __asm__ __volatile__ (
+    3fb8:	9b e0       	ldi	r25, 0x0B	; 11
+    3fba:	9a 95       	dec	r25
+    3fbc:	f1 f7       	brne	.-4      	; 0x3fba <uartDelay+0x2>
+    3fbe:	08 95       	ret
 
-00003fd4 <getLen>:
-    LED_PIN |= _BV(LED);
+00003fc0 <getLen>:
   } while (--count);
 }
+#endif
 
 uint8_t getLen() {
   getch();
-    3fd4:	f0 df       	rcall	.-32     	; 0x3fb6 <getch>
+    3fc0:	eb df       	rcall	.-42     	; 0x3f98 <getch>
   length = getch();
-    3fd6:	ef df       	rcall	.-34     	; 0x3fb6 <getch>
-    3fd8:	80 93 02 02 	sts	0x0202, r24
+    3fc2:	ea df       	rcall	.-44     	; 0x3f98 <getch>
+    3fc4:	80 93 02 02 	sts	0x0202, r24
   return getch();
 }
-    3fdc:	ec cf       	rjmp	.-40     	; 0x3fb6 <getch>
+    3fc8:	e7 cf       	rjmp	.-50     	; 0x3f98 <getch>
+
+00003fca <watchdogConfig>:
+    "wdr\n"
+  );
+}
 
-00003fde <verifySpace>:
+void watchdogConfig(uint8_t x) {
+  WDTCSR = _BV(WDCE) | _BV(WDE);
+    3fca:	e0 e6       	ldi	r30, 0x60	; 96
+    3fcc:	f0 e0       	ldi	r31, 0x00	; 0
+    3fce:	98 e1       	ldi	r25, 0x18	; 24
+    3fd0:	90 83       	st	Z, r25
+  WDTCSR = x;
+    3fd2:	80 83       	st	Z, r24
+}
+    3fd4:	08 95       	ret
+
+00003fd6 <appStart>:
+
+void appStart() {
+  watchdogConfig(0);
+    3fd6:	80 e0       	ldi	r24, 0x00	; 0
+    3fd8:	f8 df       	rcall	.-16     	; 0x3fca <watchdogConfig>
+  __asm__ __volatile__ (
+    3fda:	ee 27       	eor	r30, r30
+    3fdc:	ff 27       	eor	r31, r31
+    3fde:	09 94       	ijmp
+
+00003fe0 <verifySpace>:
   do getch(); while (--count);
   verifySpace();
 }
 
 void verifySpace() {
   if (getch() != CRC_EOP) appStart();
-    3fde:	eb df       	rcall	.-42     	; 0x3fb6 <getch>
-    3fe0:	80 32       	cpi	r24, 0x20	; 32
-    3fe2:	09 f0       	breq	.+2      	; 0x3fe6 <verifySpace+0x8>
-    3fe4:	e5 df       	rcall	.-54     	; 0x3fb0 <appStart>
+    3fe0:	db df       	rcall	.-74     	; 0x3f98 <getch>
+    3fe2:	80 32       	cpi	r24, 0x20	; 32
+    3fe4:	09 f0       	breq	.+2      	; 0x3fe8 <verifySpace+0x8>
+    3fe6:	f7 df       	rcall	.-18     	; 0x3fd6 <appStart>
   putch(STK_INSYNC);
-    3fe6:	84 e1       	ldi	r24, 0x14	; 20
+    3fe8:	84 e1       	ldi	r24, 0x14	; 20
 }
-    3fe8:	d4 cf       	rjmp	.-88     	; 0x3f92 <putch>
-  while(!(UCSR0A & _BV(RXC0))) if (TIFR1 & _BV(TOV1)) appStart();
-  LED_PORT |= _BV(LED);
-  return UDR0;
+    3fea:	c7 cf       	rjmp	.-114    	; 0x3f7a <putch>
+    ::[count] "M" (UART_B_VALUE)
+  );
 }
+#endif
 
 void getNch(uint8_t count) {
-    3fea:	1f 93       	push	r17
-    3fec:	18 2f       	mov	r17, r24
+    3fec:	1f 93       	push	r17
+    3fee:	18 2f       	mov	r17, r24
 
-00003fee <getNch>:
+00003ff0 <getNch>:
   do getch(); while (--count);
-    3fee:	e3 df       	rcall	.-58     	; 0x3fb6 <getch>
-    3ff0:	11 50       	subi	r17, 0x01	; 1
-    3ff2:	e9 f7       	brne	.-6      	; 0x3fee <getNch>
+    3ff0:	d3 df       	rcall	.-90     	; 0x3f98 <getch>
+    3ff2:	11 50       	subi	r17, 0x01	; 1
+    3ff4:	e9 f7       	brne	.-6      	; 0x3ff0 <getNch>
   verifySpace();
-    3ff4:	f4 df       	rcall	.-24     	; 0x3fde <verifySpace>
+    3ff6:	f4 df       	rcall	.-24     	; 0x3fe0 <verifySpace>
 }
-    3ff6:	1f 91       	pop	r17
-    3ff8:	08 95       	ret
+    3ff8:	1f 91       	pop	r17
+    3ffa:	08 95       	ret

+ 32 - 32
optiboot/bootloaders/optiboot/optiboot_pro_8MHz.hex

@@ -1,34 +1,34 @@
-:103E000085E08093810082E08093C00098E19093E8
-:103E1000C10086E08093C20083E38093C40084B72E
-:103E200014BE909360001092600081FFC1D0259A6B
-:103E300002E088E19EEFB5D0B09BFECF1D9A015005
-:103E4000C1F7DD24D394B8E0CB2EA5E0EA2EF1E152
-:103E5000FF2EB1D0813421F481E0C7D083E024C0AB
-:103E6000823411F484E103C0853419F485E0BDD0B7
-:103E70008DC08535A1F49FD0082F10E0109301026A
-:103E80000093000298D090E0982F8827802B912BE8
-:103E9000880F991F909301028093000276C08635A7
-:103EA00029F484E0A2D080E074D070C0843609F098
-:103EB00046C090D0863409F07BD0E0910002F091AA
-:103EC000010283E080935700E895C0E0D1E073D011
-:103ED0008993809102028150809302028823B9F76E
-:103EE00007B600FCFDCF7BD040910002509101024B
-:103EF000A0E0B1E02C9130E011968C91119790E008
-:103F0000982F8827822B932B1296FA010C01D092BE
-:103F10005700E89511244E5F5F4FF1E0A038BF07CE
-:103F200049F7E0910002F0910102E0925700E89514
-:103F300007B600FCFDCFF0925700E89527C0843704
-:103F4000B9F448D04CD0E0910002F09101023196D2
-:103F5000F0930102E09300023197E4918E2F19D083
-:103F600080910202815080930202882361F70EC083
-:103F7000853739F434D08EE10CD084E90AD086E05C
-:103F800093CF813511F4C092600029D080E101D037
-:103F900060CF982F8091C00085FFFCCF9093C60022
-:103FA0000895909385008093840081E086BB0895F6
-:103FB000EE27FF2709942D988EEB90EFF2DF02C0D9
-:103FC000B099F6DF8091C00087FFFACF2D9A8091DB
-:103FD000C6000895F0DFEFDF80930202ECCFEBDF45
-:103FE000803209F0E5DF84E1D4CF1F93182FE3DF9F
-:0A3FF0001150E9F7F4DF1F91089566
+:103E000085E08093810084B714BE81FFE4D08DE00B
+:103E1000DCD0259A519A86E028E13EEF91E030937C
+:103E200085002093840096BBB09BFECF1D9AA89579
+:103E30008150A9F7DD24D394A5E0EA2EF1E1FF2E0D
+:103E4000ABD0813421F481E0D1D083E024C082342E
+:103E500011F484E103C0853419F485E0C7D08AC029
+:103E60008535A1F499D0082F10E01093010200933A
+:103E7000000292D090E0982F8827802B912B880FFA
+:103E8000991F909301028093000273C0863529F434
+:103E900084E0ACD080E071D06DC0843609F043C0BE
+:103EA0008FD0E0910002F091010283E080935700EF
+:103EB000E895C0E0D1E070D08993809102028150F2
+:103EC000809302028823B9F78BD007B600FCFDCFA0
+:103ED0004091000250910102A0E0B1E02C9130E04D
+:103EE00011968C91119790E0982F8827822B932B15
+:103EF0001296FA010C01D0925700E89511244E5FFA
+:103F00005F4FF1E0A038BF0749F7E0910002F09160
+:103F10000102E0925700E89507B600FCFDCFF09251
+:103F20005700E89527C08437B9F44AD059D0E091BA
+:103F30000002F09101023196F0930102E093000239
+:103F40003197E4918E2F19D0809102028150809395
+:103F50000202882361F70EC0853739F441D08EE123
+:103F60000CD084E90AD086E096CF813511F488E040
+:103F70002CD036D080E101D063CF2AE030E08095AC
+:103F8000089410F4599802C0599A000015D014D022
+:103F900086952A95B1F70895A89529E030E04899CB
+:103FA000FECF0AD009D008D08894489908942A9561
+:103FB00011F08795F7CF089598E09A95F1F7089555
+:103FC000EBDFEADF80930202E7CFE0E6F0E098E182
+:103FD00090838083089580E0F8DFEE27FF2709941F
+:103FE000DBDF803209F0F7DF84E1C7CF1F93182FA2
+:0C3FF000D3DF1150E9F7F4DF1F910895B2
 :0400000300003E00BB
 :00000001FF

+ 320 - 282
optiboot/bootloaders/optiboot/optiboot_pro_8MHz.lst

@@ -3,25 +3,25 @@ optiboot_pro_8MHz.elf:     file format elf32-avr
 
 Sections:
 Idx Name          Size      VMA       LMA       File off  Algn
-  0 .text         000001fa  00003e00  00003e00  00000054  2**1
+  0 .text         000001fc  00003e00  00003e00  00000054  2**1
                   CONTENTS, ALLOC, LOAD, READONLY, CODE
-  1 .debug_aranges 00000028  00000000  00000000  0000024e  2**0
+  1 .debug_aranges 00000028  00000000  00000000  00000250  2**0
                   CONTENTS, READONLY, DEBUGGING
-  2 .debug_pubnames 00000064  00000000  00000000  00000276  2**0
+  2 .debug_pubnames 00000078  00000000  00000000  00000278  2**0
                   CONTENTS, READONLY, DEBUGGING
-  3 .debug_info   0000022f  00000000  00000000  000002da  2**0
+  3 .debug_info   00000275  00000000  00000000  000002f0  2**0
                   CONTENTS, READONLY, DEBUGGING
-  4 .debug_abbrev 00000164  00000000  00000000  00000509  2**0
+  4 .debug_abbrev 000001a3  00000000  00000000  00000565  2**0
                   CONTENTS, READONLY, DEBUGGING
-  5 .debug_line   000003c8  00000000  00000000  0000066d  2**0
+  5 .debug_line   000003b8  00000000  00000000  00000708  2**0
                   CONTENTS, READONLY, DEBUGGING
-  6 .debug_frame  00000090  00000000  00000000  00000a38  2**2
+  6 .debug_frame  000000a0  00000000  00000000  00000ac0  2**2
                   CONTENTS, READONLY, DEBUGGING
-  7 .debug_str    0000011c  00000000  00000000  00000ac8  2**0
+  7 .debug_str    00000133  00000000  00000000  00000b60  2**0
                   CONTENTS, READONLY, DEBUGGING
-  8 .debug_loc    000001d6  00000000  00000000  00000be4  2**0
+  8 .debug_loc    000001a0  00000000  00000000  00000c93  2**0
                   CONTENTS, READONLY, DEBUGGING
-  9 .debug_ranges 00000068  00000000  00000000  00000dba  2**0
+  9 .debug_ranges 00000070  00000000  00000000  00000e33  2**0
                   CONTENTS, READONLY, DEBUGGING
 
 Disassembly of section .text:
@@ -35,449 +35,487 @@ Disassembly of section .text:
 int main(void) {
     3e00:	85 e0       	ldi	r24, 0x05	; 5
     3e02:	80 93 81 00 	sts	0x0081, r24
-    [addr5]"i"(_SFR_MEM_ADDR(UBRR0L)), [val5]"i"((F_CPU + BAUD_RATE * 4L) / (BAUD_RATE * 8L) - 1)
-  );
-#else
-  // Set up Timer 1 for timeout counter
-  TCCR1B = _BV(CS12) | _BV(CS10); // div 1024
-  UCSR0A = _BV(U2X0); //Double speed mode USART0
-    3e06:	82 e0       	ldi	r24, 0x02	; 2
-    3e08:	80 93 c0 00 	sts	0x00C0, r24
-  UCSR0B = _BV(RXEN0) | _BV(TXEN0);
-    3e0c:	98 e1       	ldi	r25, 0x18	; 24
-    3e0e:	90 93 c1 00 	sts	0x00C1, r25
   UCSR0C = _BV(UCSZ00) | _BV(UCSZ01);
-    3e12:	86 e0       	ldi	r24, 0x06	; 6
-    3e14:	80 93 c2 00 	sts	0x00C2, r24
   UBRR0L = (uint8_t)( (F_CPU + BAUD_RATE * 4L) / (BAUD_RATE * 8L) - 1 );
-    3e18:	83 e3       	ldi	r24, 0x33	; 51
-    3e1a:	80 93 c4 00 	sts	0x00C4, r24
 #endif
 
   // Adaboot no-wait mod
   ch = MCUSR;
-    3e1e:	84 b7       	in	r24, 0x34	; 52
+    3e06:	84 b7       	in	r24, 0x34	; 52
   MCUSR = 0;
-    3e20:	14 be       	out	0x34, r1	; 52
-  WDTCSR = _BV(WDCE) | _BV(WDE);
-    3e22:	90 93 60 00 	sts	0x0060, r25
-  WDTCSR = 0;
-    3e26:	10 92 60 00 	sts	0x0060, r1
+    3e08:	14 be       	out	0x34, r1	; 52
   if (!(ch & _BV(EXTRF))) appStart();
-    3e2a:	81 ff       	sbrs	r24, 1
-    3e2c:	c1 d0       	rcall	.+386    	; 0x3fb0 <appStart>
+    3e0a:	81 ff       	sbrs	r24, 1
+    3e0c:	e4 d0       	rcall	.+456    	; 0x3fd6 <appStart>
+
+  // Set up watchdog to trigger after 500ms
+  watchdogConfig(_BV(WDP2)|_BV(WDP0)|_BV(WDE));
+    3e0e:	8d e0       	ldi	r24, 0x0D	; 13
+    3e10:	dc d0       	rcall	.+440    	; 0x3fca <watchdogConfig>
 
-  /* set LED pin as output */
+  /* Set LED pin as output */
   LED_DDR |= _BV(LED);
-    3e2e:	25 9a       	sbi	0x04, 5	; 4
-    3e30:	02 e0       	ldi	r16, 0x02	; 2
-  putch(STK_INSYNC);
+    3e12:	25 9a       	sbi	0x04, 5	; 4
+
+#ifdef SOFT_UART
+  /* Set TX pin as output */
+  UART_DDR |= _BV(UART_TX_BIT);
+    3e14:	51 9a       	sbi	0x0a, 1	; 10
+    3e16:	86 e0       	ldi	r24, 0x06	; 6
+}
+
+#if LED_START_FLASHES > 0
+void flash_led(uint8_t count) {
+  do {
+    TCNT1 = -(F_CPU/(1024*16));
+    3e18:	28 e1       	ldi	r18, 0x18	; 24
+    3e1a:	3e ef       	ldi	r19, 0xFE	; 254
+    TIFR1 = _BV(TOV1);
+    3e1c:	91 e0       	ldi	r25, 0x01	; 1
 }
 
+#if LED_START_FLASHES > 0
 void flash_led(uint8_t count) {
   do {
-    setTimer(-(F_CPU/(1024*16))); // 62ms
-    3e32:	88 e1       	ldi	r24, 0x18	; 24
-    3e34:	9e ef       	ldi	r25, 0xFE	; 254
-    3e36:	b5 d0       	rcall	.+362    	; 0x3fa2 <setTimer>
+    TCNT1 = -(F_CPU/(1024*16));
+    3e1e:	30 93 85 00 	sts	0x0085, r19
+    3e22:	20 93 84 00 	sts	0x0084, r18
+    TIFR1 = _BV(TOV1);
+    3e26:	96 bb       	out	0x16, r25	; 22
+    while(!(TIFR1 & _BV(TOV1)));
+    3e28:	b0 9b       	sbis	0x16, 0	; 22
+    3e2a:	fe cf       	rjmp	.-4      	; 0x3e28 <main+0x28>
+    LED_PIN |= _BV(LED);
+    3e2c:	1d 9a       	sbi	0x03, 5	; 3
+  return getch();
+}
+
+// Watchdog functions. These are only safe with interrupts turned off.
+void watchdogReset() {
+  __asm__ __volatile__ (
+    3e2e:	a8 95       	wdr
+    TCNT1 = -(F_CPU/(1024*16));
+    TIFR1 = _BV(TOV1);
     while(!(TIFR1 & _BV(TOV1)));
-    3e38:	b0 9b       	sbis	0x16, 0	; 22
-    3e3a:	fe cf       	rjmp	.-4      	; 0x3e38 <main+0x38>
     LED_PIN |= _BV(LED);
-    3e3c:	1d 9a       	sbi	0x03, 5	; 3
+    watchdogReset();
   } while (--count);
-    3e3e:	01 50       	subi	r16, 0x01	; 1
-    3e40:	c1 f7       	brne	.-16     	; 0x3e32 <main+0x32>
+    3e30:	81 50       	subi	r24, 0x01	; 1
+    3e32:	a9 f7       	brne	.-22     	; 0x3e1e <main+0x1e>
     /* get character from UART */
     ch = getch();
 
     if(ch == STK_GET_PARAMETER) {
       // GET PARAMETER returns a generic 0x03 reply - enough to keep Avrdude happy
       getNch(1);
-    3e42:	dd 24       	eor	r13, r13
-    3e44:	d3 94       	inc	r13
-      putch(SIGNATURE_1);
-      putch(SIGNATURE_2);
-    }
-    else if (ch == 'Q') {
-      // Adaboot no-wait mod
-      WDTCSR = _BV(WDE);
-    3e46:	b8 e0       	ldi	r27, 0x08	; 8
-    3e48:	cb 2e       	mov	r12, r27
+    3e34:	dd 24       	eor	r13, r13
+    3e36:	d3 94       	inc	r13
         boot_page_fill((uint16_t)(void*)addrPtr,a);
         addrPtr += 2;
       } while (--ch);
       
       // Write from programming buffer
       boot_page_write((uint16_t)(void*)address);
-    3e4a:	a5 e0       	ldi	r26, 0x05	; 5
-    3e4c:	ea 2e       	mov	r14, r26
+    3e38:	a5 e0       	ldi	r26, 0x05	; 5
+    3e3a:	ea 2e       	mov	r14, r26
       boot_spm_busy_wait();
 
       // Reenable read access to flash
       boot_rww_enable();
-    3e4e:	f1 e1       	ldi	r31, 0x11	; 17
-    3e50:	ff 2e       	mov	r15, r31
-  flash_led(NUM_LED_FLASHES * 2);
+    3e3c:	f1 e1       	ldi	r31, 0x11	; 17
+    3e3e:	ff 2e       	mov	r15, r31
+#endif
 
-  /* forever loop */
+  /* Forever loop */
   for (;;) {
     /* get character from UART */
     ch = getch();
-    3e52:	b1 d0       	rcall	.+354    	; 0x3fb6 <getch>
+    3e40:	ab d0       	rcall	.+342    	; 0x3f98 <getch>
 
     if(ch == STK_GET_PARAMETER) {
-    3e54:	81 34       	cpi	r24, 0x41	; 65
-    3e56:	21 f4       	brne	.+8      	; 0x3e60 <main+0x60>
+    3e42:	81 34       	cpi	r24, 0x41	; 65
+    3e44:	21 f4       	brne	.+8      	; 0x3e4e <main+0x4e>
       // GET PARAMETER returns a generic 0x03 reply - enough to keep Avrdude happy
       getNch(1);
-    3e58:	81 e0       	ldi	r24, 0x01	; 1
-    3e5a:	c7 d0       	rcall	.+398    	; 0x3fea <verifySpace+0xc>
+    3e46:	81 e0       	ldi	r24, 0x01	; 1
+    3e48:	d1 d0       	rcall	.+418    	; 0x3fec <verifySpace+0xc>
       putch(0x03);
-    3e5c:	83 e0       	ldi	r24, 0x03	; 3
-    3e5e:	24 c0       	rjmp	.+72     	; 0x3ea8 <main+0xa8>
+    3e4a:	83 e0       	ldi	r24, 0x03	; 3
+    3e4c:	24 c0       	rjmp	.+72     	; 0x3e96 <main+0x96>
     }
     else if(ch == STK_SET_DEVICE) {
-    3e60:	82 34       	cpi	r24, 0x42	; 66
-    3e62:	11 f4       	brne	.+4      	; 0x3e68 <main+0x68>
+    3e4e:	82 34       	cpi	r24, 0x42	; 66
+    3e50:	11 f4       	brne	.+4      	; 0x3e56 <main+0x56>
       // SET DEVICE is ignored
       getNch(20);
-    3e64:	84 e1       	ldi	r24, 0x14	; 20
-    3e66:	03 c0       	rjmp	.+6      	; 0x3e6e <main+0x6e>
+    3e52:	84 e1       	ldi	r24, 0x14	; 20
+    3e54:	03 c0       	rjmp	.+6      	; 0x3e5c <main+0x5c>
     }
     else if(ch == STK_SET_DEVICE_EXT) {
-    3e68:	85 34       	cpi	r24, 0x45	; 69
-    3e6a:	19 f4       	brne	.+6      	; 0x3e72 <main+0x72>
+    3e56:	85 34       	cpi	r24, 0x45	; 69
+    3e58:	19 f4       	brne	.+6      	; 0x3e60 <main+0x60>
       // SET DEVICE EXT is ignored
       getNch(5);
-    3e6c:	85 e0       	ldi	r24, 0x05	; 5
-    3e6e:	bd d0       	rcall	.+378    	; 0x3fea <verifySpace+0xc>
-    3e70:	8d c0       	rjmp	.+282    	; 0x3f8c <main+0x18c>
+    3e5a:	85 e0       	ldi	r24, 0x05	; 5
+    3e5c:	c7 d0       	rcall	.+398    	; 0x3fec <verifySpace+0xc>
+    3e5e:	8a c0       	rjmp	.+276    	; 0x3f74 <main+0x174>
     }
     else if(ch == STK_LOAD_ADDRESS) {
-    3e72:	85 35       	cpi	r24, 0x55	; 85
-    3e74:	a1 f4       	brne	.+40     	; 0x3e9e <main+0x9e>
+    3e60:	85 35       	cpi	r24, 0x55	; 85
+    3e62:	a1 f4       	brne	.+40     	; 0x3e8c <main+0x8c>
       // LOAD ADDRESS
       address = getch();
-    3e76:	9f d0       	rcall	.+318    	; 0x3fb6 <getch>
-    3e78:	08 2f       	mov	r16, r24
-    3e7a:	10 e0       	ldi	r17, 0x00	; 0
-    3e7c:	10 93 01 02 	sts	0x0201, r17
-    3e80:	00 93 00 02 	sts	0x0200, r16
+    3e64:	99 d0       	rcall	.+306    	; 0x3f98 <getch>
+    3e66:	08 2f       	mov	r16, r24
+    3e68:	10 e0       	ldi	r17, 0x00	; 0
+    3e6a:	10 93 01 02 	sts	0x0201, r17
+    3e6e:	00 93 00 02 	sts	0x0200, r16
       address = (address & 0xff) | (getch() << 8);
-    3e84:	98 d0       	rcall	.+304    	; 0x3fb6 <getch>
-    3e86:	90 e0       	ldi	r25, 0x00	; 0
-    3e88:	98 2f       	mov	r25, r24
-    3e8a:	88 27       	eor	r24, r24
-    3e8c:	80 2b       	or	r24, r16
-    3e8e:	91 2b       	or	r25, r17
+    3e72:	92 d0       	rcall	.+292    	; 0x3f98 <getch>
+    3e74:	90 e0       	ldi	r25, 0x00	; 0
+    3e76:	98 2f       	mov	r25, r24
+    3e78:	88 27       	eor	r24, r24
+    3e7a:	80 2b       	or	r24, r16
+    3e7c:	91 2b       	or	r25, r17
       address += address; // Convert from word address to byte address
-    3e90:	88 0f       	add	r24, r24
-    3e92:	99 1f       	adc	r25, r25
-    3e94:	90 93 01 02 	sts	0x0201, r25
-    3e98:	80 93 00 02 	sts	0x0200, r24
-    3e9c:	76 c0       	rjmp	.+236    	; 0x3f8a <main+0x18a>
+    3e7e:	88 0f       	add	r24, r24
+    3e80:	99 1f       	adc	r25, r25
+    3e82:	90 93 01 02 	sts	0x0201, r25
+    3e86:	80 93 00 02 	sts	0x0200, r24
+    3e8a:	73 c0       	rjmp	.+230    	; 0x3f72 <main+0x172>
       verifySpace();
     }
     else if(ch == STK_UNIVERSAL) {
-    3e9e:	86 35       	cpi	r24, 0x56	; 86
-    3ea0:	29 f4       	brne	.+10     	; 0x3eac <main+0xac>
+    3e8c:	86 35       	cpi	r24, 0x56	; 86
+    3e8e:	29 f4       	brne	.+10     	; 0x3e9a <main+0x9a>
       // UNIVERSAL command is ignored
       getNch(4);
-    3ea2:	84 e0       	ldi	r24, 0x04	; 4
-    3ea4:	a2 d0       	rcall	.+324    	; 0x3fea <verifySpace+0xc>
+    3e90:	84 e0       	ldi	r24, 0x04	; 4
+    3e92:	ac d0       	rcall	.+344    	; 0x3fec <verifySpace+0xc>
       putch(0x00);
-    3ea6:	80 e0       	ldi	r24, 0x00	; 0
-    3ea8:	74 d0       	rcall	.+232    	; 0x3f92 <putch>
-    3eaa:	70 c0       	rjmp	.+224    	; 0x3f8c <main+0x18c>
+    3e94:	80 e0       	ldi	r24, 0x00	; 0
+    3e96:	71 d0       	rcall	.+226    	; 0x3f7a <putch>
+    3e98:	6d c0       	rjmp	.+218    	; 0x3f74 <main+0x174>
     }
     /* Write memory, length is big endian and is in bytes  */
     else if(ch == STK_PROG_PAGE) {
-    3eac:	84 36       	cpi	r24, 0x64	; 100
-    3eae:	09 f0       	breq	.+2      	; 0x3eb2 <main+0xb2>
-    3eb0:	46 c0       	rjmp	.+140    	; 0x3f3e <main+0x13e>
+    3e9a:	84 36       	cpi	r24, 0x64	; 100
+    3e9c:	09 f0       	breq	.+2      	; 0x3ea0 <main+0xa0>
+    3e9e:	43 c0       	rjmp	.+134    	; 0x3f26 <main+0x126>
       // PROGRAM PAGE - we support flash programming only, not EEPROM
       uint8_t *bufPtr;
       uint16_t addrPtr;
-      
-      if (getLen() != 'F') appStart(); // Abort is not flash programming
-    3eb2:	90 d0       	rcall	.+288    	; 0x3fd4 <getLen>
-    3eb4:	86 34       	cpi	r24, 0x46	; 70
-    3eb6:	09 f0       	breq	.+2      	; 0x3eba <main+0xba>
-    3eb8:	7b d0       	rcall	.+246    	; 0x3fb0 <appStart>
-  
+
+      getLen();
+    3ea0:	8f d0       	rcall	.+286    	; 0x3fc0 <getLen>
+
       // Immediately start page erase - this will 4.5ms
       boot_page_erase((uint16_t)(void*)address);
-    3eba:	e0 91 00 02 	lds	r30, 0x0200
-    3ebe:	f0 91 01 02 	lds	r31, 0x0201
-    3ec2:	83 e0       	ldi	r24, 0x03	; 3
-    3ec4:	80 93 57 00 	sts	0x0057, r24
-    3ec8:	e8 95       	spm
-    3eca:	c0 e0       	ldi	r28, 0x00	; 0
-    3ecc:	d1 e0       	ldi	r29, 0x01	; 1
+    3ea2:	e0 91 00 02 	lds	r30, 0x0200
+    3ea6:	f0 91 01 02 	lds	r31, 0x0201
+    3eaa:	83 e0       	ldi	r24, 0x03	; 3
+    3eac:	80 93 57 00 	sts	0x0057, r24
+    3eb0:	e8 95       	spm
+    3eb2:	c0 e0       	ldi	r28, 0x00	; 0
+    3eb4:	d1 e0       	ldi	r29, 0x01	; 1
 
       // While that is going on, read in page contents
       bufPtr = buff;
       do *bufPtr++ = getch();
-    3ece:	73 d0       	rcall	.+230    	; 0x3fb6 <getch>
-    3ed0:	89 93       	st	Y+, r24
+    3eb6:	70 d0       	rcall	.+224    	; 0x3f98 <getch>
+    3eb8:	89 93       	st	Y+, r24
       while (--length);
-    3ed2:	80 91 02 02 	lds	r24, 0x0202
-    3ed6:	81 50       	subi	r24, 0x01	; 1
-    3ed8:	80 93 02 02 	sts	0x0202, r24
-    3edc:	88 23       	and	r24, r24
-    3ede:	b9 f7       	brne	.-18     	; 0x3ece <main+0xce>
+    3eba:	80 91 02 02 	lds	r24, 0x0202
+    3ebe:	81 50       	subi	r24, 0x01	; 1
+    3ec0:	80 93 02 02 	sts	0x0202, r24
+    3ec4:	88 23       	and	r24, r24
+    3ec6:	b9 f7       	brne	.-18     	; 0x3eb6 <main+0xb6>
 
+      // Read command terminator, start reply
+      verifySpace();
+    3ec8:	8b d0       	rcall	.+278    	; 0x3fe0 <verifySpace>
+      
       // If only a partial page is to be programmed, the erase might not be complete.
       // So check that here
       boot_spm_busy_wait();
-    3ee0:	07 b6       	in	r0, 0x37	; 55
-    3ee2:	00 fc       	sbrc	r0, 0
-    3ee4:	fd cf       	rjmp	.-6      	; 0x3ee0 <main+0xe0>
+    3eca:	07 b6       	in	r0, 0x37	; 55
+    3ecc:	00 fc       	sbrc	r0, 0
+    3ece:	fd cf       	rjmp	.-6      	; 0x3eca <main+0xca>
 
-      // Read command terminator, start reply
-      verifySpace();
-    3ee6:	7b d0       	rcall	.+246    	; 0x3fde <verifySpace>
-      
       // Copy buffer into programming buffer
       bufPtr = buff;
       addrPtr = (uint16_t)(void*)address;
-    3ee8:	40 91 00 02 	lds	r20, 0x0200
-    3eec:	50 91 01 02 	lds	r21, 0x0201
-    3ef0:	a0 e0       	ldi	r26, 0x00	; 0
-    3ef2:	b1 e0       	ldi	r27, 0x01	; 1
+    3ed0:	40 91 00 02 	lds	r20, 0x0200
+    3ed4:	50 91 01 02 	lds	r21, 0x0201
+    3ed8:	a0 e0       	ldi	r26, 0x00	; 0
+    3eda:	b1 e0       	ldi	r27, 0x01	; 1
       ch = SPM_PAGESIZE / 2;
       do {
         uint16_t a;
         a = *bufPtr++;
-    3ef4:	2c 91       	ld	r18, X
-    3ef6:	30 e0       	ldi	r19, 0x00	; 0
+    3edc:	2c 91       	ld	r18, X
+    3ede:	30 e0       	ldi	r19, 0x00	; 0
         a |= (*bufPtr++) << 8;
-    3ef8:	11 96       	adiw	r26, 0x01	; 1
-    3efa:	8c 91       	ld	r24, X
-    3efc:	11 97       	sbiw	r26, 0x01	; 1
-    3efe:	90 e0       	ldi	r25, 0x00	; 0
-    3f00:	98 2f       	mov	r25, r24
-    3f02:	88 27       	eor	r24, r24
-    3f04:	82 2b       	or	r24, r18
-    3f06:	93 2b       	or	r25, r19
+    3ee0:	11 96       	adiw	r26, 0x01	; 1
+    3ee2:	8c 91       	ld	r24, X
+    3ee4:	11 97       	sbiw	r26, 0x01	; 1
+    3ee6:	90 e0       	ldi	r25, 0x00	; 0
+    3ee8:	98 2f       	mov	r25, r24
+    3eea:	88 27       	eor	r24, r24
+    3eec:	82 2b       	or	r24, r18
+    3eee:	93 2b       	or	r25, r19
 #define buff    ((uint8_t*)(0x100))
 #define address (*(uint16_t*)(0x200))
 #define length  (*(uint8_t*)(0x202))
 
 /* main program starts here */
 int main(void) {
-    3f08:	12 96       	adiw	r26, 0x02	; 2
+    3ef0:	12 96       	adiw	r26, 0x02	; 2
       ch = SPM_PAGESIZE / 2;
       do {
         uint16_t a;
         a = *bufPtr++;
         a |= (*bufPtr++) << 8;
         boot_page_fill((uint16_t)(void*)addrPtr,a);
-    3f0a:	fa 01       	movw	r30, r20
-    3f0c:	0c 01       	movw	r0, r24
-    3f0e:	d0 92 57 00 	sts	0x0057, r13
-    3f12:	e8 95       	spm
-    3f14:	11 24       	eor	r1, r1
+    3ef2:	fa 01       	movw	r30, r20
+    3ef4:	0c 01       	movw	r0, r24
+    3ef6:	d0 92 57 00 	sts	0x0057, r13
+    3efa:	e8 95       	spm
+    3efc:	11 24       	eor	r1, r1
         addrPtr += 2;
-    3f16:	4e 5f       	subi	r20, 0xFE	; 254
-    3f18:	5f 4f       	sbci	r21, 0xFF	; 255
+    3efe:	4e 5f       	subi	r20, 0xFE	; 254
+    3f00:	5f 4f       	sbci	r21, 0xFF	; 255
       } while (--ch);
-    3f1a:	f1 e0       	ldi	r31, 0x01	; 1
-    3f1c:	a0 38       	cpi	r26, 0x80	; 128
-    3f1e:	bf 07       	cpc	r27, r31
-    3f20:	49 f7       	brne	.-46     	; 0x3ef4 <main+0xf4>
+    3f02:	f1 e0       	ldi	r31, 0x01	; 1
+    3f04:	a0 38       	cpi	r26, 0x80	; 128
+    3f06:	bf 07       	cpc	r27, r31
+    3f08:	49 f7       	brne	.-46     	; 0x3edc <main+0xdc>
       
       // Write from programming buffer
       boot_page_write((uint16_t)(void*)address);
-    3f22:	e0 91 00 02 	lds	r30, 0x0200
-    3f26:	f0 91 01 02 	lds	r31, 0x0201
-    3f2a:	e0 92 57 00 	sts	0x0057, r14
-    3f2e:	e8 95       	spm
+    3f0a:	e0 91 00 02 	lds	r30, 0x0200
+    3f0e:	f0 91 01 02 	lds	r31, 0x0201
+    3f12:	e0 92 57 00 	sts	0x0057, r14
+    3f16:	e8 95       	spm
       boot_spm_busy_wait();
-    3f30:	07 b6       	in	r0, 0x37	; 55
-    3f32:	00 fc       	sbrc	r0, 0
-    3f34:	fd cf       	rjmp	.-6      	; 0x3f30 <main+0x130>
+    3f18:	07 b6       	in	r0, 0x37	; 55
+    3f1a:	00 fc       	sbrc	r0, 0
+    3f1c:	fd cf       	rjmp	.-6      	; 0x3f18 <main+0x118>
 
       // Reenable read access to flash
       boot_rww_enable();
-    3f36:	f0 92 57 00 	sts	0x0057, r15
-    3f3a:	e8 95       	spm
-    3f3c:	27 c0       	rjmp	.+78     	; 0x3f8c <main+0x18c>
+    3f1e:	f0 92 57 00 	sts	0x0057, r15
+    3f22:	e8 95       	spm
+    3f24:	27 c0       	rjmp	.+78     	; 0x3f74 <main+0x174>
     }
     /* Read memory block mode, length is big endian.  */
     else if(ch == STK_READ_PAGE) {
-    3f3e:	84 37       	cpi	r24, 0x74	; 116
-    3f40:	b9 f4       	brne	.+46     	; 0x3f70 <main+0x170>
+    3f26:	84 37       	cpi	r24, 0x74	; 116
+    3f28:	b9 f4       	brne	.+46     	; 0x3f58 <main+0x158>
       // READ PAGE - we only read flash
       getLen();
-    3f42:	48 d0       	rcall	.+144    	; 0x3fd4 <getLen>
+    3f2a:	4a d0       	rcall	.+148    	; 0x3fc0 <getLen>
       verifySpace();
-    3f44:	4c d0       	rcall	.+152    	; 0x3fde <verifySpace>
+    3f2c:	59 d0       	rcall	.+178    	; 0x3fe0 <verifySpace>
       do putch(pgm_read_byte_near(address++));
-    3f46:	e0 91 00 02 	lds	r30, 0x0200
-    3f4a:	f0 91 01 02 	lds	r31, 0x0201
-    3f4e:	31 96       	adiw	r30, 0x01	; 1
-    3f50:	f0 93 01 02 	sts	0x0201, r31
-    3f54:	e0 93 00 02 	sts	0x0200, r30
-    3f58:	31 97       	sbiw	r30, 0x01	; 1
-    3f5a:	e4 91       	lpm	r30, Z+
-    3f5c:	8e 2f       	mov	r24, r30
-    3f5e:	19 d0       	rcall	.+50     	; 0x3f92 <putch>
+    3f2e:	e0 91 00 02 	lds	r30, 0x0200
+    3f32:	f0 91 01 02 	lds	r31, 0x0201
+    3f36:	31 96       	adiw	r30, 0x01	; 1
+    3f38:	f0 93 01 02 	sts	0x0201, r31
+    3f3c:	e0 93 00 02 	sts	0x0200, r30
+    3f40:	31 97       	sbiw	r30, 0x01	; 1
+    3f42:	e4 91       	lpm	r30, Z+
+    3f44:	8e 2f       	mov	r24, r30
+    3f46:	19 d0       	rcall	.+50     	; 0x3f7a <putch>
       while (--length);
-    3f60:	80 91 02 02 	lds	r24, 0x0202
-    3f64:	81 50       	subi	r24, 0x01	; 1
-    3f66:	80 93 02 02 	sts	0x0202, r24
-    3f6a:	88 23       	and	r24, r24
-    3f6c:	61 f7       	brne	.-40     	; 0x3f46 <main+0x146>
-    3f6e:	0e c0       	rjmp	.+28     	; 0x3f8c <main+0x18c>
+    3f48:	80 91 02 02 	lds	r24, 0x0202
+    3f4c:	81 50       	subi	r24, 0x01	; 1
+    3f4e:	80 93 02 02 	sts	0x0202, r24
+    3f52:	88 23       	and	r24, r24
+    3f54:	61 f7       	brne	.-40     	; 0x3f2e <main+0x12e>
+    3f56:	0e c0       	rjmp	.+28     	; 0x3f74 <main+0x174>
     }
 
     /* Get device signature bytes  */
     else if(ch == STK_READ_SIGN) {
-    3f70:	85 37       	cpi	r24, 0x75	; 117
-    3f72:	39 f4       	brne	.+14     	; 0x3f82 <main+0x182>
+    3f58:	85 37       	cpi	r24, 0x75	; 117
+    3f5a:	39 f4       	brne	.+14     	; 0x3f6a <main+0x16a>
       // READ SIGN - return what Avrdude wants to hear
       verifySpace();
-    3f74:	34 d0       	rcall	.+104    	; 0x3fde <verifySpace>
+    3f5c:	41 d0       	rcall	.+130    	; 0x3fe0 <verifySpace>
       putch(SIGNATURE_0);
-    3f76:	8e e1       	ldi	r24, 0x1E	; 30
-    3f78:	0c d0       	rcall	.+24     	; 0x3f92 <putch>
+    3f5e:	8e e1       	ldi	r24, 0x1E	; 30
+    3f60:	0c d0       	rcall	.+24     	; 0x3f7a <putch>
       putch(SIGNATURE_1);
-    3f7a:	84 e9       	ldi	r24, 0x94	; 148
-    3f7c:	0a d0       	rcall	.+20     	; 0x3f92 <putch>
+    3f62:	84 e9       	ldi	r24, 0x94	; 148
+    3f64:	0a d0       	rcall	.+20     	; 0x3f7a <putch>
       putch(SIGNATURE_2);
-    3f7e:	86 e0       	ldi	r24, 0x06	; 6
-    3f80:	93 cf       	rjmp	.-218    	; 0x3ea8 <main+0xa8>
+    3f66:	86 e0       	ldi	r24, 0x06	; 6
+    3f68:	96 cf       	rjmp	.-212    	; 0x3e96 <main+0x96>
     }
     else if (ch == 'Q') {
-    3f82:	81 35       	cpi	r24, 0x51	; 81
-    3f84:	11 f4       	brne	.+4      	; 0x3f8a <main+0x18a>
+    3f6a:	81 35       	cpi	r24, 0x51	; 81
+    3f6c:	11 f4       	brne	.+4      	; 0x3f72 <main+0x172>
       // Adaboot no-wait mod
-      WDTCSR = _BV(WDE);
-    3f86:	c0 92 60 00 	sts	0x0060, r12
+      watchdogConfig(_BV(WDE));
+    3f6e:	88 e0       	ldi	r24, 0x08	; 8
+    3f70:	2c d0       	rcall	.+88     	; 0x3fca <watchdogConfig>
       verifySpace();
     }
     else {
       // This covers the response to commands like STK_ENTER_PROGMODE
       verifySpace();
-    3f8a:	29 d0       	rcall	.+82     	; 0x3fde <verifySpace>
+    3f72:	36 d0       	rcall	.+108    	; 0x3fe0 <verifySpace>
     }
     putch(STK_OK);
-    3f8c:	80 e1       	ldi	r24, 0x10	; 16
-    3f8e:	01 d0       	rcall	.+2      	; 0x3f92 <putch>
-    3f90:	60 cf       	rjmp	.-320    	; 0x3e52 <main+0x52>
-
-00003f92 <putch>:
-  }
-}
+    3f74:	80 e1       	ldi	r24, 0x10	; 16
+    3f76:	01 d0       	rcall	.+2      	; 0x3f7a <putch>
+    3f78:	63 cf       	rjmp	.-314    	; 0x3e40 <main+0x40>
 
+00003f7a <putch>:
 void putch(char ch) {
-    3f92:	98 2f       	mov	r25, r24
+#ifndef SOFT_UART
   while (!(UCSR0A & _BV(UDRE0)));
-    3f94:	80 91 c0 00 	lds	r24, 0x00C0
-    3f98:	85 ff       	sbrs	r24, 5
-    3f9a:	fc cf       	rjmp	.-8      	; 0x3f94 <putch+0x2>
   UDR0 = ch;
-    3f9c:	90 93 c6 00 	sts	0x00C6, r25
-}
-    3fa0:	08 95       	ret
-
-00003fa2 <setTimer>:
-
-void setTimer(uint16_t counts) {
-  TCNT1 = counts;
-    3fa2:	90 93 85 00 	sts	0x0085, r25
-    3fa6:	80 93 84 00 	sts	0x0084, r24
-  TIFR1 = _BV(TOV1);
-    3faa:	81 e0       	ldi	r24, 0x01	; 1
-    3fac:	86 bb       	out	0x16, r24	; 22
+#else
+  __asm__ __volatile__ (
+    3f7a:	2a e0       	ldi	r18, 0x0A	; 10
+    3f7c:	30 e0       	ldi	r19, 0x00	; 0
+    3f7e:	80 95       	com	r24
+    3f80:	08 94       	sec
+    3f82:	10 f4       	brcc	.+4      	; 0x3f88 <putch+0xe>
+    3f84:	59 98       	cbi	0x0b, 1	; 11
+    3f86:	02 c0       	rjmp	.+4      	; 0x3f8c <putch+0x12>
+    3f88:	59 9a       	sbi	0x0b, 1	; 11
+    3f8a:	00 00       	nop
+    3f8c:	15 d0       	rcall	.+42     	; 0x3fb8 <uartDelay>
+    3f8e:	14 d0       	rcall	.+40     	; 0x3fb8 <uartDelay>
+    3f90:	86 95       	lsr	r24
+    3f92:	2a 95       	dec	r18
+    3f94:	b1 f7       	brne	.-20     	; 0x3f82 <putch+0x8>
+      [uartBit] "I" (UART_TX_BIT)
+    :
+      "r25"
+  );
+#endif
 }
-    3fae:	08 95       	ret
+    3f96:	08 95       	ret
 
-00003fb0 <appStart>:
-  length = getch();
+00003f98 <getch>:
   return getch();
 }
 
-void appStart() {
+// Watchdog functions. These are only safe with interrupts turned off.
+void watchdogReset() {
   __asm__ __volatile__ (
-    3fb0:	ee 27       	eor	r30, r30
-    3fb2:	ff 27       	eor	r31, r31
-    3fb4:	09 94       	ijmp
+    3f98:	a8 95       	wdr
+#ifdef LED_DATA_FLASH
+  LED_PIN |= _BV(LED);
+#endif
 
-00003fb6 <getch>:
-  TCNT1 = counts;
-  TIFR1 = _BV(TOV1);
+  return ch;
 }
+    3f9a:	29 e0       	ldi	r18, 0x09	; 9
+    3f9c:	30 e0       	ldi	r19, 0x00	; 0
+    3f9e:	48 99       	sbic	0x09, 0	; 9
+    3fa0:	fe cf       	rjmp	.-4      	; 0x3f9e <getch+0x6>
+    3fa2:	0a d0       	rcall	.+20     	; 0x3fb8 <uartDelay>
+    3fa4:	09 d0       	rcall	.+18     	; 0x3fb8 <uartDelay>
+    3fa6:	08 d0       	rcall	.+16     	; 0x3fb8 <uartDelay>
+    3fa8:	88 94       	clc
+    3faa:	48 99       	sbic	0x09, 0	; 9
+    3fac:	08 94       	sec
+    3fae:	2a 95       	dec	r18
+    3fb0:	11 f0       	breq	.+4      	; 0x3fb6 <getch+0x1e>
+    3fb2:	87 95       	ror	r24
+    3fb4:	f7 cf       	rjmp	.-18     	; 0x3fa4 <getch+0xc>
+    3fb6:	08 95       	ret
+
+00003fb8 <uartDelay>:
+#if UART_B_VALUE > 255
+#error Baud rate too slow for soft UART
+#endif
 
-uint8_t getch(void) {
-  LED_PORT &= ~_BV(LED);
-    3fb6:	2d 98       	cbi	0x05, 5	; 5
-  setTimer(-(F_CPU/(1024*2))); // 500ms
-    3fb8:	8e eb       	ldi	r24, 0xBE	; 190
-    3fba:	90 ef       	ldi	r25, 0xF0	; 240
-    3fbc:	f2 df       	rcall	.-28     	; 0x3fa2 <setTimer>
-    3fbe:	02 c0       	rjmp	.+4      	; 0x3fc4 <getch+0xe>
-  while(!(UCSR0A & _BV(RXC0))) if (TIFR1 & _BV(TOV1)) appStart();
-    3fc0:	b0 99       	sbic	0x16, 0	; 22
-    3fc2:	f6 df       	rcall	.-20     	; 0x3fb0 <appStart>
-    3fc4:	80 91 c0 00 	lds	r24, 0x00C0
-    3fc8:	87 ff       	sbrs	r24, 7
-    3fca:	fa cf       	rjmp	.-12     	; 0x3fc0 <getch+0xa>
-  LED_PORT |= _BV(LED);
-    3fcc:	2d 9a       	sbi	0x05, 5	; 5
-  return UDR0;
-    3fce:	80 91 c6 00 	lds	r24, 0x00C6
-}
-    3fd2:	08 95       	ret
+void uartDelay() {
+  __asm__ __volatile__ (
+    3fb8:	98 e0       	ldi	r25, 0x08	; 8
+    3fba:	9a 95       	dec	r25
+    3fbc:	f1 f7       	brne	.-4      	; 0x3fba <uartDelay+0x2>
+    3fbe:	08 95       	ret
 
-00003fd4 <getLen>:
-    LED_PIN |= _BV(LED);
+00003fc0 <getLen>:
   } while (--count);
 }
+#endif
 
 uint8_t getLen() {
   getch();
-    3fd4:	f0 df       	rcall	.-32     	; 0x3fb6 <getch>
+    3fc0:	eb df       	rcall	.-42     	; 0x3f98 <getch>
   length = getch();
-    3fd6:	ef df       	rcall	.-34     	; 0x3fb6 <getch>
-    3fd8:	80 93 02 02 	sts	0x0202, r24
+    3fc2:	ea df       	rcall	.-44     	; 0x3f98 <getch>
+    3fc4:	80 93 02 02 	sts	0x0202, r24
   return getch();
 }
-    3fdc:	ec cf       	rjmp	.-40     	; 0x3fb6 <getch>
+    3fc8:	e7 cf       	rjmp	.-50     	; 0x3f98 <getch>
+
+00003fca <watchdogConfig>:
+    "wdr\n"
+  );
+}
 
-00003fde <verifySpace>:
+void watchdogConfig(uint8_t x) {
+  WDTCSR = _BV(WDCE) | _BV(WDE);
+    3fca:	e0 e6       	ldi	r30, 0x60	; 96
+    3fcc:	f0 e0       	ldi	r31, 0x00	; 0
+    3fce:	98 e1       	ldi	r25, 0x18	; 24
+    3fd0:	90 83       	st	Z, r25
+  WDTCSR = x;
+    3fd2:	80 83       	st	Z, r24
+}
+    3fd4:	08 95       	ret
+
+00003fd6 <appStart>:
+
+void appStart() {
+  watchdogConfig(0);
+    3fd6:	80 e0       	ldi	r24, 0x00	; 0
+    3fd8:	f8 df       	rcall	.-16     	; 0x3fca <watchdogConfig>
+  __asm__ __volatile__ (
+    3fda:	ee 27       	eor	r30, r30
+    3fdc:	ff 27       	eor	r31, r31
+    3fde:	09 94       	ijmp
+
+00003fe0 <verifySpace>:
   do getch(); while (--count);
   verifySpace();
 }
 
 void verifySpace() {
   if (getch() != CRC_EOP) appStart();
-    3fde:	eb df       	rcall	.-42     	; 0x3fb6 <getch>
-    3fe0:	80 32       	cpi	r24, 0x20	; 32
-    3fe2:	09 f0       	breq	.+2      	; 0x3fe6 <verifySpace+0x8>
-    3fe4:	e5 df       	rcall	.-54     	; 0x3fb0 <appStart>
+    3fe0:	db df       	rcall	.-74     	; 0x3f98 <getch>
+    3fe2:	80 32       	cpi	r24, 0x20	; 32
+    3fe4:	09 f0       	breq	.+2      	; 0x3fe8 <verifySpace+0x8>
+    3fe6:	f7 df       	rcall	.-18     	; 0x3fd6 <appStart>
   putch(STK_INSYNC);
-    3fe6:	84 e1       	ldi	r24, 0x14	; 20
+    3fe8:	84 e1       	ldi	r24, 0x14	; 20
 }
-    3fe8:	d4 cf       	rjmp	.-88     	; 0x3f92 <putch>
-  while(!(UCSR0A & _BV(RXC0))) if (TIFR1 & _BV(TOV1)) appStart();
-  LED_PORT |= _BV(LED);
-  return UDR0;
+    3fea:	c7 cf       	rjmp	.-114    	; 0x3f7a <putch>
+    ::[count] "M" (UART_B_VALUE)
+  );
 }
+#endif
 
 void getNch(uint8_t count) {
-    3fea:	1f 93       	push	r17
-    3fec:	18 2f       	mov	r17, r24
+    3fec:	1f 93       	push	r17
+    3fee:	18 2f       	mov	r17, r24
 
-00003fee <getNch>:
+00003ff0 <getNch>:
   do getch(); while (--count);
-    3fee:	e3 df       	rcall	.-58     	; 0x3fb6 <getch>
-    3ff0:	11 50       	subi	r17, 0x01	; 1
-    3ff2:	e9 f7       	brne	.-6      	; 0x3fee <getNch>
+    3ff0:	d3 df       	rcall	.-90     	; 0x3f98 <getch>
+    3ff2:	11 50       	subi	r17, 0x01	; 1
+    3ff4:	e9 f7       	brne	.-6      	; 0x3ff0 <getNch>
   verifySpace();
-    3ff4:	f4 df       	rcall	.-24     	; 0x3fde <verifySpace>
+    3ff6:	f4 df       	rcall	.-24     	; 0x3fe0 <verifySpace>
 }
-    3ff6:	1f 91       	pop	r17
-    3ff8:	08 95       	ret
+    3ff8:	1f 91       	pop	r17
+    3ffa:	08 95       	ret