Subversion Repositories Projects

Rev

Rev 1307 | Show entire file | Ignore whitespace | Details | Blame | Last modification | View Log | RSS feed

Rev 1307 Rev 1308
Line -... Line 1...
-
 
1
/*****************************************************************************
-
 
2
*
-
 
3
* AVRPROG compatible boot-loader
-
 
4
* Version  : 0.85 (Dec. 2008)
-
 
5
* Compiler : avr-gcc 4.1.2 / avr-libc 1.4.6
-
 
6
* size     : depends on features and startup ( minmal features < 512 words)
-
 
7
* by       : Martin Thomas, Kaiserslautern, Germany
-
 
8
*            eversmith@heizung-thomas.de
-
 
9
*            Additional code and improvements contributed by:
-
 
10
*           - Uwe Bonnes
-
 
11
*           - Bjoern Riemer
-
 
12
*           - Olaf Rempel
-
 
13
*
-
 
14
* License  : Copyright (c) 2006-2008 M. Thomas, U. Bonnes, O. Rempel
-
 
15
*            Free to use. You have to mention the copyright
-
 
16
*            owners in source-code and documentation of derived
-
 
17
*            work. No warranty! (Yes, you can insert the BSD
-
 
18
*            license here)
-
 
19
*
-
 
20
* Tested with ATmega8, ATmega16, ATmega162, ATmega32, ATmega324P,
-
 
21
*             ATmega644, ATmega644P, ATmega128, AT90CAN128
-
 
22
*
-
 
23
* - Initial versions have been based on the Butterfly bootloader-code
-
 
24
*   by Atmel Corporation (Authors: BBrandal, PKastnes, ARodland, LHM)
-
 
25
*
-
 
26
****************************************************************************
-
 
27
*
-
 
28
*  See the makefile and readme.txt for information on how to adapt
-
 
29
*  the linker-settings to the selected Boot Size (BOOTSIZE=xxxx) and
-
 
30
*  the MCU-type. Other configurations futher down in this file.
-
 
31
*
-
 
32
*  With BOOT_SIMPLE, minimal features and discarded int-vectors
-
 
33
*  this bootloader has should fit into a a 512 word (1024, 0x400 bytes)
-
 
34
*  bootloader-section.
-
 
35
*
-
 
36
****************************************************************************/
-
 
37
/*
-
 
38
        TODOs:
-
 
39
        - check lock-bits set
-
 
40
        - __bad_interrupt still linked even with modified
-
 
41
          linker-scripts which needs a default-handler,
-
 
42
          "wasted": 3 words for AVR5 (>8kB), 2 words for AVR4
-
 
43
        - Check watchdog-disable-function in avr-libc.
-
 
44
*/
-
 
45
// tabsize: 4
-
 
46
 
-
 
47
// Fuses ATmega 644P D7 DC FC
-
 
48
 
-
 
49
 
-
 
50
/* MCU frequency */
-
 
51
#ifndef F_CPU
-
 
52
// #define F_CPU 7372800
-
 
53
#define F_CPU (20000000)
-
 
54
#endif
-
 
55
 
-
 
56
#define BOOTSIZE 1024
-
 
57
 
-
 
58
#define set_LED1()      (PORTC &= ~(1 << PC3))
-
 
59
#define clr_LED1()      (PORTC |=  (1 << PC3))
-
 
60
#define set_LED2()      (PORTC &= ~(1 << PC2))
-
 
61
#define clr_LED2()      (PORTC |=  (1 << PC2))
-
 
62
#define set_LED3()      (PORTB &= ~(1 << PB1))
-
 
63
#define clr_LED3()      (PORTB |=  (1 << PB1))
-
 
64
#define set_LED4()      (PORTB &= ~(1 << PB0))
-
 
65
#define clr_LED4()      (PORTB |=  (1 << PB0))
-
 
66
 
-
 
67
/* UART Baudrate */
-
 
68
// #define BAUDRATE 9600
-
 
69
// #define BAUDRATE 19200
-
 
70
#define BAUDRATE 115200
-
 
71
 
-
 
72
/* use "Double Speed Operation" */
-
 
73
//#define UART_DOUBLESPEED
-
 
74
 
-
 
