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

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

Adding new version

File size: 52.1 KB
Line 
1/*****************************************************************************
2Title:     STK500v2 compatible bootloader
3           Modified for Wiring board ATMega128-16MHz
4Author:    Peter Fleury <pfleury@gmx.ch>   http://jump.to/fleury
5Compiler:  avr-gcc 3.4.5 or 4.1 / avr-libc 1.4.3
6Hardware:  All AVRs with bootloader support, tested with ATmega8
7License:   GNU General Public License
8
9Modified:  Worapoht Kornkaewwattanakul <dev@avride.com>   http://www.avride.com
10Date:      17 October 2007
11Update:    1st, 29 Dec 2007 : Enable CMD_SPI_MULTI but ignore unused command by return 0x00 byte response..
12Compiler:  WINAVR20060421
13Description: add timeout feature like previous Wiring bootloader
14
15DESCRIPTION:
16    This program allows an AVR with bootloader capabilities to
17    read/write its own Flash/EEprom. To enter Programming mode
18    an input pin is checked. If this pin is pulled low, programming mode
19    is entered. If not, normal execution is done from $0000
20    "reset" vector in Application area.
21    Size fits into a 1024 word bootloader section
22        when compiled with avr-gcc 4.1
23        (direct replace on Wiring Board without fuse setting changed)
24
25USAGE:
26    - Set AVR MCU type and clock-frequency (F_CPU) in the Makefile.
27    - Set baud rate below (AVRISP only works with 115200 bps)
28    - compile/link the bootloader with the supplied Makefile
29    - program the "Boot Flash section size" (BOOTSZ fuses),
30      for boot-size 1024 words:  program BOOTSZ01
31    - enable the BOOT Reset Vector (program BOOTRST)
32    - Upload the hex file to the AVR using any ISP programmer
33    - Program Boot Lock Mode 3 (program BootLock 11 and BootLock 12 lock bits) // (leave them)
34    - Reset your AVR while keeping PROG_PIN pulled low // (for enter bootloader by switch)
35    - Start AVRISP Programmer (AVRStudio/Tools/Program AVR)
36    - AVRISP will detect the bootloader
37    - Program your application FLASH file and optional EEPROM file using AVRISP
38
39Note:
40    Erasing the device without flashing, through AVRISP GUI button "Erase Device"
41    is not implemented, due to AVRStudio limitations.
42    Flash is always erased before programming.
43
44        AVRdude:
45        Please uncomment #define REMOVE_CMD_SPI_MULTI when using AVRdude.
46        Comment #define REMOVE_PROGRAM_LOCK_BIT_SUPPORT to reduce code size
47        Read Fuse Bits and Read/Write Lock Bits is not supported
48
49NOTES:
50    Based on Atmel Application Note AVR109 - Self-programming
51    Based on Atmel Application Note AVR068 - STK500v2 Protocol
52
53LICENSE:
54    Copyright (C) 2006 Peter Fleury
55
56    This program is free software; you can redistribute it and/or modify
57    it under the terms of the GNU General Public License as published by
58    the Free Software Foundation; either version 2 of the License, or
59    any later version.
60
61    This program is distributed in the hope that it will be useful,
62    but WITHOUT ANY WARRANTY; without even the implied warranty of
63    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
64    GNU General Public License for more details.
65
66*****************************************************************************/
67
68//************************************************************************
69//*     Edit History
70//************************************************************************
71//*     Jul  7, 2010    <MLS> = Mark Sproul msproul@skycharoit.com
72//*     Jul  7, 2010    <MLS> Working on mega2560. No Auto-restart
73//*     Jul  7, 2010    <MLS> Switched to 8K bytes (4K words) so that we have room for the monitor
74//*     Jul  8, 2010    <MLS> Found older version of source that had auto restart, put that code back in
75//*     Jul  8, 2010    <MLS> Adding monitor code
76//*     Jul 11, 2010    <MLS> Added blinking LED while waiting for download to start
77//*     Jul 11, 2010    <MLS> Added EEPROM test
78//*     Jul 29, 2010    <MLS> Added recchar_timeout for timing out on bootloading
79//*     Aug 23, 2010    <MLS> Added support for atmega2561
80//*     Aug 26, 2010    <MLS> Removed support for BOOT_BY_SWITCH
81//*     Sep  8, 2010    <MLS> Added support for atmega16
82//*     Nov  9, 2010    <MLS> Issue 392:Fixed bug that 3 !!! in code would cause it to jump to monitor
83//*     Jun 24, 2011    <MLS> Removed analogRead (was not used)
84//*     Dec 29, 2011    <MLS> Issue 181: added watch dog timmer support
85//*     Dec 29, 2011    <MLS> Issue 505:  bootloader is comparing the seqNum to 1 or the current sequence
86//*     Jan  1, 2012    <MLS> Issue 543: CMD_CHIP_ERASE_ISP now returns STATUS_CMD_FAILED instead of STATUS_CMD_OK
87//*     Jan  1, 2012    <MLS> Issue 543: Write EEPROM now does something (NOT TESTED)
88//*     Jan  1, 2012    <MLS> Issue 544: stk500v2 bootloader doesn't support reading fuses
89//************************************************************************
90
91//************************************************************************
92//*     these are used to test issues
93//*     http://code.google.com/p/arduino/issues/detail?id=505
94//*     Reported by mark.stubbs, Mar 14, 2011
95//*     The STK500V2 bootloader is comparing the seqNum to 1 or the current sequence
96//*     (IE: Requiring the sequence to be 1 or match seqNum before continuing). 
97//*     The correct behavior is for the STK500V2 to accept the PC's sequence number, and echo it back for the reply message.
98#define _FIX_ISSUE_505_
99//************************************************************************
100//*     Issue 181: added watch dog timmer support
101#define _FIX_ISSUE_181_
102
103#include        <inttypes.h>
104#include        <avr/io.h>
105#include        <avr/interrupt.h>
106#include        <avr/boot.h>
107#include        <avr/pgmspace.h>
108#include        <util/delay.h>
109#include        <avr/eeprom.h>
110#include        <avr/common.h>
111#include        <stdlib.h>
112#include        "command.h"
113
114
115#if defined(_MEGA_BOARD_) || defined(_BOARD_AMBER128_) || defined(__AVR_ATmega1280__) || defined(__AVR_ATmega2560__) \
116        || defined(__AVR_ATmega2561__) || defined(__AVR_ATmega1284P__) || defined(ENABLE_MONITOR)
117        #undef          ENABLE_MONITOR
118        #define         ENABLE_MONITOR
119        static void     RunMonitor(void);
120#endif
121
122#ifndef EEWE
123        #define EEWE    1
124#endif
125#ifndef EEMWE
126        #define EEMWE   2
127#endif
128
129//#define       _DEBUG_SERIAL_
130//#define       _DEBUG_WITH_LEDS_
131
132
133/*
134 * Uncomment the following lines to save code space
135 */
136//#define       REMOVE_PROGRAM_LOCK_BIT_SUPPORT         // disable program lock bits
137//#define       REMOVE_BOOTLOADER_LED                           // no LED to show active bootloader
138//#define       REMOVE_CMD_SPI_MULTI                            // disable processing of SPI_MULTI commands, Remark this line for AVRDUDE <Worapoht>
139//
140
141
142
143//************************************************************************
144//*     LED on pin "PROGLED_PIN" on port "PROGLED_PORT"
145//*     indicates that bootloader is active
146//*     PG2 -> LED on Wiring board
147//************************************************************************
148#define         BLINK_LED_WHILE_WAITING
149
150#ifdef _MEGA_BOARD_
151        #define PROGLED_PORT    PORTB
152        #define PROGLED_DDR             DDRB
153        #define PROGLED_PIN             PINB7
154#elif defined( _BOARD_AMBER128_ )
155        //*     this is for the amber 128 http://www.soc-robotics.com/
156        //*     onbarod led is PORTE4
157        #define PROGLED_PORT    PORTD
158        #define PROGLED_DDR             DDRD
159        #define PROGLED_PIN             PINE7
160#elif defined( _CEREBOTPLUS_BOARD_ ) || defined(_CEREBOT_II_BOARD_)
161        //*     this is for the Cerebot 2560 board and the Cerebot-ii
162        //*     onbarod leds are on PORTE4-7
163        #define PROGLED_PORT    PORTE
164        #define PROGLED_DDR             DDRE
165        #define PROGLED_PIN             PINE7
166#elif defined( _PENGUINO_ )
167        //*     this is for the Penguino
168        //*     onbarod led is PORTE4
169        #define PROGLED_PORT    PORTC
170        #define PROGLED_DDR             DDRC
171        #define PROGLED_PIN             PINC6
172#elif defined( _ANDROID_2561_ ) || defined( __AVR_ATmega2561__ )
173        //*     this is for the Boston Android 2561
174        //*     onbarod led is PORTE4
175        #define PROGLED_PORT    PORTA
176        #define PROGLED_DDR             DDRA
177        #define PROGLED_PIN             PINA3
178#elif defined( _BOARD_MEGA16 )
179        //*     onbarod led is PORTA7
180        #define PROGLED_PORT    PORTA
181        #define PROGLED_DDR             DDRA
182        #define PROGLED_PIN             PINA7
183        #define UART_BAUDRATE_DOUBLE_SPEED 0
184
185#elif defined( _BOARD_BAHBOT_ )
186        //*     dosent have an onboard LED but this is what will probably be added to this port
187        #define PROGLED_PORT    PORTB
188        #define PROGLED_DDR             DDRB
189        #define PROGLED_PIN             PINB0
190
191#elif defined( _BOARD_ROBOTX_ )
192        #define PROGLED_PORT    PORTB
193        #define PROGLED_DDR             DDRB
194        #define PROGLED_PIN             PINB6
195#elif defined( _BOARD_CUSTOM1284_BLINK_B0_ )
196        #define PROGLED_PORT    PORTB
197        #define PROGLED_DDR             DDRB
198        #define PROGLED_PIN             PINB0
199#elif defined( _BOARD_CUSTOM1284_ )
200        #define PROGLED_PORT    PORTD
201        #define PROGLED_DDR             DDRD
202        #define PROGLED_PIN             PIND5
203#elif defined( _AVRLIP_ )
204        #define PROGLED_PORT    PORTB
205        #define PROGLED_DDR             DDRB
206        #define PROGLED_PIN             PINB5
207#elif defined( _BOARD_STK500_ )
208        #define PROGLED_PORT    PORTA
209        #define PROGLED_DDR             DDRA
210        #define PROGLED_PIN             PINA7
211#elif defined( _BOARD_STK502_ )
212        #define PROGLED_PORT    PORTB
213        #define PROGLED_DDR             DDRB
214        #define PROGLED_PIN             PINB5
215#elif defined( _BOARD_STK525_ )
216        #define PROGLED_PORT    PORTB
217        #define PROGLED_DDR             DDRB
218        #define PROGLED_PIN             PINB7
219#else
220        #define PROGLED_PORT    PORTG
221        #define PROGLED_DDR             DDRG
222        #define PROGLED_PIN             PING2
223#endif
224
225
226
227/*
228 * define CPU frequency in Mhz here if not defined in Makefile
229 */
230#ifndef F_CPU
231        #define F_CPU 16000000UL
232#endif
233
234#define _BLINK_LOOP_COUNT_      (F_CPU / 2250)
235/*
236 * UART Baudrate, AVRStudio AVRISP only accepts 115200 bps
237 */
238
239#ifndef BAUDRATE
240        #define BAUDRATE 115200
241#endif
242
243/*
244 *  Enable (1) or disable (0) USART double speed operation
245 */
246#ifndef UART_BAUDRATE_DOUBLE_SPEED
247        #if defined (__AVR_ATmega32__)
248                #define UART_BAUDRATE_DOUBLE_SPEED 0
249        #else
250                #define UART_BAUDRATE_DOUBLE_SPEED 1
251        #endif
252#endif
253
254/*
255 * HW and SW version, reported to AVRISP, must match version of AVRStudio
256 */
257#define CONFIG_PARAM_BUILD_NUMBER_LOW   0
258#define CONFIG_PARAM_BUILD_NUMBER_HIGH  0
259#define CONFIG_PARAM_HW_VER                             0x0F
260#define CONFIG_PARAM_SW_MAJOR                   2
261#define CONFIG_PARAM_SW_MINOR                   0x0A
262
263/*
264 * Calculate the address where the bootloader starts from FLASHEND and BOOTSIZE
265 * (adjust BOOTSIZE below and BOOTLOADER_ADDRESS in Makefile if you want to change the size of the bootloader)
266 */
267//#define BOOTSIZE 1024
268#if FLASHEND > 0x0F000
269        #define BOOTSIZE 8192
270#else
271        #define BOOTSIZE 2048
272#endif
273
274#define APP_END  (FLASHEND -(2*BOOTSIZE) + 1)
275
276/*
277 * Signature bytes are not available in avr-gcc io_xxx.h
278 */
279#if defined (__AVR_ATmega8__)
280        #define SIGNATURE_BYTES 0x1E9307
281#elif defined (__AVR_ATmega16__)
282        #define SIGNATURE_BYTES 0x1E9403
283#elif defined (__AVR_ATmega32__)
284        #define SIGNATURE_BYTES 0x1E9502
285#elif defined (__AVR_ATmega8515__)
286        #define SIGNATURE_BYTES 0x1E9306
287#elif defined (__AVR_ATmega8535__)
288        #define SIGNATURE_BYTES 0x1E9308
289#elif defined (__AVR_ATmega162__)
290        #define SIGNATURE_BYTES 0x1E9404
291#elif defined (__AVR_ATmega128__)
292        #define SIGNATURE_BYTES 0x1E9702
293#elif defined (__AVR_ATmega1280__)
294        #define SIGNATURE_BYTES 0x1E9703
295#elif defined (__AVR_ATmega2560__)
296        #define SIGNATURE_BYTES 0x1E9801
297#elif defined (__AVR_ATmega2561__)
298        #define SIGNATURE_BYTES 0x1e9802
299#elif defined (__AVR_ATmega1284P__)
300        #define SIGNATURE_BYTES 0x1e9705
301#elif defined (__AVR_ATmega640__)
302        #define SIGNATURE_BYTES  0x1e9608
303#elif defined (__AVR_ATmega64__)
304        #define SIGNATURE_BYTES  0x1E9602
305#elif defined (__AVR_ATmega169__)
306        #define SIGNATURE_BYTES  0x1e9405
307#elif defined (__AVR_AT90USB1287__)
308        #define SIGNATURE_BYTES  0x1e9782
309#else
310        #error "no signature definition for MCU available"
311#endif
312
313
314#if defined(_BOARD_ROBOTX_) || defined(__AVR_AT90USB1287__) || defined(__AVR_AT90USB1286__)
315        #define UART_BAUD_RATE_LOW                      UBRR1L
316        #define UART_STATUS_REG                         UCSR1A
317        #define UART_CONTROL_REG                        UCSR1B
318        #define UART_ENABLE_TRANSMITTER         TXEN1
319        #define UART_ENABLE_RECEIVER            RXEN1
320        #define UART_TRANSMIT_COMPLETE          TXC1
321        #define UART_RECEIVE_COMPLETE           RXC1
322        #define UART_DATA_REG                           UDR1
323        #define UART_DOUBLE_SPEED                       U2X1
324
325#elif defined(__AVR_ATmega8__) || defined(__AVR_ATmega16__) || defined(__AVR_ATmega32__) \
326        || defined(__AVR_ATmega8515__) || defined(__AVR_ATmega8535__)
327        /* ATMega8 with one USART */
328        #define UART_BAUD_RATE_LOW                      UBRRL
329        #define UART_STATUS_REG                         UCSRA
330        #define UART_CONTROL_REG                        UCSRB
331        #define UART_ENABLE_TRANSMITTER         TXEN
332        #define UART_ENABLE_RECEIVER            RXEN
333        #define UART_TRANSMIT_COMPLETE          TXC
334        #define UART_RECEIVE_COMPLETE           RXC
335        #define UART_DATA_REG                           UDR
336        #define UART_DOUBLE_SPEED                       U2X
337
338#elif defined(__AVR_ATmega64__) || defined(__AVR_ATmega128__) || defined(__AVR_ATmega162__) \
339         || defined(__AVR_ATmega1280__) || defined(__AVR_ATmega2560__) || defined(__AVR_ATmega2561__)
340        /* ATMega with two USART, use UART0 */
341        #define UART_BAUD_RATE_LOW                      UBRR0L
342        #define UART_STATUS_REG                         UCSR0A
343        #define UART_CONTROL_REG                        UCSR0B
344        #define UART_ENABLE_TRANSMITTER         TXEN0
345        #define UART_ENABLE_RECEIVER            RXEN0
346        #define UART_TRANSMIT_COMPLETE          TXC0
347        #define UART_RECEIVE_COMPLETE           RXC0
348        #define UART_DATA_REG                           UDR0
349        #define UART_DOUBLE_SPEED                       U2X0
350#elif defined(UBRR0L) && defined(UCSR0A) && defined(TXEN0)
351        /* ATMega with two USART, use UART0 */
352        #define UART_BAUD_RATE_LOW                      UBRR0L
353        #define UART_STATUS_REG                         UCSR0A
354        #define UART_CONTROL_REG                        UCSR0B
355        #define UART_ENABLE_TRANSMITTER         TXEN0
356        #define UART_ENABLE_RECEIVER            RXEN0
357        #define UART_TRANSMIT_COMPLETE          TXC0
358        #define UART_RECEIVE_COMPLETE           RXC0
359        #define UART_DATA_REG                           UDR0
360        #define UART_DOUBLE_SPEED                       U2X0
361#elif defined(UBRRL) && defined(UCSRA) && defined(UCSRB) && defined(TXEN) && defined(RXEN)
362        //* catch all
363        #define UART_BAUD_RATE_LOW                      UBRRL
364        #define UART_STATUS_REG                         UCSRA
365        #define UART_CONTROL_REG                        UCSRB
366        #define UART_ENABLE_TRANSMITTER         TXEN
367        #define UART_ENABLE_RECEIVER            RXEN
368        #define UART_TRANSMIT_COMPLETE          TXC
369        #define UART_RECEIVE_COMPLETE           RXC
370        #define UART_DATA_REG                           UDR
371        #define UART_DOUBLE_SPEED                       U2X
372#else
373        #error "no UART definition for MCU available"
374#endif
375
376
377
378/*
379 * Macro to calculate UBBR from XTAL and baudrate
380 */
381#if defined(__AVR_ATmega32__) && UART_BAUDRATE_DOUBLE_SPEED
382        #define UART_BAUD_SELECT(baudRate,xtalCpu) ((xtalCpu / 4 / baudRate - 1) / 2)
383#elif defined(__AVR_ATmega32__)
384        #define UART_BAUD_SELECT(baudRate,xtalCpu) ((xtalCpu / 8 / baudRate - 1) / 2)
385#elif UART_BAUDRATE_DOUBLE_SPEED
386        #define UART_BAUD_SELECT(baudRate,xtalCpu) (((float)(xtalCpu))/(((float)(baudRate))*8.0)-1.0+0.5)
387#else
388        #define UART_BAUD_SELECT(baudRate,xtalCpu) (((float)(xtalCpu))/(((float)(baudRate))*16.0)-1.0+0.5)
389#endif
390
391
392/*
393 * States used in the receive state machine
394 */
395#define ST_START                0
396#define ST_GET_SEQ_NUM  1
397#define ST_MSG_SIZE_1   2
398#define ST_MSG_SIZE_2   3
399#define ST_GET_TOKEN    4
400#define ST_GET_DATA             5
401#define ST_GET_CHECK    6
402#define ST_PROCESS              7
403
404/*
405 * use 16bit address variable for ATmegas with <= 64K flash
406 */
407#if defined(RAMPZ)
408        typedef uint32_t address_t;
409#else
410        typedef uint16_t address_t;
411#endif
412
413/*
414 * function prototypes
415 */
416static void sendchar(char c);
417static unsigned char recchar(void);
418
419/*
420 * since this bootloader is not linked against the avr-gcc crt1 functions,
421 * to reduce the code size, we need to provide our own initialization
422 */
423void __jumpMain (void) __attribute__ ((naked)) __attribute__ ((section (".init9")));
424#include <avr/sfr_defs.h>
425
426//#define       SPH_REG 0x3E
427//#define       SPL_REG 0x3D
428
429//*****************************************************************************
430void __jumpMain(void)
431{
432//*     July 17, 2010   <MLS> Added stack pointer initialzation
433//*     the first line did not do the job on the ATmega128
434
435        asm volatile ( ".set __stack, %0" :: "i" (RAMEND) );
436
437//*     set stack pointer to top of RAM
438
439        asm volatile ( "ldi     16, %0" :: "i" (RAMEND >> 8) );
440        asm volatile ( "out %0,16" :: "i" (AVR_STACK_POINTER_HI_ADDR) );
441
442        asm volatile ( "ldi     16, %0" :: "i" (RAMEND & 0x0ff) );
443        asm volatile ( "out %0,16" :: "i" (AVR_STACK_POINTER_LO_ADDR) );
444
445        asm volatile ( "clr __zero_reg__" );                                                                    // GCC depends on register r1 set to 0
446        asm volatile ( "out %0, __zero_reg__" :: "I" (_SFR_IO_ADDR(SREG)) );    // set SREG to 0
447        asm volatile ( "jmp main");                                                                                             // jump to main()
448}
449
450
451//*****************************************************************************
452void delay_ms(unsigned int timedelay)
453{
454        unsigned int i;
455        for (i=0;i<timedelay;i++)
456        {
457                _delay_ms(0.5);
458        }
459}
460
461
462//*****************************************************************************
463/*
464 * send single byte to USART, wait until transmission is completed
465 */
466static void sendchar(char c)
467{
468        UART_DATA_REG   =       c;                                                                              // prepare transmission
469        while (!(UART_STATUS_REG & (1 << UART_TRANSMIT_COMPLETE)));     // wait until byte sent
470        UART_STATUS_REG |= (1 << UART_TRANSMIT_COMPLETE);                       // delete TXCflag
471}
472
473
474//************************************************************************
475static int      Serial_Available(void)
476{
477        return(UART_STATUS_REG & (1 << UART_RECEIVE_COMPLETE)); // wait for data
478}
479
480
481//*****************************************************************************
482/*
483 * Read single byte from USART, block if no data available
484 */
485static unsigned char recchar(void)
486{
487        while (!(UART_STATUS_REG & (1 << UART_RECEIVE_COMPLETE)))
488        {
489                // wait for data
490        }
491        return UART_DATA_REG;
492}
493
494#define MAX_TIME_COUNT  (F_CPU >> 1)
495//*****************************************************************************
496static unsigned char recchar_timeout(void)
497{
498uint32_t count = 0;
499
500        while (!(UART_STATUS_REG & (1 << UART_RECEIVE_COMPLETE)))
501        {
502                // wait for data
503                count++;
504                if (count > MAX_TIME_COUNT)
505                {
506                unsigned int    data;
507                #if (FLASHEND > 0x10000)
508                        data    =       pgm_read_word_far(0);   //*     get the first word of the user program
509                #else
510                        data    =       pgm_read_word_near(0);  //*     get the first word of the user program
511                #endif
512                        if (data != 0xffff)                                     //*     make sure its valid before jumping to it.
513                        {
514                                asm volatile(
515                                                "clr    r30             \n\t"
516                                                "clr    r31             \n\t"
517                                                "ijmp   \n\t"
518                                                );
519                        }
520                        count   =       0;
521                }
522        }
523        return UART_DATA_REG;
524}
525
526//*     for watch dog timer startup
527void (*app_start)(void) = 0x0000;
528
529
530//*****************************************************************************
531int main(void)
532{
533        address_t               address                 =       0;
534        address_t               eraseAddress    =       0;
535        unsigned char   msgParseState;
536        unsigned int    ii                              =       0;
537        unsigned char   checksum                =       0;
538        unsigned char   seqNum                  =       0;
539        unsigned int    msgLength               =       0;
540        unsigned char   msgBuffer[285];
541        unsigned char   c, *p;
542        unsigned char   isLeave = 0;
543
544        unsigned long   boot_timeout;
545        unsigned long   boot_timer;
546        unsigned int    boot_state;
547#ifdef ENABLE_MONITOR
548        unsigned int    exPointCntr             =       0;
549        unsigned int    rcvdCharCntr    =       0;
550#endif
551
552        //*     some chips dont set the stack properly
553        asm volatile ( ".set __stack, %0" :: "i" (RAMEND) );
554        asm volatile ( "ldi     16, %0" :: "i" (RAMEND >> 8) );
555        asm volatile ( "out %0,16" :: "i" (AVR_STACK_POINTER_HI_ADDR) );
556        asm volatile ( "ldi     16, %0" :: "i" (RAMEND & 0x0ff) );
557        asm volatile ( "out %0,16" :: "i" (AVR_STACK_POINTER_LO_ADDR) );
558
559#ifdef _FIX_ISSUE_181_
560        //************************************************************************
561        //*     Dec 29, 2011    <MLS> Issue #181, added watch dog timmer support
562        //*     handle the watch dog timer
563        uint8_t mcuStatusReg;
564        mcuStatusReg    =       MCUSR;
565
566        __asm__ __volatile__ ("cli");
567        __asm__ __volatile__ ("wdr");
568        MCUSR   =       0;
569        WDTCSR  |=      _BV(WDCE) | _BV(WDE);
570        WDTCSR  =       0;
571        __asm__ __volatile__ ("sei");
572        // check if WDT generated the reset, if so, go straight to app
573        if (mcuStatusReg & _BV(WDRF))
574        {
575                app_start();
576        }
577        //************************************************************************
578#endif
579
580
581        boot_timer      =       0;
582        boot_state      =       0;
583
584#ifdef BLINK_LED_WHILE_WAITING
585//      boot_timeout    =        90000;         //*     should be about 4 seconds
586//      boot_timeout    =       170000;
587        boot_timeout    =        20000;         //*     should be about 1 second
588#else
589        boot_timeout    =       3500000; // 7 seconds , approx 2us per step when optimize "s"
590#endif
591        /*
592         * Branch to bootloader or application code ?
593         */
594
595#ifndef REMOVE_BOOTLOADER_LED
596        /* PROG_PIN pulled low, indicate with LED that bootloader is active */
597        PROGLED_DDR             |=      (1<<PROGLED_PIN);
598//      PROGLED_PORT    &=      ~(1<<PROGLED_PIN);      // active low LED ON
599        PROGLED_PORT    |=      (1<<PROGLED_PIN);       // active high LED ON
600
601#ifdef _DEBUG_WITH_LEDS_
602        for (ii=0; ii<3; ii++)
603        {
604                PROGLED_PORT    &=      ~(1<<PROGLED_PIN);      // turn LED off
605                delay_ms(100);
606                PROGLED_PORT    |=      (1<<PROGLED_PIN);       // turn LED on
607                delay_ms(100);
608        }
609#endif
610
611#endif
612        /*
613         * Init UART
614         * set baudrate and enable USART receiver and transmiter without interrupts
615         */
616#if UART_BAUDRATE_DOUBLE_SPEED
617        UART_STATUS_REG         |=      (1 <<UART_DOUBLE_SPEED);
618#endif
619        UART_BAUD_RATE_LOW      =       UART_BAUD_SELECT(BAUDRATE,F_CPU);
620        UART_CONTROL_REG        =       (1 << UART_ENABLE_RECEIVER) | (1 << UART_ENABLE_TRANSMITTER);
621
622        asm volatile ("nop");                   // wait until port has changed
623
624#ifdef _DEBUG_SERIAL_
625//      delay_ms(500);
626
627        sendchar('s');
628        sendchar('t');
629        sendchar('k');
630//      sendchar('5');
631//      sendchar('0');
632//      sendchar('0');
633        sendchar('v');
634        sendchar('2');
635        sendchar(0x0d);
636        sendchar(0x0a);
637
638        delay_ms(100);
639#endif
640
641        while (boot_state==0)
642        {
643                while ((!(Serial_Available())) && (boot_state == 0))            // wait for data
644                {
645                        _delay_ms(0.001);
646                        boot_timer++;
647                        if (boot_timer > boot_timeout)
648                        {
649                                boot_state      =       1; // (after ++ -> boot_state=2 bootloader timeout, jump to main 0x00000 )
650                        }
651                #ifdef BLINK_LED_WHILE_WAITING
652                        if ((boot_timer % _BLINK_LOOP_COUNT_) == 0)
653                        {
654                                //*     toggle the LED
655                                PROGLED_PORT    ^=      (1<<PROGLED_PIN);       // turn LED ON
656                        }
657                #endif
658                }
659                boot_state++; // ( if boot_state=1 bootloader received byte from UART, enter bootloader mode)
660        }
661
662
663        if (boot_state==1)
664        {
665                //*     main loop
666                while (!isLeave)
667                {
668                        /*
669                         * Collect received bytes to a complete message
670                         */
671                        msgParseState   =       ST_START;
672                        while ( msgParseState != ST_PROCESS )
673                        {
674                                if (boot_state==1)
675                                {
676                                        boot_state      =       0;
677                                        c                       =       UART_DATA_REG;
678                                }
679                                else
680                                {
681                                //      c       =       recchar();
682                                        c       =       recchar_timeout();
683                                       
684                                }
685
686                        #ifdef ENABLE_MONITOR
687                                rcvdCharCntr++;
688
689                                if ((c == '!')  && (rcvdCharCntr < 10))
690                                {
691                                        exPointCntr++;
692                                        if (exPointCntr == 3)
693                                        {
694                                                RunMonitor();
695                                                exPointCntr             =       0;      //      reset back to zero so we dont get in an endless loop
696                                                isLeave                 =       1;
697                                                msgParseState   =       99;     //*     we dont want it do anything
698                                                break;
699                                        }
700                                }
701                                else
702                                {
703                                        exPointCntr     =       0;
704                                }
705                        #endif
706
707                                switch (msgParseState)
708                                {
709                                        case ST_START:
710                                                if ( c == MESSAGE_START )
711                                                {
712                                                        msgParseState   =       ST_GET_SEQ_NUM;
713                                                        checksum                =       MESSAGE_START^0;
714                                                }
715                                                break;
716
717                                        case ST_GET_SEQ_NUM:
718                                        #ifdef _FIX_ISSUE_505_
719                                                seqNum                  =       c;
720                                                msgParseState   =       ST_MSG_SIZE_1;
721                                                checksum                ^=      c;
722                                        #else
723                                                if ( (c == 1) || (c == seqNum) )
724                                                {
725                                                        seqNum                  =       c;
726                                                        msgParseState   =       ST_MSG_SIZE_1;
727                                                        checksum                ^=      c;
728                                                }
729                                                else
730                                                {
731                                                        msgParseState   =       ST_START;
732                                                }
733                                        #endif
734                                                break;
735
736                                        case ST_MSG_SIZE_1:
737                                                msgLength               =       c<<8;
738                                                msgParseState   =       ST_MSG_SIZE_2;
739                                                checksum                ^=      c;
740                                                break;
741
742                                        case ST_MSG_SIZE_2:
743                                                msgLength               |=      c;
744                                                msgParseState   =       ST_GET_TOKEN;
745                                                checksum                ^=      c;
746                                                break;
747
748                                        case ST_GET_TOKEN:
749                                                if ( c == TOKEN )
750                                                {
751                                                        msgParseState   =       ST_GET_DATA;
752                                                        checksum                ^=      c;
753                                                        ii                              =       0;
754                                                }
755                                                else
756                                                {
757                                                        msgParseState   =       ST_START;
758                                                }
759                                                break;
760
761                                        case ST_GET_DATA:
762                                                msgBuffer[ii++] =       c;
763                                                checksum                ^=      c;
764                                                if (ii == msgLength )
765                                                {
766                                                        msgParseState   =       ST_GET_CHECK;
767                                                }
768                                                break;
769
770                                        case ST_GET_CHECK:
771                                                if ( c == checksum )
772                                                {
773                                                        msgParseState   =       ST_PROCESS;
774                                                }
775                                                else
776                                                {
777                                                        msgParseState   =       ST_START;
778                                                }
779                                                break;
780                                }       //      switch
781                        }       //      while(msgParseState)
782
783                        /*
784                         * Now process the STK500 commands, see Atmel Appnote AVR068
785                         */
786
787                        switch (msgBuffer[0])
788                        {
789        #ifndef REMOVE_CMD_SPI_MULTI
790                                case CMD_SPI_MULTI:
791                                        {
792                                                unsigned char answerByte;
793                                                unsigned char flag=0;
794
795                                                if ( msgBuffer[4]== 0x30 )
796                                                {
797                                                        unsigned char signatureIndex    =       msgBuffer[6];
798
799                                                        if ( signatureIndex == 0 )
800                                                        {
801                                                                answerByte      =       (SIGNATURE_BYTES >> 16) & 0x000000FF;
802                                                        }
803                                                        else if ( signatureIndex == 1 )
804                                                        {
805                                                                answerByte      =       (SIGNATURE_BYTES >> 8) & 0x000000FF;
806                                                        }
807                                                        else
808                                                        {
809                                                                answerByte      =       SIGNATURE_BYTES & 0x000000FF;
810                                                        }
811                                                }
812                                                else if ( msgBuffer[4] & 0x50 )
813                                                {
814                                                //*     Issue 544:      stk500v2 bootloader doesn't support reading fuses
815                                                //*     I cant find the docs that say what these are supposed to be but this was figured out by trial and error
816                                                //      answerByte      =       boot_lock_fuse_bits_get(GET_LOW_FUSE_BITS);
817                                                //      answerByte      =       boot_lock_fuse_bits_get(GET_HIGH_FUSE_BITS);
818                                                //      answerByte      =       boot_lock_fuse_bits_get(GET_EXTENDED_FUSE_BITS);
819                                                        if (msgBuffer[4] == 0x50)
820                                                        {
821                                                                answerByte      =       boot_lock_fuse_bits_get(GET_LOW_FUSE_BITS);
822                                                        }
823                                                        else if (msgBuffer[4] == 0x58)
824                                                        {
825                                                                answerByte      =       boot_lock_fuse_bits_get(GET_HIGH_FUSE_BITS);
826                                                        }
827                                                        else
828                                                        {
829                                                                answerByte      =       0;
830                                                        }
831                                                }
832                                                else
833                                                {
834                                                        answerByte      =       0; // for all others command are not implemented, return dummy value for AVRDUDE happy <Worapoht>
835                                                }
836                                                if ( !flag )
837                                                {
838                                                        msgLength               =       7;
839                                                        msgBuffer[1]    =       STATUS_CMD_OK;
840                                                        msgBuffer[2]    =       0;
841                                                        msgBuffer[3]    =       msgBuffer[4];
842                                                        msgBuffer[4]    =       0;
843                                                        msgBuffer[5]    =       answerByte;
844                                                        msgBuffer[6]    =       STATUS_CMD_OK;
845                                                }
846                                        }
847                                        break;
848        #endif
849                                case CMD_SIGN_ON:
850                                        msgLength               =       11;
851                                        msgBuffer[1]    =       STATUS_CMD_OK;
852                                        msgBuffer[2]    =       8;
853                                        msgBuffer[3]    =       'A';
854                                        msgBuffer[4]    =       'V';
855                                        msgBuffer[5]    =       'R';
856                                        msgBuffer[6]    =       'I';
857                                        msgBuffer[7]    =       'S';
858                                        msgBuffer[8]    =       'P';
859                                        msgBuffer[9]    =       '_';
860                                        msgBuffer[10]   =       '2';
861                                        break;
862
863                                case CMD_GET_PARAMETER:
864                                        {
865                                                unsigned char value;
866
867                                                switch(msgBuffer[1])
868                                                {
869                                                case PARAM_BUILD_NUMBER_LOW:
870                                                        value   =       CONFIG_PARAM_BUILD_NUMBER_LOW;
871                                                        break;
872                                                case PARAM_BUILD_NUMBER_HIGH:
873                                                        value   =       CONFIG_PARAM_BUILD_NUMBER_HIGH;
874                                                        break;
875                                                case PARAM_HW_VER:
876                                                        value   =       CONFIG_PARAM_HW_VER;
877                                                        break;
878                                                case PARAM_SW_MAJOR:
879                                                        value   =       CONFIG_PARAM_SW_MAJOR;
880                                                        break;
881                                                case PARAM_SW_MINOR:
882                                                        value   =       CONFIG_PARAM_SW_MINOR;
883                                                        break;
884                                                default:
885                                                        value   =       0;
886                                                        break;
887                                                }
888                                                msgLength               =       3;
889                                                msgBuffer[1]    =       STATUS_CMD_OK;
890                                                msgBuffer[2]    =       value;
891                                        }
892                                        break;
893
894                                case CMD_LEAVE_PROGMODE_ISP:
895                                        isLeave =       1;
896                                        //*     fall thru
897
898                                case CMD_SET_PARAMETER:
899                                case CMD_ENTER_PROGMODE_ISP:
900                                        msgLength               =       2;
901                                        msgBuffer[1]    =       STATUS_CMD_OK;
902                                        break;
903
904                                case CMD_READ_SIGNATURE_ISP:
905                                        {
906                                                unsigned char signatureIndex    =       msgBuffer[4];
907                                                unsigned char signature;
908
909                                                if ( signatureIndex == 0 )
910                                                        signature       =       (SIGNATURE_BYTES >>16) & 0x000000FF;
911                                                else if ( signatureIndex == 1 )
912                                                        signature       =       (SIGNATURE_BYTES >> 8) & 0x000000FF;
913                                                else
914                                                        signature       =       SIGNATURE_BYTES & 0x000000FF;
915
916                                                msgLength               =       4;
917                                                msgBuffer[1]    =       STATUS_CMD_OK;
918                                                msgBuffer[2]    =       signature;
919                                                msgBuffer[3]    =       STATUS_CMD_OK;
920                                        }
921                                        break;
922
923                                case CMD_READ_LOCK_ISP:
924                                        msgLength               =       4;
925                                        msgBuffer[1]    =       STATUS_CMD_OK;
926                                        msgBuffer[2]    =       boot_lock_fuse_bits_get( GET_LOCK_BITS );
927                                        msgBuffer[3]    =       STATUS_CMD_OK;
928                                        break;
929
930                                case CMD_READ_FUSE_ISP:
931                                        {
932                                                unsigned char fuseBits;
933
934                                                if ( msgBuffer[2] == 0x50 )
935                                                {
936                                                        if ( msgBuffer[3] == 0x08 )
937                                                                fuseBits        =       boot_lock_fuse_bits_get( GET_EXTENDED_FUSE_BITS );
938                                                        else
939                                                                fuseBits        =       boot_lock_fuse_bits_get( GET_LOW_FUSE_BITS );
940                                                }
941                                                else
942                                                {
943                                                        fuseBits        =       boot_lock_fuse_bits_get( GET_HIGH_FUSE_BITS );
944                                                }
945                                                msgLength               =       4;
946                                                msgBuffer[1]    =       STATUS_CMD_OK;
947                                                msgBuffer[2]    =       fuseBits;
948                                                msgBuffer[3]    =       STATUS_CMD_OK;
949                                        }
950                                        break;
951
952        #ifndef REMOVE_PROGRAM_LOCK_BIT_SUPPORT
953                                case CMD_PROGRAM_LOCK_ISP:
954                                        {
955                                                unsigned char lockBits  =       msgBuffer[4];
956
957                                                lockBits        =       (~lockBits) & 0x3C;     // mask BLBxx bits
958                                                boot_lock_bits_set(lockBits);           // and program it
959                                                boot_spm_busy_wait();
960
961                                                msgLength               =       3;
962                                                msgBuffer[1]    =       STATUS_CMD_OK;
963                                                msgBuffer[2]    =       STATUS_CMD_OK;
964                                        }
965                                        break;
966        #endif
967                                case CMD_CHIP_ERASE_ISP:
968                                        eraseAddress    =       0;
969                                        msgLength               =       2;
970                                //      msgBuffer[1]    =       STATUS_CMD_OK;
971                                        msgBuffer[1]    =       STATUS_CMD_FAILED;      //*     isue 543, return FAILED instead of OK
972                                        break;
973
974                                case CMD_LOAD_ADDRESS:
975        #if defined(RAMPZ)
976                                        address =       ( ((address_t)(msgBuffer[1])<<24)|((address_t)(msgBuffer[2])<<16)|((address_t)(msgBuffer[3])<<8)|(msgBuffer[4]) )<<1;
977        #else
978                                        address =       ( ((msgBuffer[3])<<8)|(msgBuffer[4]) )<<1;              //convert word to byte address
979        #endif
980                                        msgLength               =       2;
981                                        msgBuffer[1]    =       STATUS_CMD_OK;
982                                        break;
983
984                                case CMD_PROGRAM_FLASH_ISP:
985                                case CMD_PROGRAM_EEPROM_ISP:
986                                        {
987                                                unsigned int    size    =       ((msgBuffer[1])<<8) | msgBuffer[2];
988                                                unsigned char   *p      =       msgBuffer+10;
989                                                unsigned int    data;
990                                                unsigned char   highByte, lowByte;
991                                                address_t               tempaddress     =       address;
992
993
994                                                if ( msgBuffer[0] == CMD_PROGRAM_FLASH_ISP )
995                                                {
996                                                        // erase only main section (bootloader protection)
997                                                        if (eraseAddress < APP_END )
998                                                        {
999                                                                boot_page_erase(eraseAddress);  // Perform page erase
1000                                                                boot_spm_busy_wait();           // Wait until the memory is erased.
1001                                                                eraseAddress += SPM_PAGESIZE;   // point to next page to be erase
1002                                                        }
1003
1004                                                        /* Write FLASH */
1005                                                        do {
1006                                                                lowByte         =       *p++;
1007                                                                highByte        =       *p++;
1008
1009                                                                data            =       (highByte << 8) | lowByte;
1010                                                                boot_page_fill(address,data);
1011
1012                                                                address =       address + 2;    // Select next word in memory
1013                                                                size    -=      2;                              // Reduce number of bytes to write by two
1014                                                        } while (size);                                 // Loop until all bytes written
1015
1016                                                        boot_page_write(tempaddress);
1017                                                        boot_spm_busy_wait();
1018                                                        boot_rww_enable();                              // Re-enable the RWW section
1019                                                }
1020                                                else
1021                                                {
1022                                                        //*     issue 543, this should work, It has not been tested.
1023                                                        uint16_t ii = address >> 1;
1024                                                        /* write EEPROM */
1025                                                        while (size) {
1026                                                                eeprom_write_byte((uint8_t*)ii, *p++);
1027                                                                address+=2;                                             // Select next EEPROM byte
1028                                                                ii++;
1029                                                                size--;
1030                                                        }
1031                                                }
1032                                                msgLength               =       2;
1033                                                msgBuffer[1]    =       STATUS_CMD_OK;
1034                                        }
1035                                        break;
1036
1037                                case CMD_READ_FLASH_ISP:
1038                                case CMD_READ_EEPROM_ISP:
1039                                        {
1040                                                unsigned int    size    =       ((msgBuffer[1])<<8) | msgBuffer[2];
1041                                                unsigned char   *p              =       msgBuffer+1;
1042                                                msgLength                               =       size+3;
1043
1044                                                *p++    =       STATUS_CMD_OK;
1045                                                if (msgBuffer[0] == CMD_READ_FLASH_ISP )
1046                                                {
1047                                                        unsigned int data;
1048
1049                                                        // Read FLASH
1050                                                        do {
1051                                                //#if defined(RAMPZ)
1052                                                #if (FLASHEND > 0x10000)
1053                                                                data    =       pgm_read_word_far(address);
1054                                                #else
1055                                                                data    =       pgm_read_word_near(address);
1056                                                #endif
1057                                                                *p++    =       (unsigned char)data;            //LSB
1058                                                                *p++    =       (unsigned char)(data >> 8);     //MSB
1059                                                                address +=      2;                                                      // Select next word in memory
1060                                                                size    -=      2;
1061                                                        }while (size);
1062                                                }
1063                                                else
1064                                                {
1065                                                        /* Read EEPROM */
1066                                                        do {
1067                                                                EEARL   =       address;                        // Setup EEPROM address
1068                                                                EEARH   =       ((address >> 8));
1069                                                                address++;                                      // Select next EEPROM byte
1070                                                                EECR    |=      (1<<EERE);                      // Read EEPROM
1071                                                                *p++    =       EEDR;                           // Send EEPROM data
1072                                                                size--;
1073                                                        } while (size);
1074                                                }
1075                                                *p++    =       STATUS_CMD_OK;
1076                                        }
1077                                        break;
1078
1079                                default:
1080                                        msgLength               =       2;
1081                                        msgBuffer[1]    =       STATUS_CMD_FAILED;
1082                                        break;
1083                        }
1084
1085                        /*
1086                         * Now send answer message back
1087                         */
1088                        sendchar(MESSAGE_START);
1089                        checksum        =       MESSAGE_START^0;
1090
1091                        sendchar(seqNum);
1092                        checksum        ^=      seqNum;
1093
1094                        c                       =       ((msgLength>>8)&0xFF);
1095                        sendchar(c);
1096                        checksum        ^=      c;
1097
1098                        c                       =       msgLength&0x00FF;
1099                        sendchar(c);
1100                        checksum ^= c;
1101
1102                        sendchar(TOKEN);
1103                        checksum ^= TOKEN;
1104
1105                        p       =       msgBuffer;
1106                        while ( msgLength )
1107                        {
1108                                c       =       *p++;
1109                                sendchar(c);
1110                                checksum ^=c;
1111                                msgLength--;
1112                        }
1113                        sendchar(checksum);
1114                        seqNum++;
1115       
1116                #ifndef REMOVE_BOOTLOADER_LED
1117                        //*     <MLS>   toggle the LED
1118                        PROGLED_PORT    ^=      (1<<PROGLED_PIN);       // active high LED ON
1119                #endif
1120
1121                }
1122        }
1123
1124#ifdef _DEBUG_WITH_LEDS_
1125        //*     this is for debugging it can be removed
1126        for (ii=0; ii<10; ii++)
1127        {
1128                PROGLED_PORT    &=      ~(1<<PROGLED_PIN);      // turn LED off
1129                delay_ms(200);
1130                PROGLED_PORT    |=      (1<<PROGLED_PIN);       // turn LED on
1131                delay_ms(200);
1132        }
1133        PROGLED_PORT    &=      ~(1<<PROGLED_PIN);      // turn LED off
1134#endif
1135
1136#ifdef _DEBUG_SERIAL_
1137        sendchar('j');
1138//      sendchar('u');
1139//      sendchar('m');
1140//      sendchar('p');
1141//      sendchar(' ');
1142//      sendchar('u');
1143//      sendchar('s');
1144//      sendchar('r');
1145        sendchar(0x0d);
1146        sendchar(0x0a);
1147
1148        delay_ms(100);
1149#endif
1150
1151
1152#ifndef REMOVE_BOOTLOADER_LED
1153        PROGLED_DDR             &=      ~(1<<PROGLED_PIN);      // set to default
1154        PROGLED_PORT    &=      ~(1<<PROGLED_PIN);      // active low LED OFF
1155//      PROGLED_PORT    |=      (1<<PROGLED_PIN);       // active high LED OFf
1156        delay_ms(100);                                                  // delay after exit
1157#endif
1158
1159
1160        asm volatile ("nop");                   // wait until port has changed
1161
1162        /*
1163         * Now leave bootloader
1164         */
1165
1166        UART_STATUS_REG &=      0xfd;
1167        boot_rww_enable();                              // enable application section
1168
1169
1170        asm volatile(
1171                        "clr    r30             \n\t"
1172                        "clr    r31             \n\t"
1173                        "ijmp   \n\t"
1174                        );
1175//      asm volatile ( "push r1" "\n\t"         // Jump to Reset vector in Application Section
1176//                                      "push r1" "\n\t"
1177//                                      "ret"    "\n\t"
1178//                                      ::);
1179
1180         /*
1181         * Never return to stop GCC to generate exit return code
1182         * Actually we will never reach this point, but the compiler doesn't
1183         * understand this
1184         */
1185        for(;;);
1186}
1187
1188/*
1189base address = f800
1190
1191avrdude: Device signature = 0x1e9703
1192avrdude: safemode: lfuse reads as FF
1193avrdude: safemode: hfuse reads as DA
1194avrdude: safemode: efuse reads as F5
1195avrdude>
1196
1197
1198base address = f000
1199avrdude: Device signature = 0x1e9703
1200avrdude: safemode: lfuse reads as FF
1201avrdude: safemode: hfuse reads as D8
1202avrdude: safemode: efuse reads as F5
1203avrdude>
1204*/
1205
1206//************************************************************************
1207#ifdef ENABLE_MONITOR
1208#include        <math.h>
1209
1210unsigned long   gRamIndex;
1211unsigned long   gFlashIndex;
1212unsigned long   gEepromIndex;
1213
1214
1215#define true    1
1216#define false   0
1217
1218#include        "avr_cpunames.h"
1219
1220#ifndef _AVR_CPU_NAME_
1221        #error cpu name not defined
1222#endif
1223
1224#ifdef _VECTORS_SIZE
1225        #define kInterruptVectorCount (_VECTORS_SIZE / 4)
1226#else
1227        #define kInterruptVectorCount 23
1228#endif
1229
1230
1231void    PrintDecInt(int theNumber, int digitCnt);
1232
1233#ifdef _AVR_CPU_NAME_
1234        const char      gTextMsg_CPU_Name[]                     PROGMEM =       _AVR_CPU_NAME_;
1235#else
1236        const char      gTextMsg_CPU_Name[]                     PROGMEM =       "UNKNOWN";
1237#endif
1238
1239        const char      gTextMsg_Explorer[]                     PROGMEM =       "Arduino explorer stk500V2 by MLS";
1240        const char      gTextMsg_Prompt[]                       PROGMEM =       "Bootloader>";
1241        const char      gTextMsg_HUH[]                          PROGMEM =       "Huh?";
1242        const char      gTextMsg_COMPILED_ON[]          PROGMEM =       "Compiled on = ";
1243        const char      gTextMsg_CPU_Type[]                     PROGMEM =       "CPU Type    = ";
1244        const char      gTextMsg_AVR_ARCH[]                     PROGMEM =       "__AVR_ARCH__= ";
1245        const char      gTextMsg_AVR_LIBC[]                     PROGMEM =       "AVR LibC Ver= ";
1246        const char      gTextMsg_GCC_VERSION[]          PROGMEM =       "GCC Version = ";
1247        const char      gTextMsg_CPU_SIGNATURE[]        PROGMEM =       "CPU ID      = ";
1248        const char      gTextMsg_FUSE_BYTE_LOW[]        PROGMEM =       "Low fuse    = ";
1249        const char      gTextMsg_FUSE_BYTE_HIGH[]       PROGMEM =       "High fuse   = ";
1250        const char      gTextMsg_FUSE_BYTE_EXT[]        PROGMEM =       "Ext fuse    = ";
1251        const char      gTextMsg_FUSE_BYTE_LOCK[]       PROGMEM =       "Lock fuse   = ";
1252        const char      gTextMsg_GCC_DATE_STR[]         PROGMEM =       __DATE__;
1253        const char      gTextMsg_AVR_LIBC_VER_STR[]     PROGMEM =       __AVR_LIBC_VERSION_STRING__;
1254        const char      gTextMsg_GCC_VERSION_STR[]      PROGMEM =       __VERSION__;
1255        const char      gTextMsg_VECTOR_HEADER[]        PROGMEM =       "V#   ADDR   op code     instruction addr   Interrupt";
1256        const char      gTextMsg_noVector[]                     PROGMEM =       "no vector";
1257        const char      gTextMsg_rjmp[]                         PROGMEM =       "rjmp  ";
1258        const char      gTextMsg_jmp[]                          PROGMEM =       "jmp ";
1259        const char      gTextMsg_WHAT_PORT[]            PROGMEM =       "What port:";
1260        const char      gTextMsg_PortNotSupported[]     PROGMEM =       "Port not supported";
1261        const char      gTextMsg_MustBeLetter[]         PROGMEM =       "Must be a letter";
1262        const char      gTextMsg_SPACE[]                        PROGMEM =       " ";
1263        const char      gTextMsg_WriteToEEprom[]        PROGMEM =       "Writting EE";
1264        const char      gTextMsg_ReadingEEprom[]        PROGMEM =       "Reading EE";
1265        const char      gTextMsg_EEPROMerrorCnt[]       PROGMEM =       "EE err cnt=";
1266        const char      gTextMsg_PORT[]                         PROGMEM =       "PORT";
1267
1268
1269//************************************************************************
1270//*     Help messages
1271        const char      gTextMsg_HELP_MSG_0[]           PROGMEM =       "0=Zero addr";
1272        const char      gTextMsg_HELP_MSG_QM[]          PROGMEM =       "?=CPU stats";
1273        const char      gTextMsg_HELP_MSG_AT[]          PROGMEM =       "@=EEPROM test";
1274        const char      gTextMsg_HELP_MSG_B[]           PROGMEM =       "B=Blink LED";
1275        const char      gTextMsg_HELP_MSG_E[]           PROGMEM =       "E=Dump EEPROM";
1276        const char      gTextMsg_HELP_MSG_F[]           PROGMEM =       "F=Dump FLASH";
1277        const char      gTextMsg_HELP_MSG_H[]           PROGMEM =       "H=Help";
1278        const char      gTextMsg_HELP_MSG_L[]           PROGMEM =       "L=List I/O Ports";
1279//      const char      gTextMsg_HELP_MSG_Q[]           PROGMEM =       "Q=Quit & jump to user pgm";
1280        const char      gTextMsg_HELP_MSG_Q[]           PROGMEM =       "Q=Quit";
1281        const char      gTextMsg_HELP_MSG_R[]           PROGMEM =       "R=Dump RAM";
1282        const char      gTextMsg_HELP_MSG_V[]           PROGMEM =       "V=show interrupt Vectors";
1283        const char      gTextMsg_HELP_MSG_Y[]           PROGMEM =       "Y=Port blink";
1284
1285        const char      gTextMsg_END[]                          PROGMEM =       "*";
1286
1287
1288//************************************************************************
1289void    PrintFromPROGMEM(const void *dataPtr, unsigned char offset)
1290{
1291char    theChar;
1292
1293        dataPtr         +=      offset;
1294
1295        do {
1296        #if (FLASHEND > 0x10000)
1297                theChar =       pgm_read_byte_far((uint16_t)dataPtr++);
1298        #else
1299                theChar =       pgm_read_byte_near((uint16_t)dataPtr++);
1300        #endif
1301                if (theChar != 0)
1302                {
1303                        sendchar(theChar);
1304                }
1305        } while (theChar != 0);
1306}
1307
1308//************************************************************************
1309void    PrintNewLine(void)
1310{
1311        sendchar(0x0d);
1312        sendchar(0x0a);
1313}
1314
1315
1316//************************************************************************
1317void    PrintFromPROGMEMln(const void *dataPtr, unsigned char offset)
1318{
1319        PrintFromPROGMEM(dataPtr, offset);
1320
1321        PrintNewLine();
1322}
1323
1324
1325//************************************************************************
1326void    PrintString(char *textString)
1327{
1328char    theChar;
1329int             ii;
1330
1331        theChar         =       1;
1332        ii                      =       0;
1333        while (theChar != 0)
1334        {
1335                theChar =       textString[ii];
1336                if (theChar != 0)
1337                {
1338                        sendchar(theChar);
1339                }
1340                ii++;
1341        }
1342}
1343
1344//************************************************************************
1345void    PrintHexByte(unsigned char theByte)
1346{
1347char    theChar;
1348
1349        theChar =       0x30 + ((theByte >> 4) & 0x0f);
1350        if (theChar > 0x39)
1351        {
1352                theChar +=      7;
1353        }
1354        sendchar(theChar );
1355
1356        theChar =       0x30 + (theByte & 0x0f);
1357        if (theChar > 0x39)
1358        {
1359                theChar +=      7;
1360        }
1361        sendchar(theChar );
1362}
1363
1364//************************************************************************
1365void    PrintDecInt(int theNumber, int digitCnt)
1366{
1367int     theChar;
1368int     myNumber;
1369
1370        myNumber        =       theNumber;
1371
1372        if ((myNumber > 100) || (digitCnt >= 3))
1373        {
1374                theChar         =       0x30 + myNumber / 100;
1375                sendchar(theChar );
1376        }
1377
1378        if ((myNumber > 10) || (digitCnt >= 2))
1379        {
1380                theChar =       0x30  + ((myNumber % 100) / 10 );
1381                sendchar(theChar );
1382        }
1383        theChar =       0x30 + (myNumber % 10);
1384        sendchar(theChar );
1385}
1386
1387
1388
1389
1390//************************************************************************
1391static void     PrintCPUstats(void)
1392{
1393unsigned char fuseByte;
1394
1395        PrintFromPROGMEMln(gTextMsg_Explorer, 0);
1396
1397        PrintFromPROGMEM(gTextMsg_COMPILED_ON, 0);
1398        PrintFromPROGMEMln(gTextMsg_GCC_DATE_STR, 0);
1399
1400        PrintFromPROGMEM(gTextMsg_CPU_Type, 0);
1401        PrintFromPROGMEMln(gTextMsg_CPU_Name, 0);
1402
1403        PrintFromPROGMEM(gTextMsg_AVR_ARCH, 0);
1404        PrintDecInt(__AVR_ARCH__, 1);
1405        PrintNewLine();
1406
1407        PrintFromPROGMEM(gTextMsg_GCC_VERSION, 0);
1408        PrintFromPROGMEMln(gTextMsg_GCC_VERSION_STR, 0);
1409
1410        //*     these can be found in avr/version.h
1411        PrintFromPROGMEM(gTextMsg_AVR_LIBC, 0);
1412        PrintFromPROGMEMln(gTextMsg_AVR_LIBC_VER_STR, 0);
1413
1414#if defined(SIGNATURE_0)
1415        PrintFromPROGMEM(gTextMsg_CPU_SIGNATURE, 0);
1416        //*     these can be found in avr/iomxxx.h
1417        PrintHexByte(SIGNATURE_0);
1418        PrintHexByte(SIGNATURE_1);
1419        PrintHexByte(SIGNATURE_2);
1420        PrintNewLine();
1421#endif
1422
1423
1424#if defined(GET_LOW_FUSE_BITS)
1425        //*     fuse settings
1426        PrintFromPROGMEM(gTextMsg_FUSE_BYTE_LOW, 0);
1427        fuseByte        =       boot_lock_fuse_bits_get(GET_LOW_FUSE_BITS);
1428        PrintHexByte(fuseByte);
1429        PrintNewLine();
1430
1431        PrintFromPROGMEM(gTextMsg_FUSE_BYTE_HIGH, 0);
1432        fuseByte        =       boot_lock_fuse_bits_get(GET_HIGH_FUSE_BITS);
1433        PrintHexByte(fuseByte);
1434        PrintNewLine();
1435
1436        PrintFromPROGMEM(gTextMsg_FUSE_BYTE_EXT, 0);
1437        fuseByte        =       boot_lock_fuse_bits_get(GET_EXTENDED_FUSE_BITS);
1438        PrintHexByte(fuseByte);
1439        PrintNewLine();
1440
1441        PrintFromPROGMEM(gTextMsg_FUSE_BYTE_LOCK, 0);
1442        fuseByte        =       boot_lock_fuse_bits_get(GET_LOCK_BITS);
1443        PrintHexByte(fuseByte);
1444        PrintNewLine();
1445
1446#endif
1447
1448}
1449
1450
1451//************************************************************************
1452static void BlinkLED(void)
1453{
1454        PROGLED_DDR             |=      (1<<PROGLED_PIN);
1455        PROGLED_PORT    |=      (1<<PROGLED_PIN);       // active high LED ON
1456
1457        while (!Serial_Available())
1458        {
1459                PROGLED_PORT    &=      ~(1<<PROGLED_PIN);      // turn LED off
1460                delay_ms(100);
1461                PROGLED_PORT    |=      (1<<PROGLED_PIN);       // turn LED on
1462                delay_ms(100);
1463        }
1464        recchar();      //      get the char out of the buffer
1465}
1466
1467enum
1468{
1469        kDUMP_FLASH     =       0,
1470        kDUMP_EEPROM,
1471        kDUMP_RAM
1472};
1473
1474//************************************************************************
1475static void     DumpHex(unsigned char dumpWhat, unsigned long startAddress, unsigned char numRows)
1476{
1477unsigned long   myAddressPointer;
1478uint8_t                 ii;
1479unsigned char   theValue;
1480char                    asciiDump[18];
1481unsigned char   *ramPtr;
1482
1483
1484        ramPtr                          =       0;
1485        theValue                        =       0;
1486        myAddressPointer        =       startAddress;
1487        while (numRows > 0)
1488        {
1489                if (myAddressPointer > 0x10000)
1490                {
1491                        PrintHexByte((myAddressPointer >> 16) & 0x00ff);
1492                }
1493                PrintHexByte((myAddressPointer >> 8) & 0x00ff);
1494                PrintHexByte(myAddressPointer & 0x00ff);
1495                sendchar(0x20);
1496                sendchar('-');
1497                sendchar(0x20);
1498
1499                asciiDump[0]            =       0;
1500                for (ii=0; ii<16; ii++)
1501                {
1502                        switch(dumpWhat)
1503                        {
1504                                case kDUMP_FLASH:
1505                                #if (FLASHEND > 0x10000)
1506                                        theValue        =       pgm_read_byte_far(myAddressPointer);
1507                                #else
1508                                        theValue        =       pgm_read_byte_near(myAddressPointer);
1509                                #endif
1510                                        break;
1511
1512                                case kDUMP_EEPROM:
1513                                        theValue        =       eeprom_read_byte((uint8_t *)(uint16_t)myAddressPointer);
1514                                        break;
1515
1516                                case kDUMP_RAM:
1517                                        theValue        =       ramPtr[myAddressPointer];
1518                                        break;
1519
1520                        }
1521                        PrintHexByte(theValue);
1522                        sendchar(0x20);
1523                        if ((theValue >= 0x20) && (theValue < 0x7f))
1524                        {
1525                                asciiDump[ii % 16]      =       theValue;
1526                        }
1527                        else
1528                        {
1529                                asciiDump[ii % 16]      =       '.';
1530                        }
1531
1532                        myAddressPointer++;
1533                }
1534                asciiDump[16]   =       0;
1535                PrintString(asciiDump);
1536                PrintNewLine();
1537
1538                numRows--;
1539        }
1540}
1541
1542
1543
1544//************************************************************************
1545//*     returns amount of extended memory
1546static void     EEPROMtest(void)
1547{
1548int             ii;
1549char    theChar;
1550char    theEEPROMchar;
1551int             errorCount;
1552
1553        PrintFromPROGMEMln(gTextMsg_WriteToEEprom, 0);
1554        PrintNewLine();
1555        ii                      =       0;
1556#if (FLASHEND > 0x10000)
1557        while (((theChar = pgm_read_byte_far(((uint16_t)gTextMsg_Explorer) + ii)) != '*') && (ii < 512))
1558#else
1559        while (((theChar = pgm_read_byte_near(((uint16_t)gTextMsg_Explorer) + ii)) != '*') && (ii < 512))
1560#endif
1561        {
1562                eeprom_write_byte((uint8_t *)ii, theChar);
1563                if (theChar == 0)
1564                {
1565                        PrintFromPROGMEM(gTextMsg_SPACE, 0);
1566                }
1567                else
1568                {
1569                        sendchar(theChar);
1570                }
1571                ii++;
1572        }
1573
1574        //*     no go back through and test
1575        PrintNewLine();
1576        PrintNewLine();
1577        PrintFromPROGMEMln(gTextMsg_ReadingEEprom, 0);
1578        PrintNewLine();
1579        errorCount      =       0;
1580        ii                      =       0;
1581#if (FLASHEND > 0x10000)
1582        while (((theChar = pgm_read_byte_far((uint16_t)gTextMsg_Explorer + ii)) != '*') && (ii < 512))
1583#else
1584        while (((theChar = pgm_read_byte_near((uint16_t)gTextMsg_Explorer + ii)) != '*') && (ii < 512))
1585#endif
1586        {
1587                theEEPROMchar   =       eeprom_read_byte((uint8_t *)ii);
1588                if (theEEPROMchar == 0)
1589                {
1590                        PrintFromPROGMEM(gTextMsg_SPACE, 0);
1591                }
1592                else
1593                {
1594                        sendchar(theEEPROMchar);
1595                }
1596                if (theEEPROMchar != theChar)
1597                {
1598                        errorCount++;
1599                }
1600                ii++;
1601        }
1602        PrintNewLine();
1603        PrintNewLine();
1604        PrintFromPROGMEM(gTextMsg_EEPROMerrorCnt, 0);
1605        PrintDecInt(errorCount, 1);
1606        PrintNewLine();
1607        PrintNewLine();
1608
1609        gEepromIndex    =       0;      //*     set index back to zero for next eeprom dump
1610
1611}
1612
1613
1614
1615#if (FLASHEND > 0x08000)
1616//*     this includes the interrupt names for the monitor portion. There is no longer enough
1617//*     memory to include this
1618//      #include        "avrinterruptnames.h"
1619//      #ifndef _INTERRUPT_NAMES_DEFINED_
1620//              #warning Interrupt vectors not defined
1621//      #endif
1622#endif
1623
1624//************************************************************************
1625static void     VectorDisplay(void)
1626{
1627unsigned long   byte1;
1628unsigned long   byte2;
1629unsigned long   byte3;
1630unsigned long   byte4;
1631unsigned long   word1;
1632unsigned long   word2;
1633int                             vectorIndex;
1634unsigned long   myMemoryPtr;
1635unsigned long   wordMemoryAddress;
1636unsigned long   realitiveAddr;
1637unsigned long   myFullAddress;
1638unsigned long   absoluteAddr;
1639#if defined(_INTERRUPT_NAMES_DEFINED_)
1640        long            stringPointer;
1641#endif
1642
1643        myMemoryPtr             =       0;
1644        vectorIndex             =       0;
1645        PrintFromPROGMEMln(gTextMsg_CPU_Name, 0);
1646        PrintFromPROGMEMln(gTextMsg_VECTOR_HEADER, 0);
1647        //                                       V#   ADDR   op code
1648        //                                        1 - 0000 = C3 BB 00 00 rjmp 03BB >000776 RESET
1649        while (vectorIndex < kInterruptVectorCount)
1650        {
1651                wordMemoryAddress       =       myMemoryPtr / 2;
1652                //                                       01 - 0000 = 12 34
1653                PrintDecInt(vectorIndex + 1, 2);
1654                sendchar(0x20);
1655                sendchar('-');
1656                sendchar(0x20);
1657                PrintHexByte((wordMemoryAddress >> 8) & 0x00ff);
1658                PrintHexByte((wordMemoryAddress) & 0x00ff);
1659                sendchar(0x20);
1660                sendchar('=');
1661                sendchar(0x20);
1662
1663       
1664                //*     the AVR is LITTLE ENDIAN, swap the byte order
1665        #if (FLASHEND > 0x10000)
1666                byte1   =       pgm_read_byte_far(myMemoryPtr++);
1667                byte2   =       pgm_read_byte_far(myMemoryPtr++);
1668                byte3   =       pgm_read_byte_far(myMemoryPtr++);
1669                byte4   =       pgm_read_byte_far(myMemoryPtr++);
1670        #else
1671                byte1   =       pgm_read_byte_near(myMemoryPtr++);
1672                byte2   =       pgm_read_byte_near(myMemoryPtr++);
1673                byte3   =       pgm_read_byte_near(myMemoryPtr++);
1674                byte4   =       pgm_read_byte_near(myMemoryPtr++);
1675        #endif
1676                word1   =       (byte2 << 8) + byte1;
1677                word2   =       (byte4 << 8) + byte3;
1678
1679
1680                PrintHexByte(byte2);
1681                sendchar(0x20);
1682                PrintHexByte(byte1);
1683                sendchar(0x20);
1684                PrintHexByte(byte4);
1685                sendchar(0x20);
1686                PrintHexByte(byte3);
1687                sendchar(0x20);
1688       
1689                if (word1 == 0xffff)
1690                {
1691                        PrintFromPROGMEM(gTextMsg_noVector, 0);
1692                }
1693                else if ((word1 & 0xc000) == 0xc000)
1694                {
1695                        //*     rjmp instruction
1696                        realitiveAddr   =       word1 & 0x3FFF;
1697                        absoluteAddr    =       wordMemoryAddress + realitiveAddr;      //*     add the offset to the current address
1698                        absoluteAddr    =       absoluteAddr << 1;                                      //*     multiply by 2 for byte address
1699
1700                        PrintFromPROGMEM(gTextMsg_rjmp, 0);
1701                        PrintHexByte((realitiveAddr >> 8) & 0x00ff);
1702                        PrintHexByte((realitiveAddr) & 0x00ff);
1703                        sendchar(0x20);
1704                        sendchar('>');
1705                        PrintHexByte((absoluteAddr >> 16) & 0x00ff);
1706                        PrintHexByte((absoluteAddr >> 8) & 0x00ff);
1707                        PrintHexByte((absoluteAddr) & 0x00ff);
1708       
1709                }
1710                else if ((word1 & 0xfE0E) == 0x940c)
1711                {
1712                        //*     jmp instruction, this is REALLY complicated, refer to the instruction manual (JMP)
1713                        myFullAddress   =       ((byte1 & 0x01) << 16) +
1714                                                                ((byte1 & 0xf0) << 17) +
1715                                                                ((byte2 & 0x01) << 21) +
1716                                                                word2;
1717                                                       
1718                        absoluteAddr    =       myFullAddress << 1;
1719                                                       
1720                        PrintFromPROGMEM(gTextMsg_jmp, 0);
1721                        PrintHexByte((myFullAddress >> 16) & 0x00ff);
1722                        PrintHexByte((myFullAddress >> 8) & 0x00ff);
1723                        PrintHexByte((myFullAddress) & 0x00ff);
1724                        sendchar(0x20);
1725                        sendchar('>');
1726                        PrintHexByte((absoluteAddr >> 16) & 0x00ff);
1727                        PrintHexByte((absoluteAddr >> 8) & 0x00ff);
1728                        PrintHexByte((absoluteAddr) & 0x00ff);
1729                }
1730
1731        #if defined(_INTERRUPT_NAMES_DEFINED_)
1732                sendchar(0x20);
1733        #if (FLASHEND > 0x10000)
1734                stringPointer   =       pgm_read_word_far(&(gInterruptNameTable[vectorIndex]));
1735        #else
1736                stringPointer   =       pgm_read_word_near(&(gInterruptNameTable[vectorIndex]));
1737        #endif
1738                PrintFromPROGMEM((char *)stringPointer, 0);
1739        #endif
1740                PrintNewLine();
1741
1742                vectorIndex++;
1743        }
1744}
1745
1746//************************************************************************
1747static void     PrintAvailablePort(char thePortLetter)
1748{
1749        PrintFromPROGMEM(gTextMsg_PORT, 0);
1750        sendchar(thePortLetter);
1751        PrintNewLine();
1752}
1753
1754//************************************************************************
1755static void     ListAvailablePorts(void)
1756{
1757
1758#ifdef DDRA
1759        PrintAvailablePort('A');
1760#endif
1761
1762#ifdef DDRB
1763        PrintAvailablePort('B');
1764#endif
1765
1766#ifdef DDRC
1767        PrintAvailablePort('C');
1768#endif
1769
1770#ifdef DDRD
1771        PrintAvailablePort('D');
1772#endif
1773
1774#ifdef DDRE
1775        PrintAvailablePort('E');
1776#endif
1777
1778#ifdef DDRF
1779        PrintAvailablePort('F');
1780#endif
1781
1782#ifdef DDRG
1783        PrintAvailablePort('G');
1784#endif
1785
1786#ifdef DDRH
1787        PrintAvailablePort('H');
1788#endif
1789
1790#ifdef DDRI
1791        PrintAvailablePort('I');
1792#endif
1793
1794#ifdef DDRJ
1795        PrintAvailablePort('J');
1796#endif
1797
1798#ifdef DDRK
1799        PrintAvailablePort('K');
1800#endif
1801
1802#ifdef DDRL
1803        PrintAvailablePort('L');
1804#endif
1805
1806}
1807
1808//************************************************************************
1809static void     AVR_PortOutput(void)
1810{
1811char    portLetter;
1812char    getCharFlag;
1813
1814        PrintFromPROGMEM(gTextMsg_WHAT_PORT, 0);
1815
1816        portLetter      =       recchar();
1817        portLetter      =       portLetter & 0x5f;
1818        sendchar(portLetter);
1819        PrintNewLine();
1820
1821        if ((portLetter >= 'A') && (portLetter <= 'Z'))
1822        {
1823                getCharFlag     =       true;
1824                switch(portLetter)
1825                {
1826                #ifdef DDRA
1827                        case 'A':
1828                                DDRA    =       0xff;
1829                                while (!Serial_Available())
1830                                {
1831                                        PORTA   ^=      0xff;
1832                                        delay_ms(200);
1833                                }
1834                                PORTA   =       0;
1835                                break;
1836                #endif
1837
1838                #ifdef DDRB
1839                        case 'B':
1840                                DDRB    =       0xff;
1841                                while (!Serial_Available())
1842                                {
1843                                        PORTB   ^=      0xff;
1844                                        delay_ms(200);
1845                                }
1846                                PORTB   =       0;
1847                                break;
1848                #endif
1849
1850                #ifdef DDRC
1851                        case 'C':
1852                                DDRC    =       0xff;
1853                                while (!Serial_Available())
1854                                {
1855                                        PORTC   ^=      0xff;
1856                                        delay_ms(200);
1857                                }
1858                                PORTC   =       0;
1859                                break;
1860                #endif
1861
1862                #ifdef DDRD
1863                        case 'D':
1864                                DDRD    =       0xff;
1865                                while (!Serial_Available())
1866                                {
1867                                        PORTD   ^=      0xff;
1868                                        delay_ms(200);
1869                                }
1870                                PORTD   =       0;
1871                                break;
1872                #endif
1873
1874                #ifdef DDRE
1875                        case 'E':
1876                                DDRE    =       0xff;
1877                                while (!Serial_Available())
1878                                {
1879                                        PORTE   ^=      0xff;
1880                                        delay_ms(200);
1881                                }
1882                                PORTE   =       0;
1883                                break;
1884                #endif
1885
1886                #ifdef DDRF
1887                        case 'F':
1888                                DDRF    =       0xff;
1889                                while (!Serial_Available())
1890                                {
1891                                        PORTF   ^=      0xff;
1892                                        delay_ms(200);
1893                                }
1894                                PORTF   =       0;
1895                                break;
1896                #endif
1897
1898                #ifdef DDRG
1899                        case 'G':
1900                                DDRG    =       0xff;
1901                                while (!Serial_Available())
1902                                {
1903                                        PORTG   ^=      0xff;
1904                                        delay_ms(200);
1905                                }
1906                                PORTG   =       0;
1907                                break;
1908                #endif
1909
1910                #ifdef DDRH
1911                        case 'H':
1912                                DDRH    =       0xff;
1913                                while (!Serial_Available())
1914                                {
1915                                        PORTH   ^=      0xff;
1916                                        delay_ms(200);
1917                                }
1918                                PORTH   =       0;
1919                                break;
1920                #endif
1921
1922                #ifdef DDRI
1923                        case 'I':
1924                                DDRI    =       0xff;
1925                                while (!Serial_Available())
1926                                {
1927                                        PORTI   ^=      0xff;
1928                                        delay_ms(200);
1929                                }
1930                                PORTI   =       0;
1931                                break;
1932                #endif
1933
1934                #ifdef DDRJ
1935                        case 'J':
1936                                DDRJ    =       0xff;
1937                                while (!Serial_Available())
1938                                {
1939                                        PORTJ   ^=      0xff;
1940                                        delay_ms(200);
1941                                }
1942                                PORTJ   =       0;
1943                                break;
1944                #endif
1945
1946                #ifdef DDRK
1947                        case 'K':
1948                                DDRK    =       0xff;
1949                                while (!Serial_Available())
1950                                {
1951                                        PORTK   ^=      0xff;
1952                                        delay_ms(200);
1953                                }
1954                                PORTK   =       0;
1955                                break;
1956                #endif
1957
1958                #ifdef DDRL
1959                        case 'L':
1960                                DDRL    =       0xff;
1961                                while (!Serial_Available())
1962                                {
1963                                        PORTL   ^=      0xff;
1964                                        delay_ms(200);
1965                                }
1966                                PORTL   =       0;
1967                                break;
1968                #endif
1969
1970                        default:
1971                                PrintFromPROGMEMln(gTextMsg_PortNotSupported, 0);
1972                                getCharFlag     =       false;
1973                                break;
1974                }
1975                if (getCharFlag)
1976                {
1977                        recchar();
1978                }
1979        }
1980        else
1981        {
1982                PrintFromPROGMEMln(gTextMsg_MustBeLetter, 0);
1983        }
1984}
1985
1986
1987//*******************************************************************
1988static void PrintHelp(void)
1989{
1990        PrintFromPROGMEMln(gTextMsg_HELP_MSG_0, 0);
1991        PrintFromPROGMEMln(gTextMsg_HELP_MSG_QM, 0);
1992        PrintFromPROGMEMln(gTextMsg_HELP_MSG_AT, 0);
1993        PrintFromPROGMEMln(gTextMsg_HELP_MSG_B, 0);
1994        PrintFromPROGMEMln(gTextMsg_HELP_MSG_E, 0);
1995        PrintFromPROGMEMln(gTextMsg_HELP_MSG_F, 0);
1996        PrintFromPROGMEMln(gTextMsg_HELP_MSG_H, 0);
1997
1998        PrintFromPROGMEMln(gTextMsg_HELP_MSG_L, 0);
1999        PrintFromPROGMEMln(gTextMsg_HELP_MSG_Q, 0);
2000        PrintFromPROGMEMln(gTextMsg_HELP_MSG_R, 0);
2001        PrintFromPROGMEMln(gTextMsg_HELP_MSG_V, 0);
2002        PrintFromPROGMEMln(gTextMsg_HELP_MSG_Y, 0);
2003}
2004
2005//************************************************************************
2006static void     RunMonitor(void)
2007{
2008char                    keepGoing;
2009unsigned char   theChar;
2010int                             ii, jj;
2011
2012        for (ii=0; ii<5; ii++)
2013        {
2014                for (jj=0; jj<25; jj++)
2015                {
2016                        sendchar('!');
2017                }
2018                PrintNewLine();
2019        }
2020
2021        gRamIndex                       =       0;
2022        gFlashIndex                     =       0;
2023        gEepromIndex            =       0;
2024
2025        PrintFromPROGMEMln(gTextMsg_Explorer, 0);
2026
2027        keepGoing       =       1;
2028        while (keepGoing)
2029        {
2030                PrintFromPROGMEM(gTextMsg_Prompt, 0);
2031                theChar =       recchar();
2032                if (theChar >= 0x60)
2033                {
2034                        theChar =       theChar & 0x5F;
2035                }
2036
2037                if (theChar >= 0x20)
2038                {
2039                        sendchar(theChar);
2040                        sendchar(0x20);
2041                }
2042
2043                switch(theChar)
2044                {
2045                        case '0':
2046                                PrintFromPROGMEMln(gTextMsg_HELP_MSG_0, 2);
2047                                gFlashIndex             =       0;
2048                                gRamIndex               =       0;
2049                                gEepromIndex    =       0;
2050                                break;
2051
2052                        case '?':
2053                                PrintFromPROGMEMln(gTextMsg_HELP_MSG_QM, 2);
2054                                PrintCPUstats();
2055                                break;
2056
2057                        case '@':
2058                                PrintFromPROGMEMln(gTextMsg_HELP_MSG_AT, 2);
2059                                EEPROMtest();
2060                                break;
2061
2062                        case 'B':
2063                                PrintFromPROGMEMln(gTextMsg_HELP_MSG_B, 2);
2064                                BlinkLED();
2065                                break;
2066
2067                        case 'E':
2068                                PrintFromPROGMEMln(gTextMsg_HELP_MSG_E, 2);
2069                                DumpHex(kDUMP_EEPROM, gEepromIndex, 16);
2070                                gEepromIndex    +=      256;
2071                                if (gEepromIndex > E2END)
2072                                {
2073                                        gEepromIndex    =       0;
2074                                }
2075                                break;
2076               
2077                        case 'F':
2078                                PrintFromPROGMEMln(gTextMsg_HELP_MSG_F, 2);
2079                                DumpHex(kDUMP_FLASH, gFlashIndex, 16);
2080                                gFlashIndex     +=      256;
2081                                break;
2082
2083                        case 'H':
2084                                PrintFromPROGMEMln(gTextMsg_HELP_MSG_H, 2);
2085                                PrintHelp();
2086                                break;
2087
2088                        case 'L':
2089                                PrintFromPROGMEMln(gTextMsg_HELP_MSG_L, 2);
2090                                ListAvailablePorts();
2091                                break;
2092
2093                        case 'Q':
2094                                PrintFromPROGMEMln(gTextMsg_HELP_MSG_Q, 2);
2095                                keepGoing       =       false;
2096                                break;
2097
2098                        case 'R':
2099                                PrintFromPROGMEMln(gTextMsg_HELP_MSG_R, 2);
2100                                DumpHex(kDUMP_RAM, gRamIndex, 16);
2101                                gRamIndex       +=      256;
2102                                break;
2103
2104                        case 'V':
2105                                PrintFromPROGMEMln(gTextMsg_HELP_MSG_V, 2);
2106                                VectorDisplay();
2107                                break;
2108
2109                        case 'Y':
2110                                PrintFromPROGMEMln(gTextMsg_HELP_MSG_Y, 2);
2111                                AVR_PortOutput();
2112                                break;
2113                       
2114                        default:
2115                                PrintFromPROGMEMln(gTextMsg_HUH, 0);
2116                                break;
2117                }
2118        }
2119}
2120
2121#endif
2122
Note: See TracBrowser for help on using the repository browser.