Optiboot now at version 8.0

Optiboot version 8 is available.

The major points relevant to Arduino users include:

  • Cleanup of the MCUSR (reset reason) behavior.
  • Ability to jump to the bootloader "as a service" to reload new code (with a bit of care.)
  • an available do_spm() function that allows an application to write to flash memory by calling code withing the bootloader.

Other changes:

  • update switches for more recent compiler versions (as consequence is that it no longer quite works with WinAVR or the IDE1.0.3 compiler.)
  • Add options and "help" target to makefiles.
  • Fold in Hans's (MCUDude's) miniCore, megaCore, mightyCore, and majorCore to support a very large number of ATmega targets.
  • Fold in DrAzzy's ATtinyCore, to support a bunch of the more capable ATtiny targets.
  • On targets with 1k bootloaders, include text info about the build in the binar
  • Make sure the "Virtual Boot Partition" targets work (needed for (4), but... other platforms too!)
  • Add and update test tools and sketches.
  • with a bit of luck, you COULD compile an ATmega328 Optiboot that includes EEPROM read and write capability that still fits in 512bytes (but you have to turn off the do_spm feature, and removing the startup LED blinking.)
  • Various internal cleanups and generalizations.

Most of this work has been available for a long time now, from MCUDude, DrAzzy, and/or Majekw. I've just finally gotten around to including it in the "master" Optiboot tree.

There is a .json package for the board manager on the release sub-page, but it's become quite minimal compared to the targets and options that are supported. Unless you want to mess with the source code or build a bootloader with a particularly strange combination of features, it is a much better alternative to use one of the "board" definitions from MCUDude or DrAzzy that include a wide variety of .hex files of the bootloader, AND "core" code to support the processors. (MCUDude's cores contain several thousand permutations of optiboot*.hex files for different baud rate, processor clock rates, and uart choice.

As far as I can tell the combination of optiboot, avrdude, and the nDTR capacitor trick is nearly impossible to break. No matter how I messed up the program I can just bootload a new one (nothing gets locked and blocks a new upload). This is so important for firmware development, and few seem to get it right.

Thanks for sharing the work @westfw and others.

Thanks.

If life ever is so kind as to stop throwing bullshit at me for long enough that I can catch my breath, I intend to update optiboot and also add support for all the UART-less attiny boards.

Heh; it took ME long enough to merge in YOUR code...

Wait a bit longer, and I'll probably convert the tiny targets (and makeall.tiny) to use MCUDude-style parametric looping and hex file naming (like "optiboot_atmega328pb_UART_38400_8000000L.hex")

In the occasional battles over who is responsible for the success of Arduino, I don't think that either the authors of the bootloaders, or the decision to figure out how to use a bootloader that permitted "upload" from any operating system, get nearly enough credit. Being able to used an Arduino "plugs and play" was SO important!

Man. By the time I get to it, I think I'm going to need to get help from you on how to work with it....

I also should be noted that Optiboot now supports ATmega2560:

Thanks to everyone for the great work on this project! I'm very glad to see the development work all unified in one project.

Awesome!

It would be great if you were able to update the documentation. Most of it seems kind of outdated.

I cloned the repo, put it into my build environment (also kicked the compiler version up to the one that came with 1.8.7). I'm going to try to build new versions of the bootloaders for ATTinyCore, and see if I can make it work with the soft UART option on the 84/861/88.

  1. Which vector is it choosing to use to jump to the program code when using virtual boot on the boards defined in makefile.tiny?

  2. I added an entry for the tiny84 by copying the entry for the 841. But now a bunch of defines not used for the attiny841 are getting pulled in: (note that I've kept my omake.bat, which is pointed at the files in the location I use them in - it's the skeleton of a 1.0.6 install for make, but with the compiler updated)

c:\arduino-1.0.6\hardware\arduino\bootloaders\optiboot_bld>omake attiny841at8

