Skip to main content

Software Version & Hardware Version

Hardware Version

The Hardware Version is used to identify the type of hardware on which software is running. In Memfault, a device always has exactly one Hardware Version. It can be used to identify different device types being tracked in the same Project (i.e. smart-toaster and smart-oven) and different board revisions of the same device type (i.e. smart-toaster-evt, smart-toaster-pvt, etc.).

By default, the Hardware Version of an individual Device is set permanently during the first time it reports in to Memfault. To enable updating this field, please contact us.

Requirements

Hardware Versions must be between 1 and 128 characters long and can only contain the following characters: a-z, A-Z, 0-9, -_.+:\()[]/, and spaces.

MCU

The software running on your devices will need to report its Hardware Version. Please see the core/device info component of the Firmware SDK for details on how to set this up on the device's software side.

Android

On Android, Memfault uses the ro.product.model system property as the device's Hardware Version by default. From the Android product documentation:

The board/device layer represents [...] the bare schematics of a product. These include the peripherals on the board and their configuration.

Linux

On Linux, the Hardware Version needs to be reported to memfaultd by the memfault-device-info program, which you need to implement as part of the integration.

Software Type

A Software Type can be thought of as a "namespace" for Software Versions. The Software Type is used to identify the separate pieces of software running on a given device. This can be images running on different MCUs (i.e main-mcu-app & bluetooth-mcu) or different images running on the same MCU (i.e main-mcu-bootloader & main-mcu-app).

The Software Type is also included in a Trace's Signature. See the callout below for pitfalls.

Requirements

Software Types must be between 1 and 128 characters long and can only contain the following characters: a-z, A-Z, 0-9, -_.+:\()[]/, and spaces.

caution

It is not recommended to use Software Types to distinguish between software build variants (i.e. main-mcu-development & main-mcu-prod), because:

  1. It does not play nicely with Memfault's concept of "Primary Software Type" (see below). We recommend encoding build variants into the Software Version instead, by suffixing the version (i.e. 1.0.0-development).

  2. The Software Type is included in a Trace's Signature. This means that Traces with identical contents (e.g. crash stacktrace) but different Software Types will result in different Issues being created. In short, it breaks the Trace deduplication, causing multiple Issues for the same root cause to be created.

Primary Software Type

Memfault's platform uses the notion of "Primary Software Type" to identify the main software version for a device.

Each Hardware Version has a single matching Primary Software Type associated with it, which is set from the Software Type for the first device reporting in with a particular Hardware Version. The association can also be modified later from the Settings page. An example:

The Primary Software Type is used to populate the Software Version field on the individual Device page, as well as when filtering for the device, and how it appears in various fleet-level charts. When Memfault OTA is used to deploy software, the versions of OTA Releases are also expected to be derived from Software Versions of the Primary Software Type.

You can configure the Primary Software Type in Settings –> Hardware –> Create Hardware Version.

MCU

The software running on your devices will need to report its Software Type correctly such that it matches what has been configured in the Project. Please see the core/device info component of the Firmware SDK for details on how to set this up on the device's software side.

Android

Memfault uses android-build as the Software Type for the Android OS itself.

Android Applications have a Software Type equal to their application ID, e.g. com.acme.smartsink.

Linux

On Linux, the Software Type is specified in the memfaultd.conf file and can be overridden via memfault-device-info.

Software Version

A Software Version is a single build of a particular Software Type. Software Versions are used in Memfault in a variety of ways, including but not limited to:

  • Displaying Issue distributions by version.
  • Determining regressions: re-opening an Issue if a defect recurs in a newer Software Version after the Issue was marked as resolved.
  • Checking if a device is up to date: if your Project uses Memfault to deploy firmware, the firmware's Software Version is used to determine if a device requires an update.
Requirements

Aside from the requirements that follow from the chosen versioning scheme, Software Versions must be between 1 and 128 characters long and can only contain the following characters: a-z, A-Z, 0-9, -_.+:\()[]/, and spaces.

Versioning Schemes

Human-readable and understandable software versions go a long way. A good scheme allows everyone involved in a project to quickly determine whether a device's build is new, old, or a one-off build built by an engineer. On top of readability, a good versioning scheme allows trivial and algorithmic comparisons between software versions.

Comparison between versions is also a fundamental input to Memfault's OTA system. Consult the section Updating Behavior on our OTA documentation to see how the rules below are applied to OTA.

