Thursday, May 24, 2018

Picoboot Adruino with autobaud

Since the v1 release of picobootSTK500, I've been able to test it on many different Arduino compatible boards.  The biggest problem I've had relates to the various baud rates used by different bootloaders.  Optiboot, which is used on the Uno, uses 115.2kbps, while the Pro Mini m328 uses 57.6kbps.  The default baud rate for the Pro Mini m168 is even lower at 19.2kbps.  While modifying the boards.txt file is not difficult, it introduced unexpected problems.  For testing purposes I keep a couple boards with a stock bootloader, and they won't work unless I change the baud rate back to the default.  I also keep a couple versions of the Arduino IDE for compatibility tests, which adds to the confusion of changing boards.txt files.  Having had some time to think about the best solution, I decided to add automatic baud rate detection to picoboot.

From reading the avrdude source, I knew that it starts communication with the target by sendingthe GET_SYNC command '0' at least 3 times.  '0' is ASCII character 48, and when sent over a serial UART connection, the bitstream including start and stop bits is 0 00001100 1.  With 5 assembler instructions, I can count the low duration of the frame:
1:  sbic UART_PIN, 0 ; wait for start bit
    rjmp 1b
1:  adiw XL, 1 ; count low time
    sbis UART_PIN, 0
    rjmp 1b

The counting loop takes 5 cycles, and since there are 5 low bits, the final counter value is the number of cycles per bit.  Dividing that number by 8 and then subtracting one gives the AVR USART UBRR value in double-speed (U2X) mode.

The Arduino bootloader protocol is almost identical to the stk500 protocol, and so it is relatively easy to write a bootloader that is compatible with both.  For this version I decided to eschew stk500 compatibility in order to save a few bytes of code.  Because of that, and to make it more obvious that it is an Arduino-compatible bootloader, I renamed it to picobootArduino.

With picobootSTK500 v1, a LED on PB5 (Arduino pin 13) was used to indicate that the bootloader was waiting for communication from the host.  In order to make it simpler to use with a bare ATmega168/328 chip on a breadboard, while the bootloader is waiting it brings the Tx pin (PD1) low, which will light up the Rx LED on the connected USB-TTL converter.  As with v1, resetting the AVR will cause it to toggle between the bootloader and the loaded app.  This means it works easily with TTL adapters that do not have a DTR pin for the Arduino auto-reset feature, as well as simplifying it's use with a bare breadboarded AVR.

Despite adding the extra code for the autobaud function, the bootloader is still less than 256 bytes.  In my testing with a 16Mhz Pro Mini clone, the bootloader worked reliably with baud rates from 19,200 to 115,200.  The code and pre-built versions for ATmega328 & ATmega168 are available from my github repo.

I also plan to test the bootloader on the mega88 and mega8, where a small bootloader is more beneficial given their limited code size.


  1. Hi man i just tested this and it works perfect, a side benefit with this bootloader seems to be that it can handle uploads over wifi a lot better then the standard boothloader, uploading over esp8266 with esp-link works 9 of 10 times, instead of 1 in 10... So really good work. A 8hmz version of the .hex file wouldn't hurt if you have the time.
    Another strange but good thing i can set esp-link to 115200 and arduino ide upload speed to 57600 and the upload still works... strange but really useful. Thanks alot for the work you put into this!!!

    1. The same .hex file should work for both 8 & 16Mhz (and even 12), except that 115.2kbps will be flaky due to the limitations of the hardware UART. I'm planning to do a version that works on the ATmega8A (the UART register names are a bit different). When I get around to that I'll probably also test to make sure the autobaud works at different clock speeds.

  2. Hi, Ralph, thanks a lot for your bootloader. I am working in a project with several arduino pro minis, and I normaly use MCUSR register at the begining of my sketches to know the reset cause.
    With optiboot, even 7.0 version ( I can't get MCUSR value properly. (My last projects used ATMEGA328P IC's directly, so no bootloader, so no problem with MCUSR)
    I want to check your picoboot, and I want to know if it is only necessary to change boards.txt (optiboot -> picoboot), so my PL2303 adapter will work afterwards. I know that I have to burn the booloader with ISP, but I don't know, I have not read how to enter in bootloader after. Does DTR pin of my adapter works as usual?