X-Git-Url: http://git.linex4red.de/pub/USBasp.git/blobdiff_plain/6ffa080eb257892c7cad9f80f8bfef99b4896082..39f1c0c136520a3f4746ad6381d1242979125ff3:/firmware/isp.c diff --git a/firmware/isp.c b/firmware/isp.c index 5153c8eb4..6305aacab 100644 --- a/firmware/isp.c +++ b/firmware/isp.c @@ -1,274 +1,304 @@ /* - isp.c - part of USBasp - - Autor..........: Thomas Fischl - Description....: Provides functions for communication/programming - over ISP interface - Licence........: GNU GPL v2 (see Readme.txt) - Creation Date..: 2005-02-23 - Last change....: 2007-07-23 -*/ + * isp.c - part of USBasp + * + * Autor..........: Thomas Fischl + * Description....: Provides functions for communication/programming + * over ISP interface + * Licence........: GNU GPL v2 (see Readme.txt) + * Creation Date..: 2005-02-23 + * Last change....: 2009-02-28 + */ #include #include "isp.h" #include "clock.h" +#include "usbasp.h" #define spiHWdisable() SPCR = 0 -void spiHWenable() { +uchar sck_sw_delay; +uchar sck_spcr; +uchar sck_spsr; - /* enable SPI, master, 375kHz SCK */ - SPCR = (1 << SPE) | (1 << MSTR) | (1 << SPR1); - SPSR = (1 << SPI2X); +void spiHWenable() { + SPCR = sck_spcr; + SPSR = sck_spsr; } void ispSetSCKOption(uchar option) { - if (option == 0) { - - /* use software spi */ - ispTransmit = ispTransmit_sw; - // spiHWdisable(); - - } else { - - /* use hardware spi */ - ispTransmit = ispTransmit_hw; - - } + if (option == USBASP_ISP_SCK_AUTO) + option = USBASP_ISP_SCK_375; + + if (option >= USBASP_ISP_SCK_93_75) { + ispTransmit = ispTransmit_hw; + sck_spsr = 0; + + switch (option) { + + case USBASP_ISP_SCK_1500: + /* enable SPI, master, 1.5MHz, XTAL/8 */ + sck_spcr = (1 << SPE) | (1 << MSTR) | (1 << SPR0); + sck_spsr = (1 << SPI2X); + case USBASP_ISP_SCK_750: + /* enable SPI, master, 750kHz, XTAL/16 */ + sck_spcr = (1 << SPE) | (1 << MSTR) | (1 << SPR0); + break; + case USBASP_ISP_SCK_375: + default: + /* enable SPI, master, 375kHz, XTAL/32 (default) */ + sck_spcr = (1 << SPE) | (1 << MSTR) | (1 << SPR1); + sck_spsr = (1 << SPI2X); + break; + case USBASP_ISP_SCK_187_5: + /* enable SPI, master, 187.5kHz XTAL/64 */ + sck_spcr = (1 << SPE) | (1 << MSTR) | (1 << SPR1); + break; + case USBASP_ISP_SCK_93_75: + /* enable SPI, master, 93.75kHz XTAL/128 */ + sck_spcr = (1 << SPE) | (1 << MSTR) | (1 << SPR1) | (1 << SPR0); + break; + } + + } else { + ispTransmit = ispTransmit_sw; + switch (option) { + + case USBASP_ISP_SCK_32: + sck_sw_delay = 3; + + break; + case USBASP_ISP_SCK_16: + sck_sw_delay = 6; + + break; + case USBASP_ISP_SCK_8: + sck_sw_delay = 12; + + break; + case USBASP_ISP_SCK_4: + sck_sw_delay = 24; + + break; + case USBASP_ISP_SCK_2: + sck_sw_delay = 48; + + break; + case USBASP_ISP_SCK_1: + sck_sw_delay = 96; + + break; + case USBASP_ISP_SCK_0_5: + sck_sw_delay = 192; + + break; + } + } } void ispDelay() { - uint8_t starttime = TIMERVALUE; - while ((uint8_t) (TIMERVALUE - starttime) < 12) { } + uint8_t starttime = TIMERVALUE; + while ((uint8_t) (TIMERVALUE - starttime) < sck_sw_delay) { + } } void ispConnect() { - /* all ISP pins are inputs before */ - /* now set output pins */ - ISP_DDR |= (1 << ISP_RST) | (1 << ISP_SCK) | (1 << ISP_MOSI); + /* all ISP pins are inputs before */ + /* now set output pins */ + ISP_DDR |= (1 << ISP_RST) | (1 << ISP_SCK) | (1 << ISP_MOSI); - /* reset device */ - ISP_OUT &= ~(1 << ISP_RST); /* RST low */ - ISP_OUT &= ~(1 << ISP_SCK); /* SCK low */ + /* reset device */ + ISP_OUT &= ~(1 << ISP_RST); /* RST low */ + ISP_OUT &= ~(1 << ISP_SCK); /* SCK low */ - /* positive reset pulse > 2 SCK (target) */ - ispDelay(); - ISP_OUT |= (1 << ISP_RST); /* RST high */ - ispDelay(); - ISP_OUT &= ~(1 << ISP_RST); /* RST low */ + /* positive reset pulse > 2 SCK (target) */ + ispDelay(); + ISP_OUT |= (1 << ISP_RST); /* RST high */ + ispDelay(); + ISP_OUT &= ~(1 << ISP_RST); /* RST low */ - if (ispTransmit == ispTransmit_hw) { - spiHWenable(); - } + if (ispTransmit == ispTransmit_hw) { + spiHWenable(); + } } void ispDisconnect() { - /* 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)); + /* 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)); - /* disable hardware SPI */ - spiHWdisable(); + /* disable hardware SPI */ + spiHWdisable(); } uchar ispTransmit_sw(uchar send_byte) { - uchar rec_byte = 0; - uchar i; - for (i = 0; i < 8; i++) { - - /* set MSB to MOSI-pin */ - if ((send_byte & 0x80) != 0) { - ISP_OUT |= (1 << ISP_MOSI); /* MOSI high */ - } else { - ISP_OUT &= ~(1 << ISP_MOSI); /* MOSI low */ - } - /* shift to next bit */ - send_byte = send_byte << 1; - - /* receive data */ - rec_byte = rec_byte << 1; - if ((ISP_IN & (1 << ISP_MISO)) != 0) { - rec_byte++; - } - - /* pulse SCK */ - ISP_OUT |= (1 << ISP_SCK); /* SCK high */ - ispDelay(); - ISP_OUT &= ~(1 << ISP_SCK); /* SCK low */ - ispDelay(); - } - - return rec_byte; + uchar rec_byte = 0; + uchar i; + for (i = 0; i < 8; i++) { + + /* set MSB to MOSI-pin */ + if ((send_byte & 0x80) != 0) { + ISP_OUT |= (1 << ISP_MOSI); /* MOSI high */ + } else { + ISP_OUT &= ~(1 << ISP_MOSI); /* MOSI low */ + } + /* shift to next bit */ + send_byte = send_byte << 1; + + /* receive data */ + rec_byte = rec_byte << 1; + if ((ISP_IN & (1 << ISP_MISO)) != 0) { + rec_byte++; + } + + /* pulse SCK */ + ISP_OUT |= (1 << ISP_SCK); /* SCK high */ + ispDelay(); + ISP_OUT &= ~(1 << ISP_SCK); /* SCK low */ + ispDelay(); + } + + return rec_byte; } uchar ispTransmit_hw(uchar send_byte) { - SPDR = send_byte; + SPDR = send_byte; - while (!(SPSR & (1 << SPIF))); - return SPDR; + while (!(SPSR & (1 << SPIF))) + ; + return SPDR; } uchar ispEnterProgrammingMode() { - uchar check; - uchar count = 32; + uchar check; + uchar count = 32; - while (count--) { - ispTransmit(0xAC); - ispTransmit(0x53); - check = ispTransmit(0); - ispTransmit(0); + while (count--) { + ispTransmit(0xAC); + ispTransmit(0x53); + check = ispTransmit(0); + ispTransmit(0); - if (check == 0x53) { - return 0; - } + if (check == 0x53) { + return 0; + } - spiHWdisable(); + spiHWdisable(); - /* pulse SCK */ - ISP_OUT |= (1 << ISP_SCK); /* SCK high */ - ispDelay(); - ISP_OUT &= ~(1 << ISP_SCK); /* SCK low */ - ispDelay(); + /* pulse SCK */ + ISP_OUT |= (1 << ISP_SCK); /* SCK high */ + ispDelay(); + ISP_OUT &= ~(1 << ISP_SCK); /* SCK low */ + ispDelay(); - if (ispTransmit == ispTransmit_hw) { - spiHWenable(); - } + if (ispTransmit == ispTransmit_hw) { + spiHWenable(); + } - } + } - return 1; /* error: device dosn't answer */ + return 1; /* error: device dosn't answer */ } uchar ispReadFlash(unsigned long address) { - ispTransmit(0x20 | ((address & 1) << 3)); - ispTransmit(address >> 9); - ispTransmit(address >> 1); - return ispTransmit(0); + ispTransmit(0x20 | ((address & 1) << 3)); + ispTransmit(address >> 9); + ispTransmit(address >> 1); + return ispTransmit(0); } - uchar ispWriteFlash(unsigned long address, uchar data, uchar pollmode) { - /* 0xFF is value after chip erase, so skip programming - if (data == 0xFF) { - return 0; - } - */ - - ispTransmit(0x40 | ((address & 1) << 3)); - ispTransmit(address >> 9); - ispTransmit(address >> 1); - ispTransmit(data); - - if (pollmode == 0) - return 0; - - if (data == 0x7F) { - clockWait(15); /* wait 4,8 ms */ - return 0; - } else { - - /* polling flash */ - uchar retries = 30; - uint8_t starttime = TIMERVALUE; - while (retries != 0) { - if (ispReadFlash(address) != 0x7F) { - return 0; - }; - - if ((uint8_t) (TIMERVALUE - starttime) > CLOCK_T_320us) { - starttime = TIMERVALUE; - retries --; - } - - } - return 1; /* error */ - } + /* 0xFF is value after chip erase, so skip programming + if (data == 0xFF) { + return 0; + } + */ + + ispTransmit(0x40 | ((address & 1) << 3)); + ispTransmit(address >> 9); + ispTransmit(address >> 1); + ispTransmit(data); + + if (pollmode == 0) + return 0; + + if (data == 0x7F) { + clockWait(15); /* wait 4,8 ms */ + return 0; + } else { + + /* polling flash */ + uchar retries = 30; + uint8_t starttime = TIMERVALUE; + while (retries != 0) { + if (ispReadFlash(address) != 0x7F) { + return 0; + }; + + if ((uint8_t) (TIMERVALUE - starttime) > CLOCK_T_320us) { + starttime = TIMERVALUE; + retries--; + } + + } + return 1; /* error */ + } } - uchar ispFlushPage(unsigned long address, uchar pollvalue) { - ispTransmit(0x4C); - ispTransmit(address >> 9); - ispTransmit(address >> 1); - ispTransmit(0); - + ispTransmit(0x4C); + ispTransmit(address >> 9); + ispTransmit(address >> 1); + ispTransmit(0); - if (pollvalue == 0xFF) { - clockWait(15); - return 0; - } else { + if (pollvalue == 0xFF) { + clockWait(15); + return 0; + } else { - /* polling flash */ - uchar retries = 30; - uint8_t starttime = TIMERVALUE; + /* polling flash */ + uchar retries = 30; + uint8_t starttime = TIMERVALUE; - while (retries != 0) { - if (ispReadFlash(address) != 0xFF) { - return 0; - }; + while (retries != 0) { + if (ispReadFlash(address) != 0xFF) { + return 0; + }; - if ((uint8_t) (TIMERVALUE - starttime) > CLOCK_T_320us) { - starttime = TIMERVALUE; - retries --; - } + if ((uint8_t) (TIMERVALUE - starttime) > CLOCK_T_320us) { + starttime = TIMERVALUE; + retries--; + } - } + } - return 1; /* error */ - } + return 1; /* error */ + } } - uchar ispReadEEPROM(unsigned int address) { - ispTransmit(0xA0); - ispTransmit(address >> 8); - ispTransmit(address); - return ispTransmit(0); + ispTransmit(0xA0); + ispTransmit(address >> 8); + ispTransmit(address); + return ispTransmit(0); } - uchar ispWriteEEPROM(unsigned int address, uchar data) { - ispTransmit(0xC0); - ispTransmit(address >> 8); - ispTransmit(address); - ispTransmit(data); + ispTransmit(0xC0); + ispTransmit(address >> 8); + ispTransmit(address); + ispTransmit(data); - clockWait(30); // wait 9,6 ms + clockWait(30); // wait 9,6 ms - return 0; - /* - if (data == 0xFF) { - clockWait(30); // wait 9,6 ms - return 0; - } else { - - // polling eeprom - uchar retries = 30; // about 9,6 ms - uint8_t starttime = TIMERVALUE; - - while (retries != 0) { - if (ispReadEEPROM(address) != 0xFF) { return 0; - }; - - if ((uint8_t) (TIMERVALUE - starttime) > CLOCK_T_320us) { - starttime = TIMERVALUE; - retries --; - } - - } - return 1; // error - } - */ - }