75
/* use second UART on mega128 / can128 / mega162 / mega324p / mega644p */
-
 
76
#define UART_USE_SECOND
-
 
77
 
-
 
78
/* Device-Type:
-
 
79
   For AVRProg the BOOT-option is prefered
-
 
80
   which is the "correct" value for a bootloader.
-
 
81
   avrdude may only detect the part-code for ISP */
-
 
82
#define DEVTYPE     DEVTYPE_BOOT
-
 
83
// #define DEVTYPE     DEVTYPE_ISP
-
 
84
 
-
 
85
/*
-
 
86
 * Pin "STARTPIN" on port "STARTPORT" in this port has to grounded
-
 
87
 * (active low) to start the bootloader
-
 
88
 */
-
 
89
#define BLPORT          PORTA
-
 
90
#define BLDDR           DDRA
-
 
91
#define BLPIN           PINA
-
 
92
#define BLPNUM          PINA4
-
 
93
 
-
 
94
/*
-
 
95
 * Define if Watchdog-Timer should be disable at startup
-
 
96
 */
-
 
97
#define DISABLE_WDT_AT_STARTUP
-
 
98
 
-
 
99
/*
-
 
100
 * Watchdog-reset is issued at exit
-
 
101
 * define the timeout-value here (see avr-libc manual)
-
 
102
 */
-
 
103
#define EXIT_WDT_TIME   WDTO_250MS
-
 
104
 
-
 
105
/*
-
 
106
 * Select startup-mode
-
 
107
 * SIMPLE-Mode - Jump to bootloader main BL-loop if key is
-
 
108
 *   pressed (Pin grounded) "during" reset or jump to the
-
 
109
 *   application if the pin is not grounded. The internal
-
 
110
 *   pull-up resistor is enabled during the startup and
-
 
111
 *   gets disabled before the application is started.
-
 
112
 * POWERSAVE-Mode - Startup is separated in two loops
-
 
113
 *   which makes power-saving a little easier if no firmware
-
 
114
 *   is on the chip. Needs more memory
-
 
115
 * BOOTICE-Mode - to flash the JTAGICE upgrade.ebn file.
-
 
116
 *   No startup-sequence in this mode. Jump directly to the
-
 
117
 *   parser-loop on reset
-
 
118
 *   F_CPU in BOOTICEMODE must be 7372800 Hz to be compatible
-
 
119
 *   with the org. JTAGICE-Firmware
-
 
120
 * WAIT-mode waits 1 sec for the defined character if nothing
-
 
121
 *    is recived then the user prog is started.
-
 
122
 */
-
 
123
#define START_SIMPLE
-
 
124
//#define START_WAIT
-
 
125
//#define START_POWERSAVE
-
 
126
//#define START_BOOTICE
-
 
127
 
-
 
128
/* character to start the bootloader in mode START_WAIT */
-
 
129
#define START_WAIT_UARTCHAR 'S'
-
 
130
 
-
 
131
/* wait-time for START_WAIT mode ( t = WAIT_TIME * 10ms ) */
-
 
132
#define WAIT_VALUE 100 /* here: 100*10ms = 1000ms = 1sec */
-
 
133
 
-
 
134
/*
-
 
135
 * enable/disable readout of fuse and lock-bits
-
 
136
 * (AVRPROG has to detect the AVR correctly by device-code
-
 
137
 * to show the correct information).
-
 
138
 */
-
 
139
//#define ENABLEREADFUSELOCK
-
 
140
 
-
 
141
/* enable/disable write of lock-bits
-
 
142
 * WARNING: lock-bits can not be reseted by bootloader (as far as I know)
-
 
143
 * Only protection no unprotection, "chip erase" from bootloader only
-
 
144
 * clears the flash but does no real "chip erase" (this is not possible
-
 
145
 * with a bootloader as far as I know)
-
 
146
 * Keep this undefined!
-
 
147
 */
-
 
148
//#define WRITELOCKBITS
-
 
149
 
-
 
150
/*
-
 
151
 * define the following if the bootloader should not output
-
 
152
 * itself at flash read (will fake an empty boot-section)
-
 
153
 */
-
 
154
#define READ_PROTECT_BOOTLOADER
-
 
155
 
