Mistake on this page? Email us

Firmware update

There are two aspects of firmware update:

  • The integration of firmware update API to your application.
  • Preparing and orchestrating the firmware update process, either the full image or delta update.

Integrating firmware update API to an application

To update a firmware image, you must integrate your application with a bootloader. See the bootloader documentation.

Firmware update is an in-built feature of Client Lite. If your application needs control points for the firmware update process, you can pass callbacks to the application to manage the process.

Configuring the application

To set up your application to support firmware update:

  1. Add #define MBED_CLOUD_CLIENT_FOTA_ENABLE 1 macro to the mbed_cloud_client_user_config.h file used by the application.

  2. Configure the following parameters in your application's json file:

    Note: The configuration must match the configuration used in the bootloader build.

    • "target.header_offset": "0x8000" - FOTA image header offset in internal flash. The header contains image metadata, such as version, digest and size.

      Note: The FOTA image header must reside on erase block boundary as it will be overwritten during the firmware udpate.

    • "target.app_offset": "0x8200" - Firmware image offset in internal flash. This value is passed to the linker script for relocating the firmware application to the desired offset. This relocation is required for bootloader to work.

      Note: The offset address must be naturally aligned to a power of two, where the alignment value is greater than or equal to (number of exceptions supported x 4), with a minimum alignment of 128 bytes.

    • "fota.block-device-type":"FOTA_INTERNAL_FLASH_BD" - FOTA library BlockDevice type used for storing and reading a firmware candidate. Available options are:

      • FOTA_INTERNAL_FLASH_BD - (Mbed OS environment only) Internal flash BlockDevice to be used for saving the firmware candidate.

      • FOTA_CUSTOM_BD - (Mbed OS environment only) Allows the application to select a custom BlockDevice. The application is expected to implement a BlockDevice getter function mbed::BlockDevice *fota_bd_get_custom_bd().

        An example of using Mbed OS default BlockDevice:

        mbed::BlockDevice *fota_bd_get_custom_bd()
        {
            return mbed::BlockDevice::get_default_instance();
        }
        
      • FOTA_EXTERNAL_BD - Allows the application to implement its own version of a BlockDevice by all functions in the fota_block_device.h header file.

    • "fota.storage-start-address": "0x..." - Address for the candidate storage.

      • If you select FOTA_INTERNAL_FLASH_BD as the FOTA storage type, the address is a physical address in internal flash.
      • In all other cases, the storage address is relative to the BlockDevice start address and can be considered as an offset.
    • "fota.storage-size": 256*1024 - FOTA candidate storage size.

    • "fota.encryption-support": True - (Optional) Enable firmware candidate encryption on storage. AEC-CMM encryption is used to both encrypt and authenticate the candidate.

    • "fota.candidate-block-size": 1024 - (Optional - only relevant when encryption-support=True) Set encryption block size. Bigger block size requires more RAM.

    • "target.header_format": [] (Mbed OS environment only) FOTA image header template specification for Mbed OS post-build script. This instructs the Mbed-OS postbuild to forge the FOTA image header in the format expected by the FOTA library.

      An example:

      "target.header_format": [
        ["magic", "const", "32le", "0x5c0253a3"],
        ["firmwareSize", "size", "32le", ["application"]],
        ["firmwareVersion", "const", "64le", "0x0"],
        ["firmwareDigest", "digest", "SHA256", "application"],
        ["precursorDigest", "digest", "SHA256", "application"]
      ]
      

Example configuration

A reference example of configuring the firmware update parameters in the mbed_app.json file for an NRF52840_DK board:

    "target.header_offset": "0x8000",
    "target.app_offset": "0x8200",
    "target.header_format": [
         ["magic", "const", "32le", "0x5c0253a3"],
         ["firmwareSize", "size", "32le", ["application"]],
         ["firmwareVersion", "const", "64le", "0x0"],
         ["firmwareDigest", "digest", "SHA256", "application"],
         ["precursorDigest", "digest", "SHA256", "application"]
    ],
    "fota.block-device-type": "FOTA_INTERNAL_FLASH_BD",
    "fota.storage-start-address": "(MBED_CONF_STORAGE_TDB_INTERNAL_INTERNAL_BASE_ADDRESS+MBED_CONF_STORAGE_TDB_INTERNAL_INTERNAL_SIZE)",
    "fota.storage-size": "(512*1024-MBED_CONF_STORAGE_TDB_INTERNAL_INTERNAL_SIZE)"

