Skip to main content
Version: 3.0.0

A Luos bootloader guide

The bootloader feature allows updating the firmware of any node in a Luos network. It's useful for quickly upgrading your application software without using specific programming tools and without physically accessing your boards.

This page first explains how the bootloader works from a high-level perspective, then how to use it on already supported targets (STM32 L4/F4/G4/F0, ATSAMD21, ...).

A third section details the requested changes to make a Luos application compatible with this bootloader.

How It Worksā€‹

The bootloader feature consists of three elements:

  • A CLI on your computer, used to monitor the network and manage the update
  • A gate service connected to your computer that is able to convey commands from the CLI to the Luos network
  • A bootloader code, which is flashed in each node in the network

When you want to update the firmware of node 2 (for example), the CLI tool sends commands through JSON files to the gate, which converts them into Luos commands. During the update, if the node needs to send information to the CLI tool, it sends information to the gate, converting it into JSON files.

The exchange of Luos messages between the Gate and the Bootloader of each node, is done by using the Publisher/Subscriber method. Each time the user decides to update the firmware of a node, Pyluos creates a json message to instruct the node to get in Bootloader mode, which contains a specific topic. This message, is transfered to the node-of-interest via the gate, and the bootloader of this node, gets subscribed to this topic. After this moment, all the messages containing the Bootloader commands, and the binary firmware will be published to this topic. In that way, we are able to flash an infinite number of nodes, with almost the same number of messages sent, gaining time and effort.

The feature has been designed to be as simple as possible, and the process can be described by only a few steps:

  1. The CLI reboots the entire Luos network (except the gate) on bootloader mode, so all nodes are ready to receive and save a new firmware. At that time, the nodes that we want to update, subscribe to a specific topic shared by the CLI
  2. The CLI sends binary files to the nodes you want to update, using the pub/sub method
  3. The CLI checks the CRC of the binary files saved by the nodes
  4. The CLI reboots the entire network in application mode.

From the user's point of view, the CLI only passes through these four steps.

How To Use Itā€‹

Let's assume that you already have a network with a bootloader flashed in each node, an application running on top of the bootloader, and a gate allowing you to connect the Luos network to a computer. How can you send a new binary file to node 2 (for example)? All you need to know is how to use the CLI tool. First of all, you can use a command to detect each node in the network:

pyluos-bootloader detect <SERIAL_PORT>

If no SERIAL_PORT is passed, pyluos-bootloader will try to find an available gate in your system by itself.

In your case, you use COM3:

pyluos-bootloader detect COM3

This leads to the following result:


We can see two nodes in our network:

  • Node 1 containing the gate app
  • Node 2 containing one service

Your goal is to update the button_old service. To do that, you need to flash a new firmware in node 2 (we suppose it is called firmware_new.bin and that it has been saved in a known location on the user computer). You can then call the following command:

pyluos-bootloader flash <SERIAL_PORT> -t <target1 target2 ...> -b <file.bin>

We use the port COM3, our target node has the ID nĀ°2, and our binary file is called firmware_new.bin:

pyluos-bootloader flash COM3 -t 2 -b firmware_new.bin

In the example above, 2 is the node's ID of node 2, not to be confused with the service Pipe_mod's ID. You can't flash just one service, only the entire node. So the target must always be a node.

Let's type this command, then you should see the following text on your screen:


You can see the four steps described in the previous section, plus a few log information. First, the CLI prints the parameters used to program the network:

  • The gate id used to access the network ( this option is not active yet )
  • The list of target nodes to program
  • The binary file used to program nodes
  • The port on which the gate is connected to the user computer
  • There is a default parameter for the target list: if nothing is set, the node with the id nĀ°2 (first node after the gate) is flashed.

  • If you need help to use the tool, you can type the following command:
pyluos-bootloader flash --help

After the CLI launches the programming process, you can notice that the CLI checks if the node is ready (or alive) before programming it. Once the process is finished, you can re-run the network detection and see the following:


You can program more than one node by giving an ID list with the option -t :

pyluos-bootloader flash COM3 -t 2 3 4 -b firmware_new.bin


pyluos-bootloader flash COM3 -t {2..4} -b firmware_new.bin

Here we will program nodes with ID nĀ°2, 3, 4.


If, for some reason, you lost the connection with the network or a node during the update, the bootloader allows you to re-run the process without the need to use specific programming tools (such as a JTAG debugger). Let's see what happens if you lost the connection during the update:


The CLI tells you that you have lost the connection. Now by powering off and on your network and re-running a detection, you should see the following:


The boot_service tells the node is in bootloader mode. You just have to re-run the flashing process with the CLI:

pyluos-bootloader flash COM3 -b firmware_new.bin

