X-Git-Url: http://git.linex4red.de/pub/USBaspLoader.git/blobdiff_plain/4cadc9e7c294d43091e79c60e9fe9ad80f87f3bb..4c35c3b6d7988c8f7ff5d33c4df608cfd7b85442:/firmware/main.c diff --git a/firmware/main.c b/firmware/main.c index 91127ef..fe7d049 100644 --- a/firmware/main.c +++ b/firmware/main.c @@ -3,11 +3,10 @@ * Author: Christian Starkjohann * Author: Stephan Baerwolf * Creation Date: 2007-12-08 - * Modification Date: 2012-11-10 + * Modification Date: 2013-03-31 * Tabsize: 4 * Copyright: (c) 2007 by OBJECTIVE DEVELOPMENT Software GmbH * License: GNU GPL v2 (see License.txt) - * This Revision: $Id: main.c 786 2010-05-30 20:41:40Z cs $ */ #include "spminterface.h" /* must be included as first! */ @@ -129,8 +128,12 @@ static const uchar currentRequest = 0; static const uchar signatureBytes[4] = { #ifdef SIGNATURE_BYTES SIGNATURE_BYTES +#elif defined (__AVR_ATmega8535__) + 0x1e, 0x93, 0x08, 0 #elif defined (__AVR_ATmega8__) || defined (__AVR_ATmega8A__) || defined (__AVR_ATmega8HVA__) 0x1e, 0x93, 0x07, 0 +#elif defined (__AVR_ATmega16__) + 0x1e, 0x94, 0x03, 0 #elif defined (__AVR_ATmega32__) 0x1e, 0x95, 0x02, 0 #elif defined (__AVR_ATmega48__) || defined (__AVR_ATmega48A__) || defined (__AVR_ATmega48P__) @@ -161,35 +164,90 @@ static const uchar signatureBytes[4] = { 0x1e, 0x95, 0x14, 0 #elif defined (__AVR_ATmega328P__) 0x1e, 0x95, 0x0f, 0 +#elif defined (__AVR_ATmega640__) + 0x1e, 0x96, 0x08, 0 #elif defined (__AVR_ATmega644__) || defined (__AVR_ATmega644A__) 0x1e, 0x96, 0x09, 0 #elif defined (__AVR_ATmega644P__) || defined (__AVR_ATmega644PA__) 0x1e, 0x96, 0x0a, 0 #elif defined (__AVR_ATmega128__) 0x1e, 0x97, 0x02, 0 +#elif defined (__AVR_ATmega1280__) + 0x1e, 0x97, 0x03, 0 +#elif defined (__AVR_ATmega1281__) + 0x1e, 0x97, 0x04, 0 #elif defined (__AVR_ATmega1284__) 0x1e, 0x97, 0x06, 0 #elif defined (__AVR_ATmega1284P__) 0x1e, 0x97, 0x05, 0 +#elif defined (__AVR_ATmega2560__) + 0x1e, 0x98, 0x01, 0 +#elif defined (__AVR_ATmega2561__) + 0x1e, 0x98, 0x02, 0 #else -# error "Device signature is not known, please edit main.c!" +# if (defined(SIGNATURE_0) && defined(SIGNATURE_1) && defined(SIGNATURE_2)) +# warning "Device signature is not known - using AVR Libc suggestion..." + SIGNATURE_0, SIGNATURE_1, SIGNATURE_2, 0 +# else +# error "Device signature is not known, please edit main.c!" +# endif #endif }; /* ------------------------------------------------------------------------ */ +#if (HAVE_BOOTLOADERENTRY_FROMSOFTWARE) +void __attribute__ ((section(".init3"),naked,used,no_instrument_function)) __BOOTLOADERENTRY_FROMSOFTWARE__bootup_investigate_RAMEND(void); +void __BOOTLOADERENTRY_FROMSOFTWARE__bootup_investigate_RAMEND(void) { + asm volatile ( + "in %[mcucsrval] , %[mcucsrio]\n\t" + "ldi r29 , %[ramendhi]\n\t" + "ldi r28 , %[ramendlo]\n\t" +#if (FLASHEND>131071) + "ld %[result] , Y+\n\t" + "cpi %[result] , %[bootaddrhi]\n\t" + "brne __BOOTLOADERENTRY_FROMSOFTWARE__bootup_investigate_RAMEND_mismatch%=\n\t" +#endif + "ld %[result] , Y+\n\t" + "cpi %[result] , %[bootaddrme]\n\t" + "ld %[result] , Y+\n\t" + "breq __BOOTLOADERENTRY_FROMSOFTWARE__bootup_investigate_RAMEND_done%=\n\t" + + "__BOOTLOADERENTRY_FROMSOFTWARE__bootup_investigate_RAMEND_mismatch%=:\n\t" + "ldi %[result] , 0xff\n\t" + + "__BOOTLOADERENTRY_FROMSOFTWARE__bootup_investigate_RAMEND_done%=:\n\t" + : [result] "=a" (__BOOTLOADERENTRY_FROMSOFTWARE__bootup_RAMEND_doesmatch), + [mcucsrval] "=a" (__BOOTLOADERENTRY_FROMSOFTWARE__bootup_MCUCSR) + : [mcucsrio] "I" (_SFR_IO_ADDR(MCUCSR)), +#if (FLASHEND>131071) + [ramendhi] "M" (((RAMEND - 2) >> 8) & 0xff), + [ramendlo] "M" (((RAMEND - 2) >> 0) & 0xff), + [bootaddrhi] "M" (((__BOOTLOADERENTRY_FROMSOFTWARE__EXPECTEDADDRESS) >>16) & 0xff), +#else + [ramendhi] "M" (((RAMEND - 1) >> 8) & 0xff), + [ramendlo] "M" (((RAMEND - 1) >> 0) & 0xff), +#endif + [bootaddrme] "M" (((__BOOTLOADERENTRY_FROMSOFTWARE__EXPECTEDADDRESS) >> 8) & 0xff) + + ); +} +#endif + #if (USE_BOOTUP_CLEARRAM) /* * Under normal circumstances, RESET will not clear contents of RAM. * As always, if you want it done - do it yourself... */ -void __attribute__ ((naked)) __attribute__ ((section (".init3"))) __clearram(void); -void __clearram(void) { +void __attribute__ ((section(".init3"),naked,used,no_instrument_function)) __func_clearram(void); +void __func_clearram(void) { extern size_t __bss_end; asm volatile ( "__clearram:\n\t" +#if (!(HAVE_BOOTLOADERENTRY_FROMSOFTWARE)) "ldi r29, %[ramendhi]\n\t" "ldi r28, %[ramendlo]\n\t" +#endif "__clearramloop%=:\n\t" "st -Y , __zero_reg__\n\t" "cp r28, %A[bssend]\n\t" @@ -208,21 +266,19 @@ void __clearram(void) { static void (*nullVector)(void) __attribute__((__noreturn__)); #endif -static void __attribute__((__noreturn__)) leaveBootloader() -{ #if (USE_EXCESSIVE_ASSEMBLER) && (defined (__AVR_ATmega8__) || defined (__AVR_ATmega8A__) || defined (__AVR_ATmega8HVA__)) -asm volatile ( +static void __attribute__((naked,__noreturn__)) leaveBootloader(void); +static void leaveBootloader(void) { + asm volatile ( "cli\n\t" - "clr r30\n\t" "sbi %[usbddr], %[usbminus]\n\t" "cbi %[port], %[bit]\n\t" - "out %[usbintrenab], r30\n\t" - "out %[usbintrcfg], r30\n\t" + "out %[usbintrenab], __zero_reg__\n\t" + "out %[usbintrcfg], __zero_reg__\n\t" "ldi r31, %[ivce]\n\t" "out %[mygicr], r31\n\t" - "out %[mygicr], r30\n\t" - "clr r31\n\t" - "icall\n\t" + "out %[mygicr], __zero_reg__\n\t" + "rjmp nullVector\n\t" : : [port] "I" (_SFR_IO_ADDR(PIN_PORT(JUMPER_PORT))), [bit] "I" (PIN(JUMPER_PORT, JUMPER_BIT)), @@ -233,8 +289,10 @@ asm volatile ( [mygicr] "I" (_SFR_IO_ADDR(GICR)), [ivce] "I" (1<131071)) + EIND=0; +#endif /* We must go through a global function pointer variable instead of writing * ((void (*)(void))0)(); * because the compiler optimizes a constant 0 to "rcall 0" which is not * handled correctly by the assembler. */ nullVector(); -#endif } +#endif /* ------------------------------------------------------------------------ */ @@ -266,7 +333,9 @@ uchar usbFunctionSetup_USBASP_FUNC_TRANSMIT(usbRequest_t *rq) { rval = rq->wIndex.bytes[0] & 3; rval = signatureBytes[rval]; #if HAVE_READ_LOCK_FUSE -#if defined (__AVR_ATmega8__) || defined (__AVR_ATmega8A__) || defined (__AVR_ATmega32__) +#if defined (__AVR_ATmega8535__) || \ + defined (__AVR_ATmega8__) || defined (__AVR_ATmega8A__) || \ + defined (__AVR_ATmega16__) || defined (__AVR_ATmega32__) }else if(rq->wValue.bytes[0] == 0x58 && rq->wValue.bytes[1] == 0x00){ /* read lock bits */ rval = boot_lock_fuse_bits_get(GET_LOCK_BITS); }else if(rq->wValue.bytes[0] == 0x50 && rq->wValue.bytes[1] == 0x00){ /* read lfuse bits */ @@ -280,9 +349,14 @@ defined (__AVR_ATmega164A__) || defined (__AVR_ATmega164P__) || \ defined (__AVR_ATmega168__) || defined (__AVR_ATmega168A__) || defined (__AVR_ATmega168P__) || defined (__AVR_ATmega168PA__) || \ defined (__AVR_ATmega324A__) || defined (__AVR_ATmega324P__) || \ defined (__AVR_ATmega328__) || defined (__AVR_ATmega328P__) || \ +defined (__AVR_ATmega640__) || \ defined (__AVR_ATmega644__) || defined (__AVR_ATmega644A__) || defined (__AVR_ATmega644P__) || defined (__AVR_ATmega644PA__) || \ defined (__AVR_ATmega128__) || \ -defined (__AVR_ATmega1284__) || defined (__AVR_ATmega1284P__) +defined (__AVR_ATmega1280__) || \ +defined (__AVR_ATmega1281__) || \ +defined (__AVR_ATmega1284__) || defined (__AVR_ATmega1284P__) || \ +defined (__AVR_ATmega2560__) || \ +defined (__AVR_ATmega2561__) }else if(rq->wValue.bytes[0] == 0x58 && rq->wValue.bytes[1] == 0x00){ /* read lock bits */ rval = boot_lock_fuse_bits_get(GET_LOCK_BITS); }else if(rq->wValue.bytes[0] == 0x50 && rq->wValue.bytes[1] == 0x00){ /* read lfuse bits */ @@ -341,19 +415,19 @@ defined (__AVR_ATmega1284__) || defined (__AVR_ATmega1284P__) } -uchar usbFunctionSetup(uchar data[8]) +usbMsgLen_t usbFunctionSetup(uchar data[8]) { usbRequest_t *rq = (void *)data; -uchar len = 0; +usbMsgLen_t len = 0; static uchar replyBuffer[4]; - usbMsgPtr = replyBuffer; + usbMsgPtr = (usbMsgPtr_t)replyBuffer; if(rq->bRequest == USBASP_FUNC_TRANSMIT){ /* emulate parts of ISP protocol */ replyBuffer[3] = usbFunctionSetup_USBASP_FUNC_TRANSMIT(rq); - len = 4; + len = (usbMsgLen_t)4; }else if((rq->bRequest == USBASP_FUNC_ENABLEPROG) || (rq->bRequest == USBASP_FUNC_SETISPSCK)){ /* replyBuffer[0] = 0; is never touched and thus always 0 which means success */ - len = 1; + len = (usbMsgLen_t)1; }else if(rq->bRequest >= USBASP_FUNC_READFLASH && rq->bRequest <= USBASP_FUNC_SETLONGADDRESS){ currentAddress.w[0] = rq->wValue.word; if(rq->bRequest == USBASP_FUNC_SETLONGADDRESS){ @@ -367,7 +441,7 @@ static uchar replyBuffer[4]; #if HAVE_EEPROM_PAGED_ACCESS currentRequest = rq->bRequest; #endif - len = 0xff; /* hand over to usbFunctionRead() / usbFunctionWrite() */ + len = USB_NO_MSG; /* hand over to usbFunctionRead() / usbFunctionWrite() */ } }else if(rq->bRequest == USBASP_FUNC_DISCONNECT){ @@ -622,8 +696,18 @@ int __attribute__((__noreturn__)) main(void) #endif if(bootLoaderCondition()){ #if NEED_WATCHDOG +# if (defined(MCUSR) && defined(WDRF)) + /* + * Fix issue 6: (special thanks to coldtobi) + * + * The WDRF bit in the MCUSR needs to be cleared first, + * otherwise it is not possible to disable the watchdog + */ + MCUSR &= ~(_BV(WDRF)); +# endif wdt_disable(); /* main app may have enabled watchdog */ #endif + MCUCSR = 0; /* clear all reset flags for next time */ initForUsbConnectivity(); do{ usbPoll(); @@ -649,11 +733,11 @@ asm volatile ( ); #else if (stayinloader >= 0x10) { - if (!bootLoaderCondition()) { + if (!bootLoaderConditionSimple()) { stayinloader-=0x10; } } else { - if (bootLoaderCondition()) { + if (bootLoaderConditionSimple()) { if (stayinloader > 1) stayinloader-=2; } }