diff options
| author | cpldcpu <cpldcpu@gmail.com> | 2013-12-31 15:42:09 +0100 | 
|---|---|---|
| committer | cpldcpu <cpldcpu@gmail.com> | 2013-12-31 15:42:09 +0100 | 
| commit | 6d2ac9e09f61d6ff267961ba9ff79b0a07e78e28 (patch) | |
| tree | 6bd157b28f0a22c799a723a700343f15872d9c64 /firmware | |
| parent | 8f6ccdaccf624a3e2c727ff4e6ad2c7dc479b51b (diff) | |
| download | micronucleus-6d2ac9e09f61d6ff267961ba9ff79b0a07e78e28.tar.gz micronucleus-6d2ac9e09f61d6ff267961ba9ff79b0a07e78e28.tar.bz2 micronucleus-6d2ac9e09f61d6ff267961ba9ff79b0a07e78e28.zip | |
firmware: more global registers and unions types
Saves 70(!) bytes or so..
Diffstat (limited to 'firmware')
| -rw-r--r-- | firmware/bootloaderconfig.h | 10 | ||||
| -rw-r--r-- | firmware/main.c | 78 | ||||
| -rw-r--r-- | 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 @@ -13,6 +13,16 @@  #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  according to the hardware. 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 | 