Memfault recommends using SemVer 2.0 for versioning. Specifically, using these forms will result in the least confusion:

  1. for official releases, strict SemVer ("normal version number" per the spec):

    1.0.0

    Exactly 3 digit groups, leading zeros permitted, delimited by periods (see the spec for details).

  2. "beta" or "release candidate", etc., pre-release versions:

    1.0.0-beta.0
    1.0.0-rc.0
  3. automated nightly builds that are deployed over Memfault OTA to a Cohort:

    # using a build number (eg CI build number, or monotonically incrementing
    # based on git tag, etc.)
    1.0.0-nightly.0

    # using a calendar version. always increments, and can be generated without
    # context (assuming only 1 build is deployed per day)
    1.0.0-nightly.20220123
  4. development builds generated locally (using git sha or other identifier):

    1.2.3+092ced197518c8e304232239315c611af6ff2404

    And set the "Disable Version Checking" setting for the Cohort.

To help generate version suffixes, consider the following:

  • If using Git tags, see information on git rev-parse for generating tag strings
  • If using a calendar version, the unix date command could be used. For example, date --utc +%Y%m%d.

MCU

The device_info.software_version field may need to be populated at build time by the build script. For example, you might have a C preprocessor token that holds the string for the software version, where the value is populated by a build script:

# a C compiler option setting the SOFTWARE_VERSION token to a string
-DSOFTWARE_VERSION=\"1.0.0-nightly.20220123\"`

Please see the core/device info component of the Firmware SDK for details on how to set this up on the device's software side.

Android OS

Memfault supports extracting the Software Version for the android-build Software Type from several different sources to suit different build configurations.

By default, irrespective of the source, the Software Version will be ordered per Version Schemes.

We recommend using both the build fingerprint and a custom system property for situations where the build fingerprint does not contain a meaningful identifier; for example, if the incremental and ID parts of the fingerprint are set by the ODM and have no semantic meaning for your internal software versioning.

The full Software Version stored in Memfault will have the form:

${fingerprint}::${property}

This provides the additional functionality enabled by using the build fingerprint, while also using a system property of your choice for display and comparison purposes.

The fingerprint must uniquely identify the build, and the specified system property must also uniquely identify the build.

Memfault supports using the Android build fingerprint as the Software Version. In recent AOSP builds, the build fingerprint can be found in out/target/product/$DEVICE/build_fingerprint.txt.

If the fingerprint is used to specify the Software Version, the fingerprint must be unique for each build.

We recommend using the fingerprint instead of a single system property because it enables additional functionality such as the ability to filter traces based on fingerprint properties like the build type.

Because the build fingerprint is usually a very long string, the Memfault UI will show only the most relevant part. By default, the "incremental" component is used for display and ordering; this can be customized to instead use e.g. the "ID" component.

System Property Only

The Software Version can be sourced from any system property. The specified property must be able to uniquely identify the build (the value must be unique for each build).

Android Applications

For Android applications (instead of the Android OS), Memfault will use the APK's versionCode and versionName to compare Software Versions.

Linux

On Linux, the Software Version must be specified in the memfaultd.conf file and can be overridden by memfault-device-info.

Archiving Software Types and Versions

Memfault supports archiving Software Types and Versions. This action removes the selected Software Type or Software Version. After clicking the Archive button you'll no longer be able to see the selected Software Type/Version in the UI. The operation also marks any associated Events and Traces for deletion after 30 days.

warning

A Software Type/Version cannot be unarchived so proceed with caution!

/img/docs/platform/archive-software-version.png

Memfault's Version Ordering Internals

By default, Memfault uses Natsort. Natsort was chosen given the balance of flexibility and predictability.

Memfault uses a slight tweak on top of natsort to support rc or dev versioning schemes. This is achieved by appending a character z.

For example, these versions are sorted from oldest to newest:

1.0.0rc1
1.0.0
1.0.1-dev
1.0.1-rc2
1.0.1
1.0.12
1.0.20

To implement a "release candidate" or "alpha/beta" versioning scheme, the recommended option is to follow the SemVer 2.0 specification, for example:

1.0.0-alpha.1
1.0.0-alpha.2

Or:

1.0.0-rc.0
1.0.0-rc.1

Be cautious about more exotic versioning schemes! natsort will only handle the common scenarios.

For example, the SemVer 2.0 spec permits appending build metadata to a version number:

1.0.0+092ced197518c8e304232239315c611af6ff2404

But natsort will apply lexical ordering (under the default settings), which may not result in the expected OTA response (see "Disable Version Checking").

For example, the following three software versions are in the correct order, despite SemVer 2.0 declaring they are equal.

1.0.0+00000000
1.0.0+aaaaaaaa
1.0.0+ffffffff

Testing the Ordering

It is imperative to understand how your Software Versions will be ordered by Memfault's OTA system.

To test version ordering locally, install Natsort and create a simple Python script order.py to test it out.

from natsort import natsorted

def memfault_natsort(items: list[str]):
return natsorted(items, key=lambda x: x + "z")

versions = ['1.0.0', '1.0.0-alpha', '1.10.0-beta']

print(memfault_natsort(versions))
$ python order.py
['1.0.0-alpha', '1.0.0', '1.10.0-beta']