summaryrefslogtreecommitdiffstats
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
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
-rw-r--r--.gitignore3
-rw-r--r--Readme.txt27
-rw-r--r--commandline/Makefile24
-rwxr-xr-xcommandline/builds/Mac/micronucleusbin20328 -> 0 bytes
-rwxr-xr-xcommandline/builds/OSX/micronucleusbin0 -> 124292 bytes
-rwxr-xr-xcommandline/builds/Windows/micronucleus.exebin70631 -> 26126 bytes
-rw-r--r--commandline/cdc232.hex173
-rw-r--r--commandline/library/micronucleus_lib.c53
-rw-r--r--commandline/littleWire_v11.hex356
-rw-r--r--commandline/micronucleus.c (renamed from commandline/examples/micronucleus.c)189
-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
-rw-r--r--upgrade/readme.txt16
-rw-r--r--upgrade/releases/micronucleus-1.11-entry-ext-reset-upgrade.hex165
-rw-r--r--upgrade/releases/micronucleus-1.11-entry-jumper-pb0-upgrade.hex166
-rw-r--r--upgrade/releases/micronucleus-1.11-ledpb1-upgrade.hex165
-rw-r--r--upgrade/releases/micronucleus-1.11-upgrade.hex164
30 files changed, 1750 insertions, 1452 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/Readme.txt b/Readme.txt
index e6f19ab..ac2d7db 100644
--- a/Readme.txt
+++ b/Readme.txt
@@ -11,26 +11,33 @@ Micronucleus is now widely installed on over 40,000 Digispark devices from Digis
Changes
=======
-This is release 1.10. Please use this at your own risk. The last official release for the DigiSpark is v1.06, which can be found here: https://github.com/micronucleus/micronucleus/tree/v1.06
-
+This is release 1.11. Please use this at your own risk. The last official release for the DigiSpark is v1.06, which can be found here: https://github.com/micronucleus/micronucleus/tree/v1.06
+
+Changes compared to v1.10:
+ • The size was reduced further to 1816 bytes, allowing 6380 bytes user space.
+ (320 bytes more than in v1.06)
+ • The bootloader will always start and never quit if no user program was loaded.
+ This allows for much easier driver installation. Use the new "--erase-only"
+ function of the command line tool to create a clean device.
+ • New entrymodes have been added. See firmware release notes and source code
+ comments for details.
+ • All incoming data is now CRC checked to improve robustness.
+
Changes compared to v1.06:
• Major size optimization and code reorganization.
- • The size was reduced to 1878 bytes, allowing 6314 bytes user space (256 bytes more than in v1.06).
+ • The size was reduced to 1878 bytes, allowing 6314 bytes user space
+ (256 bytes more than in v1.06).
• The bootloader will disconnect from USB on exit.
See release notes (/firmware/releases/release notes.txt) for details.
-@cpldcpu - Dec 15th, 2013
+@cpldcpu - Jan 14th, 2013
----------------------------------------------------------------------------------
-==================================================================================
-!!%$!^%%$!#%$@#!%$@!$#@!%$#@%!#@%$!@$%#@!$%%!$#^&%$!%(*$!^%#!$@!#%$*^%!!&^%!%@$#!^
-@#$%^&*%#$%^#($)#*&($^#^*%&%%&@$*#($^&^*@$#&%^*%&($^&#^*%&$(^^%@$&^*#%@%&$^#*%^*%&
-&$%#$&^&$%@&#$*^*##*$##^$&#^%$^&*$&^&^%$#^%$&*$&#^%$*^$#^&%$*%#^$&^*%$#^$*^$$&*%#$
-==================================================================================
-----------------------------------------------------------------------------------
Special Thanks:
+ • Shay Green/@gblargg for numerous optimization ideas.
+ • Aaron Stone/@sodabrew for building the OS X command line tool and various fixes.
• Objective Development's great V-USB bitbanging usb driver
• Embedded Creations' pioneering and inspiring USBaspLoader-tiny85
• Digistump for motivation and contributing the VID/PID pair
diff --git a/commandline/Makefile b/commandline/Makefile
index af9a9ee..3c52cb4 100644
--- a/commandline/Makefile
+++ b/commandline/Makefile
@@ -1,19 +1,25 @@
# Makefile initially writen for Little-Wire by Omer Kilic <omerkilic@gmail.com>
-# Later on modified by ihsan Kehribar <ihsan@kehribar.me> for Micronucleus bootloader application.
+# Later on modified by ihsan Kehribar <ihsan@kehribar.me> for Micronucleus bootloader application.
CC=gcc
-# FIXME: Need to add OSX stuff
ifeq ($(shell uname), Linux)
- USBFLAGS = `libusb-config --cflags`
- USBLIBS = `libusb-config --libs`
+ USBFLAGS=$(shell libusb-config --cflags)
+ USBLIBS=$(shell libusb-config --libs)
EXE_SUFFIX =
OSFLAG = -D LINUX
else ifeq ($(shell uname), Darwin)
- USBFLAGS = `libusb-config --cflags`
- USBLIBS = `libusb-config --libs`
+ USBFLAGS=$(shell libusb-config --cflags || libusb-legacy-config --cflags)
+ USBLIBS=$(shell libusb-config --libs || libusb-legacy-config --libs)
EXE_SUFFIX =
OSFLAG = -D MAC_OS
+ # Uncomment these to create a static binary:
+ # USBLIBS = /opt/local/lib/libusb-legacy/libusb-legacy.a
+ # USBLIBS += -mmacosx-version-min=10.5
+ # USBLIBS += -framework CoreFoundation
+ # USBLIBS += -framework IOKit
+ # Uncomment these to create a dual architecture binary:
+ # OSFLAG += -arch x86_64 -arch i386
else
USBFLAGS = -I C:\MinGW\include
USBLIBS = -L C:\MinGW\lib -lusb
@@ -36,11 +42,11 @@ library: $(LWLIBS)
$(LWLIBS):
@echo Building library: $@...
- $(CC) $(CFLAGS) -c library/$@.c
+ $(CC) $(CFLAGS) -c library/$@.c
$(EXAMPLES): $(addsuffix .o, $(LWLIBS))
- @echo Building example: $@...
- $(CC) $(CFLAGS) -o $@$(EXE_SUFFIX) examples/$@.c $^ $(LIBS)
+ @echo Building command line tool: $@...
+ $(CC) $(CFLAGS) -o $@$(EXE_SUFFIX) $@.c $^ $(LIBS)
clean:
rm -f $(EXAMPLES)$(EXE_SUFFIX) *.o *.exe
diff --git a/commandline/builds/Mac/micronucleus b/commandline/builds/Mac/micronucleus
deleted file mode 100755
index 057528a..0000000
--- a/commandline/builds/Mac/micronucleus
+++ /dev/null
Binary files differ
diff --git a/commandline/builds/OSX/micronucleus b/commandline/builds/OSX/micronucleus
new file mode 100755
index 0000000..3ae62c4
--- /dev/null
+++ b/commandline/builds/OSX/micronucleus
Binary files differ
diff --git a/commandline/builds/Windows/micronucleus.exe b/commandline/builds/Windows/micronucleus.exe
index 25b5ba4..bfdb56b 100755
--- a/commandline/builds/Windows/micronucleus.exe
+++ b/commandline/builds/Windows/micronucleus.exe
Binary files differ
diff --git a/commandline/cdc232.hex b/commandline/cdc232.hex
deleted file mode 100644
index 81fc38f..0000000
--- a/commandline/cdc232.hex
+++ /dev/null
@@ -1,173 +0,0 @@
-:1000000054C019C4F9C124C46BC06AC069C068C0B7
-:1000100067C066C065C064C063C062C03BC40403FF
-:10002000090422037700770077002E007200650034
-:10003000630075007200730069006F006E002E008F
-:100040006A00700010035500530042002D0032007A
-:10005000330032001201100102000008C016E10551
-:10006000000101020001090243000201008032097F
-:100070000400000102020100052400100104240212
-:100080000205240600010524010301070583030876
-:1000900000FF09040100020A000000070501020236
-:1000A0000000070581020800000011241FBECFE5F3
-:1000B000D2E0DEBFCDBF10E0A0E6B0E0EEEAFAE0AD
-:1000C00002C005900D92AC36B107D9F711E0ACE64D
-:1000D000B0E001C01D92AF33B107E1F758D3E5C4DA
-:1000E0008FCFAC9A8BB780628BBF8BE480937C0000
-:1000F0008093A7008AE580937B008093A6000895F3
-:100100001F93CF93DF93DC01162FEA01888184FFD0
-:1001100005C0898198E88927898302C08AE5888398
-:10012000AE014E5F5F4F212FFA018D9181932150D7
-:100130001216DCF3CA01612F48D11C5F1883DF91CE
-:10014000CF911F91089546EA50E0DADF08954BE71A
-:1001500050E0D6DF08951F93CF93DF9360918C001A
-:10016000635067FDB3C080918900CCE0D0E0C81B2C
-:10017000D109C057DF4F80918800803118F4CE013B
-:10018000EAD29EC08D3209F08BC0683009F098C069
-:1001900083EC809370008AE58093600010926C007D
-:1001A0008881807621F0CE01A8D2282F66C09A815E
-:1001B000109279008981882321F410927A0022E03C
-:1001C00055C0853019F490938D004FC08630B9F535
-:1001D0008B81813041F484E590E090938B00809393
-:1001E0008A0022E128C0823021F4CE0171D2282F6A
-:1001F00022C08330F9F48A81882341F48EE190E0B3
-:1002000090938B0080938A0024E015C0813041F4E4
-:1002100082E290E090938B0080938A0022E20BC0F0
-:10022000823041F484E490E090938B0080938A00C4
-:1002300020E101C020E080E480936C001EC0883083
-:1002400021F421E08FE890E013C0893019F49093F5
-:100250008F000BC08A3011F421E008C08B3029F4E4
-:100260008BE480937C008093A70020E089E790E0F6
-:1002700090938B0080938A0009C02F3F39F48881C6
-:1002800087FD2E8180E880936C0006C08F818823D3
-:1002900019F48E81821708F0822F8093610010C0BC
-:1002A00080916C0087FF0CC0CE01B7D28F3F21F444
-:1002B0008EE18093600004C0882311F010926100E9
-:1002C00080918C00181614F410928C0080916000BC
-:1002D00084FF58C0809161008F3F09F453C0182FEC
-:1002E000893008F018E0811B8093610080917000D4
-:1002F00098E8892780937000112391F180916C0018
-:1003000087FF08C081E790E0612F16D2182F89304F
-:1003100098F526C020918A0030918B0086FF0DC091
-:10032000A1E7B0E080E090E0F901E80FF91FE49167
-:10033000ED9301961817C1F708C0912FD901E1E795
-:10034000F0E08D9181939150E1F71150812F90E071
-:100350001F5F0196820F931F90938B0080938A00FA
-:1003600081E790E0612F31D0612F6C5F6C3041F0FC
-:100370008FEF8093610004C08FEF809361006EE186
-:100380006093600094E186B3887131F49150D9F79D
-:1003900010928D0010928700DF91CF911F910895E8
-:1003A000A82FB92F80E090E041E050EA609530E05E
-:1003B00009C02D9182279795879510F0842795275E
-:1003C000305EC8F36F5FA8F30895EADF8D939D93C5
-:1003D0000895A6E088279927AA9569F00197E1F387
-:1003E000B399FCCFB39BFECF81E09927A6B30196CA
-:1003F00011F0A871D9F70895CF93CFB7CF93C395D4
-:10040000B39BE9F7B39B0BC0B39B09C0B39B07C079
-:10041000B39B05C0B39B03C0B39B01C0D8C00F9270
-:10042000DF93C0918900DD27C057DF4F012EB39BBA
-:1004300003C0DF910F90E6CF2F930F931F934F933D
-:100440002FEF4F6F06B303FB20F95F933F9350E00C
-:100450003BE065C016B30126502953FDC89556B33D
-:10046000012703FB25F92F7306B3B1F0502710279E
-:1004700013FB26F906B22230F0F000C016B30127B4
-:1004800003FB27F90126502906B22430E8F54F77FF
-:10049000206816B30000F6CF50274F7D206206B2C9
-:1004A000102F000000C006B300265029102713FBB0
-:1004B00026F906B2E2CF4F7B06B3206400C0DACF44
-:1004C00001265029187106B269F14E7F2160012F73
-:1004D00016B328C0002650294D7F06B22260102F87
-:1004E00029C0012650294B7F06B22460012F2DC060
-:1004F00016B301265029477F2860000006B22EC09F
-:100500004F7E06B3206130C0422706B349930026D0
-:100510005029102706B24FEF13FB20F9297F16B39D
-:1005200079F2187159F10126502906B2012703FB0F
-:1005300021F9237F06B371F2002650293150D0F003
-:1005400006B2102713FB22F9277E16B351F20126BB
-:100550005029012703FB06B223F92F7C49F2000042
-:1005600006B3102713FB24F90026502906B22F7971
-:1005700039F270CF10E21ABF00271CC03B503195F2
-:10058000C31BD04010E21ABF0881033C21F10B3499
-:1005900011F1209187001981110F1213EDCF4A81BB
-:1005A000441F093669F10D3211F0013E29F74F70F1
-:1005B00009F0042F00938E003F915F914F911F919E
-:1005C0000F912F91DF910F90CAB7C5FD18CFCF9132
-:1005D000CFBFCF91189520918E00222369F31091FF
-:1005E0008C001123D1F53430D2F130938C0020935C
-:1005F0008800109189003BE0311B309389002FC0A7
-:1006000000918C0001304CF50AE54F7049F43091AF
-:10061000600034FD25C000936000C0E7D0E024C036
-:10062000433049F030917B0034FD1AC000937B00C9
-:10063000CCE7D0E019C03091A60034FD11C0009382
-:10064000A600C7EAD0E010C0052710E000C021C016
-:10065000052710E0C89508BB14C03AE501C032ED8B
-:10066000032EC0E0D0E032E017B31861C39A08B39C
-:1006700017BB58E120E84FEF20FF052708BB27955F
-:1006800017951C3F28F700004552B0F720FF0527BB
-:10069000279508BB17951C3FB8F629913A9561F745
-:1006A000077E10918D00110F08BBC250D04011F091
-:1006B0001093870010E21ABF086017B3177E402F0F
-:1006C000477E54E05A95F1F708BB17BB48BB74CF7F
-:1006D000FC018381813049F484E590E090938B00A4
-:1006E00080938A0080915400089586E690E090936C
-:1006F0008B0080938A0083E40895FC012081822F7F
-:1007000080768032B9F49181892F8052823010F442
-:100710008FEF0895923239F480916D00882319F497
-:1007200082E080936D0027FD05C081E08093B200D8
-:1007300080E0089580E00895FC0180916E00808340
-:1007400080916F008183128213821482158288E067
-:10075000868387E00895DC010BC0E92FF0E0E454C4
-:10076000FF4F8D9180839F5F9F7790933D016150F4
-:1007700090913D01662389F780913E018150891B4C
-:100780008F77823018F48FEF80938C0008952EE0DD
-:1007900088E190E00FB6F894A89581BD0FBE21BD09
-:1007A00080E090E07AD18F3F09F081BF87EE88BB6F
-:1007B00088E187BBA89584EC99E02CE931E0F90148
-:1007C0003197F1F70197D9F717BA80EC92E190933E
-:1007D0006F0080936E0080D084DC10926D001092C8
-:1007E000B2007894A895B7DCC2D090916D0099239F
-:1007F000C9F38091A60084FFF5CF923021F482E600
-:1008000090E068E003C08AE690E062E09CDC8091C2
-:100810006D00815080936D00E5CFFC018081809355
-:100820006E00818180936F0080916E0090916F00C7
-:1008300053D081E00895B299189501BB05B50FBD5D
-:1008400009E00DBD07E000BF00E20BBF01B3189542
-:1008500001BB0FB702BB0DB50A950DBD79F00BB505
-:100860000695B29900680BBD13BB0FB51EB5011BF1
-:100870000FBD13B302B30FBF01B3189500BF04BD82
-:100880000BB50DBB00E40ABF00E60BBF02B30FBF00
-:1008900001B3189501BBF09907C00BE40EB90EBB6C
-:1008A00008B50FB901B3189500E40EB900E003BF15
-:1008B00001B31895881F9795881F9795881F97955E
-:1008C000881F9795881F9795881F9795881F9795DC
-:1008D000881F9795892F08959C0181E080BD80E84D
-:1008E00088B9B99ABA988BB78F7B8BBF1ABC13BEE5
-:1008F00010BE80EE8EB984E58DB98FEF8FB9B90146
-:100900007695679580E090E06C5E70418C4F9F4FCC
-:1009100040E050E085D021502EBD8EB589BD1DBC74
-:100920008EB590E0019695958795959587958195DB
-:1009300085BD95B58EB5891718F08EB58F5F85BDCD
-:1009400082E08ABD81E084BD90E499BF85B78C7F49
-:10095000826085BF9ABF8BB780648BBF10923E01C7
-:100960001092BB0010923C0110923D01089584B595
-:10097000882379F49091BB00983058F48DB3E92F17
-:10098000F0E0ED54FF4F80839F5F9093BB0081E0C8
-:1009900084BD80917B0084FF12C06091BB00662300
-:1009A00021F48091B200882351F083EB90E0CFDBFB
-:1009B0008091BB0088708093B2001092BB0083B717
-:1009C000882369F5E0913E0180913D018E1739F150
-:1009D000F0E0E454FF4F80816DDF20913E012F5FF6
-:1009E0002F7720933E0112BE9BE49EB91EBA982F2A
-:1009F0009295907F9F6098BD8695F8948FB983E01B
-:100A000083BF789480918C0087FF09C080913D015D
-:100A10008095820F8F77823010F010928C000895AD
-:100A200097FB092E05260ED057FD04D014D00AD00E
-:100A3000001C38F450954095309521953F4F4F4F0D
-:100A40005F4F0895F6F790958095709561957F4F6B
-:100A50008F4F9F4F0895A1E21A2EAA1BBB1BFD01C9
-:100A60000DC0AA1FBB1FEE1FFF1FA217B307E4078D
-:100A7000F50720F0A21BB30BE40BF50B661F771FE5
-:100A8000881F991F1A9469F76095709580959095C5
-:100A90009B01AC01BD01CF010895E199FECF9FBB41
-:0E0AA0008EBBE09A99278DB30895F894FFCF8E
-:0C0AAE005AFFA12000000000020003001D
-:00000001FF
diff --git a/commandline/library/micronucleus_lib.c b/commandline/library/micronucleus_lib.c
index 6bbf04c..6e574f5 100644
--- a/commandline/library/micronucleus_lib.c
+++ b/commandline/library/micronucleus_lib.c
@@ -50,17 +50,19 @@ micronucleus* micronucleus_connect() {
nucleus->version.minor = dev->descriptor.bcdDevice & 0xFF;
if (nucleus->version.major > MICRONUCLEUS_MAX_MAJOR_VERSION) {
- fprintf(stderr, "Warning: device with unknown new version of Micronucleus detected.\n");
- fprintf(stderr, "This tool doesn't know how to upload to this new device. Updates may be available.\n");
- fprintf(stderr, "Device reports version as: %d.%d\n", nucleus->version.major, nucleus->version.minor);
- return NULL;
+ fprintf(stderr,
+ "Warning: device with unknown new version of Micronucleus detected.\n"
+ "This tool doesn't know how to upload to this new device. Updates may be available.\n"
+ "Device reports version as: %d.%d\n",
+ nucleus->version.major, nucleus->version.minor);
+ return NULL;
}
nucleus->device = usb_open(dev);
// get nucleus info
unsigned char buffer[4];
- int res = usb_control_msg(nucleus->device, 0xC0, 0, 0, 0, buffer, 4, MICRONUCLEUS_USB_TIMEOUT);
+ int res = usb_control_msg(nucleus->device, 0xC0, 0, 0, 0, (char *)buffer, 4, MICRONUCLEUS_USB_TIMEOUT);
assert(res >= 4);
nucleus->flash_size = (buffer[0]<<8) + buffer[1];
@@ -102,7 +104,7 @@ int micronucleus_eraseFlash(micronucleus* deviceHandle, micronucleus_callback pr
Assertion failed: (res >= 4), function micronucleus_connect, file library/micronucleus_lib.c, line 63.
*/
if (res == -5 || res == -34 || res == -84) {
- if (res = -34) {
+ if (res == -34) {
usb_close(deviceHandle->device);
deviceHandle->device = NULL;
}
@@ -119,38 +121,49 @@ int micronucleus_writeFlash(micronucleus* deviceHandle, unsigned int program_siz
unsigned int address; // overall flash memory address
unsigned int page_address; // address within this page when copying buffer
unsigned int res;
-
+ unsigned int pagecontainsdata;
+
for (address = 0; address < deviceHandle->flash_size; address += deviceHandle->page_size) {
// work around a bug in older bootloader versions
if (deviceHandle->version.major == 1 && deviceHandle->version.minor <= 2
&& address / deviceHandle->page_size == deviceHandle->pages - 1) {
page_length = deviceHandle->flash_size % deviceHandle->page_size;
}
+
+ pagecontainsdata=0;
// copy in bytes from user program
for (page_address = 0; page_address < page_length; page_address += 1) {
if (address + page_address > program_size) {
page_buffer[page_address] = 0xFF; // pad out remainder with unprogrammed bytes
} else {
+ pagecontainsdata=1; // page contains data and needs to be written
page_buffer[page_address] = program[address + page_address]; // load from user program
}
}
+ // always write last page so bootloader can insert the tiny vector table
+ if ( address >= deviceHandle->flash_size - deviceHandle->page_size )
+ pagecontainsdata = 1;
+
// ask microcontroller to write this page's data
- res = usb_control_msg(deviceHandle->device,
- USB_ENDPOINT_OUT| USB_TYPE_VENDOR | USB_RECIP_DEVICE,
- 1,
- page_length, address,
- page_buffer, page_length,
- MICRONUCLEUS_USB_TIMEOUT);
-
- // call progress update callback if that's a thing
- if (prog) prog(((float) address) / ((float) deviceHandle->flash_size));
-
- // give microcontroller enough time to write this page and come back online
- delay(deviceHandle->write_sleep);
+ if (pagecontainsdata) {
+ res = usb_control_msg(deviceHandle->device,
+ USB_ENDPOINT_OUT| USB_TYPE_VENDOR | USB_RECIP_DEVICE,
+ 1,
+ page_length, address,
+ (char*)page_buffer, page_length,
+ MICRONUCLEUS_USB_TIMEOUT);
+
+ if (res != page_length) return -1;
+
+ // give microcontroller enough time to write this page and come back online
+ delay(deviceHandle->write_sleep);
+ }
- if (res != page_length) return -1;
+ // call progress update callback if that's a thing
+ if (prog) prog(((float) address) / ((float) deviceHandle->flash_size));
+
}
// call progress update callback with completion status
diff --git a/commandline/littleWire_v11.hex b/commandline/littleWire_v11.hex
deleted file mode 100644
index a5c07e5..0000000
--- a/commandline/littleWire_v11.hex
+++ /dev/null
@@ -1,356 +0,0 @@
-:1000000042C05CC0DDC15AC059C058C057C056C0BC
-:1000100055C054C053C052C051C050C04FC0B9CADF
-:1000200065C8B6C8D4C8FDC82DC944C961C9A1C92D
-:10003000A2C95AC8BFC9EDC9F0C954C851C886CAB7
-:1000400004030904160355005300420074006900BC
-:100050006E007900530050004900120110010000A9
-:10006000000881179F0C0401000200010902190019
-:1000700001010080640904000001FF000000070581
-:1000800081030800640011241FBECFE5D2E0DEBF6B
-:10009000CDBF10E0A0E6B0E0E0E2F6E102C00590DE
-:1000A0000D92A636B107D9F710E0A6E6B0E001C080
-:1000B0001D92AD3CB107E1F7C1D7B0CAA1CF1F93E4
-:1000C000162F2091910024FF07C02091920038E85C
-:1000D00023272093920003C02AE520939100212F2B
-:1000E000DC01E3E9F0E08D91819321501216DCF3FD
-:1000F00083E990E0612F4DD11C5F109391001F9117
-:1001000008951F93CF93DF936091A200635067FD22
-:10011000A7C080919F00CCE0D0E0C81BD109CA5590
-:10012000DF4F80919E008D3209F088C0683009F061
-:1001300095C083EC809386008AE5809360001092DE
-:1001400066008881807631F0CE01DAD38F3F09F4E2
-:1001500064C06AC09A8110928F008981882331F42B
-:10016000109290002FE830E082E052C0853019F400
-:100170009093A3004AC0863091F58B81813041F481
-:100180008AE590E09093A1008093A00082E123C0D3
-:10019000823041F48CE690E09093A1008093A0001F
-:1001A00089E119C08330B1F4992341F480E490E0EF
-:1001B0009093A1008093A00084E00DC0913051F095
-:1001C000923041F484E490E09093A1008093A000E9
-:1001D00086E101C080E090E49093660025C08830FD
-:1001E00069F0893019F49093A5000FC08A3049F066
-:1001F0008B3059F48BE48093920007C025EA30E0FD
-:1002000002C02FE830E081E003C02FE830E080E05A
-:100210003093A1002093A00007C0988197FD8E81A4
-:1002200090E89093660007C09F81992321F49E81F6
-:10023000981708F4892F8093610010C080916600A0
-:1002400087FF0CC0CE010FD38F3F21F48EE1809346
-:10025000600004C0882311F0109261001092A20087
-:100260008091600084FF5BC0809161008F3F09F442
-:1002700056C0182F893008F018E0811B8093610068
-:100280008091860098E88927809386001123B1F138
-:100290008091660087FF08C087E890E0612FC2D296
-:1002A000182F8930B0F52AC02091A0003091A1000C
-:1002B000412F415086FF0EC050E0EA01C857DF4F82
-:1002C000F901A7E8B0E084918D933196AC17BD0792
-:1002D000D1F70CC0D90150E0CA0188579F4FE7E819
-:1002E000F0E06D916193E817F907D9F74F5F5F4F21
-:1002F000420F531F5093A1004093A00087E890E065
-:10030000612F47D01C5F1C3041F08FEF809361005C
-:1003100004C08FEF809361001EE11093600084E1C0
-:1003200096B3987131F48150D9F71092A3001092CE
-:100330009D0011E0811110E080916700811729F084
-:10034000112309F4F6D410936700DF91CF911F9128
-:100350000895AC9A8BB780628BBF8BE48093920038
-:100360008AE5809391000895A82FB92F80E090E04E
-:1003700041E050EA609530E009C02D9182279795C1
-:10038000879510F084279527305EC8F36F5FA8F338
-:100390000895EADF8D939D930895A6E08827992715
-:1003A000AA9569F00197E1F3B399FCCFB39BFECF17
-:1003B00081E09927A6B3019611F0A871D9F70895A5
-:1003C000CF93CFB7CF93C395B39BE9F7B39B0BC044
-:1003D000B39B09C0B39B07C0B39B05C0B39B03C0CD
-:1003E000B39B01C0D5C00F92DF93C0919F00DD2762
-:1003F000CA55DF4F012EB39B03C0DF910F90E6CFAC
-:100400002F930F931F934F932FEF4F6F06B303FB61
-:1004100020F95F933F9350E03BE065C016B301269F
-:10042000502953FDC89556B3012703FB25F92F73B7
-:1004300006B3B1F05027102713FB26F906B222307D
-:10044000F0F000C016B3012703FB27F9012650295D
-:1004500006B22430E8F54F77206816B30000F6CFD7
-:1004600050274F7D206206B2102F000000C006B357
-:1004700000265029102713FB26F906B2E2CF4F7B46
-:1004800006B3206400C0DACF01265029187106B2E5
-:1004900069F14E7F2160012F16B328C00026502934
-:1004A0004D7F06B22260102F29C0012650294B7FB4
-:1004B00006B22460012F2DC016B301265029477FB4
-:1004C0002860000006B22EC04F7E06B3206130C007
-:1004D000422706B3499300265029102706B24FEF52
-:1004E00013FB20F9297F16B379F2187159F101260F
-:1004F000502906B2012703FB21F9237F06B371F2CD
-:10050000002650293150D0F006B2102713FB22F9F3
-:10051000277E16B351F201265029012703FB06B2AC
-:1005200023F92F7C49F2000006B3102713FB24F9AE
-:100530000026502906B22F7939F270CF10E21ABF87
-:10054000002719C03B503195C31BD04010E21ABFA1
-:100550000881033C09F10B34F9F020919D001981C9
-:10056000110F1213EDCF4A81441F093651F10D329C
-:1005700011F0013E29F70093A4003F915F914F9144
-:100580001F910F912F91DF910F90CAB7C5FD1BCF1F
-:10059000CF91CFBFCF9118952091A400222369F36A
-:1005A0001091A200112379F534307AF13093A20032
-:1005B00020939E0010919F003BE0311B30939F00E1
-:1005C00024C00091A2000130F4F40AE54F7049F410
-:1005D0003091600034FD1AC000936000C6E8D0E09E
-:1005E00019C03091910034FD11C000939100C2E90F
-:1005F000D0E010C0052710E000C021C0052710E0A2
-:10060000C89508BB14C03AE501C032ED032EC0E026
-:10061000D0E032E017B31861C39A08B317BB58E1B2
-:1006200020E84FEF20FF052708BB279517951C3FB3
-:1006300028F700004552B0F720FF0527279508BB93
-:1006400017951C3FB8F629913A9561F7077E1091EE
-:10065000A300110F08BBC250D04011F010939D00B1
-:1006600010E21ABF086017B3177E402F477E54E090
-:100670005A95F1F708BB17BB48BB7FCFFC015091DF
-:100680006500862F972FDC0194E0619128E030E02F
-:1006900040E880E0742F762309F0C09A052E00C050
-:1006A0000000000000000A94D1F7C29A052E00C095
-:1006B0000000000000000A94D1F7880FB1998F5F05
-:1006C000C098C29846952150304021F78D939150A3
-:1006D000E1F6089580917800909179009C012F5F58
-:1006E0003F4F309379002093780020917A0027FFC4
-:1006F00002C0880F991F20937E0080FF03C02860EE
-:1007000020937E00292F269520937F00969587952C
-:10071000809380008EE790E062E870E0AFDF08959C
-:10072000B99A24E030E0E1E09E2F982321F098B3BD
-:100730009C7F926002C098B39C7F98BBEE0F109292
-:10074000750007C045E04A95F1F700C09F5F9093A0
-:10075000750090917500692F70E040916300509191
-:1007600064006417750770F3C09A1092750007C093
-:1007700045E04A95F1F700C09F5F90937500909116
-:100780007500692F70E04091630050916400641718
-:10079000750770F32150304039F688B38C7F88BBE1
-:1007A0000895B99A28E030E0E1E09E2F982321F0E7
-:1007B00098B39C7F926002C098B39C7F98BBEE0F69
-:1007C0001092750007C045E04A95F1F700C09F5FA1
-:1007D0009093750090917500692F70E040916300CF
-:1007E000509164006417750770F3C09A10927500F9
-:1007F00007C045E04A95F1F700C09F5F90937500F0
-:1008000090917500692F70E04091630050916400F1
-:100810006417750770F32150304039F688B38C7F28
-:1008200088BB0895EF92FF921F93DF93CF930F92AF
-:10083000CDB7DEB7182F862F612F792F7B0108C027
-:10084000898348DF90918500F70191937F01898129
-:100850009E2D911B9817A0F30F90CF91DF911F91C0
-:10086000FF90EF900895DF92EF92FF920F931F9306
-:10087000CF93DF93F82EE62E0F2D192F50E6D52EAD
-:1008800032C0F80181918F018093810023DF809134
-:100890007E008D2580937E00C0E0D0E01DC08EE7F5
-:1008A00090E062E870E0EADE80918500909181003E
-:1008B000891741F490917600891721F09091770083
-:1008C000891789F42091650030E045E0220F331F3D
-:1008D0004A95E1F7C20FD31F20917B0030917C0035
-:1008E000C217D307E0F2802F8F198E1550F281E0E6
-:1008F000DF91CF911F910F91FF90EF90DF900895BE
-:10090000CF93DF93EC014981442341F481E2898351
-:10091000D093A100C093A00088E008C2413011F438
-:1009200086B307C15A81423011F458BBFEC102960A
-:10093000652F677021E030E0062E02C0220F331FC2
-:100940000A94E2F7433029F498B3822F80958923E3
-:1009500093C0443019F488B3822B8EC0453049F4DB
-:1009600050936500B99887B3856287BB88B3887D4B
-:1009700083C0463049F4B898C098B998C098BA98DE
-:10098000C09880E287BB78C0473041F4BE0176DE74
-:10099000D093A100C093A00084E0C8C1483031F4D6
-:1009A000509376008B8180937700BFC18C819D81AD
-:1009B0009093790080937800493011F480E211C05F
-:1009C0004B3011F480EA0DC08A819B8190937C00AA
-:1009D00080937B004A3011F480E403C04C3029F44A
-:1009E00080EC80937A008FEFA1C14D3029F487B35A
-:1009F0002095282327BB99C14E3021F487B3822B41
-:100A000087BB93C14F3009F5552329F480917D00B0
-:100A100087B9A59A0CC0513031F480917D00816076
-:100A200087B9A29A04C0523011F48FE887B9369A78
-:100A30003699FECF84B1888385B18983D093A10094
-:100A4000C093A00014BA82E071C1403159F4B89A41
-:100A5000B99A8AB5806A8ABD8AB583608ABD83B730
-:100A6000856038C0413121F459BD8C8188BD5DC19C
-:100A7000423121F488B3822B88BB57C1433129F41A
-:100A800088B32095282328BB50C1443151F486B344
-:100A900090E08223932302C0959587956A95E2F7AB
-:100AA00048C0463169F5552319F483B78B7F24C0BC
-:100AB000513031F483B78B7F83BF83B7826013C01B
-:100AC000523051F483B78B7F83BF83B7826083BF7B
-:100AD00083B7816083BF29C1533049F483B78460F1
-:100AE00083BF83B78D7F83BF83B78E7FF3CF5430AF
-:100AF00009F01BC183B7846083BF83B78D7FE7CFC5
-:100B00004F3149F49B8180E0850F911D90936400E3
-:100B1000809363000AC1403219F41ABC13BE05C1A8
-:100B2000413221F45093C50081E0B5C0423241F416
-:100B300081E18883D093A100C093A00081E0F6C03A
-:100B40004332D9F4379A86B19A81892B86B98B8141
-:100B5000813049F0813020F0823009F0E6C007C0D2
-:100B600010927D00E2C080917D00806803C080917A
-:100B70007D00806980937D00D8C0483249F48CEBB9
-:100B800090E09093A1008093A0008091C400CEC01B
-:100B9000493211F482E07FC04A3211F483E00BC085
-:100BA0004B3211F484E077C04C3211F488E073C00A
-:100BB0004D3239F489E0809368008A818093C500C2
-:100BC000B4C04E3259F48BE0809368008A818093E0
-:100BD000C5008B818093C6008C8134C04F3259F49C
-:100BE000513031F4B89AB99ABA9A509374009DC0B2
-:100BF000109274009AC0403349F450936E008B8178
-:100C000080936F008C81809370008FC0413329F4F2
-:100C10005093690010926A0088C0423311F485E055
-:100C20003AC0433321F45093C50086E034C04433C6
-:100C300061F4509368008B818093C5008C81809310
-:100C4000C6008D818093C70070C0453369F450930E
-:100C5000C5008B818093C6008C818093C7008D81F5
-:100C60008093C80080E117C0842F90E0807F90704F
-:100C7000803D910599F447704093C5008A81809327
-:100C8000C6008B818093C7008C818093C8008D81C2
-:100C90008093C9008EE08093680047C0803E910534
-:100CA00001F58AE080936800842F87708093C500E7
-:100CB00048704093C6001092750080E00BC090E031
-:100CC0000296FE01E80FF91F30818B539F4FFC0104
-:100CD0003083822F9091C500282F2F5F891778F3DA
-:100CE00022C0803F910509F587E080936800842F3A
-:100CF00088708093C50047704093C60010927500BD
-:100D000080E00BC090E00296FE01E80FF91F3081F1
-:100D10008B539F4FFC013083822F9091C600282F68
-:100D20002F5F891778F38093750080E0DF91CF9172
-:100D30000895DF92EF92FF920F931F93CF93DF936B
-:100D4000C8E0D0E0FF2460E8E62EDE2CDF0CD1BE48
-:100D500024DB082F192F89E0043318070CF4FD2C2D
-:100D6000E694219791F78F2D815081BFCF2DD0E050
-:100D7000219610C012DB8453994097FF03C09095D1
-:100D800081959F4F8017910714F4F1B68C0181B7BC
-:100D90008F5F81BF81B790E0C817D9075CF7F1BEBC
-:100DA00061B780E090E02CD4DF91CF911F910F913B
-:100DB000FF90EF90DF900895882311F0B99801C05B
-:100DC000B99ABA981092750007C025E02A95F1F7F4
-:100DD00000C09F5F9093750090917500492F50E07F
-:100DE0002091690030916A004217530770F3BA9A54
-:100DF0001092750007C025E02A95F1F700C09F5FAB
-:100E00009093750090917500492F50E020916900F2
-:100E100030916A004217530770F38111B99A08950F
-:100E2000B998BA981092750007C025E02A95F1F795
-:100E300000C04F5F4093750040917500242F30E053
-:100E40008091690090916A002817390770F386B382
-:100E5000BA9A1092750007C025E02A95F1F700C0F4
-:100E60009F5F9093750090917500492F50E02091FD
-:100E7000690030916A004217530770F386958170BC
-:100E8000089588B3897F88BBBA98B9981092750085
-:100E900007C085E08A95F1F700C04F5F4093750069
-:100EA00040917500242F30E08091690090916A0094
-:100EB0002817390770F3089587B3897F87BB10928D
-:100EC000750007C085E08A95F1F700C04F5F409339
-:100ED000750040917500242F30E080916900909159
-:100EE0006A002817390770F3B99A1092750007C085
-:100EF00085E08A95F1F700C04F5F409375004091FF
-:100F00007500242F30E08091690090916A002817C5
-:100F1000390770F3BA9A1092750007C085E08A9578
-:100F2000F1F700C04F5F4093750040917500242F8A
-:100F300030E08091690090916A002817390770F3BA
-:100F40000895B99ABA9A1092750007C085E08A95FB
-:100F5000F1F700C04F5F4093750040917500242F5A
-:100F600030E08091690090916A002817390770F38A
-:100F7000BA981092750007C085E08A95F1F700C015
-:100F80004F5F4093750040917500242F30E08091B1
-:100F9000690090916A002817390770F3B998109288
-:100FA000750007C085E08A95F1F700C04F5F409358
-:100FB000750040917500242F30E080916900909178
-:100FC0006A002817390770F308950F931F93082FAD
-:100FD00018E0802F8078F0DE000F1150D1F720DF6D
-:100FE0001F910F910895FF920F931F93F82E08E021
-:100FF00010E0110F15DF182B0150D9F7FF2011F069
-:1010000080E001C081E0D8DE1092750007C095E055
-:101010009A95F1F700C08F5F8093750080917500FD
-:10102000482F50E02091690030916A004217530721
-:1010300070F3812F1F910F91FF900895DF92EF922F
-:10104000FF920F931F93CF93DF9380E287BB88BB00
-:1010500080E090E0CDD28F3F09F081BFBB9A84E160
-:10106000E2EBF1EF3197F1F700C000008150C1F7DA
-:10107000BB9885E090E090936A008093690010929D
-:101080006400109263002EE088E190E00FB6F894BF
-:10109000A89581BD0FBE21BD10926B0010926C000F
-:1010A00010926D0010926E0010926F0010927000FE
-:1010B00010927100109268004CD97894BBE1EB2E2D
-:1010C000AAE1FA2E00E410E8A8951BD8E091680088
-:1010D000F0E0E131F10508F05AC2E15FFF4F0994F9
-:1010E00060E02AC2DD24D9C1DD2457C1B89AB9987D
-:1010F000BA9AC29A1092BC008091C5008093720087
-:10110000109373003FC0C09840E005C0F5E0FA9529
-:10111000F1F700C04F5F242F30E080916300909181
-:1011200064002817390790F3809173009091720042
-:10113000892309F0C09AC2988091BC00880F8093DF
-:10114000BC002091BC0086B390E0827090709595B1
-:101150008795280F2093BC0040E005C025E02A9524
-:10116000F1F700C04F5F242F30E080916300909131
-:1011700064002817390790F3C29A8091730086950E
-:101180008093730080917300882309F0BCCF1DC049
-:10119000BA9AC2988BEB97E00197F1F700C0000074
-:1011A0009FB7F894C29AE0E2F1E03197F1F700C0FE
-:1011B000BA9881E0B29980E08093BC009FBF8BE930
-:1011C00096E00197F1F7BA9AC29A81E0BCC180918A
-:1011D000C50080937300BA9A88E02FB7F894C2983C
-:1011E0009091730090FF0BC091E29A95F1F7C29A2B
-:1011F000E7E0F1E03197F1F700C0000009C0E7EF48
-:10120000F0E03197F1F70000C29AF7E3FA95F1F7B1
-:10121000909173009695909373002FBF8150E9F6DB
-:10122000B6C11092BC0028E08091BC0086958093E6
-:10123000BC00BA9A3FB7F894C29881E28A95F1F758
-:10124000C29A97E39A95F1F7BA9886B390E08470C2
-:1012500090709595879595958795809373003FBF7E
-:10126000E2EEF0E03197F1F700C0000080917300EA
-:10127000882329F08091BC0080688093BC002150B5
-:1012800099F6A3CFBA9A2FB7F894C298F1E2FA95DB
-:10129000F1F7C29A87E38A95F1F7BA9886B390E09E
-:1012A0008470907095958795959587958093BC00EF
-:1012B0002FBF8BCFBA9A8FB7F894C2989091C50080
-:1012C00090FF0BC091E29A95F1F7C29AE7E0F1E046
-:1012D0003197F1F700C0000009C0E7EFF0E0319767
-:1012E000F1F70000C29AF7E3FA95F1F78FBF4FC10B
-:1012F000B99AB898BA9AC298E0927200FDB88091F3
-:10130000C5008111C5981092730026C0F0E0E95322
-:10131000FF4F80818FB90EB9809172008DB940E086
-:1013200005C025E02A95F1F700C04F5F242F30E07B
-:1013300080916300909164002817390790F3769BA1
-:10134000EBCF80917300E82FF0E09FB1E454FF4FA2
-:1013500090838F5F80937300E09173008091C6004B
-:10136000E817A0F28091C5008111C59AE093C400EE
-:101370000EC187DD0CC180E090E09EDD8091C5004C
-:1013800024DE8093730013C0ED2DF0E0E953FF4F8E
-:1013900080811BDE80937300D3948091C500D816A2
-:1013A00098F38091C6008111CCDD80917300809309
-:1013B000BC000BCF8091C500882311F4DD241EC032
-:1013C000DD2404C081E00FDE8883D3942D2D30E02E
-:1013D0008091C60090E00197E901C454DF4F2817BF
-:1013E000390784F380E0FFDD88830CC0CD2DD0E089
-:1013F00081E0F9DDC454DF4F8883D3948091C60027
-:10140000D816A0F38091C700882309F49AC099DD0B
-:1014100098C08091C60084D9BAC04091C600B99ADC
-:101420002FC088B38C7F88BB41501092750007C0D5
-:1014300085E08A95F1F700C05F5F50937500509189
-:101440007500252F30E0809163009091640028178B
-:10145000390770F3C09A1092750007C095E09A950D
-:10146000F1F700C05F5F5093750050917500252F14
-:1014700030E080916300909164002817390770F381
-:10148000442379F688B38C7F88BB81C0ED2DF0E0D2
-:10149000EA53FF4F808185D9D3948091C500D81637
-:1014A000A8F375C0B998C19A88E090E071E01092F5
-:1014B000750007C0F5E0FA95F1F700C0EF5FE09323
-:1014C0007500E09175004E2F50E02091630030913F
-:1014D00064004217530770F3C09A1092750007C05A
-:1014E00025E02A95F1F700C0EF5FE0937500E091E9
-:1014F00075004E2F50E02091630030916400421738
-:10150000530770F330917300B19B04C0372B3093B5
-:10151000730005C0272F2095232320937300C098C4
-:10152000770F019721F6C198E62FF0E080917300C4
-:10153000E454FF4F80836F5F8091C600681708F402
-:10154000B1CF8091C6008093C40021C080E0E8D86C
-:101550008091C60026D98091C70023D98091C80008
-:1015600020D9109273000DC080E0DAD880E019D93C
-:1015700080E017D980E015D9809173008F5F809348
-:1015800073008091C50090917300981768F31092D2
-:10159000680080917400882309F496CD80917100D1
-:1015A000882369F490916E0090936B0090916F0086
-:1015B00090936C009091700090936D0015C0909185
-:1015C0006B00981710F4C09801C0C09A90916C00FD
-:1015D000981710F4C19801C0C19A90916D009817A6
-:1015E00010F4C29801C0C29A8F5F809371006CCDD5
-:1015F000E199FECF9FBB8EBBE09A99278DB30895EA
-:10160000262FE199FECF1CBA9FBB8EBB2DBB0FB618
-:10161000F894E29AE19A0FBE01960895F894FFCFEC
-:061620005AFF110A002828
-:00000001FF
diff --git a/commandline/examples/micronucleus.c b/commandline/micronucleus.c
index dc567da..b7d49ab 100644
--- a/commandline/examples/micronucleus.c
+++ b/commandline/micronucleus.c
@@ -1,7 +1,7 @@
/*
Created: September 2012
by ihsan Kehribar <ihsan@kehribar.me>
-
+
Permission is hereby granted, free of charge, to any person obtaining a copy of
this software and associated documentation files (the "Software"), to deal in
the Software without restriction, including without limitation the rights to
@@ -18,13 +18,14 @@
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
- SOFTWARE.
+ SOFTWARE.
*/
#include <stdio.h>
#include <errno.h>
#include <string.h>
#include <stdlib.h>
+#include <time.h>
#include "micronucleus_lib.h"
#include "littleWire_util.h"
@@ -33,7 +34,7 @@
#define CONNECT_WAIT 250 /* milliseconds to wait after detecting device on usb bus - probably excessive */
/******************************************************************************
-* Global definitions
+* Global definitions
******************************************************************************/
unsigned char dataBuffer[65536 + 256]; /* buffer for file data */
/*****************************************************************************/
@@ -41,8 +42,8 @@ unsigned char dataBuffer[65536 + 256]; /* buffer for file data */
/******************************************************************************
* Function prototypes
******************************************************************************/
-static int parseRaw(char *hexfile, char* buffer, int *startAddr, int *endAddr);
-static int parseIntelHex(char *hexfile, char* buffer, int *startAddr, int *endAddr); /* taken from bootloadHID example from obdev */
+static int parseRaw(char *hexfile, unsigned char *buffer, int *startAddr, int *endAddr);
+static int parseIntelHex(char *hexfile, unsigned char *buffer, int *startAddr, int *endAddr); /* taken from bootloadHID example from obdev */
static int parseUntilColon(FILE *fp); /* taken from bootloadHID example from obdev */
static int parseHex(FILE *fp, int numDigits); /* taken from bootloadHID example from obdev */
static void printProgress(float progress);
@@ -52,7 +53,8 @@ static int progress_total_steps = 0; // total steps for upload
static char* progress_friendly_name; // name of progress section
static int dump_progress = 0; // output computer friendly progress info
static int use_ansi = 0; // output ansi control character stuff
-static int timeout = 0; //
+static int erase_only = 0; // only erase, dont't write file
+static int timeout = 0;
/*****************************************************************************/
/******************************************************************************
@@ -67,17 +69,18 @@ int main(int argc, char **argv) {
int run = 0;
int file_type = FILE_TYPE_INTEL_HEX;
int arg_pointer = 1;
- char* usage = "usage: micronucleus [--run] [--dump-progress] [--type intel-hex|raw] [--no-ansi] [--timeout integer] filename";
+ char* usage = "usage: micronucleus [--run] [--dump-progress] [--type intel-hex|raw] [--no-ansi] [--timeout integer] [--erase-only] filename";
progress_step = 0;
progress_total_steps = 5; // steps: waiting, connecting, parsing, erasing, writing, (running)?
dump_progress = 0;
+ erase_only = 0;
timeout = 0; // no timeout by default
//#if defined(WIN)
// use_ansi = 0;
//#else
use_ansi = 1;
//#endif
-
+
while (arg_pointer < argc) {
if (strcmp(argv[arg_pointer], "--run") == 0) {
run = 1;
@@ -99,6 +102,8 @@ int main(int argc, char **argv) {
puts(" bytes (intel hex is default)");
puts(" --dump-progress: Output progress data in computer-friendly form");
puts(" for driving GUIs");
+ puts(" --erase-only: Erase the device without programming. Fills the");
+ puts(" program memory with 0xFFFF. Any files are ignored.");
puts(" --run: Ask bootloader to run the program when finished");
puts(" uploading provided program");
//#ifndef WIN
@@ -112,6 +117,9 @@ int main(int argc, char **argv) {
dump_progress = 1;
} else if (strcmp(argv[arg_pointer], "--no-ansi") == 0) {
use_ansi = 0;
+ } else if (strcmp(argv[arg_pointer], "--erase-only") == 0) {
+ erase_only = 1;
+ progress_total_steps -= 1;
} else if (strcmp(argv[arg_pointer], "--timeout") == 0) {
arg_pointer += 1;
if (sscanf(argv[arg_pointer], "%d", &timeout) != 1) {
@@ -121,41 +129,41 @@ int main(int argc, char **argv) {
} else {
file = argv[arg_pointer];
}
-
+
arg_pointer += 1;
}
-
+
if (argc < 2) {
puts(usage);
return EXIT_FAILURE;
}
-
+
setProgressData("waiting", 1);
if (dump_progress) printProgress(0.5);
printf("> Please plug in the device ... \n");
printf("> Press CTRL+C to terminate the program.\n");
-
-
+
+
time_t start_time, current_time;
time(&start_time);
-
+
while (my_device == NULL) {
delay(100);
my_device = micronucleus_connect();
-
+
time(&current_time);
if (timeout && start_time + timeout < current_time) {
break;
}
}
-
+
if (my_device == NULL) {
printf("> Device search timed out\n");
return EXIT_FAILURE;
}
-
+
printf("> Device is found!\n");
-
+
// wait for CONNECT_WAIT milliseconds with progress output
float wait = 0.0f;
setProgressData("connecting", 2);
@@ -164,10 +172,10 @@ int main(int argc, char **argv) {
wait += 50.0f;
delay(50);
}
-
+
//my_device = micronucleus_connect();
printProgress(1.0);
-
+
// if (my_device->page_size == 64) {
// printf("> Device looks like ATtiny85!\n");
// } else if (my_device->page_size == 32) {
@@ -176,101 +184,108 @@ int main(int argc, char **argv) {
// printf("> Unsupported device!\n");
// return EXIT_FAILURE;
// }
-
- printf("> Available space for user application: %d bytes\n", my_device->flash_size);
+
+ printf("> Device has firmware version %d.%d\n",my_device->version.major,my_device->version.minor);
+ printf("> Available space for user applications: %d bytes\n", my_device->flash_size);
printf("> Suggested sleep time between sending pages: %ums\n", my_device->write_sleep);
- printf("> Whole page count: %d\n", my_device->pages);
+ printf("> Whole page count: %d page size: %d\n", my_device->pages,my_device->page_size);
printf("> Erase function sleep duration: %dms\n", my_device->erase_sleep);
-
- setProgressData("parsing", 3);
- printProgress(0.0);
- memset(dataBuffer, 0xFF, sizeof(dataBuffer));
-
+
int startAddress = 1, endAddress = 0;
- if (file_type == FILE_TYPE_INTEL_HEX) {
- if (parseIntelHex(file, dataBuffer, &startAddress, &endAddress)) {
- printf("> Error loading or parsing hex file.\n");
+
+ if (!erase_only) {
+ setProgressData("parsing", 3);
+ printProgress(0.0);
+ memset(dataBuffer, 0xFF, sizeof(dataBuffer));
+
+ if (file_type == FILE_TYPE_INTEL_HEX) {
+ if (parseIntelHex(file, dataBuffer, &startAddress, &endAddress)) {
+ printf("> Error loading or parsing hex file.\n");
+ return EXIT_FAILURE;
+ }
+ } else if (file_type == FILE_TYPE_RAW) {
+ if (parseRaw(file, dataBuffer, &startAddress, &endAddress)) {
+ printf("> Error loading raw file.\n");
+ return EXIT_FAILURE;
+ }
+ }
+
+ printProgress(1.0);
+
+ if (startAddress >= endAddress) {
+ printf("> No data in input file, exiting.\n");
return EXIT_FAILURE;
}
- } else if (file_type == FILE_TYPE_RAW) {
- if (parseRaw(file, dataBuffer, &startAddress, &endAddress)) {
- printf("> Error loading raw file.\n");
+
+ if (endAddress > my_device->flash_size) {
+ printf("> Program file is %d bytes too big for the bootloader!\n", endAddress - my_device->flash_size);
return EXIT_FAILURE;
}
}
-
+
printProgress(1.0);
- if (startAddress >= endAddress) {
- printf("> No data in input file, exiting.\n");
- return EXIT_FAILURE;
- }
-
- if (endAddress > my_device->flash_size) {
- printf("> Program file is %d bytes too big for the bootloader!\n", endAddress - my_device->flash_size);
- return EXIT_FAILURE;
- }
-
setProgressData("erasing", 4);
printf("> Erasing the memory ...\n");
res = micronucleus_eraseFlash(my_device, printProgress);
-
+
if (res == 1) { // erase disconnection bug workaround
printf(">> Eep! Connection to device lost during erase! Not to worry\n");
printf(">> This happens on some computers - reconnecting...\n");
my_device = NULL;
-
+
delay(CONNECT_WAIT);
-
+
int deciseconds_till_reconnect_notice = 50; // notice after 5 seconds
while (my_device == NULL) {
delay(100);
my_device = micronucleus_connect();
deciseconds_till_reconnect_notice -= 1;
-
+
if (deciseconds_till_reconnect_notice == 0) {
printf(">> (!) Automatic reconnection not working. Unplug and reconnect\n");
printf(" device usb connector, or reset it some other way to continue.\n");
}
}
-
+
printf(">> Reconnected! Continuing upload sequence...\n");
-
+
} else if (res != 0) {
printf(">> Flash erase error %d has occured ...\n", res);
printf(">> Please unplug the device and restart the program.\n");
return EXIT_FAILURE;
}
printProgress(1.0);
-
- printf("> Starting to upload ...\n");
- setProgressData("writing", 5);
- res = micronucleus_writeFlash(my_device, endAddress, dataBuffer, printProgress);
- if (res != 0) {
- printf(">> Flash write error %d has occured ...\n", res);
- printf(">> Please unplug the device and restart the program.\n");
- return EXIT_FAILURE;
+
+ if (!erase_only) {
+ printf("> Starting to upload ...\n");
+ setProgressData("writing", 5);
+ res = micronucleus_writeFlash(my_device, endAddress, dataBuffer, printProgress);
+ if (res != 0) {
+ printf(">> Flash write error %d has occured ...\n", res);
+ printf(">> Please unplug the device and restart the program.\n");
+ return EXIT_FAILURE;
+ }
}
-
+
if (run) {
-
printf("> Starting the user app ...\n");
setProgressData("running", 6);
printProgress(0.0);
-
+
res = micronucleus_startApp(my_device);
-
+
if (res != 0) {
printf(">> Run error %d has occured ...\n", res);
printf(">> Please unplug the device and restart the program. \n");
return EXIT_FAILURE;
}
-
+
printProgress(1.0);
}
-
+
printf(">> Micronucleus done. Thank you!\n");
-
+
return EXIT_SUCCESS;
}
/******************************************************************************/
@@ -279,7 +294,7 @@ int main(int argc, char **argv) {
static void printProgress(float progress) {
static int last_step;
static int last_integer_total_progress;
-
+
if (dump_progress) {
printf("{status:\"%s\",step:%d,steps:%d,progress:%f}\n", progress_friendly_name, progress_step, progress_total_steps, progress);
} else {
@@ -290,17 +305,17 @@ static void printProgress(float progress) {
printf("\r"); // return carriage to start of line so we can type over existing text
#endif
}
-
+
float total_progress = ((float) progress_step - 1.0f) / (float) progress_total_steps;
total_progress += progress / (float) progress_total_steps;
int integer_total_progress = total_progress * 100.0f;
-
+
if (use_ansi || integer_total_progress >= last_integer_total_progress + 5) {
printf("%s: %d%% complete\n", progress_friendly_name, integer_total_progress);
last_integer_total_progress = integer_total_progress;
}
}
-
+
last_step = progress_step;
}
@@ -313,11 +328,11 @@ static void setProgressData(char* friendly, int step) {
/******************************************************************************/
static int parseUntilColon(FILE *file_pointer) {
int character;
-
+
do {
character = getc(file_pointer);
} while(character != ':' && character != EOF);
-
+
return character;
}
/******************************************************************************/
@@ -331,22 +346,22 @@ static int parseHex(FILE *file_pointer, int num_digits) {
temp[iter] = getc(file_pointer);
}
temp[iter] = 0;
-
+
return strtol(temp, NULL, 16);
}
/******************************************************************************/
/******************************************************************************/
-static int parseIntelHex(char *hexfile, char* buffer, int *startAddr, int *endAddr) {
+static int parseIntelHex(char *hexfile, unsigned char *buffer, int *startAddr, int *endAddr) {
int address, base, d, segment, i, lineLen, sum;
FILE *input;
-
+
input = strcmp(hexfile, "-") == 0 ? stdin : fopen(hexfile, "r");
if (input == NULL) {
printf("> Error opening %s: %s\n", hexfile, strerror(errno));
return 1;
}
-
+
while (parseUntilColon(input) == ':') {
sum = 0;
sum += lineLen = parseHex(input, 2);
@@ -357,18 +372,18 @@ static int parseIntelHex(char *hexfile, char* buffer, int *startAddr, int *endAd
if (segment != 0) { /* ignore lines where this byte is not 0 */
continue;
}
-
+
for (i = 0; i < lineLen; i++) {
d = parseHex(input, 2);
buffer[address++] = d;
sum += d;
}
-
+
sum += parseHex(input, 2);
if ((sum & 0xff) != 0) {
printf("> Warning: Checksum error between address 0x%x and 0x%x\n", base, address);
}
-
+
if(*startAddr > base) {
*startAddr = base;
}
@@ -376,37 +391,37 @@ static int parseIntelHex(char *hexfile, char* buffer, int *startAddr, int *endAd
*endAddr = address;
}
}
-
+
fclose(input);
return 0;
}
/******************************************************************************/
/******************************************************************************/
-static int parseRaw(char *filename, char* data_buffer, int *start_address, int *end_address) {
+static int parseRaw(char *filename, unsigned char *data_buffer, int *start_address, int *end_address) {
FILE *input;
-
+
input = strcmp(filename, "-") == 0 ? stdin : fopen(filename, "r");
-
+
if (input == NULL) {
printf("> Error reading %s: %s\n", filename, strerror(errno));
return 1;
}
-
+
*start_address = 0;
*end_address = 0;
-
+
// read in bytes from file
int byte = 0;
while (1) {
byte = getc(input);
if (byte == EOF) break;
-
+
*data_buffer = byte;
data_buffer += 1;
*end_address += 1;
}
-
+
fclose(input);
return 0;
}
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
diff --git a/upgrade/readme.txt b/upgrade/readme.txt
index 49b276a..0073ad9 100644
--- a/upgrade/readme.txt
+++ b/upgrade/readme.txt
@@ -1,22 +1,22 @@
Micronucleus Upgrade
====================
-**WARNING**: Upgrade requires more testing. Don't use it on chips you can't recover by other means. Consider it experimental for now.
+Upgrade is a virus-like payload you can upload via micronucleus (or other bootloaders!) to install a new version of micronucleus on the target chip. The upgrade program works by compiling the binary contents of a bootloader hex file in to a progmem array, then running on the chip bricking the device so it doesn't enter any existing bootloader anymore but instead runs the upgrade program exclusively. Next it erases and rewrites the bootloader in place at the same address the hex file specifies (BOOTLOADER_ADDRESS in the case of micronucleus). Once the bootloader has been rewritten, upgrade rewrites it's own interrupt vector table to point every interrupt including reset straight at the newly uploaded bootloader's interrupt vector table at whichever address it was installed.
-Upgrade is a virus-like payload you can upload via micronucleus (or other bootloaders) to install a new version of micronucleus on the target chip. The upgrade program works by copying the contents of a bootloader hex file in to a progmem array, then bricking the device so it doesn't enter the bootloader on reset but instead runs the upgrader program exclusively. Next it erases and rewrites the bootloader in place at the same address the hex file specifies (BOOTLOADER_ADDRESS in the case of micronucleus). Once the bootloader has been rewritten, upgrade rewrites it's own interrupt vector table to point every interrupt including reset straight at the newly uploaded bootloader's interrupt vector table at whichever address it was installed.
+The program then emits a beep if a piezo speaker is connected between PB0 and PB1. If you have no speaker, use an LED with positive on PB0 (requires resistor). Premade upgrades are included in releases/ for micronucleus builds. Just upload one in the usual way and wait for the beep. Once you hear the beep, the chip will automatically reboot and should enumerate over USB as a micronucleus device, ready to accept a new program.
-The program then emits a beep if a piezo speaker is connected between PB0 and PB1. If you have no speaker, use an LED with positive on PB0 (requires resistor). Premade upgraders are included in releases/ for micronucleus builds. Just upload one in the usual way and wait for the beep. Once you hear the beep, power down the device and turn it back on - it should launch your new bootloader!
+Upgrade has only been tested with micronucleus - use it to upload other bootloaders at your own risk!
-Creating an Upgrader
-====================
+Creating an Upgrade
+===================
- ruby generate-data.rb my_bootloader.hex
+ ruby generate-data.rb my_new_bootloader.hex
make clean; make
-Next upload the 'upgrade.hex' file generated, via whichever bootloader you're using. If you're using micronucleus and have the command line tool installed: micronucleus --run upgrade.hex
+Next upload the 'upgrade.hex' file generated in this folder, via whichever bootloader you're using, or an ISP or whatever - everything should work. If you're using micronucleus and have the command line tool installed: micronucleus --run upgrade.hex
-The ruby script requires ruby 1.9 be installed. On Mac OS this is best achieved via Mac Homebrew. The 1.8 version included wont do.
+The generate-data.rb script requires Ruby 1.9 or newer to be installed. If you're using an older version of Mac OS X (before Mavericks), use homebrew to install ruby with 'brew install ruby' to get a recent version. On linuxes you can usually find a package called ruby1.9 in whichever installing thingy. On windows you're on your own!
License
diff --git a/upgrade/releases/micronucleus-1.11-entry-ext-reset-upgrade.hex b/upgrade/releases/micronucleus-1.11-entry-ext-reset-upgrade.hex
new file mode 100644
index 0000000..a6a1236
--- /dev/null
+++ b/upgrade/releases/micronucleus-1.11-entry-ext-reset-upgrade.hex
@@ -0,0 +1,165 @@
+:1000000003C003C003C003C003C003C003C003C0D8
+:10008000A5C3CFC3CEC3CDC3CCC3CBC3CAC3C9C31F
+:10009000C8C3C7C3C6C3C5C3C4C3C3C3C2C317C0D1
+:1000A00016C04CC014C009021200010100803209C0
+:1000B000040000000000000012011001FF00000811
+:1000C000D01653070B01000000010403090411249A
+:1000D0001FBECFE5D2E0CDBFDEBF00EB0F9307E040
+:1000E0000F9310E0A0E6B0E0E8EEFFE102C005905B
+:1000F0000D92A636B107D9F720E0A6E6B0E001C020
+:100100001D92A639B207E1F7E2C1A82FB92F80E00E
+:1001100090E041E050EA609530E009C02D918227DF
+:100120009795879510F084279527305EC8F36F5F09
+:10013000A8F30895EADF8D939D930895CF93CFB7E9
+:10014000CF93C0915F02C03B21F4C0915E02C730E3
+:1001500021F0CF91CFBFCF91A1CFCC27C395B39B37
+:10016000E9F7B39B0BC0B39B09C0B39B07C0B39B1C
+:1001700005C0B39B03C0B39B01C0D3C00F92DF93F4
+:10018000C0917900DD27C058DF4F012EB39B03C01B
+:10019000DF910F90E6CF2F930F931F934F932FEF85
+:1001A0004F6F06B303FB20F95F933F9350E03BE0B2
+:1001B00065C016B30126502953FDC89556B30127D3
+:1001C00003FB25F92F7306B3B1F05027102713FB5B
+:1001D00026F906B22230F0F000C016B3012703FB67
+:1001E00027F90126502906B22430E8F54F77206818
+:1001F00016B30000F6CF50274F7D206206B2102FB5
+:10020000000000C006B300265029102713FB26F972
+:1002100006B2E2CF4F7B06B3206400C0DACF0126DE
+:100220005029187106B269F14E7F2160012F16B373
+:1002300028C0002650294D7F06B22260102F29C009
+:10024000012650294B7F06B22460012F2DC016B322
+:1002500001265029477F2860000006B22EC04F7E3D
+:1002600006B3206130C0422706B3499300265029C7
+:10027000102706B24FEF13FB20F9297F16B379F24E
+:10028000187159F10126502906B2012703FB21F903
+:10029000237F06B371F2002650293150D0F006B208
+:1002A000102713FB22F9277E16B351F2012650299D
+:1002B000012703FB06B223F92F7C49F2000006B3A5
+:1002C000102713FB24F90026502906B22F7939F2A2
+:1002D00070CF10E21ABF002717C03B503195C31BE7
+:1002E000D04010E21ABF0881033CF9F00B34E9F06A
+:1002F000209177001981110F1213EDCF093651F1BA
+:100300000D3211F0013E39F700937E003F915F916D
+:100310004F911F910F912F91DF910F90CAB7C5FD9B
+:100320001DCFCF91CFBFCF91189520917E00222372
+:1003300069F310917C00112321F5343022F13093C0
+:100340007C0020937800109179003BE0311B3093C2
+:10035000790019C000917C0001309CF40AE53091CD
+:10036000600034FD11C000936000CCE6D0E010C006
+:10037000052710E000C021C0052710E0C89508BB84
+:1003800014C03AE501C032ED032EC0E0D0E032E007
+:1003900017B31861C39A08B317BB58E120E84FEFB1
+:1003A00020FF052708BB279517951C3F28F700005D
+:1003B0004552B0F720FF0527279508BB17951C3F2E
+:1003C000B8F629913A9561F7077E10917D00110FDB
+:1003D00008BBC250D04011F01093770010E21ABF52
+:1003E000086017B3177E402F477E54E05A95F1F707
+:1003F00008BB17BB48BB8ACFF8942FEFB0E8A0E446
+:100400004AE0B1BF000081EE9CE0B399FECFB39B00
+:10041000FECF0197B399FDCF97FF03C0BA1B81951B
+:1004200001C0BA0FA69529F4281710F031B7282F6C
+:10043000A1E0415031F731BF000078940895F8945D
+:10044000F201329785E080935700E89578940895FB
+:10045000F201309729F4909368008093670007C0F9
+:10046000E430F10539F490936A00809369008FE5D8
+:100470009CEC1FC02CEB421628E1520639F4809107
+:100480006700909168008E559C4F13C02EEB42166A
+:1004900028E1520639F48091690090916A008D55E7
+:1004A0009C4F07C02AEB421628E1520611F481B78F
+:1004B00090E02FB7F89431E00C0130935700E895A5
+:1004C00011242F0182E0480E511C2FBF089504B65D
+:1004D00001FC14C0EDEBF8E1E491EF3F79F0F89402
+:1004E000BB9A1BBE15BA10925F02EAEBF8E1E491E9
+:1004F0008E2F81508E3F08F462C163C114BE88E123
+:1005000081BD87E081BDBB9A88E893E1ECE9F1E029
+:100510003197F1F70197D1F7BB98AC9A8BB780620E
+:100520008BBF7894712C8CE991E00197F1F7A89535
+:10053000312C60917C00162F135017FDB2C08091B2
+:100540007900CCE0D0E0C81BD109C058DF4F615022
+:10055000CE01DBDD8E3F9F4409F0A1C08091780081
+:100560008D3209F085C0183009F099C083EC809372
+:100570006C008AE580936000109266009881292FB4
+:10058000207689812223D1F0712C811108C082E666
+:1005900090E090937B0080937A0024E05FC08130EC
+:1005A00051F481E180935700E8954C805D8097FD80
+:1005B00050C02FEF4FC0382E20E050C09A811092CB
+:1005C0007500811106C01092760085E790E022E068
+:1005D0003BC0853019F490937D002CC0863009F51E
+:1005E0008B81813019F48AED98E104C0823041F4A6
+:1005F00088EC98E190937B0080937A0022E10DC013
+:10060000833051F4911108C08CEE98E190937B00F7
+:1006100080937A0024E001C020E080E480936600AB
+:100620001DC0883059F0893019F490937F0002C0C2
+:100630008A3039F085E790E020E006C08FE790E04F
+:1006400002C085E790E021E090937B0080937A00E0
+:1006500005C02E8180E88093660007C08F818111DC
+:1006600004C08E81821708F4282F2093610017C0E0
+:100670008091660087FF13C080EC481688E1580619
+:1006800020F0842D8F7339F00AC089919991E0DEB2
+:10069000125091F7F6CF95E0392E1092610010922A
+:1006A0007C008091600084FF42C0809161008F3F98
+:1006B00009F43DC0182F893008F018E0811B8093A1
+:1006C000610080916C0098E8892780936C00112369
+:1006D00011F1E0917A00F0917B008091660086FF35
+:1006E0000BC0ADE6B0E084918D9331968DE690E03D
+:1006F000810F8A13F8CF0BC0EF01ADE6B0E089910E
+:100700008D93FE018DE690E0810F8A13F8CFF09370
+:100710007B00E0937A00612F8DE690E00BDD1C5F9B
+:100720001C3019F08FEF809361001093600084E11A
+:1007300096B3987131F48150D9F710927D001092E0
+:100740007700C1E08111C0E080916B008C1729F027
+:10075000C11101C051DEC0936B00C30101963C0181
+:100760008035934C11F484E0382E232D3320E9F0AA
+:100770008AE390E20197F1F72230A9F4F894E0ECD3
+:10078000F8E1E054F10983E080935700E895309751
+:10079000C1F7412C512CC8E08FEF9FEF59DEC150BB
+:1007A000D9F74DDE02C02530E1F384E03812BBCE2C
+:1007B000EDEBF8E1E491EF3F09F4B5CE90CEE1BF67
+:1007C00000006BCCFFCF5AFF18BA400800000000B1
+:1007D0000000000000000000000000000000000019
+:1007E00000000000000000000000000011241FBEF7
+:1007F000CFE5D2E0DEBFCDBF10E0A0E6B0E0E8E894
+:10080000FAE002C005900D92A236B107D9F710E0C8
+:10081000A2E6B0E001C01D92A236B107E1F71CD1FB
+:1008200031C12ECC05C0EDE1F0E13197F1F7019730
+:100830000097C9F70895AC01407C80E090E0FC018E
+:10084000E40FF51F25913491FC01EE7FE60FF71FB1
+:100850002083318302968034910589F70895FC0145
+:10086000E07C83E080935700E89507B600FCFDCF5D
+:100870000895CF93DF93EC01AB01DB0120E030E082
+:10088000FE01E41BF50BEA0FFB1F8D919D9161E0CA
+:100890000C0160935700E89511242F5F3F4F2032E1
+:1008A000310571F785E0FE0180935700E89507B6A2
+:1008B00000FCFDCFDF91CF910895CF93DF93CDB7AB
+:1008C000DEB7C054D0400FB6F894DEBF0FBECDBF28
+:1008D0008091600090916100969587958150904439
+:1008E000FE0131969E012F5B3F4F81939193E2175A
+:1008F000F307D9F780E090E0B2DF80E090E0BE013E
+:100900006F5F7F4FB6DFC05CDF4F0FB6F894DEBF7E
+:100910000FBECDBFDF91CF9108950F931F93CF935B
+:10092000DF93CDB7DEB7C054D0400FB6F894DEBF2A
+:100930000FBECDBF00E010E040C080E090E0F801C5
+:10094000E256FF4FE80FF91F9C013595279547E0C8
+:10095000EC3CF40770F0F901EE0FFF1F21E030E0EE
+:100960002C0F3D1FE20FF31F2FEF3FEF318320834A
+:100970000DC045915491F901EE0FFF1F21E030E0C9
+:100980002C0F3D1FE20FF31F4083518302968034EA
+:100990009105A9F68091600090916100800F911FF0
+:1009A0005EDF8091600090916100800F911FBE0119
+:1009B0006F5F7F4F5EDF005C1F4F37E0003413072F
+:1009C00009F0BBCFC05CDF4F0FB6F894DEBF0FBE9F
+:1009D000CDBFDF91CF911F910F910895CF93DF93FA
+:1009E000CDB7DEB7C054D0400FB6F894DEBF0FBE0F
+:1009F000CDBF80E090E0BE016F5F7F4F1CDF8FEFC7
+:100A00009FEF9A83898380E090E029DF80E090E087
+:100A1000BE016F5F7F4F2DDFC05CDF4F0FB6F894D4
+:100A2000DEBF0FBECDBFDF91CF910895CF9387B3C7
+:100A3000836087BBC198CAEF81E090E0F3DEC19A82
+:100A400081E090E0EFDEC198C150B1F7CF910895F9
+:100A5000E0E0F0E00995089588B318BA87B38FEF06
+:100A600087BB8AEF90E0DEDE87B317BA8AEF90E0AB
+:100A7000D9DEF894B3DF51DF20DFD8DFE9DF80E093
+:080A800090E00895F894FFCF07
+:020A8800C01894
+:040000030000008079
+:00000001FF
diff --git a/upgrade/releases/micronucleus-1.11-entry-jumper-pb0-upgrade.hex b/upgrade/releases/micronucleus-1.11-entry-jumper-pb0-upgrade.hex
new file mode 100644
index 0000000..979bbdf
--- /dev/null
+++ b/upgrade/releases/micronucleus-1.11-entry-jumper-pb0-upgrade.hex
@@ -0,0 +1,166 @@
+:1000000003C003C003C003C003C003C003C003C0D8
+:10008000ABC3D5C3D4C3D3C3D2C3D1C3D0C3CFC3EF
+:10009000CEC3CDC3CCC3CBC3CAC3C9C3C8C317C0A7
+:1000A00016C04CC014C009021200010100803209C0
+:1000B000040000000000000012011001FF00000811
+:1000C000D01653070B01000000010403090411249A
+:1000D0001FBECFE5D2E0CDBFDEBF00EB0F9307E040
+:1000E0000F9310E0A0E6B0E0E4EFFFE102C005905E
+:1000F0000D92A636B107D9F720E0A6E6B0E001C020
+:100100001D92A639B207E1F7E2C1A82FB92F80E00E
+:1001100090E041E050EA609530E009C02D918227DF
+:100120009795879510F084279527305EC8F36F5F09
+:10013000A8F30895EADF8D939D930895CF93CFB7E9
+:10014000CF93C0915F02C03B21F4C0915E02C730E3
+:1001500021F0CF91CFBFCF91A1CFCC27C395B39B37
+:10016000E9F7B39B0BC0B39B09C0B39B07C0B39B1C
+:1001700005C0B39B03C0B39B01C0D3C00F92DF93F4
+:10018000C0917900DD27C058DF4F012EB39B03C01B
+:10019000DF910F90E6CF2F930F931F934F932FEF85
+:1001A0004F6F06B303FB20F95F933F9350E03BE0B2
+:1001B00065C016B30126502953FDC89556B30127D3
+:1001C00003FB25F92F7306B3B1F05027102713FB5B
+:1001D00026F906B22230F0F000C016B3012703FB67
+:1001E00027F90126502906B22430E8F54F77206818
+:1001F00016B30000F6CF50274F7D206206B2102FB5
+:10020000000000C006B300265029102713FB26F972
+:1002100006B2E2CF4F7B06B3206400C0DACF0126DE
+:100220005029187106B269F14E7F2160012F16B373
+:1002300028C0002650294D7F06B22260102F29C009
+:10024000012650294B7F06B22460012F2DC016B322
+:1002500001265029477F2860000006B22EC04F7E3D
+:1002600006B3206130C0422706B3499300265029C7
+:10027000102706B24FEF13FB20F9297F16B379F24E
+:10028000187159F10126502906B2012703FB21F903
+:10029000237F06B371F2002650293150D0F006B208
+:1002A000102713FB22F9277E16B351F2012650299D
+:1002B000012703FB06B223F92F7C49F2000006B3A5
+:1002C000102713FB24F90026502906B22F7939F2A2
+:1002D00070CF10E21ABF002717C03B503195C31BE7
+:1002E000D04010E21ABF0881033CF9F00B34E9F06A
+:1002F000209177001981110F1213EDCF093651F1BA
+:100300000D3211F0013E39F700937E003F915F916D
+:100310004F911F910F912F91DF910F90CAB7C5FD9B
+:100320001DCFCF91CFBFCF91189520917E00222372
+:1003300069F310917C00112321F5343022F13093C0
+:100340007C0020937800109179003BE0311B3093C2
+:10035000790019C000917C0001309CF40AE53091CD
+:10036000600034FD11C000936000CCE6D0E010C006
+:10037000052710E000C021C0052710E0C89508BB84
+:1003800014C03AE501C032ED032EC0E0D0E032E007
+:1003900017B31861C39A08B317BB58E120E84FEFB1
+:1003A00020FF052708BB279517951C3F28F700005D
+:1003B0004552B0F720FF0527279508BB17951C3F2E
+:1003C000B8F629913A9561F7077E10917D00110FDB
+:1003D00008BBC250D04011F01093770010E21ABF52
+:1003E000086017B3177E402F477E54E05A95F1F707
+:1003F00008BB17BB48BB8ACFF8942FEFB0E8A0E446
+:100400004AE0B1BF000081EE9CE0B399FECFB39B00
+:10041000FECF0197B399FDCF97FF03C0BA1B81951B
+:1004200001C0BA0FA69529F4281710F031B7282F6C
+:10043000A1E0415031F731BF000078940895F8945D
+:10044000F201329785E080935700E89578940895FB
+:10045000F201309729F4909368008093670007C0F9
+:10046000E430F10539F490936A00809369008FE5D8
+:100470009CEC1FC02CEB421628E1520639F4809107
+:100480006700909168008E559C4F13C02EEB42166A
+:1004900028E1520639F48091690090916A008D55E7
+:1004A0009C4F07C02AEB421628E1520611F481B78F
+:1004B00090E02FB7F89431E00C0130935700E895A5
+:1004C00011242F0182E0480E511C2FBF0895B898C7
+:1004D000C09A8DE190E10197F1F7B09B15C0EDEB6B
+:1004E000F8E1E491EF3F81F0C098F894BB9A1BBE0D
+:1004F00015BA10925F02EAEBF8E1E4918E2F815079
+:100500008E3F08F462C163C114BE88E181BD87E0FB
+:1005100081BDBB9A88E893E1ECE9F1E03197F1F70E
+:100520000197D1F7BB98AC9A8BB780628BBF789458
+:10053000712C8CE991E00197F1F7A895312C60912D
+:100540007C00162F135017FDB2C080917900CCE0CB
+:10055000D0E0C81BD109C058DF4F6150CE01D5DDB6
+:100560008E3F9F4409F0A1C0809178008D3209F040
+:1005700085C0183009F099C083EC80936C008AE53F
+:1005800080936000109266009881292F20768981DF
+:100590002223D1F0712C811108C082E690E0909363
+:1005A0007B0080937A0024E05FC0813051F481E1C8
+:1005B00080935700E8954C805D8097FD50C02FEFE9
+:1005C0004FC0382E20E050C09A81109275008111E2
+:1005D00006C01092760085E790E022E03BC08530AF
+:1005E00019F490937D002CC0863009F58B81813001
+:1005F00019F48AED98E104C0823041F488EC98E166
+:1006000090937B0080937A0022E10DC0833051F4F7
+:10061000911108C08CEE98E190937B0080937A0052
+:1006200024E001C020E080E4809366001DC0883093
+:1006300059F0893019F490937F0002C08A3039F064
+:1006400085E790E020E006C08FE790E002C085E7F4
+:1006500090E021E090937B0080937A0005C02E818A
+:1006600080E88093660007C08F81811104C08E816D
+:10067000821708F4282F2093610017C0809166002C
+:1006800087FF13C080EC481688E1580620F0842DBF
+:100690008F7339F00AC089919991DADE125091F77F
+:1006A000F6CF95E0392E1092610010927C00809177
+:1006B000600084FF42C0809161008F3F09F43DC01B
+:1006C000182F893008F018E0811B80936100809119
+:1006D0006C0098E8892780936C00112311F1E09158
+:1006E0007A00F0917B008091660086FF0BC0ADE63A
+:1006F000B0E084918D9331968DE690E0810F8A135E
+:10070000F8CF0BC0EF01ADE6B0E089918D93FE010B
+:100710008DE690E0810F8A13F8CFF0937B00E09391
+:100720007A00612F8DE690E005DD1C5F1C3019F02A
+:100730008FEF809361001093600084E196B398710D
+:1007400031F48150D9F710927D0010927700C1E00A
+:100750008111C0E080916B008C1729F0C11101C09C
+:100760004BDEC0936B00C30101963C018035934C76
+:1007700011F484E0382E232D3320E9F08AE390E24F
+:100780000197F1F72230A9F4F894E0ECF8E1E05495
+:10079000F10983E080935700E8953097C1F7412C29
+:1007A000512CC8E08FEF9FEF53DEC150D9F747DEE1
+:1007B00002C02530E1F384E03812BBCEEDEBF8E166
+:1007C000E491EF3F09F4B5CE8FCEE1BF000065CCD8
+:1007D000FFCF5AFF18BA40080000000000000000D8
+:1007E0000000000000000000000000000000000009
+:1007F000000000000000000011241FBECFE5D2E081
+:10080000DEBFCDBF10E0A0E6B0E0E4E9FAE002C050
+:1008100005900D92A236B107D9F710E0A2E6B0E03C
+:1008200001C01D92A236B107E1F71CD131C128CC1D
+:1008300005C0EDE1F0E13197F1F701970097C9F7B5
+:100840000895AC01407C80E090E0FC01E40FF51FCE
+:1008500025913491FC01EE7FE60FF71F2083318351
+:1008600002968034910589F70895FC01E07C83E0CD
+:1008700080935700E89507B600FCFDCF0895CF930D
+:10088000DF93EC01AB01DB0120E030E0FE01E41B73
+:10089000F50BEA0FFB1F8D919D9161E00C016093B8
+:1008A0005700E89511242F5F3F4F2032310571F733
+:1008B00085E0FE0180935700E89507B600FCFDCF68
+:1008C000DF91CF910895CF93DF93CDB7DEB7C054BA
+:1008D000D0400FB6F894DEBF0FBECDBF8091600050
+:1008E000909161009695879581509044FE013196D4
+:1008F0009E012F5B3F4F81939193E217F307D9F746
+:1009000080E090E0B2DF80E090E0BE016F5F7F4F5B
+:10091000B6DFC05CDF4F0FB6F894DEBF0FBECDBFB1
+:10092000DF91CF9108950F931F93CF93DF93CDB7AE
+:10093000DEB7C054D0400FB6F894DEBF0FBECDBFB7
+:1009400000E010E040C080E090E0F801E256FF4F88
+:10095000E80FF91F9C013595279547E0E83DF4071E
+:1009600070F0F901EE0FFF1F21E030E02C0F3D1F6A
+:10097000E20FF31F2FEF3FEF318320830DC045912E
+:100980005491F901EE0FFF1F21E030E02C0F3D1FC5
+:10099000E20FF31F40835183029680349105A9F63C
+:1009A0008091600090916100800F911F5EDF8091C7
+:1009B000600090916100800F911FBE016F5F7F4FBB
+:1009C0005EDF005C1F4F37E00034130709F0BBCF38
+:1009D000C05CDF4F0FB6F894DEBF0FBECDBFDF9116
+:1009E000CF911F910F910895CF93DF93CDB7DEB7CD
+:1009F000C054D0400FB6F894DEBF0FBECDBF80E02C
+:100A000090E0BE016F5F7F4F1CDF8FEF9FEF9A83F7
+:100A1000898380E090E029DF80E090E0BE016F5F95
+:100A20007F4F2DDFC05CDF4F0FB6F894DEBF0FBEE7
+:100A3000CDBFDF91CF910895CF9387B3836087BBFC
+:100A4000C198CAEF81E090E0F3DEC19A81E090E0C6
+:100A5000EFDEC198C150B1F7CF910895E0E0F0E02A
+:100A60000995089588B318BA87B38FEF87BB8AEFCB
+:100A700090E0DEDE87B317BA8AEF90E0D9DEF89413
+:100A8000B3DF51DF20DFD8DFE9DF80E090E00895B9
+:040A9000F894FFCF08
+:020A9400C01888
+:040000030000008079
+:00000001FF
diff --git a/upgrade/releases/micronucleus-1.11-ledpb1-upgrade.hex b/upgrade/releases/micronucleus-1.11-ledpb1-upgrade.hex
new file mode 100644
index 0000000..f5944e2
--- /dev/null
+++ b/upgrade/releases/micronucleus-1.11-ledpb1-upgrade.hex
@@ -0,0 +1,165 @@
+:1000000003C003C003C003C003C003C003C003C0D8
+:10008000A2C3CCC3CBC3CAC3C9C3C8C3C7C3C6C337
+:10009000C5C3C4C3C3C3C2C3C1C3C0C3BFC317C0E6
+:1000A00016C04CC014C009021200010100803209C0
+:1000B000040000000000000012011001FF00000811
+:1000C000D01653070B01000000010403090411249A
+:1000D0001FBECFE5D2E0CDBFDEBF00EB0F9307E040
+:1000E0000F9310E0A0E6B0E0E2EEFFE102C0059061
+:1000F0000D92A636B107D9F720E0A6E6B0E001C020
+:100100001D92A639B207E1F7E2C1A82FB92F80E00E
+:1001100090E041E050EA609530E009C02D918227DF
+:100120009795879510F084279527305EC8F36F5F09
+:10013000A8F30895EADF8D939D930895CF93CFB7E9
+:10014000CF93C0915F02C03B21F4C0915E02C730E3
+:1001500021F0CF91CFBFCF91A1CFCC27C395B39B37
+:10016000E9F7B39B0BC0B39B09C0B39B07C0B39B1C
+:1001700005C0B39B03C0B39B01C0D3C00F92DF93F4
+:10018000C0917900DD27C058DF4F012EB39B03C01B
+:10019000DF910F90E6CF2F930F931F934F932FEF85
+:1001A0004F6F06B303FB20F95F933F9350E03BE0B2
+:1001B00065C016B30126502953FDC89556B30127D3
+:1001C00003FB25F92F7306B3B1F05027102713FB5B
+:1001D00026F906B22230F0F000C016B3012703FB67
+:1001E00027F90126502906B22430E8F54F77206818
+:1001F00016B30000F6CF50274F7D206206B2102FB5
+:10020000000000C006B300265029102713FB26F972
+:1002100006B2E2CF4F7B06B3206400C0DACF0126DE
+:100220005029187106B269F14E7F2160012F16B373
+:1002300028C0002650294D7F06B22260102F29C009
+:10024000012650294B7F06B22460012F2DC016B322
+:1002500001265029477F2860000006B22EC04F7E3D
+:1002600006B3206130C0422706B3499300265029C7
+:10027000102706B24FEF13FB20F9297F16B379F24E
+:10028000187159F10126502906B2012703FB21F903
+:10029000237F06B371F2002650293150D0F006B208
+:1002A000102713FB22F9277E16B351F2012650299D
+:1002B000012703FB06B223F92F7C49F2000006B3A5
+:1002C000102713FB24F90026502906B22F7939F2A2
+:1002D00070CF10E21ABF002717C03B503195C31BE7
+:1002E000D04010E21ABF0881033CF9F00B34E9F06A
+:1002F000209177001981110F1213EDCF093651F1BA
+:100300000D3211F0013E39F700937E003F915F916D
+:100310004F911F910F912F91DF910F90CAB7C5FD9B
+:100320001DCFCF91CFBFCF91189520917E00222372
+:1003300069F310917C00112321F5343022F13093C0
+:100340007C0020937800109179003BE0311B3093C2
+:10035000790019C000917C0001309CF40AE53091CD
+:10036000600034FD11C000936000CCE6D0E010C006
+:10037000052710E000C021C0052710E0C89508BB84
+:1003800014C03AE501C032ED032EC0E0D0E032E007
+:1003900017B31861C39A08B317BB58E120E84FEFB1
+:1003A00020FF052708BB279517951C3F28F700005D
+:1003B0004552B0F720FF0527279508BB17951C3F2E
+:1003C000B8F629913A9561F7077E10917D00110FDB
+:1003D00008BBC250D04011F01093770010E21ABF52
+:1003E000086017B3177E402F477E54E05A95F1F707
+:1003F00008BB17BB48BB8ACFF8942FEFB0E8A0E446
+:100400004AE0B1BF000081EE9CE0B399FECFB39B00
+:10041000FECF0197B399FDCF97FF03C0BA1B81951B
+:1004200001C0BA0FA69529F4281710F031B7282F6C
+:10043000A1E0415031F731BF000078940895F8945D
+:10044000F201329785E080935700E89578940895FB
+:10045000F201309729F4909368008093670007C0F9
+:10046000E430F10539F490936A00809369008FE5D8
+:100470009CEC1FC02CEB421628E1520639F4809107
+:100480006700909168008E559C4F13C02EEB42166A
+:1004900028E1520639F48091690090916A008D55E7
+:1004A0009C4F07C02AEB421628E1520611F481B78F
+:1004B00090E02FB7F89431E00C0130935700E895A5
+:1004C00011242F0182E0480E511C2FBF089514BE45
+:1004D00088E181BD87E081BDBB9A88E893E1ECE9C2
+:1004E000F1E03197F1F70197D1F7BB98AC9A8BB750
+:1004F00080628BBF7894C198712C8CE991E0019750
+:10050000F1F7A895312C60917C00162F135017FD40
+:10051000B2C080917900CCE0D0E0C81BD109C058AE
+:10052000DF4F6150CE01F1DD8E3F9F4409F0A1C045
+:10053000809178008D3209F085C0183009F099C09B
+:1005400083EC80936C008AE58093600010926600D3
+:100550009881292F207689812223D1F0712C811155
+:1005600008C082E690E090937B0080937A0024E0BC
+:100570005FC0813051F481E180935700E8954C8051
+:100580005D8097FD50C02FEF4FC0382E20E050C047
+:100590009A8110927500811106C01092760085E74D
+:1005A00090E022E03BC0853019F490937D002CC090
+:1005B000863009F58B81813019F48AED98E104C009
+:1005C000823041F488EC98E190937B0080937A002C
+:1005D00022E10DC0833051F4911108C08CEE98E1F6
+:1005E00090937B0080937A0024E001C020E080E4B7
+:1005F000809366001DC0883059F0893019F49093BB
+:100600007F0002C08A3039F085E790E020E006C024
+:100610008FE790E002C085E790E021E090937B00B7
+:1006200080937A0005C02E8180E88093660007C021
+:100630008F81811104C08E81821708F4282F2093A6
+:10064000610017C08091660087FF13C080EC4816D8
+:1006500088E1580620F0842D8F7339F00AC0899103
+:100660009991F6DE125091F7F6CF95E0392E10925F
+:10067000610010927C008091600084FF42C08091F4
+:1006800061008F3F09F43DC0182F893008F018E051
+:10069000811B8093610080916C0098E8892780938A
+:1006A0006C00112311F1E0917A00F0917B008091B0
+:1006B000660086FF0BC0ADE6B0E084918D93319665
+:1006C0008DE690E0810F8A13F8CF0BC0EF01ADE605
+:1006D000B0E089918D93FE018DE690E0810F8A1341
+:1006E000F8CFF0937B00E0937A00612F8DE690E0E5
+:1006F00021DD1C5F1C3019F08FEF80936100109397
+:10070000600084E196B3987131F48150D9F710926A
+:100710007D0010927700C1E08111C0E080916B00F4
+:100720008C1729F0C11101C067DEC0936B00C301B3
+:1007300001963C018035934C11F484E0382E872DCE
+:100740008D7011F0B99801C0B99A232D3320E9F0CA
+:100750008AE390E20197F1F72230A9F4F894E0ECF3
+:10076000F8E1E054F10983E080935700E895309771
+:10077000C1F7412C512CC8E08FEF9FEF69DEC150CB
+:10078000D9F75DDE02C02530E1F384E03812B5CE42
+:10079000EDEBF8E1E491EF3F09F4AFCEB998F894AE
+:1007A000BB9A1BBE15BA10925F02EAEBF8E1E49126
+:1007B0008E2F81508E3F10F4E1BF00006ECCFFCF32
+:1007C0005AFF18BA400800000000000000000000B6
+:1007D0000000000000000000000000000000000019
+:1007E00000000000000011241FBECFE5D2E0DEBFF4
+:1007F000CDBF10E0A0E6B0E0E2E8FAE002C005906C
+:100800000D92A236B107D9F710E0A2E6B0E001C020
+:100810001D92A236B107E1F71CD131C131CC05C020
+:10082000EDE1F0E13197F1F701970097C9F70895ED
+:10083000AC01407C80E090E0FC01E40FF51F2591C5
+:100840003491FC01EE7FE60FF71F2083318302967F
+:100850008034910589F70895FC01E07C83E0809362
+:100860005700E89507B600FCFDCF0895CF93DF93BE
+:10087000EC01AB01DB0120E030E0FE01E41BF50BF5
+:10088000EA0FFB1F8D919D9161E00C016093570071
+:10089000E89511242F5F3F4F2032310571F785E035
+:1008A000FE0180935700E89507B600FCFDCFDF916D
+:1008B000CF910895CF93DF93CDB7DEB7C054D0402A
+:1008C0000FB6F894DEBF0FBECDBF8091600090914F
+:1008D00061009695879581509044FE0131969E0166
+:1008E0002F5B3F4F81939193E217F307D9F780E095
+:1008F00090E0B2DF80E090E0BE016F5F7F4FB6DF37
+:10090000C05CDF4F0FB6F894DEBF0FBECDBFDF91E6
+:10091000CF9108950F931F93CF93DF93CDB7DEB799
+:10092000C054D0400FB6F894DEBF0FBECDBF00E07C
+:1009300010E040C080E090E0F801E256FF4FE80F81
+:10094000F91F9C013595279547E0E63CF40770F0C8
+:10095000F901EE0FFF1F21E030E02C0F3D1FE20FE9
+:10096000F31F2FEF3FEF318320830DC0459154914A
+:10097000F901EE0FFF1F21E030E02C0F3D1FE20FC9
+:10098000F31F40835183029680349105A9F680912C
+:10099000600090916100800F911F5EDF8091600088
+:1009A00090916100800F911FBE016F5F7F4F5EDFEE
+:1009B000005C1F4F37E00034130709F0BBCFC05C69
+:1009C000DF4F0FB6F894DEBF0FBECDBFDF91CF91E2
+:1009D0001F910F910895CF93DF93CDB7DEB7C05429
+:1009E000D0400FB6F894DEBF0FBECDBF80E090E0E0
+:1009F000BE016F5F7F4F1CDF8FEF9FEF9A8389836C
+:100A000080E090E029DF80E090E0BE016F5F7F4FE3
+:100A10002DDFC05CDF4F0FB6F894DEBF0FBECDBF39
+:100A2000DF91CF910895CF9387B3836087BBC1983F
+:100A3000CAEF81E090E0F3DEC19A81E090E0EFDE62
+:100A4000C198C150B1F7CF910895E0E0F0E0099569
+:100A5000089588B318BA87B38FEF87BB8AEF90E009
+:100A6000DEDE87B317BA8AEF90E0D9DEF894B3DF01
+:100A700051DF20DFD8DFE9DF80E090E00895F894CF
+:020A8000FFCFA6
+:020A8200C0189A
+:040000030000008079
+:00000001FF
diff --git a/upgrade/releases/micronucleus-1.11-upgrade.hex b/upgrade/releases/micronucleus-1.11-upgrade.hex
new file mode 100644
index 0000000..11060a0
--- /dev/null
+++ b/upgrade/releases/micronucleus-1.11-upgrade.hex
@@ -0,0 +1,164 @@
+:1000000003C003C003C003C003C003C003C003C0D8
+:100080009AC3C4C3C3C3C2C3C1C3C0C3BFC3BEC377
+:10009000BDC3BCC3BBC3BAC3B9C3B8C3B7C317C01E
+:1000A00016C04CC014C009021200010100803209C0
+:1000B000040000000000000012011001FF00000811
+:1000C000D01653070B01000000010403090411249A
+:1000D0001FBECFE5D2E0CDBFDEBF00EB0F9307E040
+:1000E0000F9310E0A0E6B0E0E2EDFFE102C0059062
+:1000F0000D92A636B107D9F720E0A6E6B0E001C020
+:100100001D92A639B207E1F7E2C1A82FB92F80E00E
+:1001100090E041E050EA609530E009C02D918227DF
+:100120009795879510F084279527305EC8F36F5F09
+:10013000A8F30895EADF8D939D930895CF93CFB7E9
+:10014000CF93C0915F02C03B21F4C0915E02C730E3
+:1001500021F0CF91CFBFCF91A1CFCC27C395B39B37
+:10016000E9F7B39B0BC0B39B09C0B39B07C0B39B1C
+:1001700005C0B39B03C0B39B01C0D3C00F92DF93F4
+:10018000C0917900DD27C058DF4F012EB39B03C01B
+:10019000DF910F90E6CF2F930F931F934F932FEF85
+:1001A0004F6F06B303FB20F95F933F9350E03BE0B2
+:1001B00065C016B30126502953FDC89556B30127D3
+:1001C00003FB25F92F7306B3B1F05027102713FB5B
+:1001D00026F906B22230F0F000C016B3012703FB67
+:1001E00027F90126502906B22430E8F54F77206818
+:1001F00016B30000F6CF50274F7D206206B2102FB5
+:10020000000000C006B300265029102713FB26F972
+:1002100006B2E2CF4F7B06B3206400C0DACF0126DE
+:100220005029187106B269F14E7F2160012F16B373
+:1002300028C0002650294D7F06B22260102F29C009
+:10024000012650294B7F06B22460012F2DC016B322
+:1002500001265029477F2860000006B22EC04F7E3D
+:1002600006B3206130C0422706B3499300265029C7
+:10027000102706B24FEF13FB20F9297F16B379F24E
+:10028000187159F10126502906B2012703FB21F903
+:10029000237F06B371F2002650293150D0F006B208
+:1002A000102713FB22F9277E16B351F2012650299D
+:1002B000012703FB06B223F92F7C49F2000006B3A5
+:1002C000102713FB24F90026502906B22F7939F2A2
+:1002D00070CF10E21ABF002717C03B503195C31BE7
+:1002E000D04010E21ABF0881033CF9F00B34E9F06A
+:1002F000209177001981110F1213EDCF093651F1BA
+:100300000D3211F0013E39F700937E003F915F916D
+:100310004F911F910F912F91DF910F90CAB7C5FD9B
+:100320001DCFCF91CFBFCF91189520917E00222372
+:1003300069F310917C00112321F5343022F13093C0
+:100340007C0020937800109179003BE0311B3093C2
+:10035000790019C000917C0001309CF40AE53091CD
+:10036000600034FD11C000936000CCE6D0E010C006
+:10037000052710E000C021C0052710E0C89508BB84
+:1003800014C03AE501C032ED032EC0E0D0E032E007
+:1003900017B31861C39A08B317BB58E120E84FEFB1
+:1003A00020FF052708BB279517951C3F28F700005D
+:1003B0004552B0F720FF0527279508BB17951C3F2E
+:1003C000B8F629913A9561F7077E10917D00110FDB
+:1003D00008BBC250D04011F01093770010E21ABF52
+:1003E000086017B3177E402F477E54E05A95F1F707
+:1003F00008BB17BB48BB8ACFF8942FEFB0E8A0E446
+:100400004AE0B1BF000081EE9CE0B399FECFB39B00
+:10041000FECF0197B399FDCF97FF03C0BA1B81951B
+:1004200001C0BA0FA69529F4281710F031B7282F6C
+:10043000A1E0415031F731BF000078940895F8945D
+:10044000F201329785E080935700E89578940895FB
+:10045000F201309729F4909368008093670007C0F9
+:10046000E430F10539F490936A00809369008FE5D8
+:100470009CEC1FC02CEB421628E1520639F4809107
+:100480006700909168008E559C4F13C02EEB42166A
+:1004900028E1520639F48091690090916A008D55E7
+:1004A0009C4F07C02AEB421628E1520611F481B78F
+:1004B00090E02FB7F89431E00C0130935700E895A5
+:1004C00011242F0182E0480E511C2FBF089514BE45
+:1004D00088E181BD87E081BDBB9A88E893E1ECE9C2
+:1004E000F1E03197F1F70197D1F7BB98AC9A8BB750
+:1004F00080628BBF7894712C8CE991E00197F1F7C1
+:10050000A895312C60917C00162F135017FDB2C0B6
+:1005100080917900CCE0D0E0C81BD109C058DF4FF2
+:100520006150CE01F2DD8E3F9F4409F0A1C0809161
+:1005300078008D3209F085C0183009F099C083EC3D
+:1005400080936C008AE58093600010926600988129
+:10055000292F207689812223D1F0712C811108C0A6
+:1005600082E690E090937B0080937A0024E05FC065
+:10057000813051F481E180935700E8954C805D8093
+:1005800097FD50C02FEF4FC0382E20E050C09A8109
+:1005900010927500811106C01092760085E790E0F8
+:1005A00022E03BC0853019F490937D002CC086304A
+:1005B00009F58B81813019F48AED98E104C082300D
+:1005C00041F488EC98E190937B0080937A0022E1DB
+:1005D0000DC0833051F4911108C08CEE98E19093D6
+:1005E0007B0080937A0024E001C020E080E48093C7
+:1005F00066001DC0883059F0893019F490937F004F
+:1006000002C08A3039F085E790E020E006C08FE72D
+:1006100090E002C085E790E021E090937B0080931A
+:100620007A0005C02E8180E88093660007C08F8124
+:10063000811104C08E81821708F4282F2093610055
+:1006400017C08091660087FF13C080EC481688E1D0
+:10065000580620F0842D8F7339F00AC08991999142
+:10066000F7DE125091F7F6CF95E0392E1092610027
+:1006700010927C008091600084FF42C080916100F4
+:100680008F3F09F43DC0182F893008F018E0811B16
+:100690008093610080916C0098E8892780936C00BA
+:1006A000112311F1E0917A00F0917B0080916600B6
+:1006B00086FF0BC0ADE6B0E084918D9331968DE658
+:1006C00090E0810F8A13F8CF0BC0EF01ADE6B0E0E8
+:1006D00089918D93FE018DE690E0810F8A13F8CF0A
+:1006E000F0937B00E0937A00612F8DE690E022DDAD
+:1006F0001C5F1C3019F08FEF809361001093600035
+:1007000084E196B3987131F48150D9F710927D004D
+:1007100010927700C1E08111C0E080916B008C17CE
+:1007200029F0C11101C068DEC0936B00C3010196BE
+:100730003C018035934C11F484E0382E232D332076
+:10074000E9F08AE390E20197F1F72230A9F4F894F6
+:10075000E0ECF8E1E054F10983E080935700E8957C
+:100760003097C1F7412C512CC8E08FEF9FEF70DE1E
+:10077000C150D9F764DE02C02530E1F384E03812BD
+:10078000BBCEEDEBF8E1E491EF3F09F4B5CEF89480
+:10079000BB9A1BBE15BA10925F02EAEBF8E1E49136
+:1007A0008E2F81508E3F10F4E1BF000076CCFFCF3A
+:1007B0005AFF18BA400800000000000000000000C6
+:1007C0000000000000000000000000000000000029
+:1007D00000000000000011241FBECFE5D2E0DEBF04
+:1007E000CDBF10E0A0E6B0E0E2E7FAE002C005907D
+:1007F0000D92A236B107D9F710E0A2E6B0E001C031
+:100800001D92A236B107E1F71CD131C139CC05C028
+:10081000EDE1F0E13197F1F701970097C9F70895FD
+:10082000AC01407C80E090E0FC01E40FF51F2591D5
+:100830003491FC01EE7FE60FF71F2083318302968F
+:100840008034910589F70895FC01E07C83E0809372
+:100850005700E89507B600FCFDCF0895CF93DF93CE
+:10086000EC01AB01DB0120E030E0FE01E41BF50B05
+:10087000EA0FFB1F8D919D9161E00C016093570081
+:10088000E89511242F5F3F4F2032310571F785E045
+:10089000FE0180935700E89507B600FCFDCFDF917D
+:1008A000CF910895CF93DF93CDB7DEB7C054D0403A
+:1008B0000FB6F894DEBF0FBECDBF8091600090915F
+:1008C00061009695879581509044FE0131969E0176
+:1008D0002F5B3F4F81939193E217F307D9F780E0A5
+:1008E00090E0B2DF80E090E0BE016F5F7F4FB6DF47
+:1008F000C05CDF4F0FB6F894DEBF0FBECDBFDF91F7
+:10090000CF9108950F931F93CF93DF93CDB7DEB7A9
+:10091000C054D0400FB6F894DEBF0FBECDBF00E08C
+:1009200010E040C080E090E0F801E256FF4FE80F91
+:10093000F91F9C013595279547E0E63BF40770F0D9
+:10094000F901EE0FFF1F21E030E02C0F3D1FE20FF9
+:10095000F31F2FEF3FEF318320830DC0459154915A
+:10096000F901EE0FFF1F21E030E02C0F3D1FE20FD9
+:10097000F31F40835183029680349105A9F680913C
+:10098000600090916100800F911F5EDF8091600098
+:1009900090916100800F911FBE016F5F7F4F5EDFFE
+:1009A000005C1F4F37E00034130709F0BBCFC05C79
+:1009B000DF4F0FB6F894DEBF0FBECDBFDF91CF91F2
+:1009C0001F910F910895CF93DF93CDB7DEB7C05439
+:1009D000D0400FB6F894DEBF0FBECDBF80E090E0F0
+:1009E000BE016F5F7F4F1CDF8FEF9FEF9A8389837C
+:1009F00080E090E029DF80E090E0BE016F5F7F4FF4
+:100A00002DDFC05CDF4F0FB6F894DEBF0FBECDBF49
+:100A1000DF91CF910895CF9387B3836087BBC1984F
+:100A2000CAEF81E090E0F3DEC19A81E090E0EFDE72
+:100A3000C198C150B1F7CF910895E0E0F0E0099579
+:100A4000089588B318BA87B38FEF87BB8AEF90E019
+:100A5000DEDE87B317BA8AEF90E0D9DEF894B3DF11
+:100A600051DF20DFD8DFE9DF80E090E00895F894DF
+:020A7000FFCFB6
+:020A7200C018AA
+:040000030000008079
+:00000001FF