summaryrefslogtreecommitdiffstats
path: root/firmware
diff options
context:
space:
mode:
authorTim <cpldcpu@gmail.com>2014-01-14 23:40:25 -0800
committerTim <cpldcpu@gmail.com>2014-01-14 23:40:25 -0800
commit993bed77e563054f12ac61b5d8f93e2cb548525e (patch)
tree7fc9a7dc6860dbb9823f646b261d4238d7fd802e /firmware
parent18e258ace5c610e1e40f53adaca402b46820f72a (diff)
parent34b0f0f0b6ef651bb30878341cba2a28a107d82d (diff)
downloadmicronucleus-993bed77e563054f12ac61b5d8f93e2cb548525e.tar.gz
micronucleus-993bed77e563054f12ac61b5d8f93e2cb548525e.tar.bz2
micronucleus-993bed77e563054f12ac61b5d8f93e2cb548525e.zip
Merge pull request #34 from micronucleus/testing
v1.11 - pull request
Diffstat (limited to 'firmware')
-rw-r--r--firmware/Makefile8
-rw-r--r--firmware/Roadmap.txt29
-rw-r--r--firmware/bootloaderconfig.h292
-rw-r--r--firmware/libs-device/Readme.txt22
-rw-r--r--firmware/libs-device/osccal.c183
-rw-r--r--firmware/libs-device/osccal.h57
-rw-r--r--firmware/libs-device/osctune.h88
-rw-r--r--firmware/main.c484
-rw-r--r--firmware/osccalASM.S (renamed from firmware/libs-device/osccalASM.S)0
-rw-r--r--firmware/releases/micronucleus-1.11-entry_ext_reset.hex119
-rw-r--r--firmware/releases/micronucleus-1.11-entry_jumper_pb0.hex120
-rw-r--r--firmware/releases/micronucleus-1.11-ledpb1.hex119
-rw-r--r--firmware/releases/micronucleus-1.11.hex118
-rw-r--r--firmware/releases/release notes.txt45
-rw-r--r--firmware/usbconfig.h17
15 files changed, 914 insertions, 787 deletions
diff --git a/firmware/Makefile b/firmware/Makefile
index 0905d0a..941310c 100644
--- a/firmware/Makefile
+++ b/firmware/Makefile
@@ -24,7 +24,7 @@ LOCKOPT = -U lock:w:0x2f:m
# - for the size of your device (8kb = 1024 * 8 = 8192) subtract above value 2124... = 6068
# - How many pages in is that? 6068 / 64 (tiny85 page size in bytes) = 94.8125
# - round that down to 94 - our new bootloader address is 94 * 64 = 6016, in hex = 1780
-BOOTLOADER_ADDRESS = 1880
+BOOTLOADER_ADDRESS = 18C0
PROGRAMMER = -c USBasp
# PROGRAMMER contains AVRDUDE options to address your programmer
@@ -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..a93e6ff 100644
--- a/firmware/bootloaderconfig.h
+++ b/firmware/bootloaderconfig.h
@@ -12,13 +12,16 @@
#ifndef __bootloaderconfig_h_included__
#define __bootloaderconfig_h_included__
-// uncomment this to enable the 'jumper from d5 to gnd to enable programming' mode
-//#define BUILD_JUMPER_MODE 1
-
-#ifndef BOOTLOADER_ADDRESS
-#define BOOTLOADER_ADDRESS 0
+/*
+ * 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
@@ -51,46 +54,46 @@ these macros are defined, the boot loader uses them.
#define HARDWARE_CONFIG TINY85_HARDWARE_CONFIG_2
#define USB_CFG_IOPORTNAME B
-/* This is the port where the USB bus is connected. When you configure it to
- * "B", the registers PORTB, PINB and DDRB will be used.
- */
+ /* This is the port where the USB bus is connected. When you configure it to
+ * "B", the registers PORTB, PINB and DDRB will be used.
+ */
#ifndef __AVR_ATtiny85__
-# define USB_CFG_DMINUS_BIT 0
-/* This is the bit number in USB_CFG_IOPORT where the USB D- line is connected.
- * This may be any bit in the port.
- */
-# define USB_CFG_DPLUS_BIT 2
-/* This is the bit number in USB_CFG_IOPORT where the USB D+ line is connected.
- * This may be any bit in the port. Please note that D+ must also be connected
- * to interrupt pin INT0!
- */
+ # define USB_CFG_DMINUS_BIT 0
+ /* This is the bit number in USB_CFG_IOPORT where the USB D- line is connected.
+ * This may be any bit in the port.
+ */
+ #define USB_CFG_DPLUS_BIT 2
+ /* This is the bit number in USB_CFG_IOPORT where the USB D+ line is connected.
+ * This may be any bit in the port. Please note that D+ must also be connected
+ * to interrupt pin INT0!
+ */
#endif
#if (defined __AVR_ATtiny85__) && (HARDWARE_CONFIG == TINY85_HARDWARE_CONFIG_1)
-# define USB_CFG_DMINUS_BIT 0
-/* This is the bit number in USB_CFG_IOPORT where the USB D- line is connected.
- * This may be any bit in the port.
- */
-# define USB_CFG_DPLUS_BIT 2
-/* This is the bit number in USB_CFG_IOPORT where the USB D+ line is connected.
- * This may be any bit in the port, but must be configured as a pin change interrupt.
- */
- #endif
+ #define USB_CFG_DMINUS_BIT 0
+ /* This is the bit number in USB_CFG_IOPORT where the USB D- line is connected.
+ * This may be any bit in the port.
+ */
+ #define USB_CFG_DPLUS_BIT 2
+ /* This is the bit number in USB_CFG_IOPORT where the USB D+ line is connected.
+ * This may be any bit in the port, but must be configured as a pin change interrupt.
+ */
+#endif
#if (defined __AVR_ATtiny85__) && (HARDWARE_CONFIG == TINY85_HARDWARE_CONFIG_2)
-# define USB_CFG_DMINUS_BIT 3
+#define USB_CFG_DMINUS_BIT 3
/* This is the bit number in USB_CFG_IOPORT where the USB D- line is connected.
* This may be any bit in the port.
*/
-# define USB_CFG_DPLUS_BIT 4
+#define USB_CFG_DPLUS_BIT 4
/* This is the bit number in USB_CFG_IOPORT where the USB D+ line is connected.
* This may be any bit in the port, but must be configured as a pin change interrupt.
*/
- #endif
+#endif
#define USB_CFG_CLOCK_KHZ (F_CPU/1000)
-/* Clock rate of the AVR in MHz. Legal values are 12000, 16000 or 16500.
+/* Clock rate of the AVR in kHz. Legal values are 12000, 16000 or 16500.
* The 16.5 MHz version of the code requires no crystal, it tolerates +/- 1%
* deviation from the nominal frequency. All other rates require a precision
* of 2000 ppm and thus a crystal!
@@ -114,82 +117,16 @@ these macros are defined, the boot loader uses them.
/* ------------------------------------------------------------------------- */
/* ---------------------- feature / code size options ---------------------- */
/* ------------------------------------------------------------------------- */
-
-//#define HAVE_EEPROM_PAGED_ACCESS 0
-/* If HAVE_EEPROM_PAGED_ACCESS is defined to 1, page mode access to EEPROM is
- * compiled in. Whether page mode or byte mode access is used by AVRDUDE
- * depends on the target device. Page mode is only used if the device supports
- * it, e.g. for the ATMega88, 168 etc. You can save quite a bit of memory by
- * disabling page mode EEPROM access. Costs ~ 138 bytes.
- */
-//#define HAVE_EEPROM_BYTE_ACCESS 0
-/* If HAVE_EEPROM_BYTE_ACCESS is defined to 1, byte mode access to EEPROM is
- * compiled in. Byte mode is only used if the device (as identified by its
- * signature) does not support page mode for EEPROM. It is required for
- * accessing the EEPROM on the ATMega8. Costs ~54 bytes.
- */
-#define BOOTLOADER_CAN_EXIT 1
-/* If this macro is defined to 1, the boot loader will exit shortly after the
- * programmer closes the connection to the device. Costs ~36 bytes.
- * Required for TINY85MODE
- */
-//#define HAVE_CHIP_ERASE 0
-/* If this macro is defined to 1, the boot loader implements the Chip Erase
- * ISP command. Otherwise pages are erased on demand before they are written.
- */
-//#define SIGNATURE_BYTES 0x1e, 0x93, 0x0b, 0 /* ATtiny85 */
-/* This macro defines the signature bytes returned by the emulated USBasp to
- * the programmer software. They should match the actual device at least in
- * memory size and features. If you don't define this, values for ATMega8,
- * ATMega88, ATMega168 and ATMega328 are guessed correctly.
- */
-
-/* The following block guesses feature options so that the resulting code
- * should fit into 2k bytes boot block with the given device and clock rate.
- * Activate by passing "-DUSE_AUTOCONFIG=1" to the compiler.
- * This requires gcc 3.4.6 for small enough code size!
- */
-// #if USE_AUTOCONFIG
-// # undef HAVE_EEPROM_PAGED_ACCESS
-// # define HAVE_EEPROM_PAGED_ACCESS (USB_CFG_CLOCK_KHZ >= 16000)
-// # undef HAVE_EEPROM_BYTE_ACCESS
-// # define HAVE_EEPROM_BYTE_ACCESS 1
-// # undef BOOTLOADER_CAN_EXIT
-// # define BOOTLOADER_CAN_EXIT 1
-// # undef SIGNATURE_BYTES
-// #endif /* USE_AUTOCONFIG */
-
-/* ------------------------------------------------------------------------- */
-
-/* Example configuration: Port D bit 3 is connected to a jumper which ties
- * this pin to GND if the boot loader is requested. Initialization allows
- * several clock cycles for the input voltage to stabilize before
- * bootLoaderCondition() samples the value.
- * We use a function for bootLoaderInit() for convenience and a macro for
- * bootLoaderCondition() for efficiency.
- */
-
-#define JUMPER_BIT 0 /* jumper is connected to this bit in port B, active low */
+/* ----------------------- Optional MCU Description ------------------------ */
/* tiny85 Architecture Specifics */
#ifndef __AVR_ATtiny85__
# error "uBoot is only designed for attiny85"
#endif
-
#define TINY85MODE
-// number of bytes before the boot loader vectors to store the tiny application vector table
-#define TINYVECTOR_RESET_OFFSET 4
-#define TINYVECTOR_USBPLUS_OFFSET 2
-#define TINYVECTOR_OSCCAL_OFFSET 6
-
-#define RESET_VECTOR_OFFSET 0
-#define USBPLUS_VECTOR_OFFSET 2
-
-//#if BOOTLOADER_CAN_EXIT == 0
-//# define BOOTLOADER_CAN_EXIT 1
-//#endif
+/* ------------- Set up interrupt configuration (CPU specific) -------------- */
// setup interrupt for Pin Change for D+
#define USB_INTR_CFG PCMSK
@@ -201,88 +138,105 @@ these macros are defined, the boot loader uses them.
#define USB_INTR_PENDING_BIT PCIF
#define USB_INTR_VECTOR PCINT0_vect
+// Microcontroller vectortable entries in the flash
+#define RESET_VECTOR_OFFSET 0
+#define USBPLUS_VECTOR_OFFSET 2
+
+// number of bytes before the boot loader vectors to store the tiny application vector table
+#define TINYVECTOR_RESET_OFFSET 4
+#define TINYVECTOR_USBPLUS_OFFSET 2
+#define TINYVECTOR_OSCCAL_OFFSET 6
+
+/* ------------------------------------------------------------------------ */
+// postscript are the few bytes at the end of programmable memory which store tinyVectors
+#define POSTSCRIPT_SIZE 6
+#define PROGMEM_SIZE (BOOTLOADER_ADDRESS - POSTSCRIPT_SIZE) /* max size of user program */
+
+/* ------------------------------------------------------------------------- */
+
+/*
+ * Define Bootloader entry condition
+ *
+ * If the entry condition is not met, the bootloader will not be activated and the user program
+ * is executed directly after a reset. If no user program has been loaded, the bootloader
+ * is always active.
+ *
+ * ENTRY_ALWAYS Always activate the bootloader after reset. Requires the least
+ * amount of code.
+ *
+ * ENTRY_WATCHDOG Activate the bootloader after a watchdog reset. This can be used
+ * to enter the bootloader from the user program.
+ * Adds 22 bytes.
+ *
+ * ENTRY_EXT_RESET Activate the bootloader after an external reset was issued by
+ * pulling the reset pin low. It may be necessary to add an external
+ * pull-up resistor to the reset pin if this entry method appears to
+ * behave unreliably.
+ * Adds 22 bytes.
+ *
+ * ENTRY_JUMPER Activate the bootloader when a specific pin is pulled low by an
+ * external jumper.
+ * Adds 34 bytes.
+ *
+ * JUMPER_PIN Pin the jumper is connected to. (e.g. PB0)
+ * JUMPER_PORT Port out register for the jumper (e.g. PORTB)
+ * JUMPER_DDR Port data direction register for the jumper (e.g. DDRB)
+ * JUMPER_INP Port inout register for the jumper (e.g. PINB)
+ *
+ */
+
+#define ENTRYMODE ENTRY_ALWAYS
+
+#define JUMPER_PIN PB0
+#define JUMPER_PORT PORTB
+#define JUMPER_DDR DDRB
+#define JUMPER_INP PINB
-// uncomment for chips with clkdiv8 enabled in fuses
-//#define LOW_POWER_MODE 1
-
-// set clock prescaler to a value before running user program
-//#define SET_CLOCK_PRESCALER _BV(CLKPS0) /* divide by 2 for 8mhz */
-
-
-#ifdef BUILD_JUMPER_MODE
- #define START_JUMPER_PIN 5
- #define digitalRead(pin) (PINB & _BV(pin))
- #define bootLoaderStartCondition() (!digitalRead(START_JUMPER_PIN))
- #define bootLoaderCondition() 1
-
- #ifndef __ASSEMBLER__ /* assembler cannot parse function definitions */
- static inline void bootLoaderInit(void) {
- // DeuxVis pin-5 pullup
- PORTB |= _BV(START_JUMPER_PIN); // has pullup enabled
- _delay_ms(10);
- }
- static inline void bootLoaderExit(void) {
- // DeuxVis pin-5 pullup
- PORTB = 0;
- }
- #endif /* __ASSEMBLER__ */
-
-#else
+#define ENTRY_ALWAYS 1
+#define ENTRY_WATCHDOG 2
+#define ENTRY_EXT_RESET 3
+#define ENTRY_JUMPER 4
+
+#if ENTRYMODE==ENTRY_ALWAYS
+ #define bootLoaderInit()
+ #define bootLoaderExit()
+ #define bootLoaderStartCondition() 1
+#elif ENTRYMODE==ENTRY_WATCHDOG
+ #define bootLoaderInit()
+ #define bootLoaderExit()
+ #define bootLoaderStartCondition() (MCUSR&_BV(WDRF))
+#elif ENTRYMODE==ENTRY_EXT_RESET
#define bootLoaderInit()
#define bootLoaderExit()
- #define bootLoaderCondition() (++idlePolls < (AUTO_EXIT_MS * 10UL))
- #if LOW_POWER_MODE
- // only starts bootloader if USB D- is pulled high on startup - by putting your pullup in to an external connector
- // you can avoid ever entering an out of spec clock speed or waiting on bootloader when that pullup isn't there
- #define bootLoaderStartCondition() \
- (PINB & (_BV(USB_CFG_DMINUS_BIT) | _BV(USB_CFG_DMINUS_BIT))) == _BV(USB_CFG_DMINUS_BIT)
- #else
- #define bootLoaderStartCondition() 1
- #endif
+ #define bootLoaderStartCondition() (MCUSR&_BV(EXTRF))
+#elif ENTRYMODE==ENTRY_JUMPER
+ // Enable pull up on jumper pin and delay to stabilize input
+ #define bootLoaderInit() {JUMPER_DDR&=~_BV(JUMPER_PIN);JUMPER_PORT|=_BV(JUMPER_PIN);_delay_ms(1);}
+ #define bootLoaderExit() {JUMPER_PORT&=~_BV(JUMPER_PIN);}
+ #define bootLoaderStartCondition() (!(JUMPER_INP&_BV(JUMPER_PIN)))
+#else
+ #error "No entry mode defined"
#endif
-/* ----------------------- Optional MCU Description ------------------------ */
-
-/* The following configurations have working defaults in usbdrv.h. You
- * usually don't need to set them explicitly. Only if you want to run
- * the driver on a device which is not yet supported or with a compiler
- * which is not fully supported (such as IAR C) or if you use a different
- * interrupt than INT0, you may have to define some of these.
- */
-/* #define USB_INTR_CFG MCUCR */
-/* #define USB_INTR_CFG_SET ((1 << ISC00) | (1 << ISC01)) */
-/* #define USB_INTR_CFG_CLR 0 */
-/* #define USB_INTR_ENABLE GIMSK */
-/* #define USB_INTR_ENABLE_BIT INT0 */
-/* #define USB_INTR_PENDING GIFR */
-/* #define USB_INTR_PENDING_BIT INTF0 */
-/* #define USB_INTR_VECTOR INT0_vect */
-
-// todo: change to pin 5
-//#define DEUXVIS_JUMPER_PIN 5
-//#define digitalRead(pin) ((PINB >> pin) & 0b00000001)
-//#define bootLoaderStartCondition() (!digitalRead(DEUXVIS_JUMPER_PIN))
-//#define bootLoaderCondition() (1)
-
-#ifndef __ASSEMBLER__ /* assembler cannot parse function definitions */
-
/*
* Define bootloader timeout value.
*
- * These will only be used if is bootLoaderCondition() evaluates idlePolls below!
+ * The bootloader will only time out if a user program was loaded.
*
* AUTO_EXIT_NO_USB_MS The bootloader will exit after this delay if no USB is connected.
* Set to 0 to disable
* Adds ~6 bytes.
* (This will wait for an USB SE0 reset from the host)
+ *
* AUTO_EXIT_MS The bootloader will exit after this delay if no USB communication
* from the host tool was received.
+ * Set to 0 to disable
*
* All values are approx. in milliseconds
*/
#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)
@@ -327,13 +281,15 @@ these macros are defined, the boot loader uses them.
#define LED_PORT PORTB
#define LED_PIN PB1
-#define LED_INIT(x) LED_PORT &=~_BV(LED_PIN);
-#define LED_EXIT(x) LED_DDR &=~_BV(LED_PIN);
-#define LED_MACRO(x) if ( x & 0xd ) {LED_DDR&=~_BV(LED_PIN);} else {LED_DDR|=_BV(LED_PIN);}
-
-#endif /* __ASSEMBLER__ */
-
-
+#if LED_PRESENT
+ #define LED_INIT(x) LED_PORT &=~_BV(LED_PIN);
+ #define LED_EXIT(x) LED_DDR &=~_BV(LED_PIN);
+ #define LED_MACRO(x) if ( x & 0xd ) {LED_DDR&=~_BV(LED_PIN);} else {LED_DDR|=_BV(LED_PIN);}
+#else
+ #define LED_INIT(x)
+ #define LED_EXIT(x)
+ #define LED_MACRO(x)
+#endif
/* ------------------------------------------------------------------------- */
#endif /* __bootloader_h_included__ */
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/osccal.h b/firmware/libs-device/osccal.h
deleted file mode 100644
index af37a43..0000000
--- a/firmware/libs-device/osccal.h
+++ /dev/null
@@ -1,57 +0,0 @@
-/* Name: osccal.h
- * Author: Christian Starkjohann
- * Creation Date: 2008-04-10
- * Changes 2013-11-04 cpldcpu@gmail.com
- * Tabsize: 4
- * Copyright: (c) 2008 by OBJECTIVE DEVELOPMENT Software GmbH
- * License: GNU GPL v2 (see License.txt), GNU GPL v3 or proprietary (CommercialLicense.txt)
- */
-
-/*
-General Description:
-This module contains a function which calibrates the AVR's internal RC
-oscillator so that the CPU runs at F_CPU (F_CPU is a macro which must be
-defined when the module is compiled, best passed in the compiler command
-line). The time reference is the USB frame clock of 1 kHz available
-immediately after a USB RESET condition. Timing is done by counting CPU
-cycles, so all interrupts must be disabled while the calibration runs.
-The size optimized assembler implementation includes its own implementation
-of usbMeasureFrameLength. Therefore USB_CFG_HAVE_MEASURE_FRAME_LENGTH should
-be set to 0 to avoid including unused code sections. It is recommended to call
-calibrateOscillatorASM() from the reset hook in usbconfig.h by including osccal.h:
-
-#include "osccal.h"
-
-This routine is an alternative to the continuous synchronization described
-in osctune.h.
-
-Algorithm used: See osccalASM.x
-
-Limitations:
-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!
-Precision depends on the OSCCAL vs. frequency dependency of the oscillator.
-Typical precision for an ATMega168 (derived from the OSCCAL vs. F_RC diagram
-in the data sheet) should be in the range of 0.4%. Only the 12.8 MHz and
-16.5 MHz versions of V-USB (with built-in receiver PLL) can tolerate this
-deviation! All other frequency modules require at least 0.2% precision.
-*/
-
-#ifndef __OSCCAL_H_INCLUDED__
-#define __OSCCAL_H_INCLUDED__
-
-#ifndef __ASSEMBLER__
- void calibrateOscillatorASM(void);
-# define USB_RESET_HOOK(resetStarts) if(!resetStarts){ calibrateOscillatorASM();}
-# define USB_CFG_HAVE_MEASURE_FRAME_LENGTH 0
-#endif
-/* This function calibrates the RC oscillator so that the CPU runs at F_CPU.
- * It MUST be called immediately after the end of a USB RESET condition!
- * Disable all interrupts during the call!
- * It is recommended that you store the resulting value in EEPROM so that a
- * good guess value is available after the next reset.
- */
-
-
-#endif /* __OSCCAL_H_INCLUDED__ */
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..16cca65 100644
--- a/firmware/main.c
+++ b/firmware/main.c
@@ -1,22 +1,22 @@
-/* Name: main.c
- * Project: Micronucleus
- * Author: Jenna Fox
- * Creation Date: 2007-12-08
- * Tabsize: 4
- * Copyright: (c) 2012 Jenna Fox
- * All changes past revision 1.06 authored by http://github.com/cpldcpu
- * Portions Copyright: (c) 2007 by OBJECTIVE DEVELOPMENT Software GmbH (USBaspLoader)
- * Portions Copyright: (c) 2012 Louis Beaudoin (USBaspLoader-tiny85)
- * License: GNU GPL v2 (see License.txt)
+/*
+ * Project: Micronucleus - v1.11
+ *
+ * Original author (c) 2012 Jenna Fox
+ *
+ * Optimizations v1.10/v1.11 (c) 2013 Tim Bo"scke - cpldcpu@gmail.com
+ * v1.11 (c) 2013 Shay Green
+ *
+ * Based on USBaspLoader-tiny85 (c) 2012 Louis Beaudoin
+ * Based on USBaspLoader (c) 2007 by OBJECTIVE DEVELOPMENT Software GmbH
*
+ * License: GNU GPL v2 (see License.txt)
*/
#define MICRONUCLEUS_VERSION_MAJOR 1
-#define MICRONUCLEUS_VERSION_MINOR 10
+#define MICRONUCLEUS_VERSION_MINOR 11
// 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,59 +26,52 @@
#include <avr/boot.h>
#include <util/delay.h>
-static void leaveBootloader() __attribute__((__noreturn__));
-
#include "bootloaderconfig.h"
-#include "usbdrv/usbdrv.c"
-/* ------------------------------------------------------------------------ */
-// postscript are the few bytes at the end of programmable memory which store tinyVectors
-// and used to in USBaspLoader-tiny85 store the checksum iirc
-#define POSTSCRIPT_SIZE 6
-#define PROGMEM_SIZE (BOOTLOADER_ADDRESS - POSTSCRIPT_SIZE) /* max size of user program */
+
+
+#include "usbdrv/usbdrv.c"
// 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
-#ifdef AUTO_EXIT_MS
-# if AUTO_EXIT_MS < (MICRONUCLEUS_WRITE_SLEEP * (BOOTLOADER_ADDRESS / SPM_PAGESIZE))
-# warning "AUTO_EXIT_MS is shorter than the time it takes to perform erase function - might affect reliability?"
-# warning "Try increasing AUTO_EXIT_MS if you have stability problems"
-# endif
+#if SPM_PAGESIZE>256
+ #error "Micronucleus only supports pagesizes up to 256 bytes"
#endif
-// events system schedules functions to run in the main loop
-static uchar events = 0; // bitmap of events to run
-#define EVENT_ERASE_APPLICATION 1
-#define EVENT_WRITE_PAGE 2
-#define EVENT_EXECUTE 4
-
-// controls state of events
-#define fireEvent(event) events |= (event)
-#define isEvent(event) (events & (event))
-#define clearEvents() events = 0
-
-// Definition of sei and cli without memory barrier keyword to prevent reloading of memory variables
-#define sei() __asm__ __volatile__ ("sei")
-#define cli() __asm__ __volatile__ ("cli")
+// command system schedules functions to run in the main loop
+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
-uint16_t idlePolls = 0; // how long have we been idle?
+#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
-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
+enum {
+ cmd_local_nop=0, // also: get device info
+ cmd_device_info=0,
+ cmd_transfer_page=1,
+ cmd_erase_application=2,
+ cmd_exit=4,
+ cmd_write_page=5,
+};
+
+// Definition of sei and cli without memory barrier keyword to prevent reloading of memory variables
+#define sei() asm volatile("sei")
+#define cli() asm volatile("cli")
+#define nop() asm volatile("nop")
/* ------------------------------------------------------------------------ */
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
@@ -86,142 +79,132 @@ static inline void leaveBootloader(void);
// - vectors in now, and write in the application stuff around them later.
// - if vectors weren't written back in immediately, usb would fail.
static inline void eraseApplication(void) {
- // erase all pages until bootloader, in reverse order (so our vectors stay in place for as long as possible)
- // while the vectors don't matter for usb comms as interrupts are disabled during erase, it's important
- // to minimise the chance of leaving the device in a state where the bootloader wont run, if there's power failure
- // during upload
-
- uint8_t i;
- uint16_t ptr = BOOTLOADER_ADDRESS;
- cli();
- while (ptr) {
- ptr -= SPM_PAGESIZE;
- boot_page_erase(ptr);
- }
+ // erase all pages until bootloader, in reverse order (so our vectors stay in place for as long as possible)
+ // while the vectors don't matter for usb comms as interrupts are disabled during erase, it's important
+ // to minimise the chance of leaving the device in a state where the bootloader wont run, if there's power failure
+ // during upload
+
+ uint8_t i;
+ uint16_t ptr = BOOTLOADER_ADDRESS;
+ cli();
+
+ while (ptr) {
+ ptr -= SPM_PAGESIZE;
+ boot_page_erase(ptr);
+ }
- currentAddress = 0;
- for (i=0; i<8; i++) writeWordToPageBuffer(0xFFFF); // Write first 8 words to fill in vectors.
- writeFlashPage(); // enables interrupts
+ currentAddress.w = 0;
+ for (i=0; i<8; i++) writeWordToPageBuffer(0xFFFF); // Write first 8 words to fill in vectors.
+ writeFlashPage(); // enables interrupts
}
// 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
- sei();
+ cli();
+ boot_page_write(currentAddress.w - 2); // will halt CPU, no waiting required
+ sei();
}
// clear memory which stores data to be written by next writeFlashPage call
-#define __boot_page_fill_clear() \
-(__extension__({ \
- __asm__ __volatile__ \
- ( \
- "sts %0, %1\n\t" \
- "spm\n\t" \
- : \
- : "i" (_SFR_MEM_ADDR(__SPM_REG)), \
- "r" ((uint8_t)(__BOOT_PAGE_FILL | (1 << CTPB))) \
- ); \
+#define __boot_page_fill_clear() \
+(__extension__({ \
+ __asm__ __volatile__ \
+ ( \
+ "sts %0, %1\n\t" \
+ "spm\n\t" \
+ : \
+ : "i" (_SFR_MEM_ADDR(__SPM_REG)), \
+ "r" ((uint8_t)(__BOOT_PAGE_FILL | (1 << CTPB))) \
+ ); \
}))
// write a word in to the page buffer, doing interrupt table modifications where they're required
static void writeWordToPageBuffer(uint16_t data) {
- uint8_t previous_sreg;
-
- // 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) {
- vectorTemp[0] = data;
- data = 0xC000 + (BOOTLOADER_ADDRESS/2) - 1;
- }
-
- if (currentAddress == USBPLUS_VECTOR_OFFSET * 2) {
- vectorTemp[1] = data;
- data = 0xC000 + (BOOTLOADER_ADDRESS/2) - 1;
- }
-
- // 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) {
- data = vectorTemp[0] + ((FLASHEND + 1) - BOOTLOADER_ADDRESS)/2 + 2 + RESET_VECTOR_OFFSET;
- } else if (currentAddress == 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) {
- data = OSCCAL;
-#endif
+ uint8_t previous_sreg;
+
+ // first two interrupt vectors get replaced with a jump to the bootloader's vector table
+ // remember vectors or the tinyvector table
+ if (currentAddress.w == RESET_VECTOR_OFFSET * 2) {
+ vectorTemp[0] = data;
+ data = 0xC000 + (BOOTLOADER_ADDRESS/2) - 1;
}
-
- 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);
+ if (currentAddress.w == USBPLUS_VECTOR_OFFSET * 2) {
+ vectorTemp[1] = data;
+ data = 0xC000 + (BOOTLOADER_ADDRESS/2) - 1;
+ }
- // increment progmem address by one word
- currentAddress += 2;
- SREG=previous_sreg;
+ // 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.w == BOOTLOADER_ADDRESS - TINYVECTOR_RESET_OFFSET) {
+ data = vectorTemp[0] + ((FLASHEND + 1) - BOOTLOADER_ADDRESS)/2 + 2 + RESET_VECTOR_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.w == BOOTLOADER_ADDRESS - TINYVECTOR_OSCCAL_OFFSET) {
+ data = OSCCAL;
+#endif
+ }
+
+ previous_sreg=SREG;
+ cli(); // ensure interrupts are disabled
+
+ boot_page_fill(currentAddress.w, data);
+
+ // increment progmem address by one word
+ currentAddress.w += 2;
+ SREG=previous_sreg;
}
+// This function is never called, it is just here to suppress a compiler warning.
+USB_PUBLIC usbMsgLen_t usbFunctionDescriptor(struct usbRequest *rq) { return 0; }
+
/* ------------------------------------------------------------------------ */
-static uchar usbFunctionSetup(uchar data[8]) {
- usbRequest_t *rq = (void *)data;
- ((uint8_t*)&idlePolls)[1] = 0; // reset idle polls when we get usb traffic
-
- static uchar replyBuffer[4] = {
- (((uint16_t)PROGMEM_SIZE) >> 8) & 0xff,
- ((uint16_t)PROGMEM_SIZE) & 0xff,
- SPM_PAGESIZE,
- MICRONUCLEUS_WRITE_SLEEP
- };
-
- if (rq->bRequest == 0) { // get device info
- usbMsgPtr = replyBuffer;
- return 4;
-
- } else if (rq->bRequest == 1) { // write page
- currentAddress = rq->wIndex.word;
- return USB_NO_MSG; // hands off work to usbFunctionWrite
-
- } else if (rq->bRequest == 2) { // erase application
- fireEvent(EVENT_ERASE_APPLICATION);
-
- } else { // exit bootloader
-# if BOOTLOADER_CAN_EXIT
- fireEvent(EVENT_EXECUTE);
-# endif
- }
-
+static uint8_t usbFunctionSetup(uint8_t data[8]) {
+ usbRequest_t *rq = (void *)data;
+
+ static uint8_t replyBuffer[4] = {
+ (((uint16_t)PROGMEM_SIZE) >> 8) & 0xff,
+ ((uint16_t)PROGMEM_SIZE) & 0xff,
+ SPM_PAGESIZE,
+ MICRONUCLEUS_WRITE_SLEEP
+ };
+
+ 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;
+ } else if (rq->bRequest == cmd_transfer_page) { // transfer 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.w = rq->wIndex.word;
+ return USB_NO_MSG; // hands off work to usbFunctionWrite
+ } else {
+ // Handle cmd_erase_application and cmd_exit
+ command=rq->bRequest;
return 0;
+ }
}
// read in a page over usb, and write it in to the flash write buffer
-static uchar usbFunctionWrite(uchar *data, uchar length) {
- do {
- // make sure we don't write over the bootloader!
- if (currentAddress >= BOOTLOADER_ADDRESS) break;
-
- writeWordToPageBuffer(*(uint16_t *) data);
- data += 2; // advance data pointer
- length -= 2;
- } while(length);
+static uint8_t usbFunctionWrite(uint8_t *data, uint8_t length) {
+ do {
+ // make sure we don't write over the bootloader!
+ if (currentAddress.w >= BOOTLOADER_ADDRESS) break;
- // 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);
-#else
- uchar isLast = ((currentAddress % SPM_PAGESIZE) == 0);
-#endif
-
- // definitely need this if! seems usbFunctionWrite gets called again in future usbPoll's in the runloop!
- if (isLast) fireEvent(EVENT_WRITE_PAGE); // ask runloop to write our page
-
- return isLast; // let vusb know we're done with this request
+ writeWordToPageBuffer(*(uint16_t *) data);
+ data += 2; // advance data pointer
+ length -= 2;
+ } while(length);
+
+ // if we have now reached another page boundary, we're done
+ uint8_t isLast = ((currentAddress.b[0] % SPM_PAGESIZE) == 0);
+ if (isLast) command=cmd_write_page; // ask runloop to write our page
+
+ return isLast; // let V-USB know we're done with this request
}
/* ------------------------------------------------------------------------ */
@@ -229,122 +212,109 @@ void PushMagicWord (void) __attribute__ ((naked)) __attribute__ ((section (".ini
// put the word "B007" at the bottom of the stack (RAMEND - RAMEND-1)
void PushMagicWord (void) {
- asm volatile("ldi r16, 0xB0"::);
- asm volatile("push r16"::);
- asm volatile("ldi r16, 0x07"::);
- asm volatile("push r16"::);
+ asm volatile("ldi r16, 0xB0"::);
+ asm volatile("push r16"::);
+ asm volatile("ldi r16, 0x07"::);
+ asm volatile("push r16"::);
+}
+
+static void initHardware (void)
+{
+ // Disable watchdog and set timeout to maximum in case the WDT is fused on
+ MCUSR=0;
+ WDTCR = 1<<WDCE | 1<<WDE;
+ WDTCR = 1<<WDP2 | 1<<WDP1 | 1<<WDP0;
+
+ /* initialize */
+ #if OSCCAL_RESTORE
+ osccal_default = OSCCAL;
+ #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
-
- bootLoaderExit();
- cli();
- usbDeviceDisconnect(); /* Disconnect micronucleus */
-
- USB_INTR_ENABLE = 0;
- USB_INTR_CFG = 0; /* also reset config bits */
+
+ bootLoaderExit();
+ cli();
+ usbDeviceDisconnect(); /* Disconnect micronucleus */
- // clear magic word from bottom of stack before jumping to the app
- *(uint8_t*)(RAMEND) = 0x00; // A single write is sufficient to invalidate magic word
+ USB_INTR_ENABLE = 0;
+ USB_INTR_CFG = 0; /* also reset config bits */
+
+ // clear magic word from bottom of stack before jumping to the app
+ *(uint8_t*)(RAMEND) = 0x00; // A single write is sufficient to invalidate magic word
-#if (!OSCCAL_RESTORE) && OSCCAL_16_5MHz
+ #if OSCCAL_RESTORE
+ OSCCAL=osccal_default;
+ nop(); // NOP to avoid CPU hickup during oscillator stabilization
+ #elif OSCCAL_16_5MHz
// adjust clock to previous calibration value, so user program always starts with same calibration
// 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;
+ nop();
}
-#endif
- // jump to application reset vector at end of flash
- asm volatile ("rjmp __vectors - 4");
+ #endif
+
+ asm volatile ("rjmp __vectors - 4"); // jump to application reset vector at end of flash
+
+ for (;;); // Make sure function does not return to help compiler optimize
}
int main(void) {
- /* initialize */
- #if OSCCAL_RESTORE
- osccal_default = OSCCAL;
- #endif
- #if (!SET_CLOCK_PRESCALER) && LOW_POWER_MODE
- uint8_t prescaler_default = CLKPR;
- #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
+ bootLoaderInit();
+
+ if (bootLoaderStartCondition()||(pgm_read_byte(BOOTLOADER_ADDRESS - TINYVECTOR_RESET_OFFSET + 1)==0xff)) {
+
+ initHardware();
+ LED_INIT();
- 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
-
-# if LED_PRESENT
- LED_INIT();
-# endif
-
- usbDeviceDisconnect(); /* do this while interrupts are disabled */
- _delay_ms(500);
- usbDeviceConnect();
- usbInit(); // Initialize INT settings after reconnect
- sei();
-
- 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();
-
-# if LED_PRESENT
- LED_MACRO( ((uint8_t*)&idlePolls)[1] )
-# endif
-
- } while(bootLoaderCondition()); /* main event loop runs so long as bootLoaderCondition remains truthy */
+ 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;
}
- // set clock prescaler to desired clock speed (changing from clkdiv8, or no division, depending on fuses)
- #if LOW_POWER_MODE
- #ifdef SET_CLOCK_PRESCALER
- CLKPR = 1 << CLKPCE;
- CLKPR = SET_CLOCK_PRESCALER;
- #else
- CLKPR = 1 << CLKPCE;
- CLKPR = prescaler_default;
- #endif
- #endif
-
-# if LED_PRESENT
- LED_EXIT();
-# endif
-
-# if OSCCAL_RESTORE
- OSCCAL=osccal_default;
- asm volatile("nop"); // NOP to avoid CPU hickup during oscillator stabilization
-# endif
+ do {
+ _delay_us(100);
+ wdt_reset(); // Only necessary if WDT is fused on
+
+ command=cmd_local_nop;
+ usbPoll();
+
+ idlePolls.w++;
+
+ // Try to execute program if bootloader exit condition is met
+ if (AUTO_EXIT_MS&&(idlePolls.w==AUTO_EXIT_MS*10L)) command=cmd_exit;
+
+ LED_MACRO( idlePolls.b[1] );
- leaveBootloader();
+ // 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.
+ if (command!=cmd_local_nop) _delay_ms(2);
+
+ if (command==cmd_erase_application)
+ eraseApplication();
+ else if (command==cmd_write_page)
+ writeFlashPage();
+
+ /* main event loop runs as long as no problem is uploaded or existing program is not executed */
+ } while((command!=cmd_exit)||(pgm_read_byte(BOOTLOADER_ADDRESS - TINYVECTOR_RESET_OFFSET + 1)==0xff));
+
+ LED_EXIT();
+ }
+
+ leaveBootloader();
}
/* ------------------------------------------------------------------------ */
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
diff --git a/firmware/releases/micronucleus-1.11-entry_ext_reset.hex b/firmware/releases/micronucleus-1.11-entry_ext_reset.hex
new file mode 100644
index 0000000..7389281
--- /dev/null
+++ b/firmware/releases/micronucleus-1.11-entry_ext_reset.hex
@@ -0,0 +1,119 @@
+:0800000077CC76CCACCC74CCBB
+:1018C00017C016C04CC014C00902120001010080EC
+:1018D0003209040000000000000012011001FF00A6
+:1018E0000008D01653070B0100000001040309048F
+:1018F00011241FBECFE5D2E0CDBFDEBF00EB0F93BA
+:1019000007E00F9310E0A0E6B0E0E8EEFFE102C0D0
+:1019100005900D92A636B107D9F720E0A6E6B0E013
+:1019200001C01D92A639B207E1F7E2C1A82FB92F75
+:1019300080E090E041E050EA609530E009C02D91F0
+:1019400082279795879510F084279527305EC8F3F6
+:101950006F5FA8F30895EADF8D939D930895CF9369
+:10196000CFB7CF93C0915F02C03B21F4C0915E021C
+:10197000C73021F0CF91CFBFCF91A1CFCC27C39556
+:10198000B39BE9F7B39B0BC0B39B09C0B39B07C0E4
+:10199000B39B05C0B39B03C0B39B01C0D3C00F92E0
+:1019A000DF93C0917900DD27C058DF4F012EB39B34
+:1019B00003C0DF910F90E6CF2F930F931F934F93A8
+:1019C0002FEF4F6F06B303FB20F95F933F9350E077
+:1019D0003BE065C016B30126502953FDC89556B3A8
+:1019E000012703FB25F92F7306B3B1F05027102709
+:1019F00013FB26F906B22230F0F000C016B301271F
+:101A000003FB27F90126502906B22430E8F54F7769
+:101A1000206816B30000F6CF50274F7D206206B233
+:101A2000102F000000C006B300265029102713FB1A
+:101A300026F906B2E2CF4F7B06B3206400C0DACFAE
+:101A400001265029187106B269F14E7F2160012FDD
+:101A500016B328C0002650294D7F06B22260102FF1
+:101A600029C0012650294B7F06B22460012F2DC0CA
+:101A700016B301265029477F2860000006B22EC009
+:101A80004F7E06B3206130C0422706B3499300263B
+:101A90005029102706B24FEF13FB20F9297F16B308
+:101AA00079F2187159F10126502906B2012703FB7A
+:101AB00021F9237F06B371F2002650293150D0F06E
+:101AC00006B2102713FB22F9277E16B351F2012626
+:101AD0005029012703FB06B223F92F7C49F20000AD
+:101AE00006B3102713FB24F90026502906B22F79DC
+:101AF00039F270CF10E21ABF002717C03B50319562
+:101B0000C31BD04010E21ABF0881033CF9F00B342C
+:101B1000E9F0209177001981110F1213EDCF0936EA
+:101B200051F10D3211F0013E39F700937E003F91E3
+:101B30005F914F911F910F912F91DF910F90CAB735
+:101B4000C5FD1DCFCF91CFBFCF91189520917E00BD
+:101B5000222369F310917C00112321F5343022F106
+:101B600030937C0020937800109179003BE0311B8A
+:101B70003093790019C000917C0001309CF40AE593
+:101B80003091600034FD11C000936000CCE6D0E0DD
+:101B900010C0052710E000C021C0052710E0C8953F
+:101BA00008BB14C03AE501C032ED032EC0E0D0E01E
+:101BB00032E017B31861C39A08B317BB58E120E8A5
+:101BC0004FEF20FF052708BB279517951C3F28F7E7
+:101BD00000004552B0F720FF0527279508BB179551
+:101BE0001C3FB8F629913A9561F7077E10917D0068
+:101BF000110F08BBC250D04011F01093770010E2D3
+:101C00001ABF086017B3177E402F477E54E05A95DD
+:101C1000F1F708BB17BB48BB8ACFF8942FEFB0E8A9
+:101C2000A0E44AE0B1BF000081EE9CE0B399FECF92
+:101C3000B39BFECF0197B399FDCF97FF03C0BA1BAB
+:101C4000819501C0BA0FA69529F4281710F031B775
+:101C5000282FA1E0415031F731BF0000789408955A
+:101C6000F894F201329785E080935700E8957894D4
+:101C70000895F201309729F49093680080936700EB
+:101C800007C0E430F10539F490936A00809369004D
+:101C90008FE59CEC1FC02CEB421628E1520639F46C
+:101CA00080916700909168008E559C4F13C02EEB79
+:101CB000421628E1520639F48091690090916A0039
+:101CC0008D559C4F07C02AEB421628E1520611F4AD
+:101CD00081B790E02FB7F89431E00C0130935700B2
+:101CE000E89511242F0182E0480E511C2FBF089562
+:101CF00004B601FC14C0EDEBF8E1E491EF3F79F09C
+:101D0000F894BB9A1BBE15BA10925F02EAEBF8E199
+:101D1000E4918E2F81508E3F08F462C163C114BEDE
+:101D200088E181BD87E081BDBB9A88E893E1ECE959
+:101D3000F1E03197F1F70197D1F7BB98AC9A8BB7E7
+:101D400080628BBF7894712C8CE991E00197F1F758
+:101D5000A895312C60917C00162F135017FDB2C04E
+:101D600080917900CCE0D0E0C81BD109C058DF4F8A
+:101D70006150CE01DBDD8E3F9F4409F0A1C0809110
+:101D800078008D3209F085C0183009F099C083ECD5
+:101D900080936C008AE580936000109266009881C1
+:101DA000292F207689812223D1F0712C811108C03E
+:101DB00082E690E090937B0080937A0024E05FC0FD
+:101DC000813051F481E180935700E8954C805D802B
+:101DD00097FD50C02FEF4FC0382E20E050C09A81A1
+:101DE00010927500811106C01092760085E790E090
+:101DF00022E03BC0853019F490937D002CC08630E2
+:101E000009F58B81813019F48AED98E104C08230A4
+:101E100041F488EC98E190937B0080937A0022E172
+:101E20000DC0833051F4911108C08CEE98E190936D
+:101E30007B0080937A0024E001C020E080E480935E
+:101E400066001DC0883059F0893019F490937F00E6
+:101E500002C08A3039F085E790E020E006C08FE7C5
+:101E600090E002C085E790E021E090937B008093B2
+:101E70007A0005C02E8180E88093660007C08F81BC
+:101E8000811104C08E81821708F4282F20936100ED
+:101E900017C08091660087FF13C080EC481688E168
+:101EA000580620F0842D8F7339F00AC089919991DA
+:101EB000E0DE125091F7F6CF95E0392E10926100D6
+:101EC00010927C008091600084FF42C0809161008C
+:101ED0008F3F09F43DC0182F893008F018E0811BAE
+:101EE0008093610080916C0098E8892780936C0052
+:101EF000112311F1E0917A00F0917B00809166004E
+:101F000086FF0BC0ADE6B0E084918D9331968DE6EF
+:101F100090E0810F8A13F8CF0BC0EF01ADE6B0E07F
+:101F200089918D93FE018DE690E0810F8A13F8CFA1
+:101F3000F0937B00E0937A00612F8DE690E00BDD5B
+:101F40001C5F1C3019F08FEF8093610010936000CC
+:101F500084E196B3987131F48150D9F710927D00E5
+:101F600010927700C1E08111C0E080916B008C1766
+:101F700029F0C11101C051DEC0936B00C30101966D
+:101F80003C018035934C11F484E0382E232D33200E
+:101F9000E9F08AE390E20197F1F72230A9F4F8948E
+:101FA000E0ECF8E1E054F10983E080935700E89514
+:101FB0003097C1F7412C512CC8E08FEF9FEF59DECD
+:101FC000C150D9F74DDE02C02530E1F384E038126C
+:101FD000BBCEEDEBF8E1E491EF3F09F4B5CE90CE46
+:081FE000E1BF00006BCCFFCF54
+:061FE8005AFF18BA400880
+:04000003000018C021
+:00000001FF
diff --git a/firmware/releases/micronucleus-1.11-entry_jumper_pb0.hex b/firmware/releases/micronucleus-1.11-entry_jumper_pb0.hex
new file mode 100644
index 0000000..96a101c
--- /dev/null
+++ b/firmware/releases/micronucleus-1.11-entry_jumper_pb0.hex
@@ -0,0 +1,120 @@
+:0800000077CC76CCACCC74CCBB
+:1018C00017C016C04CC014C00902120001010080EC
+:1018D0003209040000000000000012011001FF00A6
+:1018E0000008D01653070B0100000001040309048F
+:1018F00011241FBECFE5D2E0CDBFDEBF00EB0F93BA
+:1019000007E00F9310E0A0E6B0E0E4EFFFE102C0D3
+:1019100005900D92A636B107D9F720E0A6E6B0E013
+:1019200001C01D92A639B207E1F7E2C1A82FB92F75
+:1019300080E090E041E050EA609530E009C02D91F0
+:1019400082279795879510F084279527305EC8F3F6
+:101950006F5FA8F30895EADF8D939D930895CF9369
+:10196000CFB7CF93C0915F02C03B21F4C0915E021C
+:10197000C73021F0CF91CFBFCF91A1CFCC27C39556
+:10198000B39BE9F7B39B0BC0B39B09C0B39B07C0E4
+:10199000B39B05C0B39B03C0B39B01C0D3C00F92E0
+:1019A000DF93C0917900DD27C058DF4F012EB39B34
+:1019B00003C0DF910F90E6CF2F930F931F934F93A8
+:1019C0002FEF4F6F06B303FB20F95F933F9350E077
+:1019D0003BE065C016B30126502953FDC89556B3A8
+:1019E000012703FB25F92F7306B3B1F05027102709
+:1019F00013FB26F906B22230F0F000C016B301271F
+:101A000003FB27F90126502906B22430E8F54F7769
+:101A1000206816B30000F6CF50274F7D206206B233
+:101A2000102F000000C006B300265029102713FB1A
+:101A300026F906B2E2CF4F7B06B3206400C0DACFAE
+:101A400001265029187106B269F14E7F2160012FDD
+:101A500016B328C0002650294D7F06B22260102FF1
+:101A600029C0012650294B7F06B22460012F2DC0CA
+:101A700016B301265029477F2860000006B22EC009
+:101A80004F7E06B3206130C0422706B3499300263B
+:101A90005029102706B24FEF13FB20F9297F16B308
+:101AA00079F2187159F10126502906B2012703FB7A
+:101AB00021F9237F06B371F2002650293150D0F06E
+:101AC00006B2102713FB22F9277E16B351F2012626
+:101AD0005029012703FB06B223F92F7C49F20000AD
+:101AE00006B3102713FB24F90026502906B22F79DC
+:101AF00039F270CF10E21ABF002717C03B50319562
+:101B0000C31BD04010E21ABF0881033CF9F00B342C
+:101B1000E9F0209177001981110F1213EDCF0936EA
+:101B200051F10D3211F0013E39F700937E003F91E3
+:101B30005F914F911F910F912F91DF910F90CAB735
+:101B4000C5FD1DCFCF91CFBFCF91189520917E00BD
+:101B5000222369F310917C00112321F5343022F106
+:101B600030937C0020937800109179003BE0311B8A
+:101B70003093790019C000917C0001309CF40AE593
+:101B80003091600034FD11C000936000CCE6D0E0DD
+:101B900010C0052710E000C021C0052710E0C8953F
+:101BA00008BB14C03AE501C032ED032EC0E0D0E01E
+:101BB00032E017B31861C39A08B317BB58E120E8A5
+:101BC0004FEF20FF052708BB279517951C3F28F7E7
+:101BD00000004552B0F720FF0527279508BB179551
+:101BE0001C3FB8F629913A9561F7077E10917D0068
+:101BF000110F08BBC250D04011F01093770010E2D3
+:101C00001ABF086017B3177E402F477E54E05A95DD
+:101C1000F1F708BB17BB48BB8ACFF8942FEFB0E8A9
+:101C2000A0E44AE0B1BF000081EE9CE0B399FECF92
+:101C3000B39BFECF0197B399FDCF97FF03C0BA1BAB
+:101C4000819501C0BA0FA69529F4281710F031B775
+:101C5000282FA1E0415031F731BF0000789408955A
+:101C6000F894F201329785E080935700E8957894D4
+:101C70000895F201309729F49093680080936700EB
+:101C800007C0E430F10539F490936A00809369004D
+:101C90008FE59CEC1FC02CEB421628E1520639F46C
+:101CA00080916700909168008E559C4F13C02EEB79
+:101CB000421628E1520639F48091690090916A0039
+:101CC0008D559C4F07C02AEB421628E1520611F4AD
+:101CD00081B790E02FB7F89431E00C0130935700B2
+:101CE000E89511242F0182E0480E511C2FBF089562
+:101CF000B898C09A8DE190E10197F1F7B09B15C0BB
+:101D0000EDEBF8E1E491EF3F81F0C098F894BB9AD5
+:101D10001BBE15BA10925F02EAEBF8E1E4918E2F38
+:101D200081508E3F08F462C163C114BE88E181BD59
+:101D300087E081BDBB9A88E893E1ECE9F1E0319757
+:101D4000F1F70197D1F7BB98AC9A8BB780628BBF44
+:101D50007894712C8CE991E00197F1F7A895312CDA
+:101D600060917C00162F135017FDB2C0809179004E
+:101D7000CCE0D0E0C81BD109C058DF4F6150CE0184
+:101D8000D5DD8E3F9F4409F0A1C0809178008D324F
+:101D900009F085C0183009F099C083EC80936C007D
+:101DA0008AE580936000109266009881292F207642
+:101DB00089812223D1F0712C811108C082E690E044
+:101DC00090937B0080937A0024E05FC0813051F4CF
+:101DD00081E180935700E8954C805D8097FD50C06D
+:101DE0002FEF4FC0382E20E050C09A81109275001E
+:101DF000811106C01092760085E790E022E03BC09A
+:101E0000853019F490937D002CC0863009F58B81C4
+:101E1000813019F48AED98E104C0823041F488ECF5
+:101E200098E190937B0080937A0022E10DC083308B
+:101E300051F4911108C08CEE98E190937B0080934F
+:101E40007A0024E001C020E080E4809366001DC099
+:101E5000883059F0893019F490937F0002C08A309D
+:101E600039F085E790E020E006C08FE790E002C0FF
+:101E700085E790E021E090937B0080937A0005C095
+:101E80002E8180E88093660007C08F81811104C095
+:101E90008E81821708F4282F2093610017C080914B
+:101EA000660087FF13C080EC481688E1580620F0D2
+:101EB000842D8F7339F00AC089919991DADE12501E
+:101EC00091F7F6CF95E0392E1092610010927C00C8
+:101ED0008091600084FF42C0809161008F3F09F4CF
+:101EE0003DC0182F893008F018E0811B80936100F5
+:101EF00080916C0098E8892780936C00112311F180
+:101F0000E0917A00F0917B008091660086FF0BC023
+:101F1000ADE6B0E084918D9331968DE690E0810F2F
+:101F20008A13F8CF0BC0EF01ADE6B0E089918D9335
+:101F3000FE018DE690E0810F8A13F8CFF0937B00CD
+:101F4000E0937A00612F8DE690E005DD1C5F1C3088
+:101F500019F08FEF809361001093600084E196B3D5
+:101F6000987131F48150D9F710927D00109277006A
+:101F7000C1E08111C0E080916B008C1729F0C11184
+:101F800001C04BDEC0936B00C30101963C0180355C
+:101F9000934C11F484E0382E232D3320E9F08AE3AA
+:101FA00090E20197F1F72230A9F4F894E0ECF8E11F
+:101FB000E054F10983E080935700E8953097C1F72A
+:101FC000412C512CC8E08FEF9FEF53DEC150D9F761
+:101FD00047DE02C02530E1F384E03812BBCEEDEBE2
+:101FE000F8E1E491EF3F09F4B5CE8FCEE1BF0000F8
+:041FF00065CCFFCFEE
+:061FF4005AFF18BA400874
+:04000003000018C021
+:00000001FF
diff --git a/firmware/releases/micronucleus-1.11-ledpb1.hex b/firmware/releases/micronucleus-1.11-ledpb1.hex
new file mode 100644
index 0000000..3397f3e
--- /dev/null
+++ b/firmware/releases/micronucleus-1.11-ledpb1.hex
@@ -0,0 +1,119 @@
+:0800000077CC76CCACCC74CCBB
+:1018C00017C016C04CC014C00902120001010080EC
+:1018D0003209040000000000000012011001FF00A6
+:1018E0000008D01653070B0100000001040309048F
+:1018F00011241FBECFE5D2E0CDBFDEBF00EB0F93BA
+:1019000007E00F9310E0A0E6B0E0E2EEFFE102C0D6
+:1019100005900D92A636B107D9F720E0A6E6B0E013
+:1019200001C01D92A639B207E1F7E2C1A82FB92F75
+:1019300080E090E041E050EA609530E009C02D91F0
+:1019400082279795879510F084279527305EC8F3F6
+:101950006F5FA8F30895EADF8D939D930895CF9369
+:10196000CFB7CF93C0915F02C03B21F4C0915E021C
+:10197000C73021F0CF91CFBFCF91A1CFCC27C39556
+:10198000B39BE9F7B39B0BC0B39B09C0B39B07C0E4
+:10199000B39B05C0B39B03C0B39B01C0D3C00F92E0
+:1019A000DF93C0917900DD27C058DF4F012EB39B34
+:1019B00003C0DF910F90E6CF2F930F931F934F93A8
+:1019C0002FEF4F6F06B303FB20F95F933F9350E077
+:1019D0003BE065C016B30126502953FDC89556B3A8
+:1019E000012703FB25F92F7306B3B1F05027102709
+:1019F00013FB26F906B22230F0F000C016B301271F
+:101A000003FB27F90126502906B22430E8F54F7769
+:101A1000206816B30000F6CF50274F7D206206B233
+:101A2000102F000000C006B300265029102713FB1A
+:101A300026F906B2E2CF4F7B06B3206400C0DACFAE
+:101A400001265029187106B269F14E7F2160012FDD
+:101A500016B328C0002650294D7F06B22260102FF1
+:101A600029C0012650294B7F06B22460012F2DC0CA
+:101A700016B301265029477F2860000006B22EC009
+:101A80004F7E06B3206130C0422706B3499300263B
+:101A90005029102706B24FEF13FB20F9297F16B308
+:101AA00079F2187159F10126502906B2012703FB7A
+:101AB00021F9237F06B371F2002650293150D0F06E
+:101AC00006B2102713FB22F9277E16B351F2012626
+:101AD0005029012703FB06B223F92F7C49F20000AD
+:101AE00006B3102713FB24F90026502906B22F79DC
+:101AF00039F270CF10E21ABF002717C03B50319562
+:101B0000C31BD04010E21ABF0881033CF9F00B342C
+:101B1000E9F0209177001981110F1213EDCF0936EA
+:101B200051F10D3211F0013E39F700937E003F91E3
+:101B30005F914F911F910F912F91DF910F90CAB735
+:101B4000C5FD1DCFCF91CFBFCF91189520917E00BD
+:101B5000222369F310917C00112321F5343022F106
+:101B600030937C0020937800109179003BE0311B8A
+:101B70003093790019C000917C0001309CF40AE593
+:101B80003091600034FD11C000936000CCE6D0E0DD
+:101B900010C0052710E000C021C0052710E0C8953F
+:101BA00008BB14C03AE501C032ED032EC0E0D0E01E
+:101BB00032E017B31861C39A08B317BB58E120E8A5
+:101BC0004FEF20FF052708BB279517951C3F28F7E7
+:101BD00000004552B0F720FF0527279508BB179551
+:101BE0001C3FB8F629913A9561F7077E10917D0068
+:101BF000110F08BBC250D04011F01093770010E2D3
+:101C00001ABF086017B3177E402F477E54E05A95DD
+:101C1000F1F708BB17BB48BB8ACFF8942FEFB0E8A9
+:101C2000A0E44AE0B1BF000081EE9CE0B399FECF92
+:101C3000B39BFECF0197B399FDCF97FF03C0BA1BAB
+:101C4000819501C0BA0FA69529F4281710F031B775
+:101C5000282FA1E0415031F731BF0000789408955A
+:101C6000F894F201329785E080935700E8957894D4
+:101C70000895F201309729F49093680080936700EB
+:101C800007C0E430F10539F490936A00809369004D
+:101C90008FE59CEC1FC02CEB421628E1520639F46C
+:101CA00080916700909168008E559C4F13C02EEB79
+:101CB000421628E1520639F48091690090916A0039
+:101CC0008D559C4F07C02AEB421628E1520611F4AD
+:101CD00081B790E02FB7F89431E00C0130935700B2
+:101CE000E89511242F0182E0480E511C2FBF089562
+:101CF00014BE88E181BD87E081BDBB9A88E893E18D
+:101D0000ECE9F1E03197F1F70197D1F7BB98AC9A84
+:101D10008BB780628BBF7894C198712C8CE991E06D
+:101D20000197F1F7A895312C60917C00162F135084
+:101D300017FDB2C080917900CCE0D0E0C81BD1097A
+:101D4000C058DF4F6150CE01F1DD8E3F9F4409F056
+:101D5000A1C0809178008D3209F085C0183009F05B
+:101D600099C083EC80936C008AE5809360001092A8
+:101D700066009881292F207689812223D1F0712C49
+:101D8000811108C082E690E090937B0080937A00F6
+:101D900024E05FC0813051F481E180935700E895E1
+:101DA0004C805D8097FD50C02FEF4FC0382E20E053
+:101DB00050C09A8110927500811106C01092760071
+:101DC00085E790E022E03BC0853019F490937D00D8
+:101DD0002CC0863009F58B81813019F48AED98E1A9
+:101DE00004C0823041F488EC98E190937B008093AA
+:101DF0007A0022E10DC0833051F4911108C08CEEBD
+:101E000098E190937B0080937A0024E001C020E069
+:101E100080E4809366001DC0883059F0893019F441
+:101E200090937F0002C08A3039F085E790E020E08F
+:101E300006C08FE790E002C085E790E021E0909334
+:101E40007B0080937A0005C02E8180E88093660035
+:101E500007C08F81811104C08E81821708F4282F5A
+:101E60002093610017C08091660087FF13C080EC4B
+:101E7000481688E1580620F0842D8F7339F00AC087
+:101E800089919991F6DE125091F7F6CF95E0392EAF
+:101E90001092610010927C008091600084FF42C02B
+:101EA000809161008F3F09F43DC0182F893008F000
+:101EB00018E0811B8093610080916C0098E889276D
+:101EC00080936C00112311F1E0917A00F0917B0076
+:101ED0008091660086FF0BC0ADE6B0E084918D93E3
+:101EE00031968DE690E0810F8A13F8CF0BC0EF0199
+:101EF000ADE6B0E089918D93FE018DE690E0810F13
+:101F00008A13F8CFF0937B00E0937A00612F8DE67F
+:101F100090E021DD1C5F1C3019F08FEF8093610091
+:101F20001093600084E196B3987131F48150D9F731
+:101F300010927D0010927700C1E08111C0E0809185
+:101F40006B008C1729F0C11101C067DEC0936B00D4
+:101F5000C30101963C018035934C11F484E0382E86
+:101F6000872D8D7011F0B99801C0B99A232D3320B7
+:101F7000E9F08AE390E20197F1F72230A9F4F894AE
+:101F8000E0ECF8E1E054F10983E080935700E89534
+:101F90003097C1F7412C512CC8E08FEF9FEF69DEDD
+:101FA000C150D9F75DDE02C02530E1F384E038127C
+:101FB000B5CEEDEBF8E1E491EF3F09F4AFCEB9987F
+:101FC000F894BB9A1BBE15BA10925F02EAEBF8E1D7
+:101FD000E4918E2F81508E3F10F4E1BF00006ECC53
+:021FE000FFCF31
+:061FE2005AFF18BA400886
+:04000003000018C021
+:00000001FF
diff --git a/firmware/releases/micronucleus-1.11.hex b/firmware/releases/micronucleus-1.11.hex
new file mode 100644
index 0000000..dd31260
--- /dev/null
+++ b/firmware/releases/micronucleus-1.11.hex
@@ -0,0 +1,118 @@
+:0800000077CC76CCACCC74CCBB
+:1018C00017C016C04CC014C00902120001010080EC
+:1018D0003209040000000000000012011001FF00A6
+:1018E0000008D01653070B0100000001040309048F
+:1018F00011241FBECFE5D2E0CDBFDEBF00EB0F93BA
+:1019000007E00F9310E0A0E6B0E0E2EDFFE102C0D7
+:1019100005900D92A636B107D9F720E0A6E6B0E013
+:1019200001C01D92A639B207E1F7E2C1A82FB92F75
+:1019300080E090E041E050EA609530E009C02D91F0
+:1019400082279795879510F084279527305EC8F3F6
+:101950006F5FA8F30895EADF8D939D930895CF9369
+:10196000CFB7CF93C0915F02C03B21F4C0915E021C
+:10197000C73021F0CF91CFBFCF91A1CFCC27C39556
+:10198000B39BE9F7B39B0BC0B39B09C0B39B07C0E4
+:10199000B39B05C0B39B03C0B39B01C0D3C00F92E0
+:1019A000DF93C0917900DD27C058DF4F012EB39B34
+:1019B00003C0DF910F90E6CF2F930F931F934F93A8
+:1019C0002FEF4F6F06B303FB20F95F933F9350E077
+:1019D0003BE065C016B30126502953FDC89556B3A8
+:1019E000012703FB25F92F7306B3B1F05027102709
+:1019F00013FB26F906B22230F0F000C016B301271F
+:101A000003FB27F90126502906B22430E8F54F7769
+:101A1000206816B30000F6CF50274F7D206206B233
+:101A2000102F000000C006B300265029102713FB1A
+:101A300026F906B2E2CF4F7B06B3206400C0DACFAE
+:101A400001265029187106B269F14E7F2160012FDD
+:101A500016B328C0002650294D7F06B22260102FF1
+:101A600029C0012650294B7F06B22460012F2DC0CA
+:101A700016B301265029477F2860000006B22EC009
+:101A80004F7E06B3206130C0422706B3499300263B
+:101A90005029102706B24FEF13FB20F9297F16B308
+:101AA00079F2187159F10126502906B2012703FB7A
+:101AB00021F9237F06B371F2002650293150D0F06E
+:101AC00006B2102713FB22F9277E16B351F2012626
+:101AD0005029012703FB06B223F92F7C49F20000AD
+:101AE00006B3102713FB24F90026502906B22F79DC
+:101AF00039F270CF10E21ABF002717C03B50319562
+:101B0000C31BD04010E21ABF0881033CF9F00B342C
+:101B1000E9F0209177001981110F1213EDCF0936EA
+:101B200051F10D3211F0013E39F700937E003F91E3
+:101B30005F914F911F910F912F91DF910F90CAB735
+:101B4000C5FD1DCFCF91CFBFCF91189520917E00BD
+:101B5000222369F310917C00112321F5343022F106
+:101B600030937C0020937800109179003BE0311B8A
+:101B70003093790019C000917C0001309CF40AE593
+:101B80003091600034FD11C000936000CCE6D0E0DD
+:101B900010C0052710E000C021C0052710E0C8953F
+:101BA00008BB14C03AE501C032ED032EC0E0D0E01E
+:101BB00032E017B31861C39A08B317BB58E120E8A5
+:101BC0004FEF20FF052708BB279517951C3F28F7E7
+:101BD00000004552B0F720FF0527279508BB179551
+:101BE0001C3FB8F629913A9561F7077E10917D0068
+:101BF000110F08BBC250D04011F01093770010E2D3
+:101C00001ABF086017B3177E402F477E54E05A95DD
+:101C1000F1F708BB17BB48BB8ACFF8942FEFB0E8A9
+:101C2000A0E44AE0B1BF000081EE9CE0B399FECF92
+:101C3000B39BFECF0197B399FDCF97FF03C0BA1BAB
+:101C4000819501C0BA0FA69529F4281710F031B775
+:101C5000282FA1E0415031F731BF0000789408955A
+:101C6000F894F201329785E080935700E8957894D4
+:101C70000895F201309729F49093680080936700EB
+:101C800007C0E430F10539F490936A00809369004D
+:101C90008FE59CEC1FC02CEB421628E1520639F46C
+:101CA00080916700909168008E559C4F13C02EEB79
+:101CB000421628E1520639F48091690090916A0039
+:101CC0008D559C4F07C02AEB421628E1520611F4AD
+:101CD00081B790E02FB7F89431E00C0130935700B2
+:101CE000E89511242F0182E0480E511C2FBF089562
+:101CF00014BE88E181BD87E081BDBB9A88E893E18D
+:101D0000ECE9F1E03197F1F70197D1F7BB98AC9A84
+:101D10008BB780628BBF7894712C8CE991E001972E
+:101D2000F1F7A895312C60917C00162F135017FD08
+:101D3000B2C080917900CCE0D0E0C81BD109C05876
+:101D4000DF4F6150CE01F2DD8E3F9F4409F0A1C00C
+:101D5000809178008D3209F085C0183009F099C063
+:101D600083EC80936C008AE580936000109266009B
+:101D70009881292F207689812223D1F0712C81111D
+:101D800008C082E690E090937B0080937A0024E084
+:101D90005FC0813051F481E180935700E8954C8019
+:101DA0005D8097FD50C02FEF4FC0382E20E050C00F
+:101DB0009A8110927500811106C01092760085E715
+:101DC00090E022E03BC0853019F490937D002CC058
+:101DD000863009F58B81813019F48AED98E104C0D1
+:101DE000823041F488EC98E190937B0080937A00F4
+:101DF00022E10DC0833051F4911108C08CEE98E1BE
+:101E000090937B0080937A0024E001C020E080E47E
+:101E1000809366001DC0883059F0893019F4909382
+:101E20007F0002C08A3039F085E790E020E006C0EC
+:101E30008FE790E002C085E790E021E090937B007F
+:101E400080937A0005C02E8180E88093660007C0E9
+:101E50008F81811104C08E81821708F4282F20936E
+:101E6000610017C08091660087FF13C080EC4816A0
+:101E700088E1580620F0842D8F7339F00AC08991CB
+:101E80009991F7DE125091F7F6CF95E0392E109226
+:101E9000610010927C008091600084FF42C08091BC
+:101EA00061008F3F09F43DC0182F893008F018E019
+:101EB000811B8093610080916C0098E88927809352
+:101EC0006C00112311F1E0917A00F0917B00809178
+:101ED000660086FF0BC0ADE6B0E084918D9331962D
+:101EE0008DE690E0810F8A13F8CF0BC0EF01ADE6CD
+:101EF000B0E089918D93FE018DE690E0810F8A1309
+:101F0000F8CFF0937B00E0937A00612F8DE690E0AC
+:101F100022DD1C5F1C3019F08FEF8093610010935D
+:101F2000600084E196B3987131F48150D9F7109232
+:101F30007D0010927700C1E08111C0E080916B00BC
+:101F40008C1729F0C11101C068DEC0936B00C3017A
+:101F500001963C018035934C11F484E0382E232DFA
+:101F60003320E9F08AE390E20197F1F72230A9F4F7
+:101F7000F894E0ECF8E1E054F10983E08093570035
+:101F8000E8953097C1F7412C512CC8E08FEF9FEFB7
+:101F900070DEC150D9F764DE02C02530E1F384E081
+:101FA0003812BBCEEDEBF8E1E491EF3F09F4B5CE8A
+:101FB000F894BB9A1BBE15BA10925F02EAEBF8E1E7
+:101FC000E4918E2F81508E3F10F4E1BF000076CC5B
+:021FD000FFCF41
+:061FD2005AFF18BA400896
+:04000003000018C021
+:00000001FF
diff --git a/firmware/releases/release notes.txt b/firmware/releases/release notes.txt
index 18deb4f..0b48044 100644
--- a/firmware/releases/release notes.txt
+++ b/firmware/releases/release notes.txt
@@ -1,10 +1,45 @@
+== 1.11 - 2013-01-04 ==
+Firmware:
+ o New features
+ - The bootloader will now always start if no user program was loaded, regardless of the
+ entry condition.
+ - The bootloader will not quit if no user program is loaded. This prevents periodic
+ re-enumeration of the bootloader and should make driver installation much easier.
+ THhe new "--erase-only" function of the commandline tool can be used to erase the
+ user program and create a stable device for easier installiation.
+ - New entry modes can be selected in "bootloader.h". Please read the comments for details.
+ + ENTRY_ALWAYS
+ + ENTRY_WATCHDOG
+ + ENTRY_EXT_RESET
+ + ENTRY_JUMPER
+ - The bootloader is now able to cope with a fused-on watch dog timer.
+ o Internal changes
+ - A CRC is now performed on all incoming USB traffic.
+ - The flash buffer is now cleaned before loading a page to prevent data corruption.
+ - Further size optimizations (62 bytes gained, despite new features)
+ + Changed event system into a directly mapped command system.
+ + Introduce union types and forced global variables to registers.
+ - More sourcecode cleaning up.
+ o Size is now 1816 bytes, 6380 bytes user space. Note that avr-objcopy reports 8 bytes
+ more due to the zero vector table which is overwritten by the userprogram.
+
+Commandline tool:
+ o New features (Note: All new features are compatible with previous firmware releases)
+ - Added "--erase-only" command to erase the device without writing a new user program.
+ - The commandline tool will not transfer empty memory pages any more, resulting in
+ a significantly reduced programming time in many cases.
+ - Client firmware version will now be displayed after connecting.
+ o Internal changes:
+ - Clean up of source code
+ - Bugfixes (see commits)
+
== 1.10rc3 - 2013-12-15 ==
firmware:
o Major reorganization of the source and build system.
- - Used own crt1.s to create vector table in the first flash-page.
- - Removed all functions related to vector-table writing.
- - Refactored code and inlined all functions that were only called once.
- - Removed redundantly defined types to avoid confusion. Only C99 types are used now.
+ - Used own crt1.s to create vector table in the first flash-page.
+ - Removed all functions related to vector-table writing.
+ - Refactored code and inlined all functions that were only called once.
+ - Removed redundantly defined types to avoid confusion. Only C99 types are used now.
o Size is now 1878 bytes, 6314 bytes user space. No changes to functionality.
== 1.10rc2 - 2013-11-25 ==
@@ -120,4 +155,4 @@ commandline's c library:
o Most recent build before next release where some subtle protocol changes took place
- \ No newline at end of file
+
diff --git a/firmware/usbconfig.h b/firmware/usbconfig.h
index 560c34d..dc5cafc 100644
--- a/firmware/usbconfig.h
+++ b/firmware/usbconfig.h
@@ -110,6 +110,12 @@
* for long transfers increases the driver size.
*/
/* #define USB_RX_USER_HOOK(data, len) if(usbRxToken == (uchar)USBPID_SETUP) blinkLED(); */
+
+// Check CRC of all received data
+#define USB_RX_USER_HOOK( data, len ) { \
+if ( usbCrc16( data, len + 2 ) != 0x4FFE )\
+return;\
+}
/* This macro is a hook if you want to do unconventional things. If it is
* defined, it's inserted at the beginning of received message processing.
* If you eat the received message and don't want default processing to
@@ -163,10 +169,15 @@
#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