/*************************************************************************** * 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 #include #define F_CPU 20000000 #include #define BAUDRATE 19200 #define UART_CALC_BAUDRATE(baudRate) ((uint32_t)(F_CPU) / ((uint32_t)(baudRate)*16) -1) #define APP_END 0xF000 #define LED_RT (1< send SLA+W */ case 0x08: bcnt = 0; TWDR = (i2c_dev << 1); TWCR &= ~(1< send SLA+R */ case 0x10: bcnt = 0; TWDR = (i2c_dev << 1) | 0x01; TWCR &= ~(1< send command */ case 0x18: bcnt++; TWDR = i2c_cmd; TWCR |= (1< ? */ case 0x28: switch (i2c_cmd) { case CMD_GET_INFO: case CMD_GET_SIGNATURE: case CMD_READ_FLASH: case CMD_READ_EEPROM: TWCR |= (1<> 8); } else if (bcnt == 2) { TWDR = (i2c_address & 0xFF); } else if (bcnt == 3) { TWDR = (WRITE_COOKIE >> 8); } else if (bcnt == 4) { TWDR = (WRITE_COOKIE & 0xFF); } else if (bcnt >= 5 && bcnt < (64 +5)) { TWDR = i2c_buf[bcnt -5]; } else { i2c_complete = 1; TWCR |= (1< send ACK (send more data) */ case 0x40: TWCR |= (1< 0) boot_timeout--; } static uint16_t address; static uint8_t page_buf[256]; static void eraseFlash(void) { uint32_t addr = 0; while (APP_END > addr) { boot_page_erase(addr); boot_spm_busy_wait(); addr += SPM_PAGESIZE; } boot_rww_enable(); } static uint16_t writeFlashPage(uint16_t waddr, uint16_t size) { uint32_t pagestart = (uint32_t)waddr<<1; uint32_t baddr = pagestart; uint16_t data; uint8_t *tmp = page_buf; do { data = *tmp++; data |= *tmp++ << 8; boot_page_fill(baddr, data); baddr += 2; size -= 2; } while (size); boot_page_write(pagestart); boot_spm_busy_wait(); boot_rww_enable(); return baddr>>1; } static uint16_t writeEEpromPage(uint16_t address, uint16_t size) { uint8_t *tmp = page_buf; do { EEARL = address; EEARH = (address >> 8); EEDR = *tmp++; address++; EECR |= (1<> 8)); baddr += 2; size -= 2; } while (size); return baddr>>1; } static uint16_t readEEpromPage(uint16_t address, uint16_t size) { do { EEARL = address; EEARH = (address >> 8); EECR |= (1<> 8) & 0xFF); sendchar(sizeof(page_buf) & 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 < sizeof(page_buf); cnt++) *tmp++ = (cnt < size) ? recvchar() : 0xFF; if (dev == DEVCODE_M8) { if (val == 'F') { tmp = page_buf; while (size) { i2c_address = address; for (cnt = 0; cnt < sizeof(i2c_buf); cnt++) i2c_buf[cnt] = *tmp++; i2c_transfer(CMD_WRITE_FLASH); address += sizeof(i2c_buf); size -= sizeof(i2c_buf); } } else if (val == 'E') { } } else if (dev == DEVCODE_M644) { if (val == 'F') { address = writeFlashPage(address, size); } else if (val == 'E') { address = writeEEpromPage(address, size); } } sendchar('\r'); // Block read } else if (val == 'g') { uint16_t size = recvchar() << 8; size |= recvchar(); val = recvchar(); if (dev == DEVCODE_M8) { if (val == 'F') { while (size > 0) { uint8_t i = 0; i2c_address = address; i2c_transfer(CMD_READ_FLASH); address += sizeof(i2c_buf); while (size-- && i < sizeof(i2c_buf)) sendchar(i2c_buf[i++]); } } else if (val == 'E') { sendchar(0xff); } } else if (dev == DEVCODE_M644) { if (val == 'F') { address = readFlashPage(address, size); } else if (val == 'E') { address = readEEpromPage(address, size); } } // Chip erase } else if (val == 'e') { eraseFlash(); sendchar('\r'); // Exit upgrade } else if (val == 'E') { boot_timeout = 0; sendchar('\r'); _delay_ms(10); break; // Enter programming mode } else if (val == 'P') { /* boot loader */ i2c_transfer(CMD_BOOT_LOADER); sendchar('\r'); // Leave programming mode } else if (val == 'L') { /* boot application */ i2c_transfer(CMD_BOOT_APPLICATION); sendchar('\r'); // return programmer type } else if (val == 'p') { sendchar('S'); // Return device type } else if (val == 't') { sendchar(DEVCODE_M8); sendchar(DEVCODE_M644); sendchar(0); // clear and set LED ignored } else if ((val == 'x') || (val == 'y')) { recvchar(); sendchar('\r'); // set device } else if (val == 'T') { dev = recvchar(); sendchar('\r'); // Return software identifier } else if (val == 'S') { sendchar('F'); sendchar('C'); sendchar('_'); sendchar('B'); sendchar('O'); sendchar('O'); sendchar('T'); // Return Software Version } else if (val == 'V') { sendchar('0'); sendchar('8'); // Return Signature Bytes } else if (val == 's') { if (dev == DEVCODE_M8) { sendchar(0x07); sendchar(0x93); sendchar(0x1e); } else if (dev == DEVCODE_M644) { sendchar(0x09); sendchar(0x96); sendchar(0x1e); } else { sendchar(0xFF); sendchar(0xFF); sendchar(0xFF); } // set i2c target } else if (val >= '1' && val <= '4') { i2c_dev = val - '1' + 0x21; sendchar(val); /* ESC */ } else if (val != 0x1b) { sendchar('?'); } } } static void (*jump_to_app)(void) = 0x0000; int main(void) { DDRB = LED_GN | LED_RT; PORTB = LED_GN; /* move interrupt-vectors to bootloader */ MCUCR = (1<>8) & 0xFF; UBRR0L = (UART_CALC_BAUDRATE(BAUDRATE) & 0xFF); /* USART: rx/tx enable, 8n1 */ UCSR0B = (1< 0) { if (UCSR0A & (1<