As the IoT market is slowly maturing, IoT systems are becoming increasingly complex and versatile. As a result, embedded devices are composed of distinct firmware components made by different parties working together, often running on multiple MCUs simultaneously.
This multi-party involvement has implications for how firmware is developed and updated. Rather than creating single binaries which are built and flashed to devices at once, firmware is constructed from multiple components. Each of these components can be managed and updated separately, just like cloud applications, allowing you to do what you do best. Whether it’s developing modem firmware, application code, bootloader software, drivers for sensors, or interfaces with hardware secure modules.
Let’s explore the opportunities of remotely managing multi-component firmware in IoT devices by using the LwM2M standard.
This article is the part of a series about OTA software updates for IoT devices. Read the first article here.
When dealing with IoT devices which are highly constrained due to their limited available bandwidth, power and memory size, the process for device firmware updates (DFU) has to be carefully crafted. Updating the firmware can be resource-intensive, certainly when the network connection is unstable, leading to a lengthy update process which requires the radio to be on and drains the device’s battery.
As IoT devices become more complex, so do their firmware, leading to increasingly large update files. This not only increases the necessary time and required energy to perform an update, it also makes the update more prone to errors as the devices require a stable connection for a longer period of time.
In contrast to single-binary firmware which are to be updated fully (as described in our latest article), embedded firmware can be composed of separated code blocks which can be configured and updated independently. A component-based update process can significantly reduce the required resources for updating the device’s firmware.
Firmware is usually stored in the device’s flash memory; non-volatile memory which persists after a reboot and can be electronically rewritten. To virtually isolate different firmware components, flash memory is split into multiple partitions. Different firmware components – such as the bootloader, application firmware or the tinyML model – reside in dedicated flash partitions. Consequently, one partition can be safely updated while the others remain untouched
Embedded devices usually don’t contain just one MCU. Instead they often contain multiple processors each being responsible for a dedicated task. Next to the main MCU, the device may include one or multiple radio modems for cellular or Bluetooth communication. It may include smart sensors which include local processing to add more intelligence. For example, cameras which detect the number of cars, bikes or people passing by, or microphones which only detect specific sound events. All of these MCUs may contain flash partitions which can become updatable.
A multi-MCU IoT device with partitioned flash memory
Making flash partitions updatable
In order to make a firmware component updatable, a dedicated partition – called the update partition – needs to be created for each component. In essence, this means that each component consists of two partitions; one that runs the actual firmware, and one which is reserved to store new firmware images during firmware updates. In case flash size is restricted, update partitions can be created in external flash memory.
A multi-MCU IoT device with partitioned flash memory containing update partitions
Let’s explore what really happens deep down in the device’s flash memory when a firmware component is being updated.
The process starts when new firmware is released and uploaded to the repository. Once uploaded, the LwM2M Server informs the device about the availability of new firmware, enabling the device to download the firmware image.
Once the firmware update is initiated for a specific component, the device starts downloading the new firmware image into the dedicated update partition. After the download has completed, the application initiates a reboot. At boot, the bootloader validates the authenticity and integrity of the new firmware, once validated it initiates the swapping process.
In contrast to Linux-based systems which support “position-independent code”, microcontrollers usually can’t boot firmware directly from the update partition. As a result, the firmware residing in the update partition needs to be swapped with the original firmware. When using the open source MCUboot bootloader, the two images are swapped using the flash partition known as the scratch partition. The scratch partition acts as a buffer, allowing the bootloader to switch the new and existing firmware images between their respective partitions. Throughout the swapping process, the device goes offline and becomes unresponsive to server commands.
In the swap process, the bootloader first copies a chunk of the new firmware from the update partition to the scratch partition. It then moves the existing firmware to the update partition. Finally, it moves the new firmware chunk from the scratch partition to the original partition. This process repeats until the entire new firmware image has been moved into the original partition, completing the swap.
Running new firmware
After the swap has been completed, the bootloader initiates the new firmware from the newly flashed image. If initialized successfully, the device starts running the new firmware. The new firmware is expected to write a flag in the flash memory to indicate that the update was successful, which is done after performing several self-checks, e.g. initializing the hardware.
If no successful update flag is added to the flash memory, the bootloader assumes something went wrong and performs a rollback during the next boot. The rollback triggers the swap procedure to revert the initial firmware. Once the swap is complete, the bootloader initiates the old firmware, ensuring the device remains operational.
DFU process for a distinct firmware component
In the previous article, we’ve discussed the Firmware Update Object (/5) as defined in the LwM2M Object and Resource Registry. The creation of updatable firmware components can be accomplished through implementing the Advanced Firmware Updates Object (/33629). Object 33629 extends the functionality of the Firmware Update Object (/5) by enabling multiple Object Instances to represent the different components of device's firmware. The specific purpose of these components are not standardized and can vary depending on the implementation.
Similar to Object 5, the Advanced Firmware Updates process comprises 4 States (idle, downloading, downloaded, updating) and no less than 13 Update Results which contain all the likely outcomes of the firmware update process; providing developers with information about the update status and results.
Currently, developers are using Object 33629 as a custom LwM2M Object implementation, until it’s officially adopted into the LwM2M Object and Resource Registry.
View of the Firmware Update feature within Coiote IoT Device Management Platform
The shift from monolithic firmware to a multi-component structure in embedded devices presents an opportunity to streamline and enhance the OTA device firmware update process. This approach offers flexibility in updating specific components independently, reduces resource usage, and provides a more efficient update process.
As IoT devices become increasingly complex, moving towards multi-component FOTA updates is a logical and beneficial step. It facilitates the concurrent development of different firmware components by various parties which ensures the overall quality and functionality of IoT systems over time. As the IoT market continues to mature, this practice is likely to become the norm, making firmware updates more efficient, reliable, and user-friendly.
Subscribe to stay in the loop with all our latest content: