(tr)uSDX firmware, bootloader, application – an explanation


The term firmware means lots of things to lots of people, and you will see so many definitions that it becomes confusing.

It is apparent from postings by people about (tr)uSDX (trusdx) that the rubbery definition prevails in that environment also.

The term firmware came into being 50 odd years ago, about the time that microcomputers appeared. There was a need for a term to describe something that sat between traditional hardware and software, the programming that was 'embedded' in the system.

ATmega328P memory

In the case of the ATmega328P (as used in the (tr)uSDX), it contains three main blocks of memory and some auxilliary non-volatile storage, the three main types are:

  • RAM (volatile scratch storage used for running programs);
  • FLASH (non-volatile memory used for user programs (instructions and constant data); and
  • EEPROM (non-volatile memory often used to save settings, calibration data etc).


We might reasonably regard that all of the contents of FLASH is firmware.


(tr)uSDX uses a bootloader, user code that can be executed on startup to load user programs into FLASH. In the case of the ATmega328P, the bootloader resides in FLASH at the top of the address range. FUSE settings tell the system to start at the boot section on power on reset, and they can be used to protect the bootloader from corruption on reliable systems (this last feature is NOT used on (tr)uSDX).

Above is a map of FLASH memory for an ATmega328P for the configuration used by (tr)uSDX from the chip datasheet.

At power on reset, the program pointer is set to the bootloader section, 0x200 (512) bytes in length @ 0x7e00. The bootloader listens briefly for an loader client on the RX pin, and if it does not engage a loader client successfully, it jumps to address 0x0000 to run the application program. So, the bootloader's role is to take control upon power on reset, and pass control to the application within seconds if no suitable loader client engages.

A new ATmega328P from the factory has an erased FLASH, all locations 0xFF.

What happens if you try to execute erased memory? Well, in a lot of processors, erased memory decodes as a no operation (NOP) instruction, so nothing happens except the program counter (PC) is incremented as normal. Erased memory does not decode as a NOP in the AVR series, and lots of online discussion proposes what happens, my own theory is that 0xFFFF does not decode as any valid instruction, the PC is incremented as normal but nothing further ‘happens' during the instruction execution cycle. So, the PC will progressively increment and wrap at the top of memory. If PC starts at say 0x7800 (eg FUSE bits had not been set correctly for the bootloader section) and eventually runs into a bootloader at 0x7e00, it will execute the bootloader… which if it times out, will jump to 0x0000 and the whole things goes round again.

So, if one intends using a bootloader, the first step is to load the bootloader (usually via an ISP programmer which uses an SPI protocol under reset on the SCK, MOSI and MISO pins), and that means at least writing the bootloader section though (tr)uSDX writes the whole flash space for some reason.

Today, the current bootloader hex file is referred to as “Initial firmware” and called truSDX-initial_Bootloader.hex.


Having established  a verified bootloader that in this cases uses serial async on the TX and RX pins (as extended by the USB serial chip), a loader client can engage with the bootloader using its protocol to load the application program to the application part of flash.

You could of course load the application using ISP, or load both bootloader and application using ISP… if you have the appropriate files. The convenience of the bootloader is that the application program can be upgraded simply over the PC-USB cable.

Today, the current application hex file is called truSDX_*_Firmware.hex,. The beta download option offers the option to download a file that includes application code + bootloader called truSDX-beta_*_Bootloader.hex (which MUST be loaded using an ISP programmer (or the like).

The file names used do not help with confusion of firmware, bootloader and application.

Connection File AVRDUDE switches
Bootloader ISP truSDX-initial_Bootloader.hex -B10 to slow bit clock
Application Async serial / COM port truSDX_*_Firmware.hex -b 115200 to set Async speed

The programmer type for writing the application using the bootloader over a serial port will be “Arduino”. Do not use this type for ISP programmers, use the type appropriate to your ISP programmer hardware, eg Atmel AVR ISP, USBasp, AVRisp MKII etc.

Common problems

Common mistakes I see reported online include:

  • externalising problems, blaming something else or someone else for problems prevents overcoming the problem when it is the user's own misunderstanding or procedure that is the real problem;
  • attempting to write the bootloader using the bootloader, which will corrupt the bootloader (unprotected bootloader is a feature of (tr)uSDX));
  • associating the correct programmer type in AVRDUDE with the hardware and connection being used;
  • difficulty in writing and verifying the bootloader at default SCK speed using ISP because the MOSI waveform is distorted by heavy filtering on the (tr)uSDX) MOSI line (this can fairly be attributed to flawed instructions from the team, slow the SCK for reliable ISP).


What would I know?

I have programmed literally thousands of ATmega328P and cannot recall a programming failure or subsequent corruption of the bootloader (but then I ALWAYS protect the bootloader on these chips). I have programmed thousands of brushless DC motor Electronic Speed Controllers using ATmega328P, and countless Flight Controllers both on quadcopters and other UAVs, and NEVER had one fall out of the sky or even just malfunction as a result of firmware corruption. This can be a very reliable process with careful design and testing.