summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--.gitignore3
-rw-r--r--firmware/Makefile6
-rw-r--r--firmware/Roadmap.txt29
-rw-r--r--firmware/bootloaderconfig.h2
-rw-r--r--firmware/libs-device/Readme.txt22
-rw-r--r--firmware/libs-device/osccal.c183
-rw-r--r--firmware/libs-device/osctune.h88
-rw-r--r--firmware/main.c134
-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
diff --git a/.gitignore b/.gitignore
index 23e53ad..933e699 100644
--- a/.gitignore
+++ b/.gitignore
@@ -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