(tr)uSDX bootloader woes

A reader of my article WriteOptiBoot.bat asked about application to the (tr)uSDX project.

The first point to note is that the (tr)uSDX project uses its own bootloader, and it would appear it is proprietary code (ie secret), and one is entirely dependent on their published information.

A common user problem reported on the the (tr)uSDX project forum is inability to either:

  1. program the bootloader; and / or
  2. program the application code.

1. Program the bootloader

The bootloader, once programmed successfully (ie verified) and appropriate fuse and lock bits programmed to activate and PROTECT it, should never need replacement unless for fixes to bugs / enhancement of the bootloader itself.

That said, the instructions published at https://dl2man.de/3a-trusdx-bootloader/ do not program the LOCK bits, so their bootloader is UNPROTECTED and vulnerable to corruption by the application program. Designers of reliable systems use the LOCK bits to protect the bootloader.

Bootloaders are a small program of limited function and often residing in application flash memory. In the case of the ATmega328P, it resides at the top of application flash and fuse bits program the size of it, and the power on reset start address to the bootloader’s address. Lock bits can protect that segment of application flash from overwrite. Function may be limited, it is common that they can read and write application flash (subject to protection), may or may not read and / or write EEPROM, unlikely to write FUSE and LOCK bits or cause a bulk chip erase (ie return to factory unprogrammed state).

Bootloaders that can replace themselves are less common, and I dare say courageous. Commercial products that use encrypted distribution and trusted bootloaders can often do this, but if the update fails, the equipment needs to go back to the factory… at huge expense.

So, a good place to start is the ASSUME that:

  • the bootloader must be installed and appropriate FUSES and LOCK bits programmed on a new / fully erased ATmega328P chip using either some form of ISP serial programmer (eg AVRISP MkII), or (less likely), a HVP;
  • to update the bootloader, the same technique is probably needed;
  • once the bootloader is installed, application flash (and possibly EEPROM) can be programmed and updated using the bootloader, its interface, and a client software that supports the bootloader protocol.

A common protocol used with AVR bootloaders is known as “arduino” in AVRDUDE for example, it is actually a subset of an Atmel programmer protocol. It commonly works with the MCU’s Tx and Rx serial pins, possibly via a USB-TTL232 chip. Note there are also programmer types Arduino-FT232R, ArduinoISP, ArduinoISPorg.

Above is the correct selection in AVRDUDESS v2.17. Note in the log the command line option “-c arduino” selects the correct protocol.

To add to confusion, there are published designs to implement a USB connected Arduino board that implements a form of ISP protocol which can only work on the 6 or 10 pin ISP interface (or MCU pins). This does NOT implement the “Arduino” bootloader protocol.

Demonstrations

Let’s use an Arduino Nano (ATmega328P @ 16MHz) with a custom build of Optiboot. Optiboot ships on Nanos, this custom build can also read and write EEPROM.

Everyone loves a GUI… so lets try and read the LOCK and FUSE bits with AVRDUDESS with a USB cable onto the Nano’s USB socket, and the programmer type MUST be Arduino.

Look at the log, no problems reported, indeed it reports SUCCESS. Now look at the reported FUSE and LOCK bits, they are all zero. In fact, it did not read FUSE and LOCK bits at all, and falsely reports SUCCESS and that they are all zeros.

Now let’s try from the command line and request verbose output.

D:\src\ssc>avrdude -c arduino -P com33 -b115200 -p m328p  -U lock:r:-:h -vv

avrdude: Version 7.0
         Copyright (c) Brian Dean, http://www.bdmicro.com/
         Copyright (c) Joerg Wunsch

         System wide configuration file is "C:/bin/avrdude.conf"

         Using Port                    : com33
         Using Programmer              : arduino
         Overriding Baud Rate          : 115200
avrdude: Found device at port 'COM33'
         AVR Part                      : ATmega328P
         Chip Erase delay              : 9000 us
         PAGEL                         : PD7
         BS2                           : PC2
         RESET disposition             : dedicated
         RETRY pulse                   : SCK
         Serial program mode           : yes
         Parallel program mode         : yes
         Timeout                       : 200
         StabDelay                     : 100
         CmdexeDelay                   : 25
         SyncLoops                     : 32
         PollIndex                     : 3
         PollValue                     : 0x53
         Memory Detail                 :

                                           Block Poll               Page                       Polled
           Memory Type Alias    Mode Delay Size  Indx Paged  Size   Size #Pages MinW  MaxW   ReadBack
           ----------- -------- ---- ----- ----- ---- ------ ------ ---- ------ ----- ----- ---------
           eeprom                 65    20     4    0 no       1024    4      0  3600  3600 0xff 0xff
           flash                  65     6   128    0 yes     32768  128    256  4500  4500 0xff 0xff
           lfuse                   0     0     0    0 no          1    1      0  4500  4500 0x00 0x00
           hfuse                   0     0     0    0 no          1    1      0  4500  4500 0x00 0x00
           efuse                   0     0     0    0 no          1    1      0  4500  4500 0x00 0x00
           lock                    0     0     0    0 no          1    1      0  4500  4500 0x00 0x00
           calibration             0     0     0    0 no          1    1      0     0     0 0x00 0x00
           signature               0     0     0    0 no          3    1      0     0     0 0x00 0x00

         Programmer Type : Arduino
         Description     : Arduino
         Hardware Version: 3
         Firmware Version: 8.1