c:\arduino-1.0.6\hardware\arduino\bootloaders\optiboot_bld>..\..\..\tools\avr\utils\bin\make OS=windows ENV=arduino attiny841at8
c:/arduino-1.0.6/hardware/tools/avr/utils/bin/make attiny841     AVR_FREQ=8000000L BAUD_RATE=57600
make[1]: Entering directory `c:/arduino-1.0.6/hardware/arduino/bootloaders/optiboot_bld'
avr-gcc (GCC) 5.4.0
Copyright (C) 2015 Free Software Foundation, Inc.
This is free software; see the source for copying conditions.  There is NO
warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.

BAUD RATE CHECK: Desired: 57600, Real: 58823, UBRRL = 16, Difference=2.1%
../../../tools/avr/bin/avr-gcc -g -Wall -Os -fno-split-wide-types -mrelax -mmcu=attiny841 -DF_CPU=8000000L  -DBAUD_RATE=57600 -DLED_START_FLASHES=3          '-DVIRTUAL_BOOT_PARTITION' '-DFOURPAGEERASE'    -c -o optiboot.o optiboot.c
optiboot.c:355:6: warning: #warning BAUD_RATE off by greater than 2% [-Wcpp]
     #warning BAUD_RATE off by greater than 2%
      ^
../../../tools/avr/bin/avr-gcc -g -Wall -Os -fno-split-wide-types -mrelax -mmcu=attiny841 -DF_CPU=8000000L  -DBAUD_RATE=57600 -DLED_START_FLASHES=3          '-DVIRTUAL_BOOT_PARTITION' '-DFOURPAGEERASE'  -Wl,--section-start=.text=0x1d80 -Wl,--section-start=.version=0x1ffe -Wl,--relax -nostartfiles -o optiboot_attiny841.elf optiboot.o
../../../tools/avr/bin/avr-size optiboot_attiny841.elf
   text    data     bss     dec     hex filename
    596       0       0     596     254 optiboot_attiny841.elf
../../../tools/avr/bin/avr-objcopy -j .text -j .data -j .version --set-section-flags .version=alloc,load -O ihex optiboot_attiny841.elf optiboot_attiny841.hex
..\..\..\tools\avr\bin\avr-objdump -h -S optiboot_attiny841.elf > optiboot_attiny841.lst
rm optiboot_attiny841.elf optiboot.o
make[1]: Leaving directory `c:/arduino-1.0.6/hardware/arduino/bootloaders/optiboot_bld'
mv optiboot_attiny841.hex optiboot_attiny841at8.hex
mv optiboot_attiny841.lst optiboot_attiny841at8.lst

vs 84

c:\arduino-1.0.6\hardware\arduino\bootloaders\optiboot_bld>omake attiny84at8

c:\arduino-1.0.6\hardware\arduino\bootloaders\optiboot_bld>..\..\..\tools\avr\utils\bin\make OS=windows ENV=arduino attiny84at8
c:/arduino-1.0.6/hardware/tools/avr/utils/bin/make attiny84      AVR_FREQ=8000000L BAUD_RATE=19200
make[1]: Entering directory `c:/arduino-1.0.6/hardware/arduino/bootloaders/optiboot_bld'
avr-gcc (GCC) 5.4.0
Copyright (C) 2015 Free Software Foundation, Inc.
This is free software; see the source for copying conditions.  There is NO
warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.

<command-line>:0:0: warning: "LED_START_FLASHES" redefined
<command-line>:0:0: note: this is the location of the previous definition
<command-line>:0:0: warning: "LED_START_FLASHES" redefined
<command-line>:0:0: note: this is the location of the previous definition
<command-line>:0:0: warning: "LED_START_FLASHES" redefined
<command-line>:0:0: note: this is the location of the previous definition
BAUD RATE CHECK: Desired: 19200, Real: 19230, UBRRL = 51, Difference=0.1%
../../../tools/avr/bin/avr-gcc -g -Wall -Os -fno-split-wide-types -mrelax -mmcu=attiny84 -DF_CPU=8000000L  -DBAUD_RATE=19200 -DLED_START_FLASHES=3    -DLED_START_FLASHES=0      -DSOFT_UART -DVIRTUAL_BOOT_PARTITION -Dsave_vect_num=4 -DBAUD_RATE=19200 -DLED_START_FLASHES=3    -DLED_START_FLASHES=0      '-DVIRTUAL_BOOT_PARTITION' '-DSOFT_UART'    -c -o optiboot.o optiboot.c
<command-line>:0:0: warning: "LED_START_FLASHES" redefined
<command-line>:0:0: note: this is the location of the previous definition
<command-line>:0:0: warning: "LED_START_FLASHES" redefined
<command-line>:0:0: note: this is the location of the previous definition
<command-line>:0:0: warning: "LED_START_FLASHES" redefined
<command-line>:0:0: note: this is the location of the previous definition
../../../tools/avr/bin/avr-gcc -g -Wall -Os -fno-split-wide-types -mrelax -mmcu=attiny84 -DF_CPU=8000000L  -DBAUD_RATE=19200 -DLED_START_FLASHES=3    -DLED_START_FLASHES=0      -DSOFT_UART -DVIRTUAL_BOOT_PARTITION -Dsave_vect_num=4 -DBAUD_RATE=19200 -DLED_START_FLASHES=3    -DLED_START_FLASHES=0      '-DVIRTUAL_BOOT_PARTITION' '-DSOFT_UART'  -Wl,--section-start=.text=0x1d80 -Wl,--section-start=.version=0x1ffe -Wl,--relax -nostartfiles -o optiboot_attiny84.elf optiboot.o
../../../tools/avr/bin/avr-size optiboot_attiny84.elf
   text    data     bss     dec     hex filename
    568       0       0     568     238 optiboot_attiny84.elf
../../../tools/avr/bin/avr-objcopy -j .text -j .data -j .version --set-section-flags .version=alloc,load -O ihex optiboot_attiny84.elf optiboot_attiny84.hex
..\..\..\tools\avr\bin\avr-objdump -h -S optiboot_attiny84.elf > optiboot_attiny84.lst
rm optiboot.o optiboot_attiny84.elf
make[1]: Leaving directory `c:/arduino-1.0.6/hardware/arduino/bootloaders/optiboot_bld'
mv optiboot_attiny84.hex optiboot_attiny84at8.hex
mv optiboot_attiny84.lst optiboot_attiny84at8.lst

