From: Stephan Baerwolf Date: Mon, 19 Nov 2012 11:14:02 +0000 (+0100) Subject: MANIAC: optimize whole code via new feature "USE_EXCESSIVE_ASSEMBLER" X-Git-Tag: v0.95~6 X-Git-Url: http://git.linex4red.de/pub/USBaspLoader.git/commitdiff_plain/10e1fed1cd81721e60f400025355daf2d8f17410?ds=inline MANIAC: optimize whole code via new feature "USE_EXCESSIVE_ASSEMBLER" Signed-off-by: Stephan Baerwolf --- diff --git a/Makefile.inc b/Makefile.inc index b3dbb40..c5bd13e 100644 --- a/Makefile.inc +++ b/Makefile.inc @@ -32,7 +32,7 @@ LOCKOPT = -U lock:w:0x3f:m # you may also want to UNprogram SUT1 to get a SLOWER bootup (lfuse then would be 0x3f) FUSEOPT_8 = -U lfuse:w:0x1f:m -U hfuse:w:0xc0:m BOOTLOADER_ADDRESS_8 = 0x1800 -DEFINES_8 = -DCONFIG_NO__BOOTLOADER_CAN_EXIT -DCONFIG_NO__PRECISESLEEP +DEFINES_8 = -DCONFIG_USE__EXCESSIVE_ASSEMBLER -DCONFIG_NO__NEED_WATCHDOG -DCONFIG_NO__PRECISESLEEP #untested (WARNING: may destroy ISP ability!) diff --git a/firmware/bootloaderconfig.h b/firmware/bootloaderconfig.h index 005d9bb..af67d6e 100644 --- a/firmware/bootloaderconfig.h +++ b/firmware/bootloaderconfig.h @@ -275,6 +275,19 @@ these macros are defined, the boot loader usees them. * instead the right content of the flash memory. */ +#ifdef CONFIG_USE__EXCESSIVE_ASSEMBLER +# define USE_EXCESSIVE_ASSEMBLER 1 +#else +# define USE_EXCESSIVE_ASSEMBLER 0 +#endif +/* This macro enables large codeareas of hand-optimized assembler code. + * WARNING: + * It will only work properly on devices with <64k of flash memory and SRAM. + * Some configuration macros (when changed) may not be applied correctly + * (since their behaviour is raced within asm)! + * Nevertheless this feature saves lots of memory. + */ + //#define SIGNATURE_BYTES 0x1e, 0x93, 0x07, 0 /* ATMega8 */ /* This macro defines the signature bytes returned by the emulated USBasp to * the programmer software. They should match the actual device at least in @@ -299,6 +312,10 @@ these macros are defined, the boot loader usees them. # define MCUCSR MCUSR #endif +/* WARNING: + * following commands and macros may not be evaluated properly when 'USE_EXCESSIVE_ASSEMBLER" + */ + static inline void bootLoaderInit(void) { PIN_DDR(JUMPER_PORT) = 0; diff --git a/firmware/main.c b/firmware/main.c index 9358b5e..56368ff 100644 --- a/firmware/main.c +++ b/firmware/main.c @@ -42,8 +42,6 @@ -static void leaveBootloader() __attribute__((__noreturn__)); - #include "bootloaderconfig.h" #include "usbdrv/usbdrv.c" @@ -180,10 +178,37 @@ static const uchar signatureBytes[4] = { /* ------------------------------------------------------------------------ */ +#if !USE_EXCESSIVE_ASSEMBLER static void (*nullVector)(void) __attribute__((__noreturn__)); +#endif -static void leaveBootloader() +static void __attribute__((__noreturn__)) leaveBootloader() { +#if USE_EXCESSIVE_ASSEMBLER +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" + "ldi r31, %[ivce]\n\t" + "out %[mygicr], r31\n\t" + "out %[mygicr], r30\n\t" + "clr r31\n\t" + "icall\n\t" + : + : [port] "I" (_SFR_IO_ADDR(PIN_PORT(JUMPER_PORT))), + [bit] "I" (PIN(JUMPER_PORT, JUMPER_BIT)), + [usbintrenab] "I" (_SFR_IO_ADDR(USB_INTR_ENABLE)), + [usbintrcfg] "I" (_SFR_IO_ADDR(USB_INTR_CFG)), + [usbddr] "I" (_SFR_IO_ADDR(USBDDR)), + [usbminus] "I" (USBMINUS), + [mygicr] "I" (_SFR_IO_ADDR(GICR)), + [ivce] "I" (1<>0)&0xff) == 0) +uchar usbFunctionWrite(uchar *data, uchar len) +{ +uchar isLast; + + DBG1(0x31, (void *)¤tAddress.l, 4); + if(len > bytesRemaining) + len = bytesRemaining; + bytesRemaining -= len; + isLast = bytesRemaining == 0; + if(currentRequest >= USBASP_FUNC_READEEPROM){ + uchar i; + for(i = 0; i < len; i++){ + eeprom_write_byte((void *)(currentAddress.w[0]++), *data++); + } + }else{ + asm volatile ( + "sbrc %[len], 0\n\t" + "inc %[len]\n\t" +"usbFunctionWrite_flashloop:\n\t" + "subi %[len], 2\n\t" + "brlo usbFunctionWrite_finished\n\t" + +#if HAVE_BLB11_SOFTW_LOCKBIT + "cpi r31, %[blsaddrhi]\n\t" /* accelerated BLB11_SOFTW_LOCKBIT check */ + "brsh usbFunctionWrite_finished\n\t" +// "brlo usbFunctionWrite_addrunlock_ok\n\t" +// "brne usbFunctionWrite_finished\n\t" +// "cpi r30, %[blsaddrlo]\n\t" +// "brlo usbFunctionWrite_addrunlock_ok\n\t" +// "rjmp usbFunctionWrite_finished\n\t" +// "usbFunctionWrite_addrunlock_ok:\n\t" +#endif + "rcall usbFunctionWrite_waitA\n\t" + "cli\n\t" /* r0 or r1 may be __zero_reg__ and may become dangerous nonzero within interrupts */ + "ld r0, X+\n\t" + "ld r1, X+\n\t" + + "ldi r18, %[pagfillval]\n\t" + "rcall usbFunctionWrite_saveflash\n\t" /* page fill */ + + "mov r18, r30\n\t" + "subi r18, 0xfe\n\t" /* add with 2 */ + "andi r18, %[pagemask]\n\t" + "breq usbFunctionWrite_pageisfull\n\t" + "tst %[islast]\n\t" + "breq usbFunctionWrite_skippageisfull\n\t" + "tst %[isLastPage]\n\t" + "breq usbFunctionWrite_skippageisfull\n\t" + "cpi %[len], 0\n\t" + "brne usbFunctionWrite_skippageisfull\n\t" + +"usbFunctionWrite_pageisfull:\n\t" /* start writing the page */ + "ldi r18, %[pageraseval]\n\t" + "rcall usbFunctionWrite_saveflash\n\t" /* page erase */ + "rcall usbFunctionWrite_waitA\n\t" + + "ldi r18, %[pagwriteval]\n\t" + "rcall usbFunctionWrite_saveflash\n\t" /* page write */ + "rcall usbFunctionWrite_waitA\n\t" + + "in __tmp_reg__, %[spmcr]\n\t" + "sbrs __tmp_reg__, %[rwwsbbit]\n\t" + "rjmp usbFunctionWrite_skippageisfull\n\t" + "ldi r18, %[rwwenrval]\n\t" + "rcall usbFunctionWrite_saveflash\n\t" /* reenable rww*/ +// "rcall usbFunctionWrite_waitA\n\t" + + +"usbFunctionWrite_skippageisfull:\n\t" + "adiw r30, 0x2\n\t" + "rjmp usbFunctionWrite_flashloop\n\t" + +"usbFunctionWrite_saveflash:\n\t" + "cli\n\t" + "out %[spmcr], r18\n\t" + "spm\n\t" + "clr __zero_reg__\n\t" /* if r0 or r1 is __zero_reg__ it may have become inconsisten while page-fill */ + "sei\n\t" + "ret\n\t" + +"usbFunctionWrite_waitA:\n\t" + "in __tmp_reg__, %[spmcr]\n\t" + "sbrc __tmp_reg__, %[spmenbit]\n\t" + "rjmp usbFunctionWrite_waitA\n\t" + "ret\n\t" + +"usbFunctionWrite_finished:\n\t" + : [addr] "+z" (currentAddress.l) + + : [spmenbit] "I" (SPMEN), + [rwwsbbit] "I" (RWWSB), + [spmcr] "I" (_SFR_IO_ADDR(__SPM_REG)), + [pagfillval] "M" ((1<>8)&0xff)), +// [blsaddrlo] "M" ((uint8_t)((BOOTLOADER_PAGEADDR>>0)&0xff)), +#endif + [islast] "r" (isLast), + [isLastPage] "r" (isLastPage), + [len] "d" (len), + [dataptr] "x" (data) + + : "r0", "r1", "r18" + ); + } + return isLast; +} +#else uchar usbFunctionWrite(uchar *data, uchar len) { uchar i,isLast; @@ -385,6 +524,7 @@ uchar i,isLast; } return isLast; } +#endif uchar usbFunctionRead(uchar *data, uchar len) { @@ -444,7 +584,7 @@ static void initForUsbConnectivity(void) sei(); } -int __attribute__((noreturn)) main(void) +int __attribute__((__noreturn__)) main(void) { /* initialize */ bootLoaderInit(); @@ -462,6 +602,26 @@ int __attribute__((noreturn)) main(void) do{ usbPoll(); #if BOOTLOADER_CAN_EXIT +#if USE_EXCESSIVE_ASSEMBLER +asm volatile ( + "cpi %[sil], 0x10\n\t" + "brlo main_stayinloader_smaller\n\t" + "sbic %[pin], %[bit]\n\t" + "subi %[sil], 0x10\n\t" + "rjmp main_stayinloader_finished\n\t" + + "main_stayinloader_smaller:\n\t" + "cpi %[sil], 0x2\n\t" + "brlo main_stayinloader_finished\n\t" + "sbis %[pin], %[bit]\n\t" + "subi %[sil], 0x2\n\t" + + "main_stayinloader_finished:\n\t" + : [sil] "+d" (stayinloader) + : [pin] "I" (_SFR_IO_ADDR(PIN_PIN(JUMPER_PORT))), + [bit] "I" (PIN(JUMPER_PORT, JUMPER_BIT)) +); +#else if (stayinloader >= 0x10) { if (!bootLoaderCondition()) { stayinloader-=0x10; @@ -472,6 +632,7 @@ int __attribute__((noreturn)) main(void) } } #endif +#endif #if BOOTLOADER_CAN_EXIT }while (stayinloader); /* main event loop, if BOOTLOADER_CAN_EXIT*/