Project

General

Profile

Statistics
| Branch: | Revision:

root / arduino-1.0 / hardware / arduino / bootloaders / optiboot / optiboot.c @ 58d82c77

History | View | Annotate | Download (21.8 KB)

1
/**********************************************************/
2
/* Optiboot bootloader for Arduino                        */
3
/*                                                        */
4
/* http://optiboot.googlecode.com                         */
5
/*                                                        */
6
/* Arduino-maintained version : See README.TXT            */
7
/* http://code.google.com/p/arduino/                      */
8
/*                                                        */
9
/* Heavily optimised bootloader that is faster and        */
10
/* smaller than the Arduino standard bootloader           */
11
/*                                                        */
12
/* Enhancements:                                          */
13
/*   Fits in 512 bytes, saving 1.5K of code space         */
14
/*   Background page erasing speeds up programming        */
15
/*   Higher baud rate speeds up programming               */
16
/*   Written almost entirely in C                         */
17
/*   Customisable timeout with accurate timeconstant      */
18
/*   Optional virtual UART. No hardware UART required.    */
19
/*   Optional virtual boot partition for devices without. */
20
/*                                                        */
21
/* What you lose:                                         */
22
/*   Implements a skeleton STK500 protocol which is       */
23
/*     missing several features including EEPROM          */
24
/*     programming and non-page-aligned writes            */
25
/*   High baud rate breaks compatibility with standard    */
26
/*     Arduino flash settings                             */
27
/*                                                        */
28
/* Fully supported:                                       */
29
/*   ATmega168 based devices  (Diecimila etc)             */
30
/*   ATmega328P based devices (Duemilanove etc)           */
31
/*                                                        */
32
/* Alpha test                                             */
33
/*   ATmega1280 based devices (Arduino Mega)              */
34
/*                                                        */
35
/* Work in progress:                                      */
36
/*   ATmega644P based devices (Sanguino)                  */
37
/*   ATtiny84 based devices (Luminet)                     */
38
/*                                                        */
39
/* Does not support:                                      */
40
/*   USB based devices (eg. Teensy)                       */
41
/*                                                        */
42
/* Assumptions:                                           */
43
/*   The code makes several assumptions that reduce the   */
44
/*   code size. They are all true after a hardware reset, */
45
/*   but may not be true if the bootloader is called by   */
46
/*   other means or on other hardware.                    */
47
/*     No interrupts can occur                            */
48
/*     UART and Timer 1 are set to their reset state      */
49
/*     SP points to RAMEND                                */
50
/*                                                        */
51
/* Code builds on code, libraries and optimisations from: */
52
/*   stk500boot.c          by Jason P. Kyle               */
53
/*   Arduino bootloader    http://arduino.cc              */
54
/*   Spiff's 1K bootloader http://spiffie.org/know/arduino_1k_bootloader/bootloader.shtml */
55
/*   avr-libc project      http://nongnu.org/avr-libc     */
56
/*   Adaboot               http://www.ladyada.net/library/arduino/bootloader.html */
57
/*   AVR305                Atmel Application Note         */
58
/*                                                        */
59
/* This program is free software; you can redistribute it */
60
/* and/or modify it under the terms of the GNU General    */
61
/* Public License as published by the Free Software       */
62
/* Foundation; either version 2 of the License, or        */
63
/* (at your option) any later version.                    */
64
/*                                                        */
65
/* This program is distributed in the hope that it will   */
66
/* be useful, but WITHOUT ANY WARRANTY; without even the  */
67
/* implied warranty of MERCHANTABILITY or FITNESS FOR A   */
68
/* PARTICULAR PURPOSE.  See the GNU General Public        */
69
/* License for more details.                              */
70
/*                                                        */
71
/* You should have received a copy of the GNU General     */
72
/* Public License along with this program; if not, write  */
73
/* to the Free Software Foundation, Inc.,                 */
74
/* 59 Temple Place, Suite 330, Boston, MA  02111-1307 USA */
75
/*                                                        */
76
/* Licence can be viewed at                               */
77
/* http://www.fsf.org/licenses/gpl.txt                    */
78
/*                                                        */
79
/**********************************************************/
80

    
81

    
82
/**********************************************************/
83
/*                                                        */
84
/* Optional defines:                                      */
85
/*                                                        */
86
/**********************************************************/
87
/*                                                        */
88
/* BIG_BOOT:                                              */
89
/* Build a 1k bootloader, not 512 bytes. This turns on    */
90
/* extra functionality.                                   */
91
/*                                                        */
92
/* BAUD_RATE:                                             */
93
/* Set bootloader baud rate.                              */
94
/*                                                        */
95
/* LUDICROUS_SPEED:                                       */
96
/* 230400 baud :-)                                        */
97
/*                                                        */
98
/* SOFT_UART:                                             */
99
/* Use AVR305 soft-UART instead of hardware UART.         */
100
/*                                                        */
101
/* LED_START_FLASHES:                                     */
102
/* Number of LED flashes on bootup.                       */
103
/*                                                        */
104
/* LED_DATA_FLASH:                                        */
105
/* Flash LED when transferring data. For boards without   */
106
/* TX or RX LEDs, or for people who like blinky lights.   */
107
/*                                                        */
108
/* SUPPORT_EEPROM:                                        */
109
/* Support reading and writing from EEPROM. This is not   */
110
/* used by Arduino, so off by default.                    */
111
/*                                                        */
112
/* TIMEOUT_MS:                                            */
113
/* Bootloader timeout period, in milliseconds.            */
114
/* 500,1000,2000,4000,8000 supported.                     */
115
/*                                                        */
116
/**********************************************************/
117
 
