~ubuntu-branches/ubuntu/precise/arduino/precise

« back to all changes in this revision

Viewing changes to hardware/arduino/bootloaders/bt/ATmegaBOOT_168.c

  • Committer: Bazaar Package Importer
  • Author(s): Scott Howard
  • Date: 2010-04-13 22:32:24 UTC
  • Revision ID: james.westby@ubuntu.com-20100413223224-jduxnd0xxnkkda02
Tags: upstream-0018+dfsg
ImportĀ upstreamĀ versionĀ 0018+dfsg

Show diffs side-by-side

added added

removed removed

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