Why are all those extra defines tacked onto the front of it?

Also, why is there a UART baud check referring to UBBRL when using SOFT_UART?

This is what I added to the makefile.tiny

#--------------------------------
# ATtiny 84, base instructions
#-------------------------------

HELPTEXT += "target attiny84     - atttiny841at<freq>  attiny841at<freq>ser1\n"
HELPTEXT += "                     - atttiny841at8_5v  attiny841at8_5vser1\n"
HELPTEXT += "                     - atttiny841at<freq>noLED\n"

attiny84: TARGET = attiny84
attiny84: MCU_TARGET = attiny84
attiny84: CFLAGS += $(COMMON_OPTIONS) '-DVIRTUAL_BOOT_PARTITION' '-DSOFT_UART' 
attiny84: AVR_FREQ ?= 8000000L
attiny84: LDSECTIONS  = -Wl,--section-start=.text=0x1d80 -Wl,--section-start=.version=0x1ffe
attiny84: $(PROGRAM)_attiny84.hex
ifndef PRODUCTION
attiny84: $(PROGRAM)_attiny84.lst
endif

attiny84at8:
	$(MAKE) attiny84	 AVR_FREQ=8000000L BAUD_RATE=19200
	mv $(PROGRAM)_attiny84.hex $(PROGRAM)_$@.hex
ifndef PRODUCTION
	mv $(PROGRAM)_attiny84.lst $(PROGRAM)_$@.lst
endif

Thanks!!

Also, why is there a UART baud check referring to UBBRL when using SOFT_UART?

Well, THAT would be a bug!
The "Clever" code that checks baud rate accuracy does NOT check for SOFT_UART. (It doesn't actually produce any code, either, so it's not a very serious bug.)

Which vector is it choosing to use to jump to the program code when using virtual boot on the boards defined in makefile.tiny?

SPM_RDY_vect_num, probably. The code says:
(Hmm. WDT might not be a good choice...)

// Vector to save original reset jump:
//   SPM Ready is least probably used, so it's default
//   if not, use old way WDT_vect_num,
//   or simply set custom save_vect_num in Makefile using vector name
//   or even raw number.
#if !defined (save_vect_num)
#if defined (SPM_RDY_vect_num)
#define save_vect_num (SPM_RDY_vect_num)
#elif defined (SPM_READY_vect_num)
#define save_vect_num (SPM_READY_vect_num)
#elif defined (WDT_vect_num)
#define save_vect_num (WDT_vect_num)

I added an entry for the tiny84 by copying the entry for the 841.

Note that there is already a "tiny84" entry in Makefile.extras; a holdover from the Luminet board.
Having another entry in Makefile.tiny will cause both sets of rules to be followed, possibly resulting in two images (for example "make atmega168" generates both an optiboot_atmega168.hex from the old makefile, and a optiboot_atmega168_UART__.hex from Makefile.mcudude.)
It looks like the warning about redefining LED_START_FLASHES comes from an attempt I made to have the tinys default to START_FLASHES=0 if no LED=pinname was mentioned. Sigh.
In general, the old style of the makefiles was to define a new board by having a full set of make targets, like you do in the current attinycore:

attiny1634at12: TARGET = attiny1634
attiny1634at12: MCU_TARGET = attiny1634
attiny1634at12: CFLAGS += $(COMMON_OPTIONS) '-DVIRTUAL_BOOT_PARTITION' '-DFOURPAGEERASE'
attiny1634at12: AVR_FREQ ?= 12000000L
attiny1634at12: LDSECTIONS  = -Wl,--section-start=.text=0x3d80 -Wl,--section-start=.version=0x3ffe
attiny1634at12: $(PROGRAM)_attiny1634at12.hex
attiny1634at12: $(PROGRAM)_attiny1634at12.lst

While the new style is to have each "board" do a recursive make with a target processor and appropriate options:

attiny1634at12:
	"$(MAKE)" attiny1634	AVR_FREQ=12000000L
	mv $(PROGRAM)_attiny1634.hex $(PROGRAM)_$@.hex
