/*************************************************************************** * Copyright (C) 09/2007 by Olaf Rempel * * razzor@kopf-tisch.de * * * * This program is free software; you can redistribute it and/or modify * * it under the terms of the GNU General Public License as published by * * the Free Software Foundation; version 2 of the License, * * * * This program is distributed in the hope that it will be useful, * * but WITHOUT ANY WARRANTY; without even the implied warranty of * * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * * GNU General Public License for more details. * * * * You should have received a copy of the GNU General Public License * * along with this program; if not, write to the * * Free Software Foundation, Inc., * * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * ***************************************************************************/ #include #include #include #include #include /* * ATMega 644P: * Fuse E: 0xFD (2.7V BOD) * Fuse H: 0xDC (1024 words bootloader) * Fuse L: 0xFF (ext. Crystal) */ #define F_CPU 20000000 #include #define BAUDRATE 57600 #define UART_CALC_BAUDRATE(baudRate) ((uint32_t)(F_CPU) / ((uint32_t)(baudRate)*16) -1) #define APP_END 0xF7FF #define LED_RT (1<> 8); EEDR = *tmp++; address++; EECR |= (1<> 8)); address += 2; size -= 2; } while (size); } static void readEEpromPage(uint16_t address, uint16_t size) { do { EEARL = address; EEARH = (address >> 8); EECR |= (1<> 8) & 0xFF); response = page_size & 0Xff; // Start buffer load } else if (val == 'B') { uint16_t size; uint16_t cnt; uint8_t *tmp = page_buf; size = recvchar() << 8; size |= recvchar(); val = recvchar(); for (cnt = 0; cnt < page_size; cnt++) *tmp++ = (cnt < size) ? recvchar() : 0xFF; if (i2c_dev != 0) { i2c_start_address(i2c_dev); i2c_master_tx(CMD_WRITE_MEMORY); i2c_master_tx((val == 'F') ? MEMTYPE_FLASH : MEMTYPE_EEPROM); i2c_master_tx(address >> 8); i2c_master_tx(address & 0xFF); address += page_size; tmp = page_buf; while (cnt--) i2c_master_tx(*tmp++); i2c_stop(); } else { if (val == 'F') { writeFlashPage(address, size); } else if (val == 'E') { writeEEpromPage(address, size); } address += size; } response = '\r'; // Block read } else if (val == 'g') { uint16_t size = recvchar() << 8; size |= recvchar(); val = recvchar(); if (i2c_dev != 0) { i2c_start_address(i2c_dev); i2c_master_tx(CMD_READ_MEMORY); i2c_master_tx((val == 'F') ? MEMTYPE_FLASH : MEMTYPE_EEPROM); i2c_master_tx(address >> 8); i2c_master_tx(address & 0xFF); i2c_start_address(i2c_dev | 0x01); while (size--) { sendchar(i2c_master_rx(size > 0)); address++; } i2c_stop(); } else { if (val == 'F') { readFlashPage(address, size); } else if (val == 'E') { readEEpromPage(address, size); } address += size; } // Chip erase } else if (val == 'e') { if (i2c_dev == 0) { eraseFlash(); } response = '\r'; // Exit upgrade } else if (val == 'E') { sendchar('\r'); if (i2c_dev == 0) { return; } // Enter / Leave programming mode } else if (val == 'P' || val == 'L') { if (i2c_dev != 0) { val = (val == 'P') ? BOOTTYPE_BOOTLOADER : BOOTTYPE_APPLICATION; i2c_switch_app(i2c_dev, val); } response = '\r'; // return programmer type } else if (val == 'p') { response = 'S'; // Return device type } else if (val == 't') { sendchar((i2c_dev == 0) ? OWN_DEVCODE : TWI_DEVCODE); response = '\0'; // clear and set LED ignored } else if ((val == 'x') || (val == 'y') || (val == 'T')) { recvchar(); response = '\r'; // Return software identifier } else if (val == 'S') { sendchar('F'); sendchar('C'); sendchar('_'); sendchar('B'); sendchar('O'); sendchar('O'); response = 'T'; // Return Software Version } else if (val == 'V' || val == 'v') { sendchar('0'); response = '8'; // Return Signature Bytes } else if (val == 's') { if (i2c_dev != 0) { sendchar(chipinfo[2]); sendchar(chipinfo[1]); response = chipinfo[0]; } else { uint8_t sig[3] = OWN_SIGNATURE; sendchar(sig[2]); sendchar(sig[1]); response = sig[0]; } // set i2c target } else if (val == '0') { i2c_dev = 0; } else if (val >= '1' && val <= '4') { i2c_dev = (val - '0' + TWI_ADDRESS_BASE) << 1; i2c_switch_app(i2c_dev, BOOTTYPE_BOOTLOADER); _delay_ms(100); i2c_print_version(i2c_dev); i2c_start_address(i2c_dev); i2c_master_tx(CMD_READ_MEMORY); i2c_master_tx(MEMTYPE_CHIPINFO); i2c_master_tx(0x00); i2c_master_tx(0x00); i2c_start_address(i2c_dev | 0x01); uint8_t i; for (i = 0; i < sizeof(chipinfo); i++) { uint8_t more = (i < (sizeof(chipinfo) -1)); chipinfo[i] = i2c_master_rx(more); } i2c_stop(); // test props } else if (val == 'k' || val == 'l') { if (i2c_dev != 0) { i2c_start_address(i2c_dev); i2c_master_tx(0x00 + (val - 'k') * 0x10); i2c_stop(); response = val; } // get Version } else if (val == 'I') { if (i2c_dev != 0) { i2c_switch_app(i2c_dev, BOOTTYPE_APPLICATION); _delay_ms(100); i2c_print_version(i2c_dev); } // fake MK-TOOL specific stuff } else if (val == 0xAA) { sendchar('M'); sendchar('K'); sendchar('B'); response = 'L'; /* ESC */ } else if (val != 0x1b) { response = '?'; } if (response != 0xFF) { sendchar(response); } val = recvchar(); } } static void (*jump_to_app)(void) __attribute__ ((noreturn)) = 0x0000; /* * For newer devices the watchdog timer remains active even after a * system reset. So disable it as soon as possible. * automagically called on startup */ void disable_wdt_timer(void) __attribute__((naked, section(".init3"))); void disable_wdt_timer(void) { MCUSR = 0; WDTCSR = (1<>8) & 0xFF; UBRR0L = (UART_CALC_BAUDRATE(BAUDRATE) & 0xFF); /* USART: rx/tx enable, 8n1 */ UCSR0B = (1< 0) { if (UCSR0A & (1<