/*************************************************************************** * Copyright (C) 02/2017 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 #define F_CPU 8000000 #include /* * attiny2313 * lfuse: 0xe4 (int rc osc, max startup time) * hfuse: 0xdf (no BOD) * efuse: 0xff (no self programming) * * PA0 -> HC590 /MRC (Counter Reset) * PB0:7 <-> D0:7 * PD0 <- RXD * PD1 -> TXD * PD2 -> HC590 CPC (Counter Clock) * PD3 -> HC590 CPR (Register Clock) * PD4 -> EEPROM /CS * PD5 -> EEPROM /WR * PD6 -> EEPROM /OE */ #define nCNTRES PORTA0 #define RXD PORTD0 #define TXD PORTD1 #define CNTCLK PORTD2 #define REGCLK PORTD3 #define nCHIPSELECT PORTD4 #define nWRITE PORTD5 #define nREAD PORTD6 #define BAUDRATE 115200 #define UART_CALC_BAUDRATE(baudRate) (((uint32_t)F_CPU) / (((uint32_t)baudRate)*16) -1) #define NOP asm volatile ("nop") /* ************************************************************************* */ #define MSGTYPE_VERSION_REQ 0x01 /* no payload */ #define MSGTYPE_PAGESIZE_REQ 0x02 /* no payload */ #define MSGTYPE_CONFIG_REQ 0x03 /* eprom_type(1), pagesize(1), reset_polarity(1) */ #define MSGTYPE_PROGMODE_REQ 0x04 /* progmode(1) */ #define MSGTYPE_SETADDRESS_REQ 0x05 /* address(3) msb first */ #define MSGTYPE_WRITE_REQ 0x06 /* data(0-pagesize) */ #define MSGTYPE_READ_REQ 0x07 /* length(1) */ #define MSGTYPE_ERROR_RSP 0x80 /* error_code(1) */ #define MSGTYPE_VERSION_RSP 0x81 /* version(?) */ #define MSGTYPE_PAGESIZE_RSP 0x82 /* pagesize(1) */ #define MSGTYPE_CONFIG_RSP 0x83 /* no payload */ #define MSGTYPE_PROGMODE_RSP 0x84 /* no payload */ #define MSGTYPE_SETADDRESS_RSP 0x85 /* no payload */ #define MSGTYPE_WRITE_RSP 0x86 /* no payload */ #define MSGTYPE_READ_RSP 0x87 /* data(0-pagesize) */ #define SUCCESS 0x00 #define ERROR_UNKNOWN_COMMAND 0x01 /* unknown message type */ #define ERROR_NOT_SUPPORTED 0x02 /* command not supported */ #define ERROR_INVALID_MODE 0x03 /* invalid progmode */ #define ERROR_INVALID_PARAMETER 0x04 /* invalid parameter in request */ #define ERROR_INVALID_ADDRESS 0x05 /* write outside of configured region */ #define RESET_POLARITY_LOW 0x00 /* low active reset */ #define RESET_POLARITY_HIGH 0x01 /* high active reset */ #define EPROM_TYPE_2K 0x02 /* 2716 */ #define EPROM_TYPE_4K 0x04 /* 2732 */ #define EPROM_TYPE_8K 0x08 /* 2764 */ #define EPROM_TYPE_16K 0x10 /* 27128 */ #define EPROM_TYPE_32K 0x20 /* 27256 */ #define EPROM_TYPE_64K 0x40 /* 27512 */ #define EPROM_TYPE_128K 0x80 /* 27010 */ #define PROGMODE_DISABLED 0x00 /* target running, no write access to RAM */ #define PROGMODE_ENABLED 0x01 /* target reset, write access to RAM */ #define PAGESIZE_MAX 64 /* ************************************************************************* */ struct _globdata { uint32_t address_max; uint32_t address; uint8_t progmode; uint8_t pagesize; }; static const uint8_t version_str[] = "e2prog v1.00"; static struct _globdata gdata = { 0 }; /* ************************************************************************* * send one byte to UART * ************************************************************************* */ static void ser_send(uint8_t data) { loop_until_bit_is_set(UCSRA, UDRIE); UDR = data; } /* ser_send */ /* ************************************************************************* * receive one byte from UART * ************************************************************************* */ static uint8_t ser_recv(void) { loop_until_bit_is_set(UCSRA, RXC); return UDR; } /* ser_recv */ /* ************************************************************************* * * ************************************************************************* */ static void address_clear(void) { /* reset address counter */ PORTA &= ~(1< address) { /* reset address counter */ PORTA &= ~(1< start polling */ if ((gdata.address & (gdata.pagesize -1)) == (gdata.pagesize -1)) { data_poll(buffer[i]); DDRB = 0xFF; } address_inc(); } data_poll(buffer[length -1]); DDRB = 0x00; PORTB = 0x00; } /* data_write */ /* ************************************************************************* * * ************************************************************************* */ int main(void) __attribute__ ((noreturn)); int main(void) { PORTA = (1<>8) & 0xFF; UBRRL = (UART_CALC_BAUDRATE(BAUDRATE) & 0xFF); UCSRC = (1< 0) && (length <= gdata.pagesize) ) { if ((gdata.address >= gdata.address_max) || ((gdata.address + length) > gdata.address_max) ) { error_code = ERROR_INVALID_ADDRESS; } else if (gdata.progmode == PROGMODE_DISABLED) { error_code = ERROR_INVALID_MODE; } else { data_write(length); ser_send(MSGTYPE_WRITE_RSP); ser_send(0x00); error_code = SUCCESS; } } break; case MSGTYPE_READ_REQ: if (length == 0x01) { uint8_t size = ser_recv(); if (size <= PAGESIZE_MAX) { if ((gdata.address >= gdata.address_max) || ((gdata.address + size) > gdata.address_max) ) { error_code = ERROR_INVALID_ADDRESS; } else if (gdata.progmode == PROGMODE_DISABLED) { error_code = ERROR_INVALID_MODE; } else { ser_send(MSGTYPE_READ_RSP); ser_send(size); data_read(size); error_code = SUCCESS; } } } break; default: error_code = ERROR_UNKNOWN_COMMAND; break; } if (error_code != SUCCESS) { /* read remaining request */ while (length--) { (void)ser_recv(); } ser_send(MSGTYPE_ERROR_RSP); ser_send(0x01); ser_send(error_code); } } } /* main */