source: arduino-1-6-7/trunk/fuentes/arduino-ide-amd64/hardware/arduino/avr/bootloaders/bt/ATmegaBOOT_168.c @ 4837

Last change on this file since 4837 was 4837, checked in by daduve, 2 years ago

Adding new version

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