118
/**********************************************************/
119
/* Version Numbers!                                       */
120
/*                                                        */
121
/* Arduino Optiboot now includes this Version number in   */
122
/* the source and object code.                            */
123
/*                                                        */
124
/* Version 3 was released as zip from the optiboot        */
125
/*  repository and was distributed with Arduino 0022.     */
126
/* Version 4 starts with the arduino repository commit    */
127
/*  that brought the arduino repository up-to-date with   */
128
/* the optiboot source tree changes since v3.             */
129
/*                                                        */
130
/**********************************************************/
131

    
132
/**********************************************************/
133
/* Edit History:                                          */
134
/*                                                          */
135
/* 4.4 WestfW: add initialization of address to keep      */
136
/*             the compiler happy.  Change SC'ed targets. */
137
/*             Return the SW version via READ PARAM       */
138
/* 4.3 WestfW: catch framing errors in getch(), so that   */
139
/*             AVRISP works without HW kludges.           */
140
/*  http://code.google.com/p/arduino/issues/detail?id=368n*/
141
/* 4.2 WestfW: reduce code size, fix timeouts, change     */
142
/*             verifySpace to use WDT instead of appstart */
143
/* 4.1 WestfW: put version number in binary.                  */
144
/**********************************************************/
145

    
146
#define OPTIBOOT_MAJVER 4
147
#define OPTIBOOT_MINVER 4
148

    
149
#define MAKESTR(a) #a
150
#define MAKEVER(a, b) MAKESTR(a*256+b)
151

    
152
asm("  .section .version\n"
153
    "optiboot_version:  .word " MAKEVER(OPTIBOOT_MAJVER, OPTIBOOT_MINVER) "\n"
154
    "  .section .text\n");
155
 
