Project

General

Profile

Statistics
| Branch: | Revision:

root / arduino-1.0 / hardware / arduino / bootloaders / lilypad / src / ATmegaBOOT.c @ 58d82c77

History | View | Annotate | Download (25.5 KB)

1 58d82c77 Tom Mullins
/**********************************************************/
2
/* Serial Bootloader for Atmel megaAVR Controllers        */
3
/*                                                        */
4
/* tested with ATmega8, ATmega128 and ATmega168           */
5
/* should work with other mega's, see code for details    */
6
/*                                                        */
7
/* ATmegaBOOT.c                                           */
8
/*                                                        */
9
/* 20070626: hacked for Arduino Diecimila (which auto-    */
10
/*           resets when a USB connection is made to it)  */
11
/*           by D. Mellis                                 */
12
/* 20060802: hacked for Arduino by D. Cuartielles         */
13
/*           based on a previous hack by D. Mellis        */
14
/*           and D. Cuartielles                           */
15
/*                                                        */
16
/* Monitor and debug functions were added to the original */
17
/* code by Dr. Erik Lins, chip45.com. (See below)         */
18
/*                                                        */
19
/* Thanks to Karl Pitrich for fixing a bootloader pin     */
20
/* problem and more informative LED blinking!             */
21
/*                                                        */
22
/* For the latest version see:                            */
23
/* http://www.chip45.com/                                 */
24
/*                                                        */
25
/* ------------------------------------------------------ */
26
/*                                                        */
27
/* based on stk500boot.c                                  */
28
/* Copyright (c) 2003, Jason P. Kyle                      */
29
/* All rights reserved.                                   */
30
/* see avr1.org for original file and information         */
31
/*                                                        */
32
/* This program is free software; you can redistribute it */
33
/* and/or modify it under the terms of the GNU General    */
34
/* Public License as published by the Free Software       */
35
/* Foundation; either version 2 of the License, or        */
36
/* (at your option) any later version.                    */
37
/*                                                        */
38
/* This program is distributed in the hope that it will   */
39
/* be useful, but WITHOUT ANY WARRANTY; without even the  */
40
/* implied warranty of MERCHANTABILITY or FITNESS FOR A   */
41
/* PARTICULAR PURPOSE.  See the GNU General Public        */
42
/* License for more details.                              */
43
/*                                                        */
44
/* You should have received a copy of the GNU General     */
45
/* Public License along with this program; if not, write  */
46
/* to the Free Software Foundation, Inc.,                 */
47
/* 59 Temple Place, Suite 330, Boston, MA  02111-1307 USA */
48
/*                                                        */
49
/* Licence can be viewed at                               */
50
/* http://www.fsf.org/licenses/gpl.txt                    */
51
/*                                                        */
52
/* Target = Atmel AVR m128,m64,m32,m16,m8,m162,m163,m169, */
53
/* m8515,m8535. ATmega161 has a very small boot block so  */
54
/* isn't supported.                                       */
55
/*                                                        */
56
/* Tested with m168                                       */
57
/**********************************************************/
58
59
/* $Id$ */
60
61
62
/* some includes */
63
#include <inttypes.h>
64
#include <avr/io.h>
65
#include <avr/pgmspace.h>
66
#include <avr/interrupt.h>
67
#include <avr/wdt.h>
68
69
70
/* the current avr-libc eeprom functions do not support the ATmega168 */
71
/* own eeprom write/read functions are used instead */
72
#ifndef __AVR_ATmega168__
73
#include <avr/eeprom.h>
74
#endif
75
76
/* Use the F_CPU defined in Makefile */
77
78
/* 20060803: hacked by DojoCorp */
79
/* 20070626: hacked by David A. Mellis to decrease waiting time for auto-reset */
80
/* set the waiting time for the bootloader */
81
/* get this from the Makefile instead */
82
/* #define MAX_TIME_COUNT (F_CPU>>4) */
83
84
/* 20070707: hacked by David A. Mellis - after this many errors give up and launch application */
85
#define MAX_ERROR_COUNT 5
86
87
/* set the UART baud rate */
88
/* 20060803: hacked by DojoCorp */
89
//#define BAUD_RATE   115200
90
#define BAUD_RATE   19200
91
92
93
/* SW_MAJOR and MINOR needs to be updated from time to time to avoid warning message from AVR Studio */
94
/* never allow AVR Studio to do an update !!!! */
95
#define HW_VER         0x02
96
#define SW_MAJOR 0x01
97
#define SW_MINOR 0x10
98
99
100
/* Adjust to suit whatever pin your hardware uses to enter the bootloader */
101
/* ATmega128 has two UARTS so two pins are used to enter bootloader and select UART */
102
/* BL0... means UART0, BL1... means UART1 */
103
#ifdef __AVR_ATmega128__
104
#define BL_DDR  DDRF
105
#define BL_PORT PORTF
106
#define BL_PIN  PINF
107
#define BL0     PINF7
108
#define BL1     PINF6
109
#else
110
/* other ATmegas have only one UART, so only one pin is defined to enter bootloader */
111
#define BL_DDR  DDRD
112
#define BL_PORT PORTD
113
#define BL_PIN  PIND
114
#define BL      PIND6
115
#endif
116
117
118
/* onboard LED is used to indicate, that the bootloader was entered (3x flashing) */
119
/* if monitor functions are included, LED goes on after monitor was entered */
120
#ifdef __AVR_ATmega128__
121
/* Onboard LED is connected to pin PB7 (e.g. Crumb128, PROBOmega128, Savvy128) */
122
#define LED_DDR  DDRB
123
#define LED_PORT PORTB
124
#define LED_PIN  PINB
125
#define LED      PINB7
126
#else
127
/* Onboard LED is connected to pin PB2 (e.g. Crumb8, Crumb168) */
128
#define LED_DDR  DDRB
129
#define LED_PORT PORTB
130
#define LED_PIN  PINB
131
/* 20060803: hacked by DojoCorp, LED pin is B5 in Arduino */
132
/* #define LED      PINB2 */
133
#define LED      PINB5
134
#endif
135
136
137
/* monitor functions will only be compiled when using ATmega128, due to bootblock size constraints */
138
#ifdef __AVR_ATmega128__
139
#define MONITOR
140
#endif
141
142
143
/* define various device id's */
144
/* manufacturer byte is always the same */
145
#define SIG1        0x1E        // Yep, Atmel is the only manufacturer of AVR micros.  Single source :(
146
147
#if defined __AVR_ATmega128__
148
#define SIG2        0x97
149
#define SIG3        0x02
150
#define PAGE_SIZE        0x80U        //128 words
151
152
#elif defined __AVR_ATmega64__
153
#define SIG2        0x96
154
#define SIG3        0x02
155
#define PAGE_SIZE        0x80U        //128 words
156
157
#elif defined __AVR_ATmega32__
158
#define SIG2        0x95
159
#define SIG3        0x02
160
#define PAGE_SIZE        0x40U        //64 words
161
162
#elif defined __AVR_ATmega16__
163
#define SIG2        0x94
164
#define SIG3        0x03
165
#define PAGE_SIZE        0x40U        //64 words
166
167
#elif defined __AVR_ATmega8__
168
#define SIG2        0x93
169
#define SIG3        0x07
170
#define PAGE_SIZE        0x20U        //32 words
171
172
#elif defined __AVR_ATmega88__
173
#define SIG2        0x93
174
#define SIG3        0x0a
175
#define PAGE_SIZE        0x20U        //32 words
176
177
#elif defined __AVR_ATmega168__
178
#define SIG2        0x94
179
#define SIG3        0x06
180
#define PAGE_SIZE        0x40U        //64 words
181
182
#elif defined __AVR_ATmega162__
183
#define SIG2        0x94
184
#define SIG3        0x04
185
#define PAGE_SIZE        0x40U        //64 words
186
187
#elif defined __AVR_ATmega163__
188
#define SIG2        0x94
189
#define SIG3        0x02
190
#define PAGE_SIZE        0x40U        //64 words
191
192
#elif defined __AVR_ATmega169__
193
#define SIG2        0x94
194
#define SIG3        0x05
195
#define PAGE_SIZE        0x40U        //64 words
196
197
#elif defined __AVR_ATmega8515__
198
#define SIG2        0x93
199
#define SIG3        0x06
200
#define PAGE_SIZE        0x20U        //32 words
201
202
#elif defined __AVR_ATmega8535__
203
#define SIG2        0x93
204
#define SIG3        0x08
205
#define PAGE_SIZE        0x20U        //32 words
206
#endif
207
208
209
/* function prototypes */
210
void putch(char);
211
char getch(void);
212
void getNch(uint8_t);
213
void byte_response(uint8_t);
214
void nothing_response(void);
215
char gethex(void);
216
void puthex(char);
217
void flash_led(uint8_t);
218
219
/* some variables */
220
union address_union {
221
    uint16_t word;
222
    uint8_t  byte[2];
223
} address;
224
225
union length_union {
226
    uint16_t word;
227
    uint8_t  byte[2];
228
} length;
229
230
struct flags_struct {
231
    unsigned eeprom : 1;
232
    unsigned rampz  : 1;
233
} flags;
234
235
uint8_t buff[256];
236
uint8_t address_high;
237
238
uint8_t pagesz=0x80;
239
240
uint8_t i;
241
uint8_t bootuart = 0;
242
243
uint8_t error_count = 0;
244
245
void (*app_start)(void) = 0x0000;
246
247
248
/* main program starts here */
249
int main(void)
250
{
251
    uint8_t ch,ch2;
252
    uint16_t w;
253
254
    asm volatile("nop\n\t");
255
256
    /* set pin direction for bootloader pin and enable pullup */
257
    /* for ATmega128, two pins need to be initialized */
258
#ifdef __AVR_ATmega128__
259
    BL_DDR &= ~_BV(BL0);
260
    BL_DDR &= ~_BV(BL1);
261
    BL_PORT |= _BV(BL0);
262
    BL_PORT |= _BV(BL1);
263
#else
264
    /* We run the bootloader regardless of the state of this pin.  Thus, don't
265
    put it in a different state than the other pins.  --DAM, 070709
266
    BL_DDR &= ~_BV(BL);
267
    BL_PORT |= _BV(BL);
268
    */
269
#endif
270
271
272
#ifdef __AVR_ATmega128__
273
    /* check which UART should be used for booting */
274
    if(bit_is_clear(BL_PIN, BL0)) {
275
      bootuart = 1;
276
    }
277
    else if(bit_is_clear(BL_PIN, BL1)) {
278
      bootuart = 2;
279
    }
280
#endif
281
282
    /* check if flash is programmed already, if not start bootloader anyway */
283
    if(pgm_read_byte_near(0x0000) != 0xFF) {
284
285
#ifdef __AVR_ATmega128__
286
        /* no UART was selected, start application */
287
        if(!bootuart) {
288
          app_start();
289
        }
290
#else
291
        /* check if bootloader pin is set low */
292
        /* we don't start this part neither for the m8, nor m168 */
293
        //if(bit_is_set(BL_PIN, BL)) {
294
    //      app_start();
295
    //    }
296
#endif
297
    }
298
299
#ifdef __AVR_ATmega128__    
300
    /* no bootuart was selected, default to uart 0 */
301
    if(!bootuart) {
302
      bootuart = 1;
303
    }
304
#endif
305
306
307
    /* initialize UART(s) depending on CPU defined */
308
#ifdef __AVR_ATmega128__
309
    if(bootuart == 1) {
310
        UBRR0L = (uint8_t)(F_CPU/(BAUD_RATE*16L)-1);
311
        UBRR0H = (F_CPU/(BAUD_RATE*16L)-1) >> 8;
312
        UCSR0A = 0x00;
313
        UCSR0C = 0x06;
314
        UCSR0B = _BV(TXEN0)|_BV(RXEN0);
315
    }
316
    if(bootuart == 2) {
317
        UBRR1L = (uint8_t)(F_CPU/(BAUD_RATE*16L)-1);
318
        UBRR1H = (F_CPU/(BAUD_RATE*16L)-1) >> 8;
319
        UCSR1A = 0x00;
320
        UCSR1C = 0x06;
321
        UCSR1B = _BV(TXEN1)|_BV(RXEN1);
322
    }
323
#elif defined __AVR_ATmega163__
324
    UBRR = (uint8_t)(F_CPU/(BAUD_RATE*16L)-1);
325
    UBRRHI = (F_CPU/(BAUD_RATE*16L)-1) >> 8;
326
    UCSRA = 0x00;
327
    UCSRB = _BV(TXEN)|_BV(RXEN);        
328
#elif defined __AVR_ATmega168__
329
    UBRR0L = (uint8_t)(F_CPU/(BAUD_RATE*16L)-1);
330
    UBRR0H = (F_CPU/(BAUD_RATE*16L)-1) >> 8;
331
    UCSR0B = (1<<RXEN0) | (1<<TXEN0);
332
    UCSR0C = (1<<UCSZ00) | (1<<UCSZ01);
333
334
    /* Enable internal pull-up resistor on pin D0 (RX), in order
335
    to supress line noise that prevents the bootloader from
336
    timing out (DAM: 20070509) */
337
    DDRD &= ~_BV(PIND0);
338
    PORTD |= _BV(PIND0);
339
#elif defined __AVR_ATmega8__
340
  /* m8 */
341
  UBRRH = (((F_CPU/BAUD_RATE)/16)-1)>>8;         // set baud rate
342
  UBRRL = (((F_CPU/BAUD_RATE)/16)-1);
343
  UCSRB = (1<<RXEN)|(1<<TXEN);  // enable Rx & Tx
344
  UCSRC = (1<<URSEL)|(1<<UCSZ1)|(1<<UCSZ0);  // config USART; 8N1
345
#else
346
    /* m16,m32,m169,m8515,m8535 */
347
    UBRRL = (uint8_t)(F_CPU/(BAUD_RATE*16L)-1);
348
    UBRRH = (F_CPU/(BAUD_RATE*16L)-1) >> 8;
349
    UCSRA = 0x00;
350
    UCSRC = 0x06;
351
    UCSRB = _BV(TXEN)|_BV(RXEN);
352
#endif
353
354
    /* set LED pin as output */
355
    LED_DDR |= _BV(LED);
356
357
358
    /* flash onboard LED to signal entering of bootloader */
359
#ifdef __AVR_ATmega128__
360
    // 4x for UART0, 5x for UART1
361
    flash_led(NUM_LED_FLASHES + bootuart);
362
#else
363
    flash_led(NUM_LED_FLASHES);
364
#endif
365
    
366
    /* 20050803: by DojoCorp, this is one of the parts provoking the
367
                 system to stop listening, cancelled from the original */
368
    //putch('\0');
369
370
371
    /* forever loop */
372
    for (;;) {
373
374
        /* get character from UART */
375
        ch = getch();
376
377
        /* A bunch of if...else if... gives smaller code than switch...case ! */
378
379
        /* Hello is anyone home ? */ 
380
        if(ch=='0') {
381
            nothing_response();
382
        }
383
384
385
        /* Request programmer ID */
386
        /* Not using PROGMEM string due to boot block in m128 being beyond 64kB boundry  */
387
        /* Would need to selectively manipulate RAMPZ, and it's only 9 characters anyway so who cares.  */
388
        else if(ch=='1') {
389
            if (getch() == ' ') {
390
                putch(0x14);
391
                putch('A');
392
                putch('V');
393
                putch('R');
394
                putch(' ');
395
                putch('I');
396
                putch('S');
397
                putch('P');
398
                putch(0x10);
399
            } else {
400
                if (++error_count == MAX_ERROR_COUNT)
401
                    app_start();
402
            }
403
        }
404
405
406
        /* AVR ISP/STK500 board commands  DON'T CARE so default nothing_response */
407
        else if(ch=='@') {
408
            ch2 = getch();
409
            if (ch2>0x85) getch();
410
            nothing_response();
411
        }
412
413
414
        /* AVR ISP/STK500 board requests */
415
        else if(ch=='A') {
416
            ch2 = getch();
417
            if(ch2==0x80) byte_response(HW_VER);                // Hardware version
418
            else if(ch2==0x81) byte_response(SW_MAJOR);        // Software major version
419
            else if(ch2==0x82) byte_response(SW_MINOR);        // Software minor version
420
            else if(ch2==0x98) byte_response(0x03);                // Unknown but seems to be required by avr studio 3.56
421
            else byte_response(0x00);                                // Covers various unnecessary responses we don't care about
422
        }
423
424
425
        /* Device Parameters  DON'T CARE, DEVICE IS FIXED  */
426
        else if(ch=='B') {
427
            getNch(20);
428
            nothing_response();
429
        }
430
431
432
        /* Parallel programming stuff  DON'T CARE  */
433
        else if(ch=='E') {
434
            getNch(5);
435
            nothing_response();
436
        }
437
438
439
        /* Enter programming mode  */
440
        else if(ch=='P') {
441
            nothing_response();
442
        }
443
444
445
        /* Leave programming mode  */
446
        else if(ch=='Q') {
447
            nothing_response();
448
        }
449
450
451
        /* Erase device, don't care as we will erase one page at a time anyway.  */
452
        else if(ch=='R') {
453
            nothing_response();
454
        }
455
456
457
        /* Set address, little endian. EEPROM in bytes, FLASH in words  */
458
        /* Perhaps extra address bytes may be added in future to support > 128kB FLASH.  */
459
        /* This might explain why little endian was used here, big endian used everywhere else.  */
460
        else if(ch=='U') {
461
            address.byte[0] = getch();
462
            address.byte[1] = getch();
463
            nothing_response();
464
        }
465
466
467
        /* Universal SPI programming command, disabled.  Would be used for fuses and lock bits.  */
468
        else if(ch=='V') {
469
            getNch(4);
470
            byte_response(0x00);
471
        }
472
473
474
        /* Write memory, length is big endian and is in bytes  */
475
        else if(ch=='d') {
476
            length.byte[1] = getch();
477
            length.byte[0] = getch();
478
            flags.eeprom = 0;
479
            if (getch() == 'E') flags.eeprom = 1;
480
            for (w=0;w<length.word;w++) {
481
                buff[w] = getch();                                // Store data in buffer, can't keep up with serial data stream whilst programming pages
482
            }
483
            if (getch() == ' ') {
484
                if (flags.eeprom) {                                //Write to EEPROM one byte at a time
485
                    for(w=0;w<length.word;w++) {
486
#ifdef __AVR_ATmega168__
487
                        while(EECR & (1<<EEPE));
488
                        EEAR = (uint16_t)(void *)address.word;
489
                        EEDR = buff[w];
490
                        EECR |= (1<<EEMPE);
491
                        EECR |= (1<<EEPE);
492
#else
493
                        eeprom_write_byte((void *)address.word,buff[w]);
494
#endif
495
                        address.word++;
496
                    }                        
497
                }
498
                else {                                                //Write to FLASH one page at a time
499
                    if (address.byte[1]>127) address_high = 0x01;        //Only possible with m128, m256 will need 3rd address byte. FIXME
500
                    else address_high = 0x00;
501
#ifdef __AVR_ATmega128__
502
                    RAMPZ = address_high;
503
#endif
504
                    address.word = address.word << 1;                //address * 2 -> byte location
505
                    /* if ((length.byte[0] & 0x01) == 0x01) length.word++;        //Even up an odd number of bytes */
506
                    if ((length.byte[0] & 0x01)) length.word++;        //Even up an odd number of bytes
507
                    cli();                                        //Disable interrupts, just to be sure
508
                        // HACKME: EEPE used to be EEWE
509
                    while(bit_is_set(EECR,EEPE));                        //Wait for previous EEPROM writes to complete
510
                    asm volatile(
511
                                 "clr        r17                \n\t"        //page_word_count
512
                                 "lds        r30,address        \n\t"        //Address of FLASH location (in bytes)
513
                                 "lds        r31,address+1        \n\t"
514
                                 "ldi        r28,lo8(buff)        \n\t"        //Start of buffer array in RAM
515
                                 "ldi        r29,hi8(buff)        \n\t"
516
                                 "lds        r24,length        \n\t"        //Length of data to be written (in bytes)
517
                                 "lds        r25,length+1        \n\t"
518
                                 "length_loop:                \n\t"        //Main loop, repeat for number of words in block                                                                                                                  
519
                                 "cpi        r17,0x00        \n\t"        //If page_word_count=0 then erase page
520
                                 "brne        no_page_erase        \n\t"                                                 
521
                                 "wait_spm1:                \n\t"
522
                                 "lds        r16,%0                \n\t"        //Wait for previous spm to complete
523
                                 "andi        r16,1           \n\t"
524
                                 "cpi        r16,1           \n\t"
525
                                 "breq        wait_spm1       \n\t"
526
                                 "ldi        r16,0x03        \n\t"        //Erase page pointed to by Z
527
                                 "sts        %0,r16                \n\t"
528
                                 "spm                        \n\t"                                                         
529
#ifdef __AVR_ATmega163__
530
                                 ".word 0xFFFF                \n\t"
531
                                 "nop                        \n\t"
532
#endif
533
                                 "wait_spm2:                \n\t"
534
                                 "lds        r16,%0                \n\t"        //Wait for previous spm to complete
535
                                 "andi        r16,1           \n\t"
536
                                 "cpi        r16,1           \n\t"
537
                                 "breq        wait_spm2       \n\t"                                                                         
538
539
                                 "ldi        r16,0x11        \n\t"        //Re-enable RWW section
540
                                 "sts        %0,r16                \n\t"                                                                          
541
                                 "spm                        \n\t"
542
#ifdef __AVR_ATmega163__
543
                                 ".word 0xFFFF                \n\t"
544
                                 "nop                        \n\t"
545
#endif
546
                                 "no_page_erase:                \n\t"                                                         
547
                                 "ld        r0,Y+                \n\t"        //Write 2 bytes into page buffer
548
                                 "ld        r1,Y+                \n\t"                                                         
549
                                                         
550
                                 "wait_spm3:                \n\t"
551
                                 "lds        r16,%0                \n\t"        //Wait for previous spm to complete
552
                                 "andi        r16,1           \n\t"
553
                                 "cpi        r16,1           \n\t"
554
                                 "breq        wait_spm3       \n\t"
555
                                 "ldi        r16,0x01        \n\t"        //Load r0,r1 into FLASH page buffer
556
                                 "sts        %0,r16                \n\t"
557
                                 "spm                        \n\t"
558
                                                         
559
                                 "inc        r17                \n\t"        //page_word_count++
560
                                 "cpi r17,%1                \n\t"
561
                                 "brlo        same_page        \n\t"        //Still same page in FLASH
562
                                 "write_page:                \n\t"
563
                                 "clr        r17                \n\t"        //New page, write current one first
564
                                 "wait_spm4:                \n\t"
565
                                 "lds        r16,%0                \n\t"        //Wait for previous spm to complete
566
                                 "andi        r16,1           \n\t"
567
                                 "cpi        r16,1           \n\t"
568
                                 "breq        wait_spm4       \n\t"
569
#ifdef __AVR_ATmega163__
570
                                 "andi        r30,0x80        \n\t"        // m163 requires Z6:Z1 to be zero during page write
571
#endif                                                                                                                  
572
                                 "ldi        r16,0x05        \n\t"        //Write page pointed to by Z
573
                                 "sts        %0,r16                \n\t"
574
                                 "spm                        \n\t"
575
#ifdef __AVR_ATmega163__
576
                                 ".word 0xFFFF                \n\t"
577
                                 "nop                        \n\t"
578
                                 "ori        r30,0x7E        \n\t"        // recover Z6:Z1 state after page write (had to be zero during write)
579
#endif
580
                                 "wait_spm5:                \n\t"
581
                                 "lds        r16,%0                \n\t"        //Wait for previous spm to complete
582
                                 "andi        r16,1           \n\t"
583
                                 "cpi        r16,1           \n\t"
584
                                 "breq        wait_spm5       \n\t"                                                                         
585
                                 "ldi        r16,0x11        \n\t"        //Re-enable RWW section
586
                                 "sts        %0,r16                \n\t"                                                                          
587
                                 "spm                        \n\t"                                                          
588
#ifdef __AVR_ATmega163__
589
                                 ".word 0xFFFF                \n\t"
590
                                 "nop                        \n\t"
591
#endif
592
                                 "same_page:                \n\t"                                                         
593
                                 "adiw        r30,2                \n\t"        //Next word in FLASH
594
                                 "sbiw        r24,2                \n\t"        //length-2
595
                                 "breq        final_write        \n\t"        //Finished
596
                                 "rjmp        length_loop        \n\t"
597
                                 "final_write:                \n\t"
598
                                 "cpi        r17,0                \n\t"
599
                                 "breq        block_done        \n\t"
600
                                 "adiw        r24,2                \n\t"        //length+2, fool above check on length after short page write
601
                                 "rjmp        write_page        \n\t"
602
                                 "block_done:                \n\t"
603
                                 "clr        __zero_reg__        \n\t"        //restore zero register
604
#if defined __AVR_ATmega168__
605
                                 : "=m" (SPMCSR) : "M" (PAGE_SIZE) : "r0","r16","r17","r24","r25","r28","r29","r30","r31"
606
#else
607
                                 : "=m" (SPMCR) : "M" (PAGE_SIZE) : "r0","r16","r17","r24","r25","r28","r29","r30","r31"
608
#endif
609
                                 );
610
                    /* Should really add a wait for RWW section to be enabled, don't actually need it since we never */
611
                    /* exit the bootloader without a power cycle anyhow */
612
                }
613
                putch(0x14);
614
                putch(0x10);
615
            } else {
616
                if (++error_count == MAX_ERROR_COUNT)
617
                    app_start();
618
            }                
619
        }
620
    
621
622
        /* Read memory block mode, length is big endian.  */
623
        else if(ch=='t') {
624
            length.byte[1] = getch();
625
            length.byte[0] = getch();
626
#if defined __AVR_ATmega128__
627
            if (address.word>0x7FFF) flags.rampz = 1;                // No go with m256, FIXME
628
            else flags.rampz = 0;
629
#endif
630
            if (getch() == 'E') flags.eeprom = 1;
631
            else {
632
                flags.eeprom = 0;
633
                address.word = address.word << 1;                // address * 2 -> byte location
634
            }
635
            if (getch() == ' ') {                                // Command terminator
636
                putch(0x14);
637
                for (w=0;w < length.word;w++) {                        // Can handle odd and even lengths okay
638
                    if (flags.eeprom) {                                // Byte access EEPROM read
639
#ifdef __AVR_ATmega168__
640
                        while(EECR & (1<<EEPE));
641
                        EEAR = (uint16_t)(void *)address.word;
642
                        EECR |= (1<<EERE);
643
                        putch(EEDR);
644
#else
645
                        putch(eeprom_read_byte((void *)address.word));
646
#endif
647
                        address.word++;
648
                    }
649
                    else {
650
651
                        if (!flags.rampz) putch(pgm_read_byte_near(address.word));
652
#if defined __AVR_ATmega128__
653
                        else putch(pgm_read_byte_far(address.word + 0x10000));
654
                        // Hmmmm, yuck  FIXME when m256 arrvies
655
#endif
656
                        address.word++;
657
                    }
658
                }
659
                putch(0x10);
660
            }
661
        }
662
663
664
        /* Get device signature bytes  */
665
        else if(ch=='u') {
666
            if (getch() == ' ') {
667
                putch(0x14);
668
                putch(SIG1);
669
                putch(SIG2);
670
                putch(SIG3);
671
                putch(0x10);
672
            } else {
673
                if (++error_count == MAX_ERROR_COUNT)
674
                    app_start();
675
            }
676
        }
677
678
679
        /* Read oscillator calibration byte */
680
        else if(ch=='v') {
681
            byte_response(0x00);
682
        }
683
684
685
#ifdef MONITOR
686
687
        /* here come the extended monitor commands by Erik Lins */
688
689
        /* check for three times exclamation mark pressed */
690
        else if(ch=='!') {
691
            ch = getch();
692
            if(ch=='!') {
693
                ch = getch();
694
                if(ch=='!') {
695
696
#ifdef __AVR_ATmega128__
697
                    uint16_t extaddr;
698
#endif
699
                    uint8_t addrl, addrh;
700
701
#ifdef CRUMB128
702
                    PGM_P welcome = {"ATmegaBOOT / Crumb128 - (C) J.P.Kyle, E.Lins - 050815\n\r"};
703
#elif defined PROBOMEGA128
704
                    PGM_P welcome = {"ATmegaBOOT / PROBOmega128 - (C) J.P.Kyle, E.Lins - 050815\n\r"};
705
#elif defined SAVVY128
706
                    PGM_P welcome = {"ATmegaBOOT / Savvy128 - (C) J.P.Kyle, E.Lins - 050815\n\r"};
707
#endif
708
709
                    /* turn on LED */
710
                    LED_DDR |= _BV(LED);
711
                    LED_PORT &= ~_BV(LED);
712
713
                    /* print a welcome message and command overview */
714
                    for(i=0; welcome[i] != '\0'; ++i) {
715
                        putch(welcome[i]);
716
                    }
717
718
                    /* test for valid commands */
719
                    for(;;) {
720
                        putch('\n');
721
                        putch('\r');
722
                        putch(':');
723
                        putch(' ');
724
725
                        ch = getch();
726
                        putch(ch);
727
728
                        /* toggle LED */
729
                        if(ch == 't') {
730
                            if(bit_is_set(LED_PIN,LED)) {
731
                                LED_PORT &= ~_BV(LED);
732
                                putch('1');
733
                            } else {
734
                                LED_PORT |= _BV(LED);
735
                                putch('0');
736
                            }
737
738
                        } 
739
740
                        /* read byte from address */
741
                        else if(ch == 'r') {
742
                            ch = getch(); putch(ch);
743
                            addrh = gethex();
744
                            addrl = gethex();
745
                            putch('=');
746
                            ch = *(uint8_t *)((addrh << 8) + addrl);
747
                            puthex(ch);
748
                        }
749
750
                        /* write a byte to address  */
751
                        else if(ch == 'w') {
752
                            ch = getch(); putch(ch);
753
                            addrh = gethex();
754
                            addrl = gethex();
755
                            ch = getch(); putch(ch);
756
                            ch = gethex();
757
                            *(uint8_t *)((addrh << 8) + addrl) = ch;
758
759
                        }
760
761
                        /* read from uart and echo back */
762
                        else if(ch == 'u') {
763
                            for(;;) {
764
                                putch(getch());
765
                            }
766
                        }
767
#ifdef __AVR_ATmega128__
768
                        /* external bus loop  */
769
                        else if(ch == 'b') {
770
                            putch('b');
771
                            putch('u');
772
                            putch('s');
773
                            MCUCR = 0x80;
774
                            XMCRA = 0;
775
                            XMCRB = 0;
776
                            extaddr = 0x1100;
777
                            for(;;) {
778
                                ch = *(volatile uint8_t *)extaddr;
779
                                if(++extaddr == 0) {
780
                                    extaddr = 0x1100;
781
                                }
782
                            }
783
                        }
784
#endif
785
786
                        else if(ch == 'j') {
787
                            app_start();
788
                        }
789
790
                    }
791
                    /* end of monitor functions */
792
793
                }
794
            }
795
        }
796
        /* end of monitor */
797
#endif
798
        else if (++error_count == MAX_ERROR_COUNT) {
799
            app_start();
800
        }
801
    }
802
    /* end of forever loop */
803
804
}
805
806
807
char gethex(void) {
808
    char ah,al;
809
810
    ah = getch(); putch(ah);
811
    al = getch(); putch(al);
812
    if(ah >= 'a') {
813
        ah = ah - 'a' + 0x0a;
814
    } else if(ah >= '0') {
815
        ah -= '0';
816
    }
817
    if(al >= 'a') {
818
        al = al - 'a' + 0x0a;
819
    } else if(al >= '0') {
820
        al -= '0';
821
    }
822
    return (ah << 4) + al;
823
}
824
825
826
void puthex(char ch) {
827
    char ah,al;
828
829
    ah = (ch & 0xf0) >> 4;
830
    if(ah >= 0x0a) {
831
        ah = ah - 0x0a + 'a';
832
    } else {
833
        ah += '0';
834
    }
835
    al = (ch & 0x0f);
836
    if(al >= 0x0a) {
837
        al = al - 0x0a + 'a';
838
    } else {
839
        al += '0';
840
    }
841
    putch(ah);
842
    putch(al);
843
}
844
845
846
void putch(char ch)
847
{
848
#ifdef __AVR_ATmega128__
849
    if(bootuart == 1) {
850
        while (!(UCSR0A & _BV(UDRE0)));
851
        UDR0 = ch;
852
    }
853
    else if (bootuart == 2) {
854
        while (!(UCSR1A & _BV(UDRE1)));
855
        UDR1 = ch;
856
    }
857
#elif defined __AVR_ATmega168__
858
    while (!(UCSR0A & _BV(UDRE0)));
859
    UDR0 = ch;
860
#else
861
    /* m8,16,32,169,8515,8535,163 */
862
    while (!(UCSRA & _BV(UDRE)));
863
    UDR = ch;
864
#endif
865
}
866
867
868
char getch(void)
869
{
870
#ifdef __AVR_ATmega128__
871
    if(bootuart == 1) {
872
        while(!(UCSR0A & _BV(RXC0)));
873
        return UDR0;
874
    }
875
    else if(bootuart == 2) {
876
        while(!(UCSR1A & _BV(RXC1)));
877
        return UDR1;
878
    }
879
    return 0;
880
#elif defined __AVR_ATmega168__
881
    uint32_t count = 0;
882
    while(!(UCSR0A & _BV(RXC0))){
883
            /* 20060803 DojoCorp:: Addon coming from the previous Bootloader*/               
884
            /* HACKME:: here is a good place to count times*/
885
            count++;
886
            if (count > MAX_TIME_COUNT)
887
                    app_start();
888
     }
889
    return UDR0;
890
#else
891
    /* m8,16,32,169,8515,8535,163 */
892
    uint32_t count = 0;
893
    while(!(UCSRA & _BV(RXC))){
894
            /* 20060803 DojoCorp:: Addon coming from the previous Bootloader*/               
895
            /* HACKME:: here is a good place to count times*/
896
            count++;
897
            if (count > MAX_TIME_COUNT)
898
                    app_start();
899
     }
900
    return UDR;
901
#endif
902
}
903
904
905
void getNch(uint8_t count)
906
{
907
    uint8_t i;
908
    for(i=0;i<count;i++) {
909
#ifdef __AVR_ATmega128__
910
        if(bootuart == 1) {
911
            while(!(UCSR0A & _BV(RXC0)));
912
            UDR0;
913
        } 
914
        else if(bootuart == 2) {
915
            while(!(UCSR1A & _BV(RXC1)));
916
            UDR1;
917
        }
918
#elif defined __AVR_ATmega168__
919
        while(!(UCSR0A & _BV(RXC0)));
920
        UDR0;
921
#else
922
        /* m8,16,32,169,8515,8535,163 */
923
           /* 20060803 DojoCorp:: Addon coming from the previous Bootloader*/               
924
        //while(!(UCSRA & _BV(RXC)));
925
        //UDR;
926
    uint8_t i;
927
    for(i=0;i<count;i++) {
928
            getch(); // need to handle time out
929
    }
930
#endif                
931
    }
932
}
933
934
935
void byte_response(uint8_t val)
936
{
937
    if (getch() == ' ') {
938
        putch(0x14);
939
        putch(val);
940
        putch(0x10);
941
    } else {
942
        if (++error_count == MAX_ERROR_COUNT)
943
            app_start();
944
    }
945
}
946
947
948
void nothing_response(void)
949
{
950
    if (getch() == ' ') {
951
        putch(0x14);
952
        putch(0x10);
953
    } else {
954
        if (++error_count == MAX_ERROR_COUNT)
955
            app_start();
956
    }
957
}
958
959
void flash_led(uint8_t count)
960
{
961
    /* flash onboard LED three times to signal entering of bootloader */
962
        /* l needs to be volatile or the delay loops below might get
963
        optimized away if compiling with optimizations (DAM). */
964
    volatile uint32_t l;
965
966
    if (count == 0) {
967
      count = 3;
968
    }
969
    
970
    for (i = 0; i < count; ++i) {
971
        LED_PORT |= _BV(LED);
972
        for(l = 0; l < (F_CPU / 1000); ++l);
973
        LED_PORT &= ~_BV(LED);
974
        for(l = 0; l < (F_CPU / 1000); ++l);
975
    }
976
}
977
978
979
/* end of file ATmegaBOOT.c */