From 6d2ac9e09f61d6ff267961ba9ff79b0a07e78e28 Mon Sep 17 00:00:00 2001 From: cpldcpu Date: Tue, 31 Dec 2013 15:42:09 +0100 Subject: firmware: more global registers and unions types Saves 70(!) bytes or so.. --- firmware/bootloaderconfig.h | 10 ++++++ firmware/main.c | 78 ++++++++++++++++++++++----------------------- firmware/usbconfig.h | 11 +++++-- 3 files changed, 56 insertions(+), 43 deletions(-) diff --git a/firmware/bootloaderconfig.h b/firmware/bootloaderconfig.h index 9c06de3..a93e6ff 100644 --- a/firmware/bootloaderconfig.h +++ b/firmware/bootloaderconfig.h @@ -12,6 +12,16 @@ #ifndef __bootloaderconfig_h_included__ #define __bootloaderconfig_h_included__ +/* + * Bootloader defines + */ + +#ifndef __ASSEMBLER__ + typedef union { + uint16_t w; + uint8_t b[2]; + } uint16_union_t; +#endif /* General Description: This file (together with some settings in Makefile) configures the boot loader diff --git a/firmware/main.c b/firmware/main.c index efef481..3ad1a14 100644 --- a/firmware/main.c +++ b/firmware/main.c @@ -29,11 +29,23 @@ // verify the bootloader address aligns with page size #if BOOTLOADER_ADDRESS % SPM_PAGESIZE != 0 -# error "BOOTLOADER_ADDRESS in makefile must be a multiple of chip's pagesize" + #error "BOOTLOADER_ADDRESS in makefile must be a multiple of chip's pagesize" +#endif + +#if SPM_PAGESIZE>256 + #error "Micronucleus only supports pagesizes up to 256 bytes" #endif // command system schedules functions to run in the main loop -register uint8_t command asm( "r3" ); // register saves many bytes +register uint8_t command asm("r3"); // bind command to r3 +register uint16_union_t currentAddress asm("r4"); // r4/r5 current progmem address, used for erasing and writing +register uint16_union_t idlePolls asm("r6"); // r6/r7 idlecounter + +#if OSCCAL_RESTORE + register uint8_t osccal_default asm("r2"); +#endif + +static uint16_t vectorTemp[2]; // remember data to create tinyVector table before BOOTLOADER_ADDRESS enum { cmd_local_nop=0, // also: get device info @@ -49,15 +61,6 @@ enum { #define cli() asm volatile("cli") #define nop() asm volatile("nop") -uint16_t idlePolls = 0; // how long have we been idle? - -static uint16_t vectorTemp[2]; // remember data to create tinyVector table before BOOTLOADER_ADDRESS -static uint16_t currentAddress; // current progmem address, used for erasing and writing - -#if OSCCAL_RESTORE - static uint8_t osccal_default; // due to compiler insanity, having this as global actually saves memory -#endif - /* ------------------------------------------------------------------------ */ static inline void eraseApplication(void); static void writeFlashPage(void); @@ -85,7 +88,7 @@ static inline void eraseApplication(void) { boot_page_erase(ptr); } - currentAddress = 0; + currentAddress.w = 0; for (i=0; i<8; i++) writeWordToPageBuffer(0xFFFF); // Write first 8 words to fill in vectors. writeFlashPage(); // enables interrupts } @@ -93,7 +96,7 @@ static inline void eraseApplication(void) { // simply write currently stored page in to already erased flash memory static void writeFlashPage(void) { cli(); - boot_page_write(currentAddress - 2); // will halt CPU, no waiting required + boot_page_write(currentAddress.w - 2); // will halt CPU, no waiting required sei(); } @@ -116,12 +119,12 @@ static void writeWordToPageBuffer(uint16_t data) { // first two interrupt vectors get replaced with a jump to the bootloader's vector table // remember vectors or the tinyvector table - if (currentAddress == RESET_VECTOR_OFFSET * 2) { + if (currentAddress.w == RESET_VECTOR_OFFSET * 2) { vectorTemp[0] = data; data = 0xC000 + (BOOTLOADER_ADDRESS/2) - 1; } - if (currentAddress == USBPLUS_VECTOR_OFFSET * 2) { + if (currentAddress.w == USBPLUS_VECTOR_OFFSET * 2) { vectorTemp[1] = data; data = 0xC000 + (BOOTLOADER_ADDRESS/2) - 1; } @@ -129,12 +132,12 @@ static void writeWordToPageBuffer(uint16_t data) { // at end of page just before bootloader, write in tinyVector table // see http://embedded-creations.com/projects/attiny85-usb-bootloader-overview/avr-jtag-programmer/ // for info on how the tiny vector table works - if (currentAddress == BOOTLOADER_ADDRESS - TINYVECTOR_RESET_OFFSET) { + if (currentAddress.w == BOOTLOADER_ADDRESS - TINYVECTOR_RESET_OFFSET) { data = vectorTemp[0] + ((FLASHEND + 1) - BOOTLOADER_ADDRESS)/2 + 2 + RESET_VECTOR_OFFSET; - } else if (currentAddress == BOOTLOADER_ADDRESS - TINYVECTOR_USBPLUS_OFFSET) { + } else if (currentAddress.w == BOOTLOADER_ADDRESS - TINYVECTOR_USBPLUS_OFFSET) { data = vectorTemp[1] + ((FLASHEND + 1) - BOOTLOADER_ADDRESS)/2 + 1 + USBPLUS_VECTOR_OFFSET; #if (!OSCCAL_RESTORE) && OSCCAL_16_5MHz - } else if (currentAddress == BOOTLOADER_ADDRESS - TINYVECTOR_OSCCAL_OFFSET) { + } else if (currentAddress.w == BOOTLOADER_ADDRESS - TINYVECTOR_OSCCAL_OFFSET) { data = OSCCAL; #endif } @@ -142,10 +145,10 @@ static void writeWordToPageBuffer(uint16_t data) { previous_sreg=SREG; cli(); // ensure interrupts are disabled - boot_page_fill(currentAddress, data); + boot_page_fill(currentAddress.w, data); // increment progmem address by one word - currentAddress += 2; + currentAddress.w += 2; SREG=previous_sreg; } @@ -160,8 +163,8 @@ static uint8_t usbFunctionSetup(uint8_t data[8]) { MICRONUCLEUS_WRITE_SLEEP }; - ((uint8_t*)&idlePolls)[1] = 0; // reset idle polls when we get usb traffic - + idlePolls.b[1]=0; // reset idle polls when we get usb traffic + if (rq->bRequest == cmd_device_info) { // get device info usbMsgPtr = replyBuffer; return 4; @@ -169,7 +172,7 @@ static uint8_t usbFunctionSetup(uint8_t data[8]) { // clear page buffer as a precaution before filling the buffer in case // a previous write operation failed and there is still something in the buffer. __boot_page_fill_clear(); - currentAddress = rq->wIndex.word; + currentAddress.w = rq->wIndex.word; return USB_NO_MSG; // hands off work to usbFunctionWrite } else { // Handle cmd_erase_application and cmd_exit @@ -182,7 +185,7 @@ static uint8_t usbFunctionSetup(uint8_t data[8]) { static uint8_t usbFunctionWrite(uint8_t *data, uint8_t length) { do { // make sure we don't write over the bootloader! - if (currentAddress >= BOOTLOADER_ADDRESS) break; + if (currentAddress.w >= BOOTLOADER_ADDRESS) break; writeWordToPageBuffer(*(uint16_t *) data); data += 2; // advance data pointer @@ -190,17 +193,10 @@ static uint8_t usbFunctionWrite(uint8_t *data, uint8_t length) { } while(length); // if we have now reached another page boundary, we're done -#if SPM_PAGESIZE<256 - // Hack to reduce code size - uint8_t isLast = ((((uint8_t)currentAddress) % SPM_PAGESIZE) == 0); -#else - uint8_t isLast = ((currentAddress % SPM_PAGESIZE) == 0); -#endif - - // definitely need this if! seems usbFunctionWrite gets called again in future usbPoll's in the runloop! + uint8_t isLast = ((currentAddress.b[0] % SPM_PAGESIZE) == 0); if (isLast) command=cmd_write_page; // ask runloop to write our page - return isLast; // let vusb know we're done with this request + return isLast; // let V-USB know we're done with this request } /* ------------------------------------------------------------------------ */ @@ -271,14 +267,16 @@ int main(void) { bootLoaderInit(); - #if AUTO_EXIT_NO_USB_MS - ((uint8_t*)&idlePolls)[1]=((AUTO_EXIT_MS-AUTO_EXIT_NO_USB_MS) * 10UL)>>8; // write only high byte to save 6 bytes - #endif - if (bootLoaderStartCondition()||(pgm_read_byte(BOOTLOADER_ADDRESS - TINYVECTOR_RESET_OFFSET + 1)==0xff)) { initHardware(); LED_INIT(); + + if (AUTO_EXIT_NO_USB_MS>0) { + idlePolls.b[1]=((AUTO_EXIT_MS-AUTO_EXIT_NO_USB_MS) * 10UL)>>8; + } else { + idlePolls.b[1]=0; + } do { _delay_us(100); @@ -287,12 +285,12 @@ int main(void) { command=cmd_local_nop; usbPoll(); - idlePolls++; + idlePolls.w++; // Try to execute program if bootloader exit condition is met - if (AUTO_EXIT_MS&&(idlePolls==AUTO_EXIT_MS*10L)) command=cmd_exit; + if (AUTO_EXIT_MS&&(idlePolls.w==AUTO_EXIT_MS*10L)) command=cmd_exit; - LED_MACRO( ((uint8_t*)&idlePolls)[1] ); + LED_MACRO( idlePolls.b[1] ); // Wait for USB traffic to finish before a blocking event is executed // All events will render the MCU unresponsive to USB traffic for a while. diff --git a/firmware/usbconfig.h b/firmware/usbconfig.h index 8ccee36..dc5cafc 100644 --- a/firmware/usbconfig.h +++ b/firmware/usbconfig.h @@ -169,10 +169,15 @@ return;\ #ifndef __ASSEMBLER__ void calibrateOscillatorASM(void); - extern uint16_t idlePolls; -# define USB_RESET_HOOK(resetStarts) if(!resetStarts){ ((uint8_t*)&idlePolls)[1]= 0;calibrateOscillatorASM();} + + #if AUTO_EXIT_NO_USB_MS>0 + extern uint16_union_t idlePolls; + #define USB_RESET_HOOK(resetStarts) if(!resetStarts){ idlePolls.b[1]=0; calibrateOscillatorASM();} + #else + #define USB_RESET_HOOK(resetStarts) if(!resetStarts){ calibrateOscillatorASM();} + #endif -# define USB_CFG_HAVE_MEASURE_FRAME_LENGTH 0 + #define USB_CFG_HAVE_MEASURE_FRAME_LENGTH 0 #endif -- cgit v1.2.3