avrdude: AVR device initialized and ready to accept instructions

Reading | ################################################## | 100% 0.00s

avrdude: Device signature = 0x1e950f (probably m328p)
avrdude: reading lock memory:

Reading | ################################################## | 100% 0.01s

avrdude: writing output file ""
0x0

avrdude done.  Thank you.


D:\src\ssc>

It also shows no errors and reports the LOCK bits in this case to be zeros.

Now lets try an ISP programmer, the AVRISP MkII plugged into the 6pin ISP header on the Nano.

D:\src\ssc>avrdude -c avrisp2 -p m328p  -U lock:r:-:h -vv

avrdude: Version 7.0
         Copyright (c) Brian Dean, http://www.bdmicro.com/
         Copyright (c) Joerg Wunsch

         System wide configuration file is "C:/bin/avrdude.conf"

         Using Port                    : usb
         Using Programmer              : avrisp2
avrdude: usbdev_open(): Found AVRISP mkII, serno: 001D2C990079
         AVR Part                      : ATmega328P
         Chip Erase delay              : 9000 us
         PAGEL                         : PD7
         BS2                           : PC2
         RESET disposition             : dedicated
         RETRY pulse                   : SCK
         Serial program mode           : yes
         Parallel program mode         : yes
         Timeout                       : 200
         StabDelay                     : 100
         CmdexeDelay                   : 25
         SyncLoops                     : 32
         PollIndex                     : 3
         PollValue                     : 0x53
         Memory Detail                 :

                                           Block Poll               Page                       Polled
           Memory Type Alias    Mode Delay Size  Indx Paged  Size   Size #Pages MinW  MaxW   ReadBack
           ----------- -------- ---- ----- ----- ---- ------ ------ ---- ------ ----- ----- ---------
           eeprom                 65    20     4    0 no       1024    4      0  3600  3600 0xff 0xff
           flash                  65     6   128    0 yes     32768  128    256  4500  4500 0xff 0xff
           lfuse                   0     0     0    0 no          1    1      0  4500  4500 0x00 0x00
           hfuse                   0     0     0    0 no          1    1      0  4500  4500 0x00 0x00
           efuse                   0     0     0    0 no          1    1      0  4500  4500 0x00 0x00
           lock                    0     0     0    0 no          1    1      0  4500  4500 0x00 0x00
           calibration             0     0     0    0 no          1    1      0     0     0 0x00 0x00
           signature               0     0     0    0 no          3    1      0     0     0 0x00 0x00

         Programmer Type : STK500V2
         Description     : Atmel AVR ISP mkII
         Programmer Model: AVRISP mkII
         Hardware Version: 1
         Firmware Version Master : 1.24
         Vtarget         : 4.6 V
         SCK period      : 0.50 us

avrdude: AVR device initialized and ready to accept instructions

Reading |                                                    | 0% 0.00savrdude: stk500isp_read_byte(.., signature, 0x0, ...)
avrdude: stk500isp_read_byte(): Sending read memory command: avrdude: stk500isp_read_byte(.., signature, 0x1, ...)
Reading | #################                                  | 33% 0.01savrdude: stk500isp_read_byte(.., signature, 0x2, ...)
Reading | ################################################## | 100% 0.02s

avrdude: Device signature = 0x1e950f (probably m328p)
avrdude: reading lock memory:

Reading |                                                    | 0% 0.00savrdude: stk500isp_read_byte(.., lock, 0x0, ...)
Reading | ################################################## | 100% 0.00s

avrdude: writing output file ""
0xcf

avrdude done.  Thank you.


D:\src\ssc>

Very different output, it reports LOCK=0xCF.

Which one is correct? The latter… the Optiboot bootloader is not capable of reading FUSE and LOCK bits, but it reports SUCCESS and returns 0x00 for each. AVRDUDESS passes on the wrong results from AVRDUDE.

The user (ie YOU) need to know that Optiboot (in this case) cannot read or write FUSE or LOCK bits, and will return FALSE results.

Don’t rely upon a bootloader until you have seen evidence that it supports what you are trying to do, and tick and flick GUIs move you further from the problem… nice presentation of GARBAGE in the GUI screenshot above.

I see people insist that they have installed the bootloader successfully but cannot load the application firmware. First step in successfully solving a problem is to differentiate facts from suspicions, and the fact that the application firmware will load load begs the question, is the bootloader actually good.