This configuration defines that the firmware update candidate will be downloaded and stored into the second bank of internal flash.

FOTA callbacks

Your application must implement the callbacks specified by the FOTA application interface specification header file:

  • fota_app_on_download_authorization() - FOTA download authorization callback. The FOTA client requires application authorization to start downloading the update. The callback implementation is expected to call one of these APIs:

    • fota_app_authorize() - Authorize FOTA request.
    • fota_app_reject() - Reject FOTA request and discard the update. The update will not be reprompted.
    • fota_app_defer() - Defer the update to a later phase. This will abort the current update attempt, while preserving the update manifest. The update will be restarted on next boot. Alternatively, you can restart the update by calling fota_app_resume().
  • fota_app_on_install_authorization() - FOTA install authorization callback. The FOTA client requires application authorization to apply the update. The implementation is expected to call one of these APIs:

    • fota_app_authorize() - Authorize FOTA to install the update candidate - reboot or connectivity lost may occur during the candidate installation operation. This phase is considered critical as power loss can potentially brick the device.
    • fota_app_reject() - Reject FOTA request and discard the update. The update will not be reprompted.
    • fota_app_defer() - Defer the install to a later later phase. This will mark the candidate as valid but will not perform reboot.
  • fota_app_on_complete() - FOTA complete callback. The FOTA client notifies the application of completion or termination of the update process. The application may have postponed its main activities before authorizing an update. If the update terminates without reboot, the FOTA library notifies the application about FOTA process termination.

  • fota_app_on_download_progress() - Notifies the application on the firmware candidate download progress. It is called approximately on every five percent of the download progress.

See an example implementation of FOTA callbacks.

Note: If your application does not require an implementation of some special logic, the FOTA library provides a default implementation for callbacks listed. To enable the default implementation, inject the FOTA_DEFAULT_APP_IFS define into the application build.

We recommend that you set this define during the development phase because it shows the download progress.

Component update

The FOTA library supports update of components different from the main firmware image. A good example of such component is a BLE stack running on a co-processor.

Your application can register extra components:

  1. To define the number of components to present in the system, add this line to your your application's json file:

    "fota.num-components": x, where x is the number of components present in the system including the MAIN component of the firmware image.

  2. Inject FOTA_CUSTOM_PLATFORM define to the application build and implement the custom platform callbacks defined in the fota_platform.h header file. Implement these callbacks:

    • fota_platform_init_hook() - Platform init hook, called at FOTA module initialization.
    • fota_platform_start_update_hook() - Platform start update hook, called when the update is started.
    • fota_platform_finish_update_hook() - Platform finish update hook, called when the update has finished.
    • fota_platform_abort_update_hook() - Platform start update hook, called when update is aborted.
  3. Register components:

    In fota_platform_init_hook(), register your components by filling the component descriptor struct and calling the fota_component_add() API.

    To register a component, fill in this information:

    • component name - A string value with max nine characters, including NULL termination.
    • factory version - A string value representing the Semantic Version of the component firmware installed at the factory.
    • candidate iterate callback - A callback function the FOTA library calls for installing the candidate. The callback is called iteratively with a firmware fragment buffer pointer as an argument.
    • install alignment fragment size - The preferred installer fragment size. Typically equals to the flash program size.
    • need reboot - Specify whether the component requires system reboot after the component installation has completed.
    • post install callback - A callback function to be executed after the reboot for handling post install tasks.
    • support delta - Specify whether the component supports differential (delta) update. For the differential update, the FOTA library must have access to the current firmware installed on the component.
    • current firmware read function - (Only required if support delta is set to true) A helper function for reading the currently installed firmware of the component.
    • curr_fw_get_digest - (Only required in case support delta is set to true) A helper function for calculating the SHA256 digest of the currently installed firmware of the component.

Preparing firmware update

See the application tutorial for a quick example on a full image update.

Refer to the full update documentation on the Pelion Device Management documentation site:

Note: Code compilation, device management with Pelion and the update processes are identical in the Device Management Client example.