X-Git-Url: http://git.linex4red.de/pub/USBasp.git/blobdiff_plain/39f1c0c136520a3f4746ad6381d1242979125ff3..4e5c8347645dbff6db701f227087e717e946b6fa:/firmware/isp.c diff --git a/firmware/isp.c b/firmware/isp.c index 6305aacab..fa6c7bef6 100644 --- a/firmware/isp.c +++ b/firmware/isp.c @@ -6,7 +6,7 @@ * over ISP interface * Licence........: GNU GPL v2 (see Readme.txt) * Creation Date..: 2005-02-23 - * Last change....: 2009-02-28 + * Last change....: 2010-01-19 */ #include @@ -17,8 +17,10 @@ #define spiHWdisable() SPCR = 0 uchar sck_sw_delay; +uchar sck_sw_delay_loops; uchar sck_spcr; uchar sck_spsr; +uchar isp_hiaddr; void spiHWenable() { SPCR = sck_spcr; @@ -30,66 +32,102 @@ void ispSetSCKOption(uchar option) { if (option == USBASP_ISP_SCK_AUTO) option = USBASP_ISP_SCK_375; - if (option >= USBASP_ISP_SCK_93_75) { + if (((F_CPU <= 12000000) && (option >= USBASP_ISP_SCK_93_75)) + || ((F_CPU > 12000000) && (option >= USBASP_ISP_SCK_187_5))) { ispTransmit = ispTransmit_hw; sck_spsr = 0; + sck_sw_delay = 1; /* force RST#/SCK pulse for 320us */ + sck_sw_delay_loops = 1; 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); +# if (F_CPU <= 12000000) + /* enable SPI, master, 1.5MHz, XTAL/8 */ + sck_spcr = (1 << SPE) | (1 << MSTR) | (1 << SPR0); + sck_spsr = (1 << SPI2X); +# else + /* enable SPI, master, ~1.1MHz, XTAL/16 */ + sck_spcr = (1 << SPE) | (1 << MSTR) | (1 << SPR0); +# endif + break; case USBASP_ISP_SCK_750: - /* enable SPI, master, 750kHz, XTAL/16 */ - sck_spcr = (1 << SPE) | (1 << MSTR) | (1 << SPR0); +# if (F_CPU <= 12000000) + /* enable SPI, master, 750kHz, XTAL/16 */ + sck_spcr = (1 << SPE) | (1 << MSTR) | (1 << SPR0); +# else + /* enable SPI, master, ~531kHz, XTAL/32 */ + sck_spcr = (1 << SPE) | (1 << MSTR) | (1 << SPR1); + sck_spsr = (1 << SPI2X); +# endif 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); +# if (F_CPU <= 12000000) + /* enable SPI, master, 375kHz, XTAL/32 (default) */ + sck_spcr = (1 << SPE) | (1 << MSTR) | (1 << SPR1); + sck_spsr = (1 << SPI2X); +# else + /* enable SPI, master, ~265.6kHz XTAL/64 (default) */ + sck_spcr = (1 << SPE) | (1 << MSTR) | (1 << SPR1); +# endif 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); +# if (F_CPU <= 12000000) + /* enable SPI, master, 187.5kHz XTAL/64 */ + sck_spcr = (1 << SPE) | (1 << MSTR) | (1 << SPR1); +# else + /* enable SPI, master, ~132.81kHz XTAL/128 */ + sck_spcr = (1 << SPE) | (1 << MSTR) | (1 << SPR1) | (1 << SPR0); +# endif break; +# if (F_CPU <= 12000000) + case USBASP_ISP_SCK_93_75: + /* enable SPI, master, 93.75kHz XTAL/128 */ + sck_spcr = (1 << SPE) | (1 << MSTR) | (1 << SPR1) | (1 << SPR0); + break; +# endif } } else { ispTransmit = ispTransmit_sw; + sck_sw_delay_loops = 1; + switch (option) { +# if (F_CPU > 12000000) + case USBASP_ISP_SCK_93_75: + sck_sw_delay = 2; + + break; +# endif case USBASP_ISP_SCK_32: - sck_sw_delay = 3; + sck_sw_delay = ((3 * (F_CPU/1000000L) + 11) / 12); break; case USBASP_ISP_SCK_16: - sck_sw_delay = 6; + sck_sw_delay = ((6 * (F_CPU/1000000L) + 11) / 12); break; case USBASP_ISP_SCK_8: - sck_sw_delay = 12; + sck_sw_delay = ((12 * (F_CPU/1000000L) + 11) / 12); break; case USBASP_ISP_SCK_4: - sck_sw_delay = 24; + sck_sw_delay = ((24 * (F_CPU/1000000L) + 11) / 12); break; case USBASP_ISP_SCK_2: - sck_sw_delay = 48; + sck_sw_delay = ((48 * (F_CPU/1000000L) + 11) / 12); break; case USBASP_ISP_SCK_1: - sck_sw_delay = 96; + sck_sw_delay = ((96 * (F_CPU/1000000L) + 11) / 12); break; case USBASP_ISP_SCK_0_5: - sck_sw_delay = 192; + sck_sw_delay = ((96 * (F_CPU/1000000L) + 11) / 12); + sck_sw_delay_loops = 2; break; } @@ -99,7 +137,11 @@ void ispSetSCKOption(uchar option) { void ispDelay() { uint8_t starttime = TIMERVALUE; - while ((uint8_t) (TIMERVALUE - starttime) < sck_sw_delay) { + uint8_t loops = sck_sw_delay_loops; + + while (loops--) { + while ((uint8_t) (TIMERVALUE - starttime) < sck_sw_delay) { + } } } @@ -122,6 +164,9 @@ void ispConnect() { if (ispTransmit == ispTransmit_hw) { spiHWenable(); } + + /* Initial extended address value */ + isp_hiaddr = 0; } void ispDisconnect() { @@ -190,10 +235,11 @@ uchar ispEnterProgrammingMode() { spiHWdisable(); - /* pulse SCK */ - ISP_OUT |= (1 << ISP_SCK); /* SCK high */ + /* pulse RST */ ispDelay(); - ISP_OUT &= ~(1 << ISP_SCK); /* SCK low */ + ISP_OUT |= (1 << ISP_RST); /* RST high */ + ispDelay(); + ISP_OUT &= ~(1 << ISP_RST); /* RST low */ ispDelay(); if (ispTransmit == ispTransmit_hw) { @@ -205,7 +251,28 @@ uchar ispEnterProgrammingMode() { return 1; /* error: device dosn't answer */ } +static void ispUpdateExtended(unsigned long address) +{ + uchar curr_hiaddr; + + curr_hiaddr = (address >> 17); + + /* check if extended address byte is changed */ + if(isp_hiaddr != curr_hiaddr) + { + isp_hiaddr = curr_hiaddr; + /* Load Extended Address byte */ + ispTransmit(0x4D); + ispTransmit(0x00); + ispTransmit(isp_hiaddr); + ispTransmit(0x00); + } +} + uchar ispReadFlash(unsigned long address) { + + ispUpdateExtended(address); + ispTransmit(0x20 | ((address & 1) << 3)); ispTransmit(address >> 9); ispTransmit(address >> 1); @@ -220,6 +287,8 @@ uchar ispWriteFlash(unsigned long address, uchar data, uchar pollmode) { } */ + ispUpdateExtended(address); + ispTransmit(0x40 | ((address & 1) << 3)); ispTransmit(address >> 9); ispTransmit(address >> 1); @@ -253,6 +322,9 @@ uchar ispWriteFlash(unsigned long address, uchar data, uchar pollmode) { } uchar ispFlushPage(unsigned long address, uchar pollvalue) { + + ispUpdateExtended(address); + ispTransmit(0x4C); ispTransmit(address >> 9); ispTransmit(address >> 1);