X-Git-Url: http://git.linex4red.de/pub/USBasp.git/blobdiff_plain/5b20be02e28bb67097fc6701f7596a352b39f902..HEAD:/firmware/main.c diff --git a/firmware/main.c b/firmware/main.c index a01cfe8c6..a5d679fba 100644 --- a/firmware/main.c +++ b/firmware/main.c @@ -1,244 +1,339 @@ /* - USBasp - USB in-circuit programmer for Atmel AVR controllers - - Thomas Fischl - - License: - The project is built with AVR USB driver by Objective Development, which is - published under an own licence based on the GNU General Public License (GPL). - USBasp is also distributed under this enhanced licence. See Documentation. - - Target.........: ATMega8 at 12 MHz - Creation Date..: 2005-02-20 - Last change....: 2005-10-08 - - PC2 SCK speed option. GND -> slow (8khz SCK), - open -> fast (375kHz SCK) -*/ + * USBasp - USB in-circuit programmer for Atmel AVR controllers + * + * Thomas Fischl + * + * License........: GNU GPL v2 (see Readme.txt) + * Target.........: ATMega8 at 12 MHz + * Creation Date..: 2005-02-20 + * Last change....: 2009-02-28 + * + * PC2 SCK speed option. + * GND -> slow (8khz SCK), + * open -> software set speed (default is 375kHz SCK) + */ #include -#include #include #include #include +#include "usbasp.h" #include "usbdrv.h" #include "isp.h" #include "clock.h" - -#define USBASP_FUNC_CONNECT 1 -#define USBASP_FUNC_DISCONNECT 2 -#define USBASP_FUNC_TRANSMIT 3 -#define USBASP_FUNC_READFLASH 4 -#define USBASP_FUNC_ENABLEPROG 5 -#define USBASP_FUNC_WRITEFLASH 6 -#define USBASP_FUNC_READEEPROM 7 -#define USBASP_FUNC_WRITEEEPROM 8 - -#define PROG_STATE_IDLE 0 -#define PROG_STATE_WRITEFLASH 1 -#define PROG_STATE_READFLASH 2 -#define PROG_STATE_READEEPROM 3 -#define PROG_STATE_WRITEEEPROM 4 - -#define PROG_BLOCKFLAG_FIRST 1 -#define PROG_BLOCKFLAG_LAST 2 - -#define ledRedOn() PORTC &= ~(1 << PC1) -#define ledRedOff() PORTC |= (1 << PC1) -#define ledGreenOn() PORTC &= ~(1 << PC0) -#define ledGreenOff() PORTC |= (1 << PC0) +#include "tpi.h" +#include "tpi_defs.h" static uchar replyBuffer[8]; static uchar prog_state = PROG_STATE_IDLE; +static uchar prog_sck = USBASP_ISP_SCK_AUTO; -static unsigned int prog_address; +static uchar prog_address_newmode = 0; +static unsigned long prog_address; static unsigned int prog_nbytes = 0; -static unsigned int prog_pagesize; //TP: Mega128 fix +static unsigned int prog_pagesize; static uchar prog_blockflags; static uchar prog_pagecounter; - uchar usbFunctionSetup(uchar data[8]) { - uchar len = 0; - - if(data[1] == USBASP_FUNC_CONNECT){ - - /* set SCK speed */ - if ((PINC & (1 << PC2)) == 0) { - ispSetSCKOption(ISP_SCK_SLOW); - } else { - ispSetSCKOption(ISP_SCK_FAST); - } - - ispConnect(); - ledRedOn(); - - } else if (data[1] == USBASP_FUNC_DISCONNECT) { - ispDisconnect(); - ledRedOff(); - - } else if (data[1] == USBASP_FUNC_TRANSMIT) { - replyBuffer[0] = ispTransmit(data[2]); - replyBuffer[1] = ispTransmit(data[3]); - replyBuffer[2] = ispTransmit(data[4]); - replyBuffer[3] = ispTransmit(data[5]); - len = 4; - - } else if (data[1] == USBASP_FUNC_READFLASH) { - prog_address = (data[3] << 8) | data[2]; - prog_nbytes = (data[7] << 8) | data[6]; - prog_state = PROG_STATE_READFLASH; - len = 0xff; /* multiple in */ - - } else if (data[1] == USBASP_FUNC_READEEPROM) { - prog_address = (data[3] << 8) | data[2]; - prog_nbytes = (data[7] << 8) | data[6]; - prog_state = PROG_STATE_READEEPROM; - len = 0xff; /* multiple in */ - - } else if (data[1] == USBASP_FUNC_ENABLEPROG) { - replyBuffer[0] = ispEnterProgrammingMode();; - len = 1; - - } else if (data[1] == USBASP_FUNC_WRITEFLASH) { - prog_address = (data[3] << 8) | data[2]; - prog_pagesize = data[4]; - prog_blockflags = data[5] & 0x0F; - prog_pagesize += (((unsigned int)data[5] & 0xF0)<<4); //TP: Mega128 fix - if (prog_blockflags & PROG_BLOCKFLAG_FIRST) { - prog_pagecounter = prog_pagesize; - } - prog_nbytes = (data[7] << 8) | data[6]; - prog_state = PROG_STATE_WRITEFLASH; - len = 0xff; /* multiple out */ - - } else if (data[1] == USBASP_FUNC_WRITEEEPROM) { - prog_address = (data[3] << 8) | data[2]; - prog_pagesize = 0; - prog_blockflags = 0; - prog_nbytes = (data[7] << 8) | data[6]; - prog_state = PROG_STATE_WRITEEEPROM; - len = 0xff; /* multiple out */ - } - - usbMsgPtr = replyBuffer; - - return len; -} + uchar len = 0; + if (data[1] == USBASP_FUNC_CONNECT) { -uchar usbFunctionRead(uchar *data, uchar len) { + /* set SCK speed */ + if ((PINC & (1 << PC2)) == 0) { + ispSetSCKOption(USBASP_ISP_SCK_8); + } else { + ispSetSCKOption(prog_sck); + } - uchar i; - - /* check if programmer is in correct read state */ - if ((prog_state != PROG_STATE_READFLASH) && - (prog_state != PROG_STATE_READEEPROM)) { - return 0xff; - } - - /* fill packet */ - for (i = 0; i < len; i++) { - if (prog_state == PROG_STATE_READFLASH) { - data[i] = ispReadFlash(prog_address); - } else { - data[i] = ispReadEEPROM(prog_address); - } - prog_address++; - } - - /* last packet? */ - if (len < 8) { - prog_state = PROG_STATE_IDLE; - } - - return len; -} + /* set compatibility mode of address delivering */ + prog_address_newmode = 0; + ledRedOn(); + ispConnect(); -uchar usbFunctionWrite(uchar *data, uchar len) { + } else if (data[1] == USBASP_FUNC_DISCONNECT) { + ispDisconnect(); + ledRedOff(); + + } else if (data[1] == USBASP_FUNC_TRANSMIT) { + replyBuffer[0] = ispTransmit(data[2]); + replyBuffer[1] = ispTransmit(data[3]); + replyBuffer[2] = ispTransmit(data[4]); + replyBuffer[3] = ispTransmit(data[5]); + len = 4; + + } else if (data[1] == USBASP_FUNC_READFLASH) { + + if (!prog_address_newmode) + prog_address = (data[3] << 8) | data[2]; + + prog_nbytes = (data[7] << 8) | data[6]; + prog_state = PROG_STATE_READFLASH; + len = 0xff; /* multiple in */ + + } else if (data[1] == USBASP_FUNC_READEEPROM) { + + if (!prog_address_newmode) + prog_address = (data[3] << 8) | data[2]; + + prog_nbytes = (data[7] << 8) | data[6]; + prog_state = PROG_STATE_READEEPROM; + len = 0xff; /* multiple in */ + + } else if (data[1] == USBASP_FUNC_ENABLEPROG) { + replyBuffer[0] = ispEnterProgrammingMode(); + len = 1; + + } else if (data[1] == USBASP_FUNC_WRITEFLASH) { + + if (!prog_address_newmode) + prog_address = (data[3] << 8) | data[2]; + + prog_pagesize = data[4]; + prog_blockflags = data[5] & 0x0F; + prog_pagesize += (((unsigned int) data[5] & 0xF0) << 4); + if (prog_blockflags & PROG_BLOCKFLAG_FIRST) { + prog_pagecounter = prog_pagesize; + } + prog_nbytes = (data[7] << 8) | data[6]; + prog_state = PROG_STATE_WRITEFLASH; + len = 0xff; /* multiple out */ + + } else if (data[1] == USBASP_FUNC_WRITEEEPROM) { + + if (!prog_address_newmode) + prog_address = (data[3] << 8) | data[2]; + + prog_pagesize = 0; + prog_blockflags = 0; + prog_nbytes = (data[7] << 8) | data[6]; + prog_state = PROG_STATE_WRITEEEPROM; + len = 0xff; /* multiple out */ + + } else if (data[1] == USBASP_FUNC_SETLONGADDRESS) { + + /* set new mode of address delivering (ignore address delivered in commands) */ + prog_address_newmode = 1; + /* set new address */ + prog_address = *((unsigned long*) &data[2]); + + } else if (data[1] == USBASP_FUNC_SETISPSCK) { + + /* set sck option */ + prog_sck = data[2]; + replyBuffer[0] = 0; + len = 1; + + } else if (data[1] == USBASP_FUNC_TPI_CONNECT) { + tpi_dly_cnt = data[2] | (data[3] << 8); + + /* RST high */ + ISP_OUT |= (1 << ISP_RST); + ISP_DDR |= (1 << ISP_RST); + + clockWait(3); + + /* RST low */ + ISP_OUT &= ~(1 << ISP_RST); + ledRedOn(); - uchar i; + clockWait(16); + tpi_init(); - /* check if programmer is in correct write state */ - if ((prog_state != PROG_STATE_WRITEFLASH) && - (prog_state != PROG_STATE_WRITEEEPROM)) { - return 0xff; - } + } else if (data[1] == USBASP_FUNC_TPI_DISCONNECT) { + tpi_send_byte(TPI_OP_SSTCS(TPISR)); + tpi_send_byte(0); - for (i = 0; i < len; i++) { + clockWait(10); - if (prog_state == PROG_STATE_WRITEFLASH) { - /* Flash */ + /* pulse RST */ + ISP_OUT |= (1 << ISP_RST); + clockWait(5); + ISP_OUT &= ~(1 << ISP_RST); + clockWait(5); - if (prog_pagesize == 0) { - /* not paged */ - ispWriteFlash(prog_address, data[i], 1); - } else { - /* paged */ - ispWriteFlash(prog_address, data[i], 0); - prog_pagecounter --; - if (prog_pagecounter == 0) { - ispFlushPage(prog_address, data[i]); - prog_pagecounter = prog_pagesize; + /* set all ISP pins inputs */ + ISP_DDR &= ~((1 << ISP_RST) | (1 << ISP_SCK) | (1 << ISP_MOSI)); + /* switch pullups off */ + ISP_OUT &= ~((1 << ISP_RST) | (1 << ISP_SCK) | (1 << ISP_MOSI)); + + ledRedOff(); + + } else if (data[1] == USBASP_FUNC_TPI_RAWREAD) { + replyBuffer[0] = tpi_recv_byte(); + len = 1; + + } else if (data[1] == USBASP_FUNC_TPI_RAWWRITE) { + tpi_send_byte(data[2]); + + } else if (data[1] == USBASP_FUNC_TPI_READBLOCK) { + prog_address = (data[3] << 8) | data[2]; + prog_nbytes = (data[7] << 8) | data[6]; + prog_state = PROG_STATE_TPI_READ; + len = 0xff; /* multiple in */ + + } else if (data[1] == USBASP_FUNC_TPI_WRITEBLOCK) { + prog_address = (data[3] << 8) | data[2]; + prog_nbytes = (data[7] << 8) | data[6]; + prog_state = PROG_STATE_TPI_WRITE; + len = 0xff; /* multiple out */ + + } else if (data[1] == USBASP_FUNC_GETCAPABILITIES) { + replyBuffer[0] = USBASP_CAP_0_TPI; + replyBuffer[1] = 0; + replyBuffer[2] = 0; + replyBuffer[3] = 0; + len = 4; } - } - } else { - /* EEPROM */ - ispWriteEEPROM(prog_address, data[i]); - } + usbMsgPtr = replyBuffer; + + return len; +} + +uchar usbFunctionRead(uchar *data, uchar len) { + + uchar i; - prog_nbytes --; + /* check if programmer is in correct read state */ + if ((prog_state != PROG_STATE_READFLASH) && (prog_state + != PROG_STATE_READEEPROM) && (prog_state != PROG_STATE_TPI_READ)) { + return 0xff; + } - if (prog_nbytes == 0) { - prog_state = PROG_STATE_IDLE; - if ((prog_blockflags & PROG_BLOCKFLAG_LAST) && - (prog_pagecounter != prog_pagesize)) { + /* fill packet TPI mode */ + if(prog_state == PROG_STATE_TPI_READ) + { + tpi_read_block(prog_address, data, len); + prog_address += len; + return len; + } - /* last block and page flush pending, so flush it now */ - ispFlushPage(prog_address, data[i]); - } - } + /* fill packet ISP mode */ + for (i = 0; i < len; i++) { + if (prog_state == PROG_STATE_READFLASH) { + data[i] = ispReadFlash(prog_address); + } else { + data[i] = ispReadEEPROM(prog_address); + } + prog_address++; + } - prog_address ++; - } + /* last packet? */ + if (len < 8) { + prog_state = PROG_STATE_IDLE; + } - return 0; + return len; } +uchar usbFunctionWrite(uchar *data, uchar len) { + + uchar retVal = 0; + uchar i; + + /* check if programmer is in correct write state */ + if ((prog_state != PROG_STATE_WRITEFLASH) && (prog_state + != PROG_STATE_WRITEEEPROM) && (prog_state != PROG_STATE_TPI_WRITE)) { + return 0xff; + } + + if (prog_state == PROG_STATE_TPI_WRITE) + { + tpi_write_block(prog_address, data, len); + prog_address += len; + prog_nbytes -= len; + if(prog_nbytes <= 0) + { + prog_state = PROG_STATE_IDLE; + return 1; + } + return 0; + } + + for (i = 0; i < len; i++) { + + if (prog_state == PROG_STATE_WRITEFLASH) { + /* Flash */ + + if (prog_pagesize == 0) { + /* not paged */ + ispWriteFlash(prog_address, data[i], 1); + } else { + /* paged */ + ispWriteFlash(prog_address, data[i], 0); + prog_pagecounter--; + if (prog_pagecounter == 0) { + ispFlushPage(prog_address, data[i]); + prog_pagecounter = prog_pagesize; + } + } -int main(void) -{ - uchar i, j; + } else { + /* EEPROM */ + ispWriteEEPROM(prog_address, data[i]); + } - PORTD = 0; - PORTB = 0; /* no pullups on USB and ISP pins */ - DDRD = ~(1 << 2); /* all outputs except PD2 = INT0 */ + prog_nbytes--; - DDRB = ~0; /* output SE0 for USB reset */ - j = 0; - while(--j){ /* USB Reset by device only required on Watchdog Reset */ - i = 0; - while(--i); /* delay >10ms for USB reset */ - } - DDRB = 0; /* all USB and ISP pins inputs */ + if (prog_nbytes == 0) { + prog_state = PROG_STATE_IDLE; + if ((prog_blockflags & PROG_BLOCKFLAG_LAST) && (prog_pagecounter + != prog_pagesize)) { - DDRC = 0x03; /* all inputs except PC0, PC1 */ - PORTC = 0xfe; + /* last block and page flush pending, so flush it now */ + ispFlushPage(prog_address, data[i]); + } - clockInit(); /* init timer */ + retVal = 1; // Need to return 1 when no more data is to be received + } - ispSetSCKOption(ISP_SCK_FAST); + prog_address++; + } + + return retVal; +} + +int main(void) { + uchar i, j; + + /* no pullups on USB and ISP pins */ + PORTD = 0; + PORTB = 0; + /* all outputs except PD2 = INT0 */ + DDRD = ~(1 << 2); + + /* output SE0 for USB reset */ + DDRB = ~0; + j = 0; + /* USB Reset by device only required on Watchdog Reset */ + while (--j) { + i = 0; + /* delay >10ms for USB reset */ + while (--i) + ; + } + /* all USB and ISP pins inputs */ + DDRB = 0; + + /* all inputs except PC0, PC1 */ + DDRC = 0x03; + PORTC = 0xfe; - usbInit(); - sei(); - for(;;){ /* main event loop */ - usbPoll(); - } - return 0; + /* init timer */ + clockInit(); + + /* main event loop */ + usbInit(); + sei(); + for (;;) { + usbPoll(); + } + return 0; }