-
 
156
 
-
 
157
#define VERSION_HIGH '0'
-
 
158
#define VERSION_LOW  '8'
-
 
159
 
-
 
160
#define GET_LOCK_BITS           0x0001
-
 
161
#define GET_LOW_FUSE_BITS       0x0000
-
 
162
#define GET_HIGH_FUSE_BITS      0x0003
-
 
163
#define GET_EXTENDED_FUSE_BITS  0x0002
-
 
164
 
-
 
165
 
-
 
166
#ifdef UART_DOUBLESPEED
-
 
167
// #define UART_CALC_BAUDRATE(baudRate) (((F_CPU*10UL) / ((baudRate) *8UL) +5)/10 -1)
-
 
168
#define UART_CALC_BAUDRATE(baudRate) ((uint32_t)((F_CPU) + ((uint32_t)baudRate * 4UL)) / ((uint32_t)(baudRate) * 8UL) - 1)
-
 
169
#else
-
 
170
// #define UART_CALC_BAUDRATE(baudRate) (((F_CPU*10UL) / ((baudRate)*16UL) +5)/10 -1)
-
 
171
#define UART_CALC_BAUDRATE(baudRate) ((uint32_t)((F_CPU) + ((uint32_t)baudRate * 8UL)) / ((uint32_t)(baudRate) * 16UL) - 1)
-
 
172
#endif
-
 
173
 
-
 
174
 
-
 
175
#include <stdint.h>
-
 
176
#include <avr/io.h>
-
 
177
#include <avr/wdt.h>
-
 
178
#include <avr/boot.h>
-
 
179
#include <avr/pgmspace.h>
-
 
180
#include <avr/eeprom.h>
-
 
181
#include <avr/interrupt.h>
-
 
182
#include <util/delay.h>
-
 
183
 
-
 
184
#include "chipdef.h"
-
 
185
 
-
 
186
//#include "lcd.h"
-
 
187
 
-
 
188
uint8_t gBuffer[SPM_PAGESIZE];
-
 
189
 
-
 
190
#if defined(BOOTLOADERHASNOVECTORS)
-
 
191
#warning "This Bootloader does not link interrupt vectors - see makefile"
-
 
192
/* make the linker happy - it wants to see __vector_default */
-
 
193
// void __vector_default(void) { ; }
-
 
194
void __vector_default(void) { ; }
-
 
195
#endif
-
 
196
 
-
 
197
static void sendchar(uint8_t data)
-
 
198
{
-
 
199
        while (!(UART_STATUS & (1<<UART_TXREADY)));
-
 
200
        UART_DATA = data;
-
 
201
}
-
 
202
 
-
 
203
static uint8_t recvchar(void)
-
 
204
{
-
 
205
        while (!(UART_STATUS & (1<<UART_RXREADY)));
-
 
206
        clr_LED1();
-
 
207
        return UART_DATA;
-
 
208
}
-
 
209
 
-
 
210
static inline void eraseFlash(void)
-
 
211
{
-
 
212
        // erase only main section (bootloader protection)
-
 
213
        uint32_t addr = 0;
-
 
214
        while (APP_END > addr) {
-
 
215
                boot_page_erase(addr);          // Perform page erase
-
 
216
                boot_spm_busy_wait();           // Wait until the memory is erased.
-
 
217
                addr += SPM_PAGESIZE;
-
 
218
        }
-
 
219
        boot_rww_enable();
-
 
220
}
-
 
221
 
-
 
222
static inline void recvBuffer(pagebuf_t size)
-
 
223
{
-
 
224
        pagebuf_t cnt;
-
 
225
        uint8_t *tmp = gBuffer;
-
 
226
 
-
 
227
        for (cnt = 0; cnt < sizeof(gBuffer); cnt++) {
-
 
228
                *tmp++ = (cnt < size) ? recvchar() : 0xFF;
-
 
229
        }
-
 
230
}
-
 
231
 
-
 
232
static inline uint16_t writeFlashPage(uint16_t waddr, pagebuf_t size)
-
 
