MCU OTA Integration Guide
This tutorial covers how to manage your firmware over-the-air update flow with Memfault!
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 MCU Projects.
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.
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:
- Make sure that you've selected the right project on the top-left
- 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 Release
In the commands below, please replace ${YOUR_SOFTWARE_TYPE}
with the Software
Type this Release contains. For example, in case of an STM32 MCU we may give a
Software Type of stm32-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
1.0.0 build, we might use 1.0.0-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/stm32-fw.bin
INFO: build/stm32-fw.bin: uploaded!
INFO: You can view in the UI here:
<Link to Release in UI>
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/stm32-fw.bin
INFO: build/stm32-fw.bin: uploaded!
INFO: You can view in the UI here:
<Link to Release in UI>
Deploy Release
Now let's deploy our 1.0.0-alpha
release to 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 UI navigate to "Fleet" → "Cohorts". Click on the picker under next to the
default
Cohort under "Target Release", select 1.0.0-alpha
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!
To receive an OTA Payload, a device will need to pass these REST API query parameters:
device_serial
- This is used for determining thecohort
a Device is in.hardware_version
- OTA payloads are specific to eachhardware_version
, so this is a required parameter.software_type
- The software component on the device responsible for performing OTA updates.current_version
(optional)- The currentsoftware_version
of thesoftware_type
that performs OTA updates. This is used to determine if there is a newersoftware_version
available to be installed. If omitted, the latest version is returned for the device.
We can test this out from our computer to see the exact response a device will see. Let's assume we have the following test device:
hardware_version
: mpsoftware_type
: stm32fwcurrent_version
: 0.0.1device_serial
: DEMOSERIAL
Example Response when Newer OTA Payload Available
To simplify integration with deeply embedded devices that may not have a json
parser you can use the api/v0/releases/latest/url
endpoint to receive the url
as a text response.
$ export MEMFAULT_LATEST_URL_API_ROUTE=https://device.memfault.com/api/v0/releases/latest/url
$ curl -i -X GET \
"${MEMFAULT_LATEST_URL_API_ROUTE}?device_serial=DEMOSERIAL&hardware_version=mp&software_type=stm32-fw¤t_version=0.0.1" \
--header "Memfault-Project-Key: ${YOUR_PROJECT_KEY}"
HTTP/1.1 200 OK
content-type: text/plain; charset=utf-8
[...]
https://url/to/ota/payload
When a new firmware has been found, you will get a HTTP response with a 200 status code.
If there are no updates available (such as when the device is already on the
newest firmware) you will see a 204 (No Content) http status code in the
response. We can try it out by retrying the query with 1.0.0-alpha
as the
value for current_version
:
Example Response when Device is Up To Date
$ curl -i -X GET \
"${MEMFAULT_LATEST_URL_API_ROUTE}?device_serial=DEMOSERIAL&hardware_version=mp&software_type=stm32-fw¤t_version=0.0.1" \
--header "Memfault-Project-Key: ${YOUR_PROJECT_KEY}"
HTTP/1.1 204 NO CONTENT
memfault-reason: latest
[...]
Verbose Release Information
To query for all the information pertaining to a release you can use the
releases/latest
route instead of releases/latest/url
. In this situation
information about the release will be returned in a JSON blob:
$ export MEMFAULT_LATEST_API_ROUTE=https://device.memfault.com/api/v0/releases/latest
$ curl -i -X GET \
"${MEMFAULT_LATEST_API_ROUTE}?device_serial=DEMOSERIAL&hardware_version=mp&software_type=stm32-fw¤t_version=0.0.1" \
--header "Memfault-Project-Key: ${YOUR_PROJECT_KEY}"
HTTP/1.1 200 OK
content-type: application/json
{
"artifacts": [
{
[...]
"url": "URL_FOR_OTA_PAYLOAD"
}
],
}
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.
Firmware Integration Checklist
When querying the Memfault Latest Endpoint directly from firmware, there are a few common items you will want to confirm are setup correctly.:
Include Root Certs to Communicate with Memfault cloud
In order to build the chain of trust as part of establishing a TLS session with
Memfault cloud, you will need to make sure your embedded stack includes the
appropriate root certificates. You can find the exact list exposed in both PEM &
DER format within the memfault-firmware-sdk at
memfault/http/root_certs.h
.
Enable Server Name Indication (SNI) in TLS stack
Server Name Indication (SNI) is an extension that was added in 2003 to the TLS 1.0 Specification in RFC 3546. It's supported by effectively every modern day browser and network stack available.
Occasionally in an embedded stack the feature may not be enabled by default. If the feature is not enabled you will see a TLS/SSL handshake failure with Alert Code 80 trying to establish a TLS connection with the Memfault cloud.
To fix the issue, you just need to enable the SNI feature in your TLS stack. For example, here's what to check for some common TLS stacks used in embedded devices:
mbedTLS
- Make sureMBEDTLS_SSL_SERVER_NAME_INDICATION
is set as a config option.OpenSSL
- Make sure to callSSL_set_tlsext_host_name(ssl, <host_name>)
prior to callingSSL_connect()
.