X-Git-Url: http://git.linex4red.de/pub/USBaspLoader.git/blobdiff_plain/a48ee25be3896a771f113d1ed1d4680bdbb899d2..a3d7386c66be4c2479a15ebfa60eb733c0005dbc:/firmware/main.c?ds=inline diff --git a/firmware/main.c b/firmware/main.c index 9c8bab3..98703f9 100644 --- a/firmware/main.c +++ b/firmware/main.c @@ -112,8 +112,25 @@ typedef union longConverter{ }longConverter_t; -#if BOOTLOADER_CAN_EXIT -static volatile unsigned char stayinloader = 0xfe; +#if (BOOTLOADER_CAN_EXIT) +# if (BOOTLOADER_LOOPCYCLES_TIMEOUT) +# if (BOOTLOADER_LOOPCYCLES_TIMEOUT < 256) +# if ((HAVE_UNPRECISEWAIT)) +volatile register uint8_t timeout_remaining __asm__("r2"); +# else +static volatile uint8_t timeout_remaining; +# endif +# else +static volatile uint16_t timeout_remaining; +# endif +# endif +# if ((HAVE_UNPRECISEWAIT)) +/* here we have to assume we need to optimize for every byte */ +#define __REGISTER_stayinloader_initialValue 0xfe +volatile register uint8_t stayinloader __asm__("r17"); +# else +static volatile uint8_t stayinloader = 0xfe; +# endif #endif static longConverter_t currentAddress; /* in bytes */ @@ -128,6 +145,8 @@ 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__) @@ -194,6 +213,56 @@ static const uchar signatureBytes[4] = { /* ------------------------------------------------------------------------ */ +#if (__REGISTER_stayinloader_initialValue) +/* need to put it after libc init - otherwise it fucks up the register */ +void __attribute__ ((section(".init8"),naked,used,no_instrument_function)) __REGISTER_stayinloader_initialValue_INITIALIZATION(void); +void __REGISTER_stayinloader_initialValue_INITIALIZATION(void) { + asm volatile ( + "ldi %[silreg] , %[silval]\n\t" + : [silreg] "=a" (stayinloader) + : [silval] "M" (__REGISTER_stayinloader_initialValue) + ); +} +#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. @@ -204,8 +273,10 @@ 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" @@ -291,7 +362,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_ATmega16__) || 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 */ @@ -363,6 +436,23 @@ defined (__AVR_ATmega2561__) # endif } #endif +#if ((HAVE_BOOTLOADER_HIDDENEXITCOMMAND) && (BOOTLOADER_CAN_EXIT)) +# if ((HAVE_BOOTLOADER_HIDDENEXITCOMMAND != 0xac) && \ + (HAVE_BOOTLOADER_HIDDENEXITCOMMAND != 0x20) && (HAVE_BOOTLOADER_HIDDENEXITCOMMAND != 0x28) && \ + (HAVE_BOOTLOADER_HIDDENEXITCOMMAND != 0x40) && (HAVE_BOOTLOADER_HIDDENEXITCOMMAND != 0x48) && \ + (HAVE_BOOTLOADER_HIDDENEXITCOMMAND != 0x4c) && \ + (HAVE_BOOTLOADER_HIDDENEXITCOMMAND != 0xa0) && \ + (HAVE_BOOTLOADER_HIDDENEXITCOMMAND != 0xc0) && \ + (HAVE_BOOTLOADER_HIDDENEXITCOMMAND != 0x58) && \ + (HAVE_BOOTLOADER_HIDDENEXITCOMMAND != 0x5c) && \ + (HAVE_BOOTLOADER_HIDDENEXITCOMMAND != 0x30) && \ + (HAVE_BOOTLOADER_HIDDENEXITCOMMAND != 0xac) && \ + (HAVE_BOOTLOADER_HIDDENEXITCOMMAND != 0x50) && (HAVE_BOOTLOADER_HIDDENEXITCOMMAND != 0x58) && \ + (HAVE_BOOTLOADER_HIDDENEXITCOMMAND != 0x38)) + }else if(rq->wValue.bytes[0] == (HAVE_BOOTLOADER_HIDDENEXITCOMMAND)){ /* cause a bootLoaderExit at disconnect */ + stayinloader = 0xf1; /* we need to be connected - so assume it */ +# endif +#endif }else{ /* ignore all others, return default value == 0 */ } @@ -403,7 +493,12 @@ static uchar replyBuffer[4]; }else if(rq->bRequest == USBASP_FUNC_DISCONNECT){ #if BOOTLOADER_CAN_EXIT +# if (BOOTLOADER_LOOPCYCLES_TIMEOUT) + timeout_remaining = BOOTLOADER_LOOPCYCLES_TIMEOUT; + stayinloader = (0xfe); +# else stayinloader &= (0xfe); +# endif #endif }else{ /* ignore: others, but could be USBASP_FUNC_CONNECT */ @@ -642,6 +737,10 @@ static void initForUsbConnectivity(void) int __attribute__((__noreturn__)) main(void) { +#if ((BOOTLOADER_LOOPCYCLES_TIMEOUT) && (BOOTLOADER_CAN_EXIT)) + uint16_t __loopscycles; + timeout_remaining = BOOTLOADER_LOOPCYCLES_TIMEOUT; +#endif /* initialize */ bootLoaderInit(); odDebugInit(); @@ -663,8 +762,16 @@ int __attribute__((__noreturn__)) main(void) # endif wdt_disable(); /* main app may have enabled watchdog */ #endif + MCUCSR = 0; /* clear all reset flags for next time */ initForUsbConnectivity(); do{ +#if ((BOOTLOADER_LOOPCYCLES_TIMEOUT) && (BOOTLOADER_CAN_EXIT)) + __loopscycles++; + if (!(__loopscycles)) { + if(timeout_remaining) timeout_remaining--; + else stayinloader&=0xf1; + } +#endif usbPoll(); #if BOOTLOADER_CAN_EXIT #if USE_EXCESSIVE_ASSEMBLER @@ -688,11 +795,11 @@ asm volatile ( ); #else if (stayinloader >= 0x10) { - if (!bootLoaderCondition()) { + if (!bootLoaderConditionSimple()) { stayinloader-=0x10; } } else { - if (bootLoaderCondition()) { + if (bootLoaderConditionSimple()) { if (stayinloader > 1) stayinloader-=2; } }