156
#include <inttypes.h>
157
#include <avr/io.h>
158
#include <avr/pgmspace.h>
159

    
160
// <avr/boot.h> uses sts instructions, but this version uses out instructions
161
// This saves cycles and program memory.
162
#include "boot.h"
163

    
164

    
165
// We don't use <avr/wdt.h> as those routines have interrupt overhead we don't need.
166

    
167
#include "pin_defs.h"
168
#include "stk500.h"
169

    
170
#ifndef LED_START_FLASHES
171
#define LED_START_FLASHES 0
172
#endif
173

    
174
#ifdef LUDICROUS_SPEED
175
#define BAUD_RATE 230400L
176
#endif
177

    
178
/* set the UART baud rate defaults */
179
#ifndef BAUD_RATE
180
#if F_CPU >= 8000000L
181
#define BAUD_RATE   115200L // Highest rate Avrdude win32 will support
182
#elsif F_CPU >= 1000000L
183
#define BAUD_RATE   9600L   // 19200 also supported, but with significant error
184
#elsif F_CPU >= 128000L
185
#define BAUD_RATE   4800L   // Good for 128kHz internal RC
186
#else
187
#define BAUD_RATE 1200L     // Good even at 32768Hz
188
#endif
189
#endif
190

    
191
/* Switch in soft UART for hard baud rates */
192
#if (F_CPU/BAUD_RATE) > 280 // > 57600 for 16MHz
193
#ifndef SOFT_UART
194
#define SOFT_UART
195
#endif
196
#endif
197

    
198
/* Watchdog settings */
199
#define WATCHDOG_OFF    (0)
200
#define WATCHDOG_16MS   (_BV(WDE))
201
#define WATCHDOG_32MS   (_BV(WDP0) | _BV(WDE))
202
#define WATCHDOG_64MS   (_BV(WDP1) | _BV(WDE))
203
#define WATCHDOG_125MS  (_BV(WDP1) | _BV(WDP0) | _BV(WDE))
204
#define WATCHDOG_250MS  (_BV(WDP2) | _BV(WDE))
205
#define WATCHDOG_500MS  (_BV(WDP2) | _BV(WDP0) | _BV(WDE))
206
#define WATCHDOG_1S     (_BV(WDP2) | _BV(WDP1) | _BV(WDE))
207
#define WATCHDOG_2S     (_BV(WDP2) | _BV(WDP1) | _BV(WDP0) | _BV(WDE))
208
#ifndef __AVR_ATmega8__
209
#define WATCHDOG_4S     (_BV(WDP3) | _BV(WDE))
210
#define WATCHDOG_8S     (_BV(WDP3) | _BV(WDP0) | _BV(WDE))
211
#endif
212

    
213
/* Function Prototypes */
214
/* The main function is in init9, which removes the interrupt vector table */
215
/* we don't need. It is also 'naked', which means the compiler does not    */
216
/* generate any entry or exit code itself. */
217
int main(void) __attribute__ ((naked)) __attribute__ ((section (".init9")));
218
void putch(char);
219
uint8_t getch(void);
220
static inline void getNch(uint8_t); /* "static inline" is a compiler hint to reduce code size */
221
void verifySpace();
222
static inline void flash_led(uint8_t);
223
uint8_t getLen();
224
static inline void watchdogReset();
225
void watchdogConfig(uint8_t x);
226
#ifdef SOFT_UART
227
void uartDelay() __attribute__ ((naked));
228
#endif
229
void appStart() __attribute__ ((naked));
230

    
231
#if defined(__AVR_ATmega168__)
232
#define RAMSTART (0x100)
233
#define NRWWSTART (0x3800)
234
#elif defined(__AVR_ATmega328P__)
235
#define RAMSTART (0x100)
236
#define NRWWSTART (0x7000)
237
#elif defined (__AVR_ATmega644P__)
238
#define RAMSTART (0x100)
239
#define NRWWSTART (0xE000)
240
#elif defined(__AVR_ATtiny84__)
241
#define RAMSTART (0x100)
242
#define NRWWSTART (0x0000)
243
#elif defined(__AVR_ATmega1280__)
244
#define RAMSTART (0x200)
245
#define NRWWSTART (0xE000)
246
#elif defined(__AVR_ATmega8__) || defined(__AVR_ATmega88__)
247
#define RAMSTART (0x100)
248
#define NRWWSTART (0x1800)
249
#endif
250

    
251
/* C zero initialises all global variables. However, that requires */
252
/* These definitions are NOT zero initialised, but that doesn't matter */
253
/* This allows us to drop the zero init code, saving us memory */
254
#define buff    ((uint8_t*)(RAMSTART))
255
#ifdef VIRTUAL_BOOT_PARTITION
256
#define rstVect (*(uint16_t*)(RAMSTART+SPM_PAGESIZE*2+4))
257
#define wdtVect (*(uint16_t*)(RAMSTART+SPM_PAGESIZE*2+6))
258
#endif
259

    
260
/* main program starts here */
261
int main(void) {
262
  uint8_t ch;
263

    
264
  /*
265
   * Making these local and in registers prevents the need for initializing
266
   * them, and also saves space because code no longer stores to memory.
267
   * (initializing address keeps the compiler happy, but isn't really
268
   *  necessary, and uses 4 bytes of flash.)
269
   */
270
  register uint16_t address = 0;
271
  register uint8_t  length;
272

    
273
  // After the zero init loop, this is the first code to run.
274
  //
275
  // This code makes the following assumptions:
276
  //  No interrupts will execute
277
  //  SP points to RAMEND
278
  //  r1 contains zero
279
  //
280
  // If not, uncomment the following instructions:
281
  // cli();
282
  asm volatile ("clr __zero_reg__");
283
#ifdef __AVR_ATmega8__
284
  SP=RAMEND;  // This is done by hardware reset
285
#endif
286

    
287
  // Adaboot no-wait mod
288
  ch = MCUSR;
289
  MCUSR = 0;
290
  if (!(ch & _BV(EXTRF))) appStart();
291

    
292
#if LED_START_FLASHES > 0
293
  // Set up Timer 1 for timeout counter
294
  TCCR1B = _BV(CS12) | _BV(CS10); // div 1024
295
#endif
296
#ifndef SOFT_UART
297
#ifdef __AVR_ATmega8__
298
  UCSRA = _BV(U2X); //Double speed mode USART
299
  UCSRB = _BV(RXEN) | _BV(TXEN);  // enable Rx & Tx
300
  UCSRC = _BV(URSEL) | _BV(UCSZ1) | _BV(UCSZ0);  // config USART; 8N1
301
  UBRRL = (uint8_t)( (F_CPU + BAUD_RATE * 4L) / (BAUD_RATE * 8L) - 1 );
302
#else
303
  UCSR0A = _BV(U2X0); //Double speed mode USART0
304
  UCSR0B = _BV(RXEN0) | _BV(TXEN0);
305
  UCSR0C = _BV(UCSZ00) | _BV(UCSZ01);
306
  UBRR0L = (uint8_t)( (F_CPU + BAUD_RATE * 4L) / (BAUD_RATE * 8L) - 1 );
307
#endif
308
#endif
309

    
310
  // Set up watchdog to trigger after 500ms
311
  watchdogConfig(WATCHDOG_1S);
312

    
313
  /* Set LED pin as output */
314
  LED_DDR |= _BV(LED);
315

    
316
#ifdef SOFT_UART
317
  /* Set TX pin as output */
318
  UART_DDR |= _BV(UART_TX_BIT);
319
#endif
320

    
321
#if LED_START_FLASHES > 0
322
  /* Flash onboard LED to signal entering of bootloader */
323
  flash_led(LED_START_FLASHES * 2);
324
#endif
325

    
326
  /* Forever loop */
327
  for (;;) {
328
    /* get character from UART */
329
    ch = getch();
330

    
331
    if(ch == STK_GET_PARAMETER) {
332
      unsigned char which = getch();
333
      verifySpace();
334
      if (which == 0x82) {
335
        /*
336
         * Send optiboot version as "minor SW version"
337
         */
338
        putch(OPTIBOOT_MINVER);
339
      } else if (which == 0x81) {
340
          putch(OPTIBOOT_MAJVER);
341
      } else {
342
        /*
343
         * GET PARAMETER returns a generic 0x03 reply for
344
         * other parameters - enough to keep Avrdude happy
345
         */
346
        putch(0x03);
347
      }
348
    }
349
    else if(ch == STK_SET_DEVICE) {
350
      // SET DEVICE is ignored
351
      getNch(20);
352
    }
353
    else if(ch == STK_SET_DEVICE_EXT) {
354
      // SET DEVICE EXT is ignored
355
      getNch(5);
356
    }
357
    else if(ch == STK_LOAD_ADDRESS) {
358
      // LOAD ADDRESS
359
      uint16_t newAddress;
360
      newAddress = getch();
361
      newAddress = (newAddress & 0xff) | (getch() << 8);
362
#ifdef RAMPZ
363
      // Transfer top bit to RAMPZ
364
      RAMPZ = (newAddress & 0x8000) ? 1 : 0;
365
#endif
366
      newAddress += newAddress; // Convert from word address to byte address
367
      address = newAddress;
368
      verifySpace();
369
    }
370
    else if(ch == STK_UNIVERSAL) {
371
      // UNIVERSAL command is ignored
372
      getNch(4);
373
      putch(0x00);
374
    }
375
    /* Write memory, length is big endian and is in bytes */
376
    else if(ch == STK_PROG_PAGE) {
377
      // PROGRAM PAGE - we support flash programming only, not EEPROM
378
      uint8_t *bufPtr;
379
      uint16_t addrPtr;
380

    
381
      getch();                        /* getlen() */
382
      length = getch();
383
      getch();
384

    
385
      // If we are in RWW section, immediately start page erase
386
      if (address < NRWWSTART) __boot_page_erase_short((uint16_t)(void*)address);
387

    
388
      // While that is going on, read in page contents
389
      bufPtr = buff;
390
      do *bufPtr++ = getch();
391
      while (--length);
392

    
393
      // If we are in NRWW section, page erase has to be delayed until now.
394
      // Todo: Take RAMPZ into account
395
      if (address >= NRWWSTART) __boot_page_erase_short((uint16_t)(void*)address);
396

    
397
      // Read command terminator, start reply
398
      verifySpace();
399

    
400
      // If only a partial page is to be programmed, the erase might not be complete.
401
      // So check that here
402
      boot_spm_busy_wait();
403

    
404
#ifdef VIRTUAL_BOOT_PARTITION
405
      if ((uint16_t)(void*)address == 0) {
406
        // This is the reset vector page. We need to live-patch the code so the
407
        // bootloader runs.
408
        //
409
        // Move RESET vector to WDT vector
410
        uint16_t vect = buff[0] | (buff[1]<<8);
411
        rstVect = vect;
412
        wdtVect = buff[8] | (buff[9]<<8);
413
        vect -= 4; // Instruction is a relative jump (rjmp), so recalculate.
414
        buff[8] = vect & 0xff;
415
        buff[9] = vect >> 8;
416

    
417
        // Add jump to bootloader at RESET vector
418
        buff[0] = 0x7f;
419
        buff[1] = 0xce; // rjmp 0x1d00 instruction
420
      }
421
#endif
422

    
423
      // Copy buffer into programming buffer
424
      bufPtr = buff;
425
      addrPtr = (uint16_t)(void*)address;
426
      ch = SPM_PAGESIZE / 2;
427
      do {
428
        uint16_t a;
429
        a = *bufPtr++;
430
        a |= (*bufPtr++) << 8;
431
        __boot_page_fill_short((uint16_t)(void*)addrPtr,a);
432
        addrPtr += 2;
433
      } while (--ch);
434

    
435
      // Write from programming buffer
436
      __boot_page_write_short((uint16_t)(void*)address);
437
      boot_spm_busy_wait();
438

    
439
#if defined(RWWSRE)
440
      // Reenable read access to flash
441
      boot_rww_enable();
442
#endif
443

    
444
    }
445
    /* Read memory block mode, length is big endian.  */
446
    else if(ch == STK_READ_PAGE) {
447
      // READ PAGE - we only read flash
448
      getch();                        /* getlen() */
449
      length = getch();
450
      getch();
451

    
452
      verifySpace();
453
#ifdef VIRTUAL_BOOT_PARTITION
454
      do {
455
        // Undo vector patch in bottom page so verify passes
456
        if (address == 0)       ch=rstVect & 0xff;
457
        else if (address == 1)  ch=rstVect >> 8;
458
        else if (address == 8)  ch=wdtVect & 0xff;
459
        else if (address == 9) ch=wdtVect >> 8;
460
        else ch = pgm_read_byte_near(address);
461
        address++;
462
        putch(ch);
463
      } while (--length);
464
#else
465
#ifdef __AVR_ATmega1280__
466
//      do putch(pgm_read_byte_near(address++));
467
//      while (--length);
468
      do {
469
        uint8_t result;
470
        __asm__ ("elpm %0,Z\n":"=r"(result):"z"(address));
471
        putch(result);
472
        address++;
473
      }
474
      while (--length);
475
#else
476
      do putch(pgm_read_byte_near(address++));
477
      while (--length);
478
#endif
479
#endif
480
    }
481

    
482
    /* Get device signature bytes  */
483
    else if(ch == STK_READ_SIGN) {
484
      // READ SIGN - return what Avrdude wants to hear
485
      verifySpace();
486
      putch(SIGNATURE_0);
487
      putch(SIGNATURE_1);
488
      putch(SIGNATURE_2);
489
    }
490
    else if (ch == 'Q') {
491
      // Adaboot no-wait mod
492
      watchdogConfig(WATCHDOG_16MS);
493
      verifySpace();
494
    }
495
    else {
496
      // This covers the response to commands like STK_ENTER_PROGMODE
497
      verifySpace();
498
    }
499
    putch(STK_OK);
500
  }
501
}
502

    
503
void putch(char ch) {
504
#ifndef SOFT_UART
505
  while (!(UCSR0A & _BV(UDRE0)));
506
  UDR0 = ch;
507
#else
508
  __asm__ __volatile__ (
509
    "   com %[ch]\n" // ones complement, carry set
510
    "   sec\n"
511
    "1: brcc 2f\n"
512
    "   cbi %[uartPort],%[uartBit]\n"
513
    "   rjmp 3f\n"
514
    "2: sbi %[uartPort],%[uartBit]\n"
515
    "   nop\n"
516
    "3: rcall uartDelay\n"
517
    "   rcall uartDelay\n"
518
    "   lsr %[ch]\n"
519
    "   dec %[bitcnt]\n"
520
    "   brne 1b\n"
521
    :
522
    :
523
      [bitcnt] "d" (10),
524
      [ch] "r" (ch),
525
      [uartPort] "I" (_SFR_IO_ADDR(UART_PORT)),
526
      [uartBit] "I" (UART_TX_BIT)
527
    :
528
      "r25"
529
  );
530
#endif
531
}
532

    
533
uint8_t getch(void) {
534
  uint8_t ch;
535

    
536
#ifdef LED_DATA_FLASH
537
#ifdef __AVR_ATmega8__
538
  LED_PORT ^= _BV(LED);
539
#else
540
  LED_PIN |= _BV(LED);
541
#endif
542
#endif
543

    
544
#ifdef SOFT_UART
545
  __asm__ __volatile__ (
546
    "1: sbic  %[uartPin],%[uartBit]\n"  // Wait for start edge
547
    "   rjmp  1b\n"
548
    "   rcall uartDelay\n"          // Get to middle of start bit
549
    "2: rcall uartDelay\n"              // Wait 1 bit period
550
    "   rcall uartDelay\n"              // Wait 1 bit period
551
    "   clc\n"
552
    "   sbic  %[uartPin],%[uartBit]\n"
553
    "   sec\n"
554
    "   dec   %[bitCnt]\n"
555
    "   breq  3f\n"
556
    "   ror   %[ch]\n"
557
    "   rjmp  2b\n"
558
    "3:\n"
559
    :
560
      [ch] "=r" (ch)
561
    :
562
      [bitCnt] "d" (9),
563
      [uartPin] "I" (_SFR_IO_ADDR(UART_PIN)),
564
      [uartBit] "I" (UART_RX_BIT)
565
    :
566
      "r25"
567
);
568
#else
569
  while(!(UCSR0A & _BV(RXC0)))
570
    ;
571
  if (!(UCSR0A & _BV(FE0))) {
572
      /*
573
       * A Framing Error indicates (probably) that something is talking
574
       * to us at the wrong bit rate.  Assume that this is because it
575
       * expects to be talking to the application, and DON'T reset the
576
       * watchdog.  This should cause the bootloader to abort and run
577
       * the application "soon", if it keeps happening.  (Note that we
578
       * don't care that an invalid char is returned...)
579
       */
580
    watchdogReset();
581
  }
582
  
583
  ch = UDR0;
584
#endif
585

    
586
#ifdef LED_DATA_FLASH
587
#ifdef __AVR_ATmega8__
588
  LED_PORT ^= _BV(LED);
589
#else
590
  LED_PIN |= _BV(LED);
591
#endif
592
#endif
593

    
594
  return ch;
595
}
596

    
597
#ifdef SOFT_UART
598
// AVR350 equation: #define UART_B_VALUE (((F_CPU/BAUD_RATE)-23)/6)
599
// Adding 3 to numerator simulates nearest rounding for more accurate baud rates
600
#define UART_B_VALUE (((F_CPU/BAUD_RATE)-20)/6)
601
#if UART_B_VALUE > 255
602
#error Baud rate too slow for soft UART
603
#endif
604

    
605
void uartDelay() {
606
  __asm__ __volatile__ (
607
    "ldi r25,%[count]\n"
608
    "1:dec r25\n"
609
    "brne 1b\n"
610
    "ret\n"
611
    ::[count] "M" (UART_B_VALUE)
612
  );
613
}
614
#endif
615

    
616
void getNch(uint8_t count) {
617
  do getch(); while (--count);
618
  verifySpace();
619
}
620

    
621
void verifySpace() {
622
  if (getch() != CRC_EOP) {
623
    watchdogConfig(WATCHDOG_16MS);    // shorten WD timeout
624
    while (1)                              // and busy-loop so that WD causes
625
      ;                                      //  a reset and app start.
626
  }
627
  putch(STK_INSYNC);
628
}
629

    
630
#if LED_START_FLASHES > 0
631
void flash_led(uint8_t count) {
632
  do {
633
    TCNT1 = -(F_CPU/(1024*16));
634
    TIFR1 = _BV(TOV1);
635
    while(!(TIFR1 & _BV(TOV1)));
636
#ifdef __AVR_ATmega8__
637
    LED_PORT ^= _BV(LED);
638
#else
639
    LED_PIN |= _BV(LED);
640
#endif
641
    watchdogReset();
642
  } while (--count);
643
}
644
#endif
645

    
646
// Watchdog functions. These are only safe with interrupts turned off.
647
void watchdogReset() {
648
  __asm__ __volatile__ (
649
    "wdr\n"
650
  );
651
}
652

    
653
void watchdogConfig(uint8_t x) {
654
  WDTCSR = _BV(WDCE) | _BV(WDE);
655
  WDTCSR = x;
656
}
657

    
658
void appStart() {
659
  watchdogConfig(WATCHDOG_OFF);
660
  __asm__ __volatile__ (
661
#ifdef VIRTUAL_BOOT_PARTITION
662
    // Jump to WDT vector
663
    "ldi r30,4\n"
664
    "clr r31\n"
665
#else
666
    // Jump to RST vector
667
    "clr r30\n"
668
    "clr r31\n"
669
#endif
670
    "ijmp\n"
671
  );
672
}