Memfault OTA for Linux with SWUpdate
This guide describes how to use Memfault OTA for devices that are updated with SWUpdate. If you are not using SWUpdate, or want more control over the OTA process, you can integrate directly with the Memfault OTA REST API.
This guide assumes that you are using Yocto to build your system image but all the principles are identical if you are using SWUpdate with a different build system or a Linux distribution.
Memfault uses a globally distributed CDN for low latency and high speed downloads regardless of geolocation. It supports features such as HTTP/2, Brotli and GZip, and byte range requests, among others.
Terminology Overview
Please refer to Over-the-Air Updates (OTA) for an introduction to Memfault's OTA concepts and terminology. The paragraphs below discuss the platform-specific aspects for Embedded Linux.
Identifying a Device
For a device in a Project, several pieces of identifying information are tracked.
- Device ID: a unique identifier of a device (often the device serial number).
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. It must be an alphanumeric slug (matching this regex:
^[-a-zA-Z0-9_]+$
). - 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
, ...).
For any given device, neither of these pieces of information should ever change.
Prerequisites
The memfaultd
daemon
We strongly recommend integrating memfaultd
first. Follow the integration
guide to learn how to set this up for your device. A key
function of memfaultd
is to correctly configure and control SWUpdate.
While we recommend using memfaultd
to automate OTA configuration and benefit
from more advanced Memfault features, Memfault OTA may be used without it. This
can be done by configuring your OTA agent to talk to the Memfault API. Both
SWUpdate and RAUC have built-in support for Memfault OTA using the standard
hawkBit interface. A custom agent can also be developed using our REST API.
Consult our REST API docs if you wish to do so.
Keep meta-memfault-example
open as a reference
implementation. Your integration should look similar to it once you're done
following the steps in this tutorial.
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 from the "Project Key" section.
(Optional) Memfault CLI Tool
Releases can be managed either from the Memfault web UI or via the memfault cli tool.
Memfault CLI tool (memfault-cli
) is a Python utility that is meant to be
installed on development machines and CI infrastructure, not on the target
device. It interacts with Memfault API.
It is different from memfaultctl
, which interacts with memfaultd
. As a
small, native binary, it is optimized to run on embedded devices.
In this tutorial we will make use of the CLI client which can be installed via pip:
$ pip3 install memfault-cli
If you'd like to use the Memfault web application instead, you can always refer to our documentation on OTA Release Management and keep it open as you follow this guide.
(Optional) 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 from 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:
- Make sure that you've selected the right project on the top-left
- Click on "Settings" and then "General Settings"
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 your project. Our Yocto
example contains a working SWUpdate image
memfault-image
.
Additionally, the meta-swupdate-boards
repository
contains several examples and is a good source of working integration samples.
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.
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>
Enable developer mode
By default, your devices will be asked to poll every 12 hours by the Memfault backend. In order to speed up the integration process, we've added a developer mode setting to Cohorts.
Select the default
Cohort in Fleet → Cohorts and open its Settings view.
In it, select "Development mode: every minute" in the hawkBit polling interval
section.
Activate the Release
Now let's activate the Release in the default
Cohort.
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 application, navigate to Fleet → Cohorts. Click on the picker
under next to the default
Cohort under "Target Release", select the Release to
activate 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 SWUpdate's Suricatta daemon. It communicates with the server using the hawkBit DDI API standard.
Building SWUpdate to include Suricatta
Find the following options, either via menuconfig
or by modifying defconfig
,
and add them to defconfig
in a recipe that appends to swupdate
(here's an
example):
CONFIG_SURICATTA=y
: configures SWUpdate to include the Suricatta daemon in the build.CONFIG_SURICATTA_HAWKBIT=y
: configures Suricatta to use hawkBit server mode.- Unset
CONFIG_SURICATTA_GENERAL
: SWUpdate works either in hawkBit mode or a general-purpose HTTP server mode. Disable general-purpose HTTP server support.
Configuring the Suricatta on-device daemon to use Memfault
The memfaultd
daemon includes a SWUpdate feature to
automatically generate SWUpdate configuration file. You can control which
features are built-in, but by default, it builds
with the SWUpdate feature enabled.
The SWUpdate feature for memfaultd
constructs a valid SWUpdate configuration in a temporary file. The path of this
temporary file defaults to /tmp/swupdate.cfg
. To make SWUpdate use this file,
you may add e.g. --file /tmp/swupdate.cfg
to the SWUPDATE_ARGS
environment
variable, which gets picked up by SWUpdate. Check out the example
layer for inspiration.
To allow for further configuration, memfaultd
uses /etc/swupdate.cfg
as its
base for the generated configuration. Feel free to configure your SWUpdate
installation using /etc/swupdate.cfg
, e.g. by adding a recipe that appends to
swupdate
(see this example).
Note that /etc/swupdate.cfg
may specify a suricatta
section which will get
merged with the corresponding section in /tmp/swupdate.cfg
. The identify
section is owned by memfaultd
and would get overwritten completely.
The path to both /tmp/swupdate.cfg
and /etc/swupdate.cfg
can be configured
in /etc/memfaultd.conf
(see a full reference) like so:
{
"software_version": "1.0.0",
"software_type": "main",
"project_key": "<YOUR_PROJECT_KEY>",
"swupdate": {
"input_file": "/your/own/path/base-swupdate.cfg",
"output_file": "/your/own/path/generated-swupdate.cfg"
}
}
Remember to pass the path to output_file
as a config file for SWUpdate.
SWUpdate feature dependencies
The dependencies of the SWUpdate feature are u-boot-env
and u-boot-fw-utils
.
Make sure to include those in your image file like so:
IMAGE_INSTALL:append = " memfault-device-info u-boot-env u-boot-fw-utils"
Note that memfault-device-info
is a required executable for memfaultd
. Read
our docs on memfault-device-info
for more
information.
Add /etc/fw_env.config
to your build
See this example /etc/fw_env.config
file. SWUpdate as
well as memfaultd
's reboot reason tracking feature depend on it.
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.
Disable developer mode
Remember to undo the steps you took in Enable Developer Mode and to configure your Cohort with a value that'll work for your project on production.