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 | } |