233
{
-
 
234
        uint32_t pagestart = (uint32_t)waddr<<1;
-
 
235
        uint32_t baddr = pagestart;
-
 
236
        uint16_t data;
-
 
237
        uint8_t *tmp = gBuffer;
-
 
238
 
-
 
239
        do {
-
 
240
                data = *tmp++;
-
 
241
                data |= *tmp++ << 8;
-
 
242
                boot_page_fill(baddr, data);    // call asm routine.
-
 
243
 
-
 
244
                baddr += 2;                     // Select next word in memory
-
 
245
                size -= 2;                      // Reduce number of bytes to write by two
-
 
246
        } while (size);                         // Loop until all bytes written
-
 
247
 
-
 
248
        boot_page_write(pagestart);
-
 
249
        boot_spm_busy_wait();
-
 
250
        boot_rww_enable();              // Re-enable the RWW section
-
 
251
 
-
 
252
        return baddr>>1;
-
 
253
}
-
 
254
 
-
 
255
static inline uint16_t writeEEpromPage(uint16_t address, pagebuf_t size)
-
 
256
{
-
 
257
        uint8_t *tmp = gBuffer;
-
 
258
 
-
 
259
        do {
-
 
260
                eeprom_write_byte( (uint8_t*)address, *tmp++ );
-
 
261
                address++;                      // Select next byte
-
 
262
                size--;                         // Decreas number of bytes to write
-
 
263
        } while (size);                         // Loop until all bytes written
-
 
264
 
-
 
265
        // eeprom_busy_wait();
-
 
266
 
-
 
267
        return address;
-
 
268
}
-
 
269
 
-
 
270
static inline uint16_t readFlashPage(uint16_t waddr, pagebuf_t size)
-
 
271
{
-
 
272
        uint32_t baddr = (uint32_t)waddr<<1;
-
 
273
        uint16_t data;
-
 
274
 
-
 
275
        do {
-
 
276
#ifndef READ_PROTECT_BOOTLOADER
-
 
277
#warning "Bootloader not read-protected"
-
 
278
#if defined(RAMPZ)
-
 
279
                data = pgm_read_word_far(baddr);
-
 
280
#else
-
 
281
                data = pgm_read_word_near(baddr);
-
 
282
#endif
-
 
283
#else
-
 
284
                // don't read bootloader
-
 
285
                if ( baddr < APP_END ) {
-
 
286
#if defined(RAMPZ)
-
 
287
                        data = pgm_read_word_far(baddr);
-
 
288
#else
-
 
289
                        data = pgm_read_word_near(baddr);
-
 
290
#endif
-
 
291
                }
-
 
292
                else {
-
 
293
                        data = 0xFFFF; // fake empty
-
 
294
                }
-
 
295
#endif
-
 
296
                sendchar(data);                 // send LSB
-
 
297
                sendchar((data >> 8));          // send MSB
-
 
298
                baddr += 2;                     // Select next word in memory
-
 
299
                size -= 2;                      // Subtract two bytes from number of bytes to read
-
 
300
        } while (size);                         // Repeat until block has been read
-
 
301
 
-
 
302
        return baddr>>1;
-
 
303
}
-
 
304
 
-
 
305
static inline uint16_t readEEpromPage(uint16_t address, pagebuf_t size)
-
 
306
{
-
 
307
        do {
-
 
308
                sendchar( eeprom_read_byte( (uint8_t*)address ) );
-
 
309
                address++;
-
 
310
                size--;                         // Decrease number of bytes to read
-
 
311
        } while (size);                         // Repeat until block has been read
-
 
312
 
-
 
313
        return address;
-
 
314
}
-
 
315
 
-
 
316
#if defined(ENABLEREADFUSELOCK)
-
 
317
static uint8_t read_fuse_lock(uint16_t addr)
-
 
318
{
-
 
319
        uint8_t mode = (1<<BLBSET) | (1<<SPMEN);
-
 
320
        uint8_t retval;
-
 
321
 
-
 
322
        asm volatile
-
 
323
        (
-
 
324
                "movw r30, %3\n\t"              /* Z to addr */ \
-
 
325
                "sts %0, %2\n\t"                /* set mode in SPM_REG */ \
-
 
326
                "lpm\n\t"                       /* load fuse/lock value into r0 */ \
-
 
327
                "mov %1,r0\n\t"                 /* save return value */ \
-
 
328
                : "=m" (SPM_REG),
-
 
329
                  "=r" (retval)
-
 
330
                : "r" (mode),
-
 
331
                  "r" (addr)
-
 
332
                : "r30", "r31", "r0"
-
 
333
        );
-
 
334
        return retval;
-
 
335
}
-
 
336
#endif
-
 
337
 
-
 
338
static void send_boot(void)
-
 
339
{
-
 
340
        sendchar('A');
-
 
341
        sendchar('V');
-
 
342
        sendchar('R');
-
 
343
        sendchar('B');
-
 
344
        sendchar('O');
-
 
345
        sendchar('O');
-
 
346
        sendchar('T');
-
 
347
}
-
 
348
 
-
 
349
 
-
 
350
 
-
 
351
static void (*jump_to_app)(void) = 0x0000;
-
 
352
 
-
 
353
int main(void)
-
 
354
{
-
 
355
        uint16_t address = 0;
-
 
356
        uint8_t device = 0, val;
-
 
357
 
-
 
358
        DDRC = 0xFF;
-
 
359
        PORTC = PORTC | 0xff;
-
 
360
 
-
 
361
 
-
 
362
 
-
 
363
#ifdef DISABLE_WDT_AT_STARTUP
-
 
364
#ifdef WDT_OFF_SPECIAL
-
 
365
#warning "using target specific watchdog_off"
-
 
366
        bootloader_wdt_off();
-
 
367
#else
-
 
368
        cli();
-
 
369
        wdt_reset();
-
 
370
        wdt_disable();
-
 
371
#endif
-
 
372
#endif
-
 
373
       
-
 
374
#ifdef START_POWERSAVE
-
 
375
        uint8_t OK = 1;
-
 
376
#endif
-
 
377
 
-
 
378
        BLDDR  &= ~(1<<BLPNUM);         // set as Input
-
 
379
        BLPORT |= (1<<BLPNUM);          // Enable pullup
-
 
380
 
-
 
381
        // Set baud rate
-
 
382
        UART_BAUD_HIGH = (UART_CALC_BAUDRATE(BAUDRATE)>>8) & 0xFF;
-
 
383
        UART_BAUD_LOW = (UART_CALC_BAUDRATE(BAUDRATE) & 0xFF);
-
 
384
 
-
 
385
#ifdef UART_DOUBLESPEED
-
 
386
        UART_STATUS = ( 1<<UART_DOUBLE );
-
 
387
#endif
-
 
388
 
-
 
389
        UART_CTRL = UART_CTRL_DATA;
-
 
390
        UART_CTRL2 = UART_CTRL2_DATA;
-
 
391
       
-
 
392
#if defined(START_POWERSAVE)
-
 
393
        /*
-
 
394
                This is an adoption of the Butterfly Bootloader startup-sequence.
-
 
395
                It may look a little strange but separating the login-loop from
-
 
396
                the main parser-loop gives a lot a possibilities (timeout, sleep-modes
-
 
397
            etc.).
-
 
398
        */
-
 
399
        for(;OK;) {
-
 
400
                if ((BLPIN & (1<<BLPNUM))) {
-
 
401
                        // jump to main app if pin is not grounded
-
 
402
                        BLPORT &= ~(1<<BLPNUM); // set to default
-
 
403
#ifdef UART_DOUBLESPEED
-
 
404
                        UART_STATUS &= ~( 1<<UART_DOUBLE );
-
 
405
#endif
-
 
406
                        jump_to_app();          // Jump to application sector
-
 
407
 
-
 
408
                } else {
-
 
409
                        val = recvchar();
-
 
410
                        /* ESC */
-
 
411
                        if (val == 0x1B) {
-
 
412
                                // AVRPROG connection
-
 
413
                                // Wait for signon
-
 
414
                                while (val != 'S')
-
 
415
                                        val = recvchar();
-
 
416
 
-
 
417
                                send_boot();                    // Report signon
-
 
418
                                OK = 0;
-
 
419
 
-
 
420
                        } else {
-
 
421
                                sendchar('?');
-
 
422
                        }
-
 
423
                }
-
 
424
                // Power-Save code here
-
 
425
        }
-
 
426
 
-
 
427
#elif defined(START_SIMPLE)
-
 
428
 
-
 
429
        if ((BLPIN & (1<<BLPNUM))) {
-
 
430
                // jump to main app if pin is not grounded
-
 
431
                BLPORT &= ~(1<<BLPNUM);         // set to default               
-
 
432
#ifdef UART_DOUBLESPEED
-
 
433
                UART_STATUS &= ~( 1<<UART_DOUBLE );
-
 
434
#endif
-
 
435
                jump_to_app();                  // Jump to application sector
-
 
436
        }
-
 
437
 
-
 
438
#elif defined(START_WAIT)
-
 
439
 
-
 
440
        uint16_t cnt = 0;
-
 
441
 
-
 
442
        while (1) {
-
 
443
                if (UART_STATUS & (1<<UART_RXREADY))
-
 
444
                        if (UART_DATA == START_WAIT_UARTCHAR)
-
 
445
                                break;
-
 
446
 
-
 
447
                if (cnt++ >= WAIT_VALUE) {
-
 
448
                        BLPORT &= ~(1<<BLPNUM);         // set to default
-
 
449
                        jump_to_app();                  // Jump to application sector
-
 
450
                }
-
 
451
 
-
 
452
                _delay_ms(10);
-
 
453
        }
-
 
454
        send_boot();
-
 
455
 
-
 
456
#elif defined(START_BOOTICE)
-
 
457
#warning "BOOTICE mode - no startup-condition"
-
 
458
 
-
 
459
#else
-
 
460
#error "Select START_ condition for bootloader in main.c"
-
 
461
#endif
-
 
462
 
-
 
463
 
-
 
464
 
-
 
465
        for(;;) {
-
 
466
 
-
 
467
                set_LED1();
-
 
468
 
-
 
469
                val = recvchar();
-
 
470
 
-
 
471
                // Autoincrement?
-
 
472
                if (val == 'a') {
-
 
473
                        sendchar('Y');                  // Autoincrement is quicker
-
 
474
 
-
 
475
                //write address
-
 
476
                } else if (val == 'A') {
-
 
477
                        address = recvchar();           //read address 8 MSB
-
 
478
                        address = (address<<8) | recvchar();
-
 
479
                        sendchar('\r');
-
 
480
 
-
 
481
                // Buffer load support
-
 
482
                } else if (val == 'b') {
-
 
483
                        sendchar('Y');                                  // Report buffer load supported
-
 
484
                        sendchar((sizeof(gBuffer) >> 8) & 0xFF);        // Report buffer size in bytes
-
 
485
                        sendchar(sizeof(gBuffer) & 0xFF);
-
 
486
 
-
 
487
                // Start buffer load
-
 
488
                } else if (val == 'B') {
-
 
489
                        pagebuf_t size;
-
 
490
                        size = recvchar() << 8;                         // Load high byte of buffersize
-
 
491
                        size |= recvchar();                             // Load low byte of buffersize
-
 
492
                        val = recvchar();                               // Load memory type ('E' or 'F')
-
 
493
                        recvBuffer(size);
-
 
494
 
-
 
495
                        if (device == DEVTYPE) {
-
 
496
                                if (val == 'F') {
-
 
497
                                        address = writeFlashPage(address, size);
-
 
498
                                } else if (val == 'E') {
-
 
499
                                        address = writeEEpromPage(address, size);
-
 
500
                                }
-
 
501
                                sendchar('\r');
-
 
502
                        } else {
-
 
503
                                sendchar(0);
-
 
504
                        }
-
 
505
 
-
 
506
                // Block read
-
 
507
                } else if (val == 'g') {
-
 
508
                        pagebuf_t size;
-
 
509
                        size = recvchar() << 8;                         // Load high byte of buffersize
-
 
510
                        size |= recvchar();                             // Load low byte of buffersize
-
 
511
                        val = recvchar();                               // Get memtype
-
 
512
 
-
 
513
                        if (val == 'F') {
-
 
514
                                address = readFlashPage(address, size);
-
 
515
                        } else if (val == 'E') {
-
 
516
                                address = readEEpromPage(address, size);
-
 
517
                        }
-
 
518
 
-
 
519
                // Chip erase
-
 
520
                } else if (val == 'e') {
-
 
521
                        if (device == DEVTYPE) {
-
 
522
                                eraseFlash();
-
 
523
                        }
-
 
524
                        sendchar('\r');
-
 
525
 
-
 
526
                // Exit upgrade
-
 
527
                } else if (val == 'E') {
-
 
528
                        wdt_enable(EXIT_WDT_TIME); // Enable Watchdog Timer to give reset
-
 
529
                        sendchar('\r');
-
 
530
 
-
 
531
#ifdef WRITELOCKBITS
-
 
532
#warning "Extension 'WriteLockBits' enabled"
-
 
533
                // TODO: does not work reliably
-
 
534
                // write lockbits
-
 
535
                } else if (val == 'l') {
-
 
536
                        if (device == DEVTYPE) {
-
 
537
                                // write_lock_bits(recvchar());
-
 
538
                                boot_lock_bits_set(recvchar()); // boot.h takes care of mask
-
 
539
                                boot_spm_busy_wait();
-
 
540
                        }
-
 
541
                        sendchar('\r');
-
 
542
#endif
-
 
543
                // Enter programming mode
-
 
544
                } else if (val == 'P') {
-
 
545
                        sendchar('\r');
-
 
546
 
-
 
547
                // Leave programming mode
-
 
548
                } else if (val == 'L') {
-
 
549
                        sendchar('\r');
-
 
550
 
-
 
551
                // return programmer type
-
 
552
                } else if (val == 'p') {
-
 
553
                        sendchar('S');          // always serial programmer
-
 
554
 
-
 
555
#ifdef ENABLEREADFUSELOCK
-
 
556
#warning "Extension 'ReadFuseLock' enabled"
-
 
557
                // read "low" fuse bits
-
 
558
                } else if (val == 'F') {
-
 
559
                        sendchar(read_fuse_lock(GET_LOW_FUSE_BITS));
-
 
560
 
-
 
561
                // read lock bits
-
 
562
                } else if (val == 'r') {
-
 
563
                        sendchar(read_fuse_lock(GET_LOCK_BITS));
-
 
564
 
-
 
565
                // read high fuse bits
-
 
566
                } else if (val == 'N') {
-
 
567
                        sendchar(read_fuse_lock(GET_HIGH_FUSE_BITS));
-
 
568
 
-
 
569
                // read extended fuse bits
-
 
570
                } else if (val == 'Q') {
-
 
571
                        sendchar(read_fuse_lock(GET_EXTENDED_FUSE_BITS));
-
 
572
#endif
-
 
573
 
-
 
574
                // Return device type
-
 
575
                } else if (val == 't') {
-
 
576
                        sendchar(DEVTYPE);
-
 
577
                        sendchar(0);
-
 
578
 
-
 
579
                // clear and set LED ignored
-
 
580
                } else if ((val == 'x') || (val == 'y')) {
-
 
581
                        recvchar();
-
 
582
                        sendchar('\r');
-
 
583
 
-
 
584
                // set device
-
 
585
                } else if (val == 'T') {
-
 
586
                        device = recvchar();
-
 
587
                        sendchar('\r');
-
 
588
 
-
 
589
                // Return software identifier
-
 
590
                } else if (val == 'S') {
-
 
591
                        send_boot();
-
 
592
 
-
 
593
                // Return Software Version
-
 
594
                } else if (val == 'V') {
-
 
595
                        sendchar(VERSION_HIGH);
-
 
596
                        sendchar(VERSION_LOW);
-
 
597
 
-
 
598
                // Return Signature Bytes (it seems that 
-
 
599
                // AVRProg expects the "Atmel-byte" 0x1E last
-
 
600
                // but shows it first in the dialog-window)
-
 
601
                } else if (val == 's') {
-
 
602
                        sendchar(SIG_BYTE3);
-
 
603
                        sendchar(SIG_BYTE2);
-
 
604
                        sendchar(SIG_BYTE1);
-
 
605
 
-
 
606
                /* ESC */
-
 
607
                } else if(val != 0x1b) {
-
 
608
                        sendchar('?');
-
 
609
                }
-
 
610
 
-
 
611
        }
-
 
612
        return 0;
-
 
613
}