No matter what problem you encounter during the loading process, you have to power-off / power-on your network to see all the nodes running in bootloader mode. Once you get there, you have to use pyluos-bootloader detect / flash tools to load applications and make it work fine.

If you are using the ST-Link protocol for the communication of the gate with your computer and the flashing process is blocked in the last step of flashing with no specific reason, then you may have come through a specific problem caused by the ST-Link driver. It happens with a specific size of binary, when flashing with a Luos bootloader.


To resolve this issue, you can try to change the size of your binary by changing some bytes of your code, or you can use an other way to connect your gate, like for example FTDI, and retry flashing your application with Luos bootloader.

How to add the bootloader feature in your projectā€‹

CLI toolā€‹

The pyluos-bootloader CLI is included in pyluos since v2.0.0. So it's packed with the package when you install it with pip.


Since Luos engine v2.0.0, the gate application handles bootloader commands. From Luos engine v2.7.0 and after, you need to have at list Pyluos v.2.3.0

Install a Bootloader in your nodeā€‹

The bootloader runs in its own flash partition, which is completely isolated from the application. You have to flash it on your target before you can use the feature. Depending on your hardware, you can use an already available project or make your own bootloader.

Does Luos engine already support your target?ā€‹

The Luos engine's bootloader is available for the following targets:

  • STM32 F0 / F4 / G4 / L4 families
  • Microchip ATSAMD21J18

Projects for each of these targets can be found in the Luos engine's example folder. You can clone this repo and use projects for your application, or use them as examples to build your own bootloader for your specific target.


Examples are available for several IDEs: L4 / F4 / G4 / F0 uses platformIO, and SAMD21 uses MPLAB.

If Luos engine does not support your target yetā€‹

If no project exists for your MCU, you will have to create your bootloader project. First of all, you have to enable the bootloader feature in Luos engine. To do so, you have to add the -D BOOTLOADER parameter when you invoke your compiler. Then you have to run the library in your main() function as you would do for any other project:

#include "luos_engine.h"

int main(void)
return 0;

Luos engine will now run the bootloader application. Be careful not to initialize any package or service. Luos engine can only run the bootloader app in bootloader mode, and your package will not be executed.

Now you have to adjust your linker settings: the bootloader has to reserve a portion of the flash, and the remaining memory will be dedicated to the Luos engine's applications. You can find the memory layout of the flash resumed in the following picture:


This figure shows a third section called shared_flash, which exchanges information between the bootloader and the application. When you want to port the bootloader on a specific target, you have to specify this layout (e.g. the amount of flash you reserve for the bootloader, the shared section, and the application). Here is an example for the STM32L432: We choose to dedicate 48 kB for the bootloader, 2 kB (one flash page) for the shared section, and all remaining memory for the application. The translation in the linker file can be seen here:


Flash memory remappingā€‹

In each different Luos compatible board, we propose a default configuration of the flash memory. By default, the bootloader's code is placed in the beginning of the flash. Then there is the shared memory, and at the end we can found the applications' code, like explained in the image above. However, we give you the possibility to configure the flash as you want, by exposing some macros that you can redefine in the file node_config.h in the bootloader or in the application. These macros are the following:

BOOT_START_ADDRESSStart address of the bootloader in the flash
SHARED_MEMORY_ADDRESSStart address of the shared memory to save boot flag
SHARED_MEMORY_SECTORStart sector of the shared memory (in case of boards with flash in sectors)
APP_START_ADDRESSStart address of the application with bootloader
APP_END_ADDRESSEnd address of the application with bootloader
APP_START_SECTORStart sector of the application with bootloader (in case of boards with flash in sectors)
APP_END_SECTORLast sector of the application with bootloader (in case of boards with flash in sectors)


As for the bootloader, you have to modify your linker file in the application if you want to make it compatible with this feature. Now that we defined the memory layout, the modification is straightforward:


You also have to add the precompilation flag -D WITH_BOOTLOADER to the file platformio.ini in your application. Your application is now ready to be flashed using a bootloader.


You can find application examples in the Luos engine's repository.

Bootloader updaterā€‹

You can also update the bootloader of your node, by using the same method as for the application. This procedure need a few more steps :

  1. Compile the bootloader in "updater mode" by adding the precompilation flag -D BOOTLOADER_UPDATER to the file platformio.ini in your bootloader project.
  2. Flash the bootloader updater in your node through the bootloader command.
  3. Compile the new bootloader in "default mode" by adding the precompilation flag -D BOOTLOADER to the file platformio.ini in your bootloader project.
  4. Flash the new bootloader in your node through the bootloader command.

Then you have an updated bootloader in your node, and you can use it to update your application.


For more details about the bootloader updater, you can check the bootloader tutorial.