Skip to main content

Embedded Linux OTA Integration Guide

This tutorial covers how to manage your embedded Linux over-the-air update flow with Memfault!

Terminology Overview#

Before we get started, let's quickly recap some of the terminology used throughout the Memfault documentation and how it relates to release management.

At the top level all data in the Memfault UI is encapsulated by the "Organization" and "Project" where:

  • Organization - Entity which contains one or more projects and users. Generally one organization per company.
  • Project - A logical warehouse of all the Memfault data related to a particular set of devices. Typically there will we one project per discrete product line. For example, if your company produces a smart light as well as a smart car, these lines would usually be tracked in separate projects. You could also create a "dev" project for one-off testing and prototyping.

Project Level Filtering#

Within a "Project", data can be filtered on three dimensions:

  • Device - An edge device that communicates with the Memfault cloud. You can look at data collected at the device level to identify the exact issues impacting that unit.
  • Cohort - A grouping of devices. You will be able to filter data and deploy releases by this granularity. For example, you could use a cohort to represent devices used for different release stages ("alpha", "beta", "prod") or to identify devices by location ("office", "site A", "site B") or a combination of both ("Site A Alpha", "Site A Beta", etc). A device is always assigned to exactly one "Cohort" at any given time but can freely be moved to another at any time.
  • Fleet - All devices within a Project

Identifying a Device#

For a "Device" in a project, several pieces of identifying information are tracked.

  • Device Serial / device_serial - A unique identifier of a device. For example, this may be a serial number written into the EEPROM of your product in the factory or a chip identifier present in the silicon of the main MCU on your platform. This identifier must be unique for every device in the same Project.
  • Hardware Version / hardware_version - For a given device, the revision of hardware present. For example, this can be used to represent the different stages of manufacturing builds (evt, dvt, pvt, ...).

Note: For any given device, neither of these pieces of information should ever change.

Identifying Software#

  • Software Type / software_type - A shorthand name representing a software package running on your device.
  • Software Version / software_version - Each build of a "software_type" is uniquely identified by its "software_version".

For more information, see our Software Version documentation.

Identifying Firmware Binaries#

  • OTA Payload - This is the file that you deliver to your device when performing an over-the-air update.
  • Release - For each "Release" a unique "OTA Payload" can be deployed per "hardware_version". A set of "hardware_version" / "OTA Payload" pairs makes up a "Release".
  • Deployment - The act of publishing a "Release" to a "Cohort" generates a "Deployment". Once deployed, any device in the given "Cohort" will be able to query and update to this Release.

Getting Started#

Memfault CLI Tool#

Releases can be managed either from the Memfault web UI or via the memfault cli tool. In this tutorial we will make use of the CLI client which can be installed via pip:

$ pip3 install memfault-cli

User API Key#

This is an auth token that can be used as the "password" to make Memfault API requests which require Basic Authentication.

To locate the token, hover over your name in the top right of the dashboard and select "My Profile". Copy/paste the token in the "User API Key" section.

This API key should be passed in as the --password parameter when using the Memfault CLI.

Project & Organization Slug#

When using email & API key authentication, the Memfault CLI tool also needs to know what organization and project to target. To find the "slugs" of the organization and project in the Memfault UI:

  1. Make sure that you've selected the right project on the top-left
  2. Click on "Settings" and then "General Settings"

Project Key#

This is a token that is used when pushing data between a device and the Memfault cloud. We will be using this to query for OTA Payloads in this tutorial. To locate this token you will also want to navigate to the "Settings" -> "General" page in the Memfault UI and copy/paste the token in the "Project Key" section.

Managing Your First Release#

Create an OTA Payload#

SWUpdate expects OTA Payloads in its own .swu format. Read documentation on SWUpdate to learn how to create .swu files for yor project.

Create Release#

In the commands below, please replace ${YOUR_SOFTWARE_TYPE} with the Software Type this Release contains. For example, in case of a BeagleBone Black we may give a Software Type of bbb-fw.

Replace ${YOUR_HARDWARE_VERSION} with the Hardware Version that this Release targets. For example, when targeting the "Mass Production" hardware build, we might use a Hardware Version of mp.

Likewise, replace ${YOUR_SOFTWARE_VERSION} with the Software Version that this Release contains. For example, in case we're releasing our first cut of our 0.0.1 build, we might use 0.0.1-alpha as Software Version.

$ cd /dev/smartfridge/
$ memfault --org-token ${YOUR_ORG_TOKEN} \
--org ${YOUR_ORG_SLUG} \
--project ${YOUR_PROJECT_SLUG} \
upload-ota-payload \
--hardware-version ${YOUR_HARDWARE_VERSION} \
--software-type ${YOUR_SOFTWARE_TYPE} \
--software-version ${YOUR_SOFTWARE_VERSION} \
build/bbb-fw.swu
INFO: build/bbb-fw.swu: uploaded!
INFO: You can view in the UI here:
<Link to Release in UI>

We've uploaded build/bbb-fw.swu as the OTA Payload. In this example, we're using a SWUpdate update image (.swu), but Memfault supports any type of OTA Payload.

Tip

If you are going to be working with the same project you can add standard arguments as environment variables to your shell init file or via the command line:

$ export MEMFAULT_ORG_TOKEN=<Organization Token>
$ export MEMFAULT_ORG=<Organization slug>
$ export MEMFAULT_PROJECT=<Project slug>

With these changes, our invocation reduces to:

$ cd /dev/smartfridge/
$ memfault upload-ota-payload \
--hardware-version ${YOUR_HARDWARE_VERSION} \
--software-type ${YOUR_SOFTWARE_TYPE} \
--software-version ${YOUR_SOFTWARE_VERSION} \
build/bbb-fw.swu
INFO: build/bbb-fw.swu: uploaded!
INFO: You can view in the UI here:
<Link to Release in UI>

Deploy Release#

Now let's deploy the release to the default cohort.

note

Any new device seen that has not explicitly been assigned to a custom cohort will be part of the default cohort. To pre-create devices assigned to a specific cohort check out our api-docs.

In the UI navigate to "Fleet" -> "Cohorts". Click on the picker under next to the default cohort under "Target Release", select the Release to deploy and you will be prompted with options that can be performed for the release.

Query for OTA Payload#

Now that we have a release uploaded and published let's walk through the steps to download the release on a device!

Memfault supports SWUpdate as a way to update the software on an Embedded Linux device using its Suricatta daemon in general-purpose HTTP server mode.

Suricatta is a daemon mode of SWUpdate that runs on a device and polls a remote server for updates, downloads them, and installs them. It then reboots the system with updated software.

Building SWUpdate to include Suricatta in general-purpose HTTP server mode#

Find the following options, either via menuconfig or by modifying defconfig:

  • CONFIG_SURICATTA=y: configures SWUpdate to include the Suricatta daemon in the build.
  • CONFIG_SURICATTA_GENERAL=y: configures Suricatta to use general-purpose HTTP server mode.
  • Unset CONFIG_SURICATTA_HAWKBIT: SWUpdate works either in general-purpose HTTP server mode or in Hawkbit mode. Disable Hawkbit support.

Configuring the Suricatta on-device daemon to use Memfault#

Three sections are required in the configuration file:

  • globals: contains general settings for SWUpdate that are required for the daemon to start. In the example below, we've configured SWUpdate to output plenty of logs. You may want to tone this down for a production build.
  • gservice: through which Suricatta's general-purpose HTTP server mode is configured.
  • identify: is used to uniquely identify the device in Memfault servers, and to decide whether the device is eligible for an update.

The following configuration can be used as a starter. Save it in swupdate.cfg and remember to replace all the placeholders with valid values for your project and device:

globals:
{
verbose = true;
loglevel = 6;
syslog = true;
}
gservice =
{
url = "https://device.memfault.com/api/v0/swupdate/update";
logurl = "https://device.memfault.com/api/v0/swupdate/logs?mpk=$YOUR_PROJECT_KEY&id=$DEVICE_SERIAL&v=$SOFTWARE_VERSION&st=$SOFTWARE_TYPE&hw=$HARDWARE_VERSION";
logevent: (
{event = "check"; format="#1,date,fw"},
{event = "started"; format="#2,date,fw"},
{event = "success"; format="#3,date,fw"},
{event = "fail"; format="#4,date,fw"}
);
}
identify : (
{ name = "mpk"; value = "$YOUR_PROJECT_KEY" },
{ name = "id"; value = "$DEVICE_SERIAL" },
{ name = "v"; value = "$SOFTWARE_VERSION" },
{ name = "st"; value = "$SOFTWARE_TYPE" },
{ name = "hw"; value = "$HARDWARE_VERSION" }
);
note

When SWUpdate downloads and applies your update, it will not automatically update the $SOFTWARE_VERSION in this file. It is the responsibility of your setup to do this.

Example SWUpdate invocation#

swupdate -f /etc/swupdate.cfg -u "--polldelay $(shuf --input-range=14400-21600 --head-count=1)"

Assuming you've stored swupdate.cfg in /etc/swupdate.cfg, this command will start SWUpdate in Suricatta daemon mode and configure the daemon to poll Memfault servers every periodically at a random interval of between 14400 and 21600 seconds (4 to 6 hours).

Integration with Yocto#

The meta-memfault-swupdate-example Yocto layer is based on SWUpdate documentation on building with Yocto and should serve as an example of building your own Linux image that contains SWUpdate preconfigured to work with Memfault.

We have prepared a Dockerfile that serves as an example of using meta-memfault-swupdate-example as part of a Poky build. Read more about meta-memfault-swupdate-example in the project README.

Rollback Release#

Aborting or Rolling back from a Release which has a firmware regression is easy to do from the UI. Simply navigate to "Fleet" -> "Cohorts", click on the picker under "Options" and select the "Abort Rollout" option.