diff options
| -rw-r--r-- | .gitignore | 3 | ||||
| -rw-r--r-- | firmware/Makefile | 6 | ||||
| -rw-r--r-- | firmware/Roadmap.txt | 29 | ||||
| -rw-r--r-- | firmware/bootloaderconfig.h | 2 | ||||
| -rw-r--r-- | firmware/libs-device/Readme.txt | 22 | ||||
| -rw-r--r-- | firmware/libs-device/osccal.c | 183 | ||||
| -rw-r--r-- | firmware/libs-device/osctune.h | 88 | ||||
| -rw-r--r-- | firmware/main.c | 134 | ||||
| -rw-r--r-- | firmware/osccal.h (renamed from firmware/libs-device/osccal.h) | 0 | ||||
| -rw-r--r-- | firmware/osccalASM.S (renamed from firmware/libs-device/osccalASM.S) | 0 | 
10 files changed, 103 insertions, 364 deletions
| @@ -14,7 +14,6 @@ firmware/crt1.o  firmware/main.lss  firmware/usbdrv/oddebug.c.lst  firmware/main.hex -firmware/libs-device/osccal.o -firmware/libs-device/osccalASM.o +firmware/osccalASM.o  firmware/usbdrv/oddebug.o  firmware/usbdrv/usbdrvasm.o diff --git a/firmware/Makefile b/firmware/Makefile index 0905d0a..459052b 100644 --- a/firmware/Makefile +++ b/firmware/Makefile @@ -149,12 +149,12 @@ CC = avr-gcc  DEFINES = -DBOOTLOADER_ADDRESS=0x$(BOOTLOADER_ADDRESS) #-DDEBUG_LEVEL=2  # Remove the -fno-* options when you use gcc 3, it does not understand them  #  -CFLAGS = -g2 -nostartfiles -ffunction-sections -fdata-sections -fpack-struct -Wall -Os  -fno-inline-small-functions -fno-move-loop-invariants -fno-tree-scev-cprop  -I. -Ilibs-device -mmcu=$(DEVICE) -DF_CPU=$(F_CPU) $(DEFINES) +CFLAGS = -g2 -nostartfiles -ffunction-sections -fdata-sections -fpack-struct -Wall -Os  -fno-inline-small-functions -fno-move-loop-invariants -fno-tree-scev-cprop  -I. -mmcu=$(DEVICE) -DF_CPU=$(F_CPU) $(DEFINES)  LDFLAGS = -Wl,--relax,--section-start=.text=$(BOOTLOADER_ADDRESS),-Map=main.map,--section-start=.zerotable=0  OBJECTS =  crt1.o usbdrv/usbdrvasm.o usbdrv/oddebug.o main.o  -OBJECTS += libs-device/osccalASM.o +OBJECTS += osccalASM.o  # symbolic targets:  all: main.hex @@ -190,7 +190,7 @@ read_fuses:  	$(UISP) --rd_fuses  clean: -	rm -f main.hex main.bin main.c.lst main.map *.o usbdrv/*.o main.s usbdrv/oddebug.s usbdrv/usbdrv.s libs-device/osccalASM.o *.lss +	rm -f main.hex main.bin main.c.lst main.map *.o usbdrv/*.o main.s usbdrv/oddebug.s usbdrv/usbdrv.s *.lss  # file targets:  main.bin:	$(OBJECTS) diff --git a/firmware/Roadmap.txt b/firmware/Roadmap.txt new file mode 100644 index 0000000..1612fcd --- /dev/null +++ b/firmware/Roadmap.txt @@ -0,0 +1,29 @@ +Development Roadmap + +1.x Improvements (No protocol change, micronucleus host tool stays the same) + +Changes to client firmware: +	- Only time out bootloader if program is loaded - done +	- Move clean boot page to initialization - done +	- Integrate blargg optimizations   +		* turned "event"-variable into register to save memory +		* moved flash buffer clean to hardware initialization function +	 +2.x Improvements (New Protocol, new command line tool) + +Changes to client firmware: +	- New device support (84,841,167,861) +	- External oscillator option +	- polled USB +	- enter bootloader by external reset +	 +Changes to protocol/command line tool +	- Send different delay times for erase and program to support 481 +	- Transmit data in value and index field, don't use data payload to reduce code size and improve v-usb stability +	- Move writing of tiny vector table to host tool. Reset vector patching stays on client +			-> no risk of bricking device, since bootloader will remain active +	- erase command +	- CRC check +	 +			 +	
\ No newline at end of file diff --git a/firmware/bootloaderconfig.h b/firmware/bootloaderconfig.h index e1b2a4c..53c650f 100644 --- a/firmware/bootloaderconfig.h +++ b/firmware/bootloaderconfig.h @@ -282,7 +282,7 @@ these macros are defined, the boot loader uses them.   */  #define AUTO_EXIT_NO_USB_MS    0 -#define AUTO_EXIT_MS           6000 +#define AUTO_EXIT_MS           5000   /*   *	Defines the setting of the RC-oscillator calibration after quitting the bootloader. (OSCCAL) diff --git a/firmware/libs-device/Readme.txt b/firmware/libs-device/Readme.txt deleted file mode 100644 index 76518dc..0000000 --- a/firmware/libs-device/Readme.txt +++ /dev/null @@ -1,22 +0,0 @@ -This is the Readme file for the libs-device directory. This directory contains -code snippets which may be useful for USB device firmware. - - -WHAT IS INCLUDED IN THIS DIRECTORY? -=================================== - -osccal.c and osccal.h -  This module contains a function which calibrates the AVR's built-in RC -  oscillator based on the USB frame clock. See osccal.h for a documentation -  of the API. - -osctune.h -  This header file contains a code snippet for usbconfig.h. With this code, -  you can keep the AVR's internal RC oscillator in sync with the USB frame -  clock. This is a continuous synchronization, not a single calibration at -  USB reset as with osccal.c above. Please note that this code works only -  if D- is wired to the interrupt, not D+. - ----------------------------------------------------------------------------- -(c) 2008 by OBJECTIVE DEVELOPMENT Software GmbH. -http://www.obdev.at/ diff --git a/firmware/libs-device/osccal.c b/firmware/libs-device/osccal.c deleted file mode 100644 index 8debe49..0000000 --- a/firmware/libs-device/osccal.c +++ /dev/null @@ -1,183 +0,0 @@ -/* Name: osccal.c - * Author: Christian Starkjohann - * Creation Date: 2008-04-10 - * Tabsize: 4 - * Copyright: (c) 2008 by OBJECTIVE DEVELOPMENT Software GmbH - * License: GNU GPL v2 (see License.txt), GNU GPL v3 or proprietary (CommercialLicense.txt) - * This Revision: $Id: osccal.c 762 2009-08-12 17:10:30Z cs $ - */ - -#include <avr/io.h> -#include <avr/interrupt.h> -#ifndef uchar -#define uchar   unsigned char -#endif - -int usbMeasureFrameLengthDecreasing(int); - -/* ------------------------------------------------------------------------- */ -/* ------------------------ Oscillator Calibration ------------------------- */ -/* ------------------------------------------------------------------------- */ - -/* Calibrate the RC oscillator. Our timing reference is the Start Of Frame - * signal (a single SE0 bit) repeating every millisecond immediately after - * a USB RESET.  - * - *  - * Optimized version by cpldcpu@gmail.com, Nov 3rd 2013. - * - * Benefits: - *	  - Codesize reduced by 54 bytes. - *    - Improved robustness due to removing timeout from frame length measurement and  - *	    inserted NOP after OSCCAL writes. - * - * Changes: - *    - The new routine performs a combined binary and neighborhood search - *      in a single loop. - *      Note that the neighborhood search is necessary due to the quasi-monotonic  - *      nature of OSCCAL. (See Atmel application note AVR054). - *	  - Inserted NOP after writes to OSCCAL to avoid CPU errors during oscillator - *      stabilization.  - *    - Implemented new routine to measure frame time "usbMeasureFrameLengthDecreasing". - *		This routine takes the target time as a parameter and returns the deviation. - *	  - usbMeasureFrameLengthDecreasing measures in multiples of 5 cycles and is thus - *	    slighly more accurate. - *	  - usbMeasureFrameLengthDecreasing does not support time out anymore. The original - *	    implementation returned zero in case of time out, which would have caused the old - *      calibrateOscillator() implementation to increase OSSCAL to 255, effictively - *      overclocking and most likely crashing the CPU. The new implementation will enter - *		an infinite loop when no USB activity is encountered. The user program should - *      use the watchdog to escape from situations like this. -  *  - * This routine will work both on controllers with and without split OSCCAL range. - * The first trial value is 128 which is the lowest value of the upper OSCCAL range - * on Attiny85 and will effectively limit the search to the upper range, unless the - * RC oscillator frequency is unusually high. Under normal operation, the highest  - * tested frequency setting is 192. This corresponds to ~20 Mhz core frequency and  - * is still within spec for a 5V device. - */ - -void    calibrateOscillator(void) -{ -	uchar       step, trialValue, optimumValue; -	int         x, targetValue; -	uchar		optimumDev; -	uchar		i,xl; -	 -	targetValue = (unsigned)((double)F_CPU * 999e-6 / 5.0 + 0.5);  /* Time is measured in multiples of 5 cycles. Target is 0.999µs */ -    optimumDev = 0xff;    -  //  optimumValue = OSCCAL;  -	step=64; -	trialValue = 128; -	 -	cli(); // disable interrupts -	 -	/* -		Performs seven iterations of a binary search (stepwidth decreasing9 -		with three additional steps of a neighborhood search (step=1, trialvalue will oscillate around target value to find optimum) -	*/ - -	for(i=0; i<10; i++){ -		OSCCAL = trialValue; -		asm volatile(" NOP"); -	 -		x = usbMeasureFrameLengthDecreasing(targetValue); - -		if(x < 0)             /* frequency too high */ -		{ -			trialValue -= step; -			xl=(uchar)-x; -		} -		else                  /* frequency too low */ -		{ -			trialValue += step;			 -			xl=(uchar)x; -		} -		 -		/* -			Halve stepwidth to perform binary search. Logical oring with 1 to ensure step is never equal to zero.  -			This results in a neighborhood search with stepwidth 1 after binary search is finished.			 -			Once the neighbourhood search stage is reached, x will be smaller than +-255, hence more code can be -			saved by only working with the lower 8 bits. -		*/ -		 -		step >>= 1; -		 -		if (step==0) -		{ -			step=1;			 -			if(xl <= optimumDev){ -				optimumDev = xl; -				optimumValue = OSCCAL; -			} -		} - -	} - -	OSCCAL = optimumValue; -	asm volatile(" NOP"); -	 -	sei(); // enable interrupts -} - -void    calibrateOscillator_old(void) -{ -	uchar       step, trialValue, optimumValue; -	int         x, optimumDev, targetValue; -	uchar		i; -	 -	targetValue = (unsigned)((double)F_CPU * 999e-6 / 5.0 + 0.5);  /* Time is measured in multiples of 5 cycles. Target is 0.999µs */ -    optimumDev = 0x7f00;   // set to high positive value -    optimumValue = OSCCAL;  -	step=64; -	trialValue = 128; -	 -	/* -		Performs seven iterations of a binary search (stepwidth decreasing9 -		with three additional steps of a neighborhood search (step=1, trialvalue will oscillate around target value to find optimum) -	*/ - -	for(i=0; i<10; i++){ -		OSCCAL = trialValue; -		asm volatile(" NOP"); -	 -		x = usbMeasureFrameLengthDecreasing(targetValue); - -		if(x < 0)             /* frequency too high */ -		{ -			trialValue -= step; -			x = -x; -		} -		else                  /* frequency too low */ -		{ -			trialValue += step;			 -		} -		 -		/* -			Halve stepwidth to perform binary search. Logical oring with 1 to ensure step is never equal to zero.  -			This results in a neighborhood search with stepwidth 1 after binary search is finished.			 -		*/ -		 -		step >>= 1; -		step |=1;	 - -		if(x < optimumDev){ -			optimumDev = x; -			optimumValue = OSCCAL; -		} -	} - -	OSCCAL = optimumValue; -	asm volatile(" NOP"); -} - -/* -Note: This calibration algorithm may try OSCCAL values of up to 192 even if -the optimum value is far below 192. It may therefore exceed the allowed clock -frequency of the CPU in low voltage designs! -You may replace this search algorithm with any other algorithm you like if -you have additional constraints such as a maximum CPU clock. -For version 5.x RC oscillators (those with a split range of 2x128 steps, e.g. -ATTiny25, ATTiny45, ATTiny85), it may be useful to search for the optimum in -both regions. -*/ diff --git a/firmware/libs-device/osctune.h b/firmware/libs-device/osctune.h deleted file mode 100644 index c751648..0000000 --- a/firmware/libs-device/osctune.h +++ /dev/null @@ -1,88 +0,0 @@ -/* Name: osctune.h - * Author: Christian Starkjohann - * Creation Date: 2008-10-18 - * Tabsize: 4 - * Copyright: (c) 2008 by OBJECTIVE DEVELOPMENT Software GmbH - * License: GNU GPL v2 (see License.txt), GNU GPL v3 or proprietary (CommercialLicense.txt) - * This Revision: $Id: osctune.h 692 2008-11-07 15:07:40Z cs $ - */ - -/* -General Description: -This file is declared as C-header file although it is mostly documentation -how the RC oscillator can be kept in sync to the USB frame rate. The code -shown here must be added to usbconfig.h or this header file is included from -there. This code works only if D- is wired to the interrupt, not D+!!! - -This is an alternative to the osccal routine in osccal.c. It has the advantage -that the synchronization is done continuously and that it has more compact -code size. The disadvantages are slow synchronization (it may take a while -until the driver works), that messages immediately after the SOF pulse may be -lost (and need to be retried by the host) and that the interrupt is on D- -contrary to most examples. - -You may want to store a good calibration value in EEPROM for the next startup. -You know that the calibration value is good when the first USB message is -received. Do not store the value on every received message because the EEPROM -has a limited endurance. - -Notes: -(*) You must declare the global character variable "lastTimer0Value" in your -main code. - -(*) Timer 0 must be free running (not written by your code) and the prescaling -must be consistent with the TIMER0_PRESCALING define. - -(*) Good values for Timer 0 prescaling depend on how precise the clock must -be tuned and how far away from the default clock rate the target clock is. -For precise tuning, choose a low prescaler factor, for a broad range of tuning -choose a high one. A prescaler factor of 64 is good for the entire OSCCAL -range and allows a precision of better than +/-1%. A prescaler factor of 8 -allows tuning to slightly more than +/-6% of the default frequency and is -more precise than one step of OSCCAL. It is therefore not suitable to tune an -8 MHz oscillator to 12.5 MHz. - -Thanks to Henrik Haftmann for the idea to this routine! -*/ - -#define TIMER0_PRESCALING           64 /* must match the configuration for TIMER0 in main */ -#define TOLERATED_DEVIATION_PPT     5  /* max clock deviation before we tune in 1/10 % */ -/* derived constants: */ -#define EXPECTED_TIMER0_INCREMENT   ((F_CPU / (1000 * TIMER0_PRESCALING)) & 0xff) -#define TOLERATED_DEVIATION         (TOLERATED_DEVIATION_PPT * F_CPU / (1000000 * TIMER0_PRESCALING)) - -#ifdef __ASSEMBLER__ -macro tuneOsccal -    push    YH                              ;[0] -    in      YL, TCNT0                       ;[2] -    lds     YH, lastTimer0Value             ;[3] -    sts     lastTimer0Value, YL             ;[5] -    sub     YL, YH                          ;[7] time passed since last frame -    subi    YL, EXPECTED_TIMER0_INCREMENT   ;[8] -#if OSCCAL > 0x3f   /* outside I/O addressable range */ -    lds     YH, OSCCAL                      ;[6] -#else -    in      YH, OSCCAL                      ;[6] assembler modle uses __SFR_OFFSET == 0 -#endif -    cpi     YL, TOLERATED_DEVIATION + 1     ;[10] -    brmi    notTooHigh                      ;[11] -    subi    YH, 1                           ;[12] clock rate was too high -;   brcs    tuningOverflow                  ; optionally check for overflow -    rjmp    osctuneDone                     ;[13] -notTooHigh: -    cpi     YL, -TOLERATED_DEVIATION        ;[13] -    brpl    osctuneDone                     ;[14] not too low -    inc     YH                              ;[15] clock rate was too low -;   breq    tuningOverflow                  ; optionally check for overflow -osctuneDone: -#if OSCCAL > 0x3f   /* outside I/O addressable range */ -    sts     OSCCAL, YH                      ;[12-13] store tuned value -#else -    out     OSCCAL, YH                      ;[12-13] store tuned value -#endif -tuningOverflow: -    pop     YH                              ;[17] -    endm                                    ;[19] max number of cycles -#endif - -#define USB_SOF_HOOK        tuneOsccal diff --git a/firmware/main.c b/firmware/main.c index 6f7f180..a7deccc 100644 --- a/firmware/main.c +++ b/firmware/main.c @@ -16,7 +16,6 @@  // how many milliseconds should host wait till it sends another erase or write?  // needs to be above 4.5 (and a whole integer) as avr freezes for 4.5ms  #define MICRONUCLEUS_WRITE_SLEEP 8 -  // Use the old delay routines without NOP padding. This saves memory.  #define __DELAY_BACKWARD_COMPATIBLE__      @@ -26,8 +25,6 @@  #include <avr/boot.h>  #include <util/delay.h> -static void leaveBootloader() __attribute__((__noreturn__)); -  #include "bootloaderconfig.h"  #include "usbdrv/usbdrv.c" @@ -50,7 +47,9 @@ static void leaveBootloader() __attribute__((__noreturn__));  #endif  // events system schedules functions to run in the main loop -static uchar events = 0; // bitmap of events to run +// static uint8_t events = 0; // bitmap of events to run +register uint8_t  events asm( "r3" ); // register saves many bytes  +  #define EVENT_ERASE_APPLICATION 1  #define EVENT_WRITE_PAGE        2  #define EVENT_EXECUTE           4 @@ -77,8 +76,8 @@ static uint16_t currentAddress; // current progmem address, used for erasing and  static inline void eraseApplication(void);  static void writeFlashPage(void);  static void writeWordToPageBuffer(uint16_t data); -static uchar usbFunctionSetup(uchar data[8]); -static uchar usbFunctionWrite(uchar *data, uchar length); +static uint8_t usbFunctionSetup(uint8_t data[8]); +static uint8_t usbFunctionWrite(uint8_t *data, uint8_t length);  static inline void leaveBootloader(void);  // erase any existing application and write in jumps for usb interrupt and reset to bootloader @@ -92,14 +91,14 @@ static inline void eraseApplication(void) {      // during upload      uint8_t i; -    uint16_t ptr = BOOTLOADER_ADDRESS; +	uint16_t ptr = BOOTLOADER_ADDRESS;      cli();      while (ptr) {          ptr -= SPM_PAGESIZE;                  boot_page_erase(ptr);      } -    currentAddress = 0; +	currentAddress = 0;      for (i=0; i<8; i++) writeWordToPageBuffer(0xFFFF);  // Write first 8 words to fill in vectors.      writeFlashPage();  // enables interrupts  } @@ -150,16 +149,12 @@ static void writeWordToPageBuffer(uint16_t data) {  #if (!OSCCAL_RESTORE) && OSCCAL_16_5MHz         } else if (currentAddress == BOOTLOADER_ADDRESS - TINYVECTOR_OSCCAL_OFFSET) {          data = OSCCAL; -#endif       +#endif		      }      previous_sreg=SREG;          cli(); // ensure interrupts are disabled -    // clear page buffer as a precaution before filling the buffer on the first page -    // in case the bootloader somehow ran after user program and there was something -    // in the page buffer already -    if (currentAddress == 0x0000) __boot_page_fill_clear();      boot_page_fill(currentAddress, data);      // increment progmem address by one word @@ -168,11 +163,11 @@ static void writeWordToPageBuffer(uint16_t data) {  }  /* ------------------------------------------------------------------------ */ -static uchar usbFunctionSetup(uchar data[8]) { +static uint8_t usbFunctionSetup(uint8_t data[8]) {      usbRequest_t *rq = (void *)data;      ((uint8_t*)&idlePolls)[1] = 0;              // reset idle polls when we get usb traffic -     -    static uchar replyBuffer[4] = { +	 +    static uint8_t replyBuffer[4] = {          (((uint16_t)PROGMEM_SIZE) >> 8) & 0xff,          ((uint16_t)PROGMEM_SIZE) & 0xff,          SPM_PAGESIZE, @@ -184,6 +179,10 @@ static uchar usbFunctionSetup(uchar data[8]) {          return 4;      } else if (rq->bRequest == 1) { // write page +     +        // 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;                  return USB_NO_MSG; // hands off work to usbFunctionWrite @@ -200,7 +199,7 @@ static uchar usbFunctionSetup(uchar data[8]) {  }  // read in a page over usb, and write it in to the flash write buffer -static uchar usbFunctionWrite(uchar *data, uchar length) { +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; @@ -212,10 +211,10 @@ static uchar usbFunctionWrite(uchar *data, uchar length) {      // if we have now reached another page boundary, we're done  #if SPM_PAGESIZE<256 -    // Hack to reduce code size -    uchar isLast = ((((uchar)currentAddress) % SPM_PAGESIZE) == 0); +	// Hack to reduce code size +    uint8_t isLast = ((((uint8_t)currentAddress) % SPM_PAGESIZE) == 0);  #else -    uchar isLast = ((currentAddress % SPM_PAGESIZE) == 0); +    uint8_t isLast = ((currentAddress % SPM_PAGESIZE) == 0);  #endif      // definitely need this if! seems usbFunctionWrite gets called again in future usbPoll's in the runloop! @@ -235,15 +234,36 @@ void PushMagicWord (void) {      asm volatile("push r16"::);  } +static void initHardware (void) +{ +        MCUSR=0;    /* need this to properly disable watchdog */ +        wdt_disable(); +  +        #if LOW_POWER_MODE +            // turn off clock prescalling - chip must run at full speed for usb +            // if you might run chip at lower voltages, detect that in bootLoaderStartCondition +            CLKPR = 1 << CLKPCE; +            CLKPR = 0; +        #endif + +     +        usbDeviceDisconnect();  /* do this while interrupts are disabled */ +        _delay_ms(500);   +        usbDeviceConnect(); +        usbInit();    // Initialize INT settings after reconnect +        sei();         +} +  /* ------------------------------------------------------------------------ */  // reset system to a normal state and launch user program +static void leaveBootloader(void) __attribute__((__noreturn__));  static inline void leaveBootloader(void) { -    _delay_ms(10); // removing delay causes USB errors +   _delay_ms(10); // removing delay causes USB errors      bootLoaderExit();      cli(); -    usbDeviceDisconnect();  /* Disconnect micronucleus */ -     +	usbDeviceDisconnect();  /* Disconnect micronucleus */ +	      USB_INTR_ENABLE = 0;      USB_INTR_CFG = 0;       /* also reset config bits */ @@ -255,8 +275,8 @@ static inline void leaveBootloader(void) {      // as when it was uploaded originally      unsigned char stored_osc_calibration = pgm_read_byte(BOOTLOADER_ADDRESS - TINYVECTOR_OSCCAL_OFFSET);      if (stored_osc_calibration != 0xFF && stored_osc_calibration != 0x00) { -        OSCCAL=stored_osc_calibration; -        asm volatile("nop"); +		OSCCAL=stored_osc_calibration; +		asm volatile("nop");      }  #endif      // jump to application reset vector at end of flash @@ -273,56 +293,40 @@ int main(void) {      #endif      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 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()) { -        MCUSR=0;    /* need this to properly disable watchdog */ -        wdt_disable(); -  -        #if LOW_POWER_MODE -            // turn off clock prescalling - chip must run at full speed for usb -            // if you might run chip at lower voltages, detect that in bootLoaderStartCondition -            CLKPR = 1 << CLKPCE; -            CLKPR = 0; -        #endif +        initHardware();  #       if  LED_PRESENT              LED_INIT(); -#       endif  - -        usbDeviceDisconnect();  /* do this while interrupts are disabled */ -        _delay_ms(500);   -        usbDeviceConnect(); -        usbInit();    // Initialize INT settings after reconnect -        sei();         -         +#       endif     	          do { -            usbPoll(); -            _delay_us(100); -             -            // these next two freeze the chip for ~ 4.5ms, breaking usb protocol -            // and usually both of these will activate in the same loop, so host -            // needs to wait > 9ms before next usb request -            if (isEvent(EVENT_ERASE_APPLICATION)) eraseApplication(); -            if (isEvent(EVENT_WRITE_PAGE)) { -                _delay_us(2000); // Wait for USB traffic to finish before halting CPU with write- -                writeFlashPage();   -            } - -#       if BOOTLOADER_CAN_EXIT             -            if (isEvent(EVENT_EXECUTE)) break; // when host requests device run uploaded program -#       endif                      clearEvents(); +			usbPoll(); +            _delay_us(100); + +                // these next two freeze the chip for ~ 4.5ms, breaking usb protocol +                // and usually both of these will activate in the same loop, so host +                // needs to wait > 9ms before next usb request +                if (isEvent(EVENT_ERASE_APPLICATION)) eraseApplication(); +                if (isEvent(EVENT_WRITE_PAGE)) { +                    _delay_us(2000); // Wait for USB traffic to finish before halting CPU with write- +                    writeFlashPage();   +                }  #       if  LED_PRESENT              LED_MACRO( ((uint8_t*)&idlePolls)[1] )  #       endif -                 -        } while(bootLoaderCondition());  /* main event loop runs so long as bootLoaderCondition remains truthy */ +             +            // Only try to execute program if reset vector is set - bootloader will not time out with erased memory +            if (!bootLoaderCondition()&&(pgm_read_byte(BOOTLOADER_ADDRESS - TINYVECTOR_RESET_OFFSET + 1)!=0xff)) fireEvent(EVENT_EXECUTE); +	                             +        } while(!isEvent(EVENT_EXECUTE));  /* main event loop runs as long as program is not executed */      }      // set clock prescaler to desired clock speed (changing from clkdiv8, or no division, depending on fuses) @@ -341,8 +345,8 @@ int main(void) {  #   endif  #   if OSCCAL_RESTORE -    OSCCAL=osccal_default; -    asm volatile("nop");    // NOP to avoid CPU hickup during oscillator stabilization +	OSCCAL=osccal_default; +	asm volatile("nop");	// NOP to avoid CPU hickup during oscillator stabilization  #   endif      leaveBootloader(); diff --git a/firmware/libs-device/osccal.h b/firmware/osccal.h index af37a43..af37a43 100644 --- a/firmware/libs-device/osccal.h +++ b/firmware/osccal.h diff --git a/firmware/libs-device/osccalASM.S b/firmware/osccalASM.S index 9a317f1..9a317f1 100644 --- a/firmware/libs-device/osccalASM.S +++ b/firmware/osccalASM.S | 