ifndef PRODUCTION
	mv $(PROGRAM)_attiny1634.lst $(PROGRAM)_$@.lst
endif

(Where the "base" definition of "attiny1634" has the CPU-specific options like "-DVIRTUAL_BOOT_PARTITION' '-DFOURPAGEERASE' ... -Wl,--section-start=.text=0x3d80 ")

Okay, thanks. Most of these chips don't have SPM_RDY; will modify that part to check EE_RDY after SPM_RDY.

Most of these chips don't have SPM_RDY; will modify that part to check EE_RDY after SPM_RDY.

Ahh. That's the problem with code that tries multiple things - without any messages, it can fall over into unexpected behavior...
Speaking of which, is there a relatively easy "sanity check" for baud rate vs F_CPU that would work for the SOFT_UART platforms?

makeall.tiny.sh has lines like:

make attiny841 $*
make attiny841at184 $*
make attiny841at147 $*
make attiny841at110 $*
make attiny841at921 $*

where each of those is a Makefile target - all consistent with the original make structure (and recursive Makes as I mentioned in the previous post.)

If you look at makeall.mcudude.sh instead, you'll notice that it's "algorithmic" at the shell-script layer, essentially logically:

   for (cpuAndUart in <listof CPU and each UART they have>)
      for (freqAndBaud in <list of CPU frequencies and baud rate>)
         make $cpuAndUart FreqAndBaud
         mv target <destination dir and filename based on parameters.>

(The original also ends up building 4000+ .hex files, which seems a little excessive, which is why many of the freqAndCpu options are commented out in the main optiboot repository.)

Which I really like, but doesn't quite work for the tinys because of the way the internal clock frequencies vary between the different chips.

Argh! EE_RDY is in the second page on the 841! (and it doesn't get caught by the test for that because you test against SPM_PAGESIZE, when the vector numbers are word addressed but SPM_PAGESIZE is bytes

(edit) Haaaa! I think I got it

No idea on sanity check for SOFT_UART baud rates. I think we'll need to see how far we can push it, then back off enough for safety, and make that the test.

Branch with new bootloaders and new Makefile.tiny in NewBootloaders branch of ATTinyCore

westfw - whaddyathink?

I decided to adopt the more systematic naming of the .hex files. Also added attiny441 bootloaders too.

Hmm, having trouble telling the makefile to actually get the benefit of the noled versions - they need to start at a different offset (0x1dc0 instead of 0x1d80), otherwise there's no point to building a noled version.

Also, building attiny828at8 doesn't work - it just runs endlessly....... Don't know enough about make to debug.

I've updated the code in that branch to match the code I'm working with.

Edit: Extended it to 1634 and built for a whole bunch more parts. Everything except the 828 that used to build has been rebuilt.

And NOW we finally know why the original virtualboot implementation used WDT_vect - it would always be on the first page of flash, saving him from having to deal with the vector not being on the same page - not that it's terribly hard to deal with once you know what's happening. So it wasn't demonic inspiration (why intentionally pick a vector people use instead of one they don't?) after all, just garden variety laziness. (I know why I didn't fix this when I was first working with optiboot for my core - that was ignorance. I thought the WDT_vect was special somehow, and had to be used. I was new to embedded C and didn't know enough back then to realize that it wasn't).

having trouble telling the makefile to actually get the benefit of the noled versions - they need to start at a different offset (0x1dc0 instead of 0x1d80), otherwise there's no point to building a noled version.

I always thought that the primary use of "LED_START_FLASHES=0" was to free of a pin, rather than free up more program space. It's only recently that some optiboot features have fallen "right on the edge" where deleting the LED code adds enough space for another feature... I'll take a look at this, I guess...

Also, building attiny828at8 doesn't work - it just runs endlessly

Hmm. I have a lot of mistakes in the 828 code :frowning: I thought I tested it - obviously not! It's got a couple of bugs other than the recursion in the makefile... Perhaps I mistakenly thought it was included in the makeall.tiny.sh Fixed, though!

why is there a UART baud check referring to UBBRL when using SOFT_UART?

Also fixed. Don't do the BRG divisor analysis for SOFT_UART targets. · Optiboot/optiboot@b1b8977 · GitHub

I'm glad you're using windows. I do almost all my work on a Mac, and I think Hans (MCUdude) is a linux person. For instance, I don't think that the algorithmic "makeall" scripts I was so enthusiastic about would work on Windows (Hmm. Unless they have bash installed as well. Which you can get as a windows feature these days! (and it's also part of the Atmel tools install...))

Thanks!

Soft UART virtualboot bootloaders seem to work, too. Good shit.

LED flashes don't work on the tiny85. Probably same for the 861. Timer1 on these is not the same as on other boards. I'll see how bad it looks to fix this.

I think I have LED flashes working!