How does the Particle Bootloader Work?


I’m having trouble getting a locally compiled program to flash OTA, so I was hoping to get a better understanding of how the whole flash/bootloader system worked. Anybody mind giving an explanation?

Specific things I was wondering:

  • when you build apps from the user folder in the firmware tree and flash them, does it also flash a new version of the firmware?
  • if so, how does the bootloader check for valid firmware? I looked through the bootloader source, and saw the checks for 0x0005 or 0x0055 written to the backup register to determine validity, but don’t understand the checks that cause those to be written or not


If you use OTA to flash an app, the binary is checked against a crc32 value appended at the end.

As for DFU flashing via USB, the protocol itself will take care of that.

Here’s the info for local compile:

Thanks Kenneth!

Is there a specific instruction somewhere in the makefile or elsewhere in the compilation sequence to append the crc32 value? Is this unique to the particle build process? To clarify, I built the binary outside the particle build tree, and want to figure out why this won’t load with the particle OTA flash.

What steps the particle bootloader goes through to ensure it is receiving valid firmware. Is it checking the memory addresses the program is to be loaded into? Having firmware packaged with theuser application? Something else entirely?


It should work. Which branch are you on? I’m guessing you did not perform a system firmware flashing prior running the user firmware when compiling locally…

I’m on the latest branch. Why would I need to flash the system firmware before running user firmware? Terminology-wise, I’m also a little confused as to what the difference between user firmware and user application is as well.

but I think I figured out my problem - I was missing an error in the compiler output, and the binary I was trying to flash was 0 bytes. so I guess it checks for the binary having non-zero length :slight_smile:


Hi @beck

With modular build (two parts system firmware, one part user firmware) the OTA system tries to ensure that your user firmware is compatible with and will actually run on the system firmware, so if the versions are not correct, it can force a system firmware update.

User firmware and user application are the same thing.

A zero-byte .bin file when compiling locally means it did not compile or link correctly.

1 Like

Ok awesome! I think we’re getting to the root of what I’m trying to figure out!

So with a modular build, when I

particle flash myDevice myBin.bin

it is only flashing myBin to 0x80A0000, and not system-part1 and system-part2? And that is the whole point of a modular build, correct?

A little background: I’m working on porting the QP state machine frameworks ( to run on the Photon. The frameworks come with examples, and I’m using adapting an example written for the stm32l1xx series (ARM m3). The examples come with their own makefiles, startup code and linker scripts, and my approach thus far has been to compile the example separate from the particle firmware tree, then try to flash.

Once I resolved the zero-length binary problem, the compiled example flashed, but the photon now just breathes magenta, which I understand is safe mode and it is not running the user code. I’m assuming this is because my application conflicts with the system firmware because the linker script I’m using must be locating things in the wrong places, and/or the startup code I have also conflicts with the system firmware. Does that sound about right?