DFU over Bluetooth Mesh

The DFU specification is implemented in the Zephyr Bluetooth Mesh DFU subsystem as three separate models:

For more information about the Zephyr Bluetooth Mesh DFU subsystem, see Device Firmware Update (DFU).

The Bluetooth Mesh subsystem in nRF Connect SDK provides a set of samples that can be used for evaluation of the Bluetooth Mesh DFU specification and subsystem:

To configure and control DFU on the Firmware Distribution Server, it is required to have the Firmware Distribution Client model. The Bluetooth Mesh DFU subsystem in Zephyr provides a set of shell commands that can be used to substitute the need for the client. For the complete list of commands, see the Firmware Distribution Server model section of the Bluetooth Mesh shell documentation.

The commands can be executed in two ways:

  • Through the shell management subsystem of MCU manager (for example, using the nRF Connect Device Manager mobile application on Android or Mcumgr command-line tool).

  • By accessing the Shell module over UART.

Provisioning and configuring the devices

After programming the samples onto the boards, they need to be provisioned into the same Bluetooth Mesh network with an external provisioner device. See the documentation for provisioning the mesh DFU target device and provisioning the mesh DFU distributor device for how this is done.

After the provisioning is completed, a Configuration Client needs to add a common application key to all devices. The added application key must be bound:

  • On the Distributor: to the Firmware Distribution Server, Firmware Update Client, BLOB Transfer Server and BLOB Transfer Client models instantiated on the primary element, and to the Firmware Update Server and BLOB Transfer Server models instantiated on the secondary element of the device (see Configuring models on the Distributor node).

  • On Target nodes: to the Firmware Update Server and BLOB Transfer Server models instantiated on the primary element of the device (see Configuring models on the Target node).

The bound application key will be used in the firmware distribution procedure.

Uploading the firmware

After configuring the models, a new image can be uploaded to the Distributor. To upload the image, follow the instructions provided in the Uploading a firmware image section of the Bluetooth Mesh: Device Firmware Update (DFU) distributor sample documentation.

The uploaded image needs to be registered in the Bluetooth Mesh DFU subsystem. To achieve this, issue the mesh models dfu slot add shell command specifying size in bytes of the image that was uploaded to the Distributor. Optionally, you can provide firmware ID, metadata and Unique Resource Identifier (URI) parameters that come with the image.

For example, to allocate a slot for the Bluetooth Mesh: Device Firmware Update (DFU) target sample with image size of 241236 bytes, with firmware ID set to 0200000000000000, and metadata generated as described in Generating the firmware metadata section below, type the following command:

mesh models dfu slot add 241236 0200000000000000 020000000000000094cf24017c26f3710100

When the slot is added, the shell will print the slot ID. Take note of this ID as it will then be needed to start the DFU transfer:

Adding slot (size: 241236)
Slot added. ID: 0

Note

To update any value in a slot, issue the mesh models dfu slot del command specifying the ID of the allocated slot, and then add the slot again.

Populating the Distributor’s receivers list

Add Target nodes to the DFU transfer by issuing the mesh models dfd receivers-add shell command. This shell command is specifying the element address of a Target node with the Firmware Update Server instance and the image index on the Target node that needs to be updated. For example, for two Target nodes with addresses 0x0004 and 0x0005 respectively, and with image index 0, the command will look like this:

mesh models dfd receivers-add 0x0004,0;0x0005,0

Note

To remove all receivers from the list, issue the mesh models dfd receivers-delete-all command.

Initiating the distribution

To start the DFU transfer, issue the mesh models dfd start shell command. This command requires two mandatory arguments: app_idx and slot_idx:

  • As app_idx, use the application key index that is bound to the Firmware Distribution Server and other Firmware Update and BLOB Transfer models on the Distributor and Target nodes.

  • As slot_idx, use the ID of the slot allocated by the mesh models dfu slot add shell command on the previous step.

For example, to run the DFU transfer in unicast mode, with AppKey index 0 and slot ID 0, call:

mesh models dfd start 0 0

By default, the Firmware Distribution Server will request the Firmware Update Servers to apply the image immediately after the DFU transfer. To avoid applying the image immediately and only verify it, set the 4th argument to 0:

mesh models dfd start 0 0 0 0

Firmware distribution

The transfer will take a couple of minutes, depending on the number of Target nodes and the network quality. To check the transfer progress, call the mesh models dfd receivers-get shell command, for example:

mesh models dfd receivers-get 0 2

The output may look like this:

{
        "target_cnt": 1,
        "targets": {
                "0": { "blob_addr": 0x0004, "phase": 2, "status": 0, "blob_status": 0, "progress": 50, "img_idx": 0 }
                "1": { "blob_addr": 0x0005, "phase": 2, "status": 0, "blob_status": 0, "progress": 50, "img_idx": 0 }
        }
}

To see the distribution status, phase and parameters of the DFU transfer, use the mesh models dfd get command. When the DFU transfer successfully completes, the phase will be set to BT_MESH_DFD_PHASE_TRANSFER_SUCCESS, for example:

{ "status": 0, "phase": 2, "group": 0x0000, "app_idx": 0, "ttl": 255, "timeout_base": 0, "xfer_mode": 1, "apply": 0, "slot_idx": 0 }

The bt_mesh_dfd_phase enumeration contains the complete list of distribution phases.

Suspending the distribution

The firmware distribution can be suspended using the mesh models dfd suspend shell command. The distribution phase is switched to BT_MESH_DFD_PHASE_TRANSFER_SUSPENDED in this case.

To resume the DFU transfer, issue the mesh models dfu cli resume shell command.

Applying the firmware image

Depending on the update policy set at the start of the DFU transfer, the Firmware Distribution Server will do the following:

  • If policy_apply is set to true or omitted when the DFU transfer starts, the Firmware Distribution Server will immediately apply the new firmware on the Target nodes upon the DFU transfer completion.

  • If policy_apply is set to false, the image needs to be applied manually using the mesh models dfd apply command once the DFU transfer is completed.

When the Firmware Distribution Server starts applying the transferred image, the distribution phase is set to BT_MESH_DFD_PHASE_APPLYING_UPDATE.

After applying the new firmware, the Firmware Distribution Server will immediately request firmware ID of the currently running firmware on the Target nodes to confirm that the new firmware has been applied successfully. Depending on the bt_mesh_dfu_effect value received from the Target nodes after the DFU transfer is started, the following cases are possible:

  • If the image effect for a particular Target node is BT_MESH_DFU_EFFECT_UNPROV, the Firmware Distribution Server doesn’t expect any reply from that Target node. If the Distributor doesn’t receive any reply, it will repeat the request several times. If the Distributor eventually receives a reply, the DFU for this particular Target node is considered unsuccessful. Otherwise, the DFU is considered successful.

  • In all other cases, the Distributor expects a reply from the Target node with the firmware ID equal to the firmware ID of the transferred image. If the Target node responds with a different firmware ID or doesn’t respond at all after several requests, the DFU for this particular Target node is considered unsuccessful. Otherwise, the DFU is considered successful.

The DFU ends after the Distributor stops polling the Target nodes. If the DFU completes successfully for at least one Target node, the firmware distribution is considered as successful. In this case, the distribution phase is set to BT_MESH_DFD_PHASE_COMPLETED. If the DFU doesn’t complete successfully, the distribution phase is set to BT_MESH_DFD_PHASE_FAILED.

Cancelling the distribution

To cancel the firmware distribution, use the mesh models dfd cancel shell command. The Firmware Distribution Server will start the cancelling procedure by sending a cancel message to all Targets and will switch phase to BT_MESH_DFD_PHASE_CANCELING_UPDATE. Once the cancelling procedure is completed, the phase is set to BT_MESH_DFD_PHASE_IDLE.

Note

It is possible to cancel the firmware distribution on a specific Target node at any time by sending Firmware Update Cancel message. To do this, use the mesh models dfu cli cancel shell command specifying unicast address of the Target node.

Recovering from failed distribution

If the firmware distribution fails for any reason, the list of Target nodes should be cleared and the distribution phase should be set to BT_MESH_DFD_PHASE_IDLE before making a new attempt. To do this, run the following shell commands:

mesh models dfd receivers-delete-all
mesh models dfd cancel

To bring a stalled Target node to idle state, use the mesh models dfu cli cancel shell command.

Note

This does not affect the allocated image slots.

Generating the firmware metadata

There are two ways to generate the required DFU metadata:

  • Automated generation using the DFU metadata extraction script integrated in the nRF Connect SDK build system.

  • Manual generation by using shell commands.

Using the DFU metadata extraction script is the most efficient way of generating the required DFU metadata.

Automated metadata generation

By enabling the CONFIG_BT_MESH_DFU_METADATA_ON_BUILD option in the application, the metadata will be automatically parsed from the .elf and .config files. The parsed data is stored in the ble_mesh_metadata.json file. The file is placed in the dfu_application.zip archive in the build folder of the application. Additionally, the metadata string required by the mesh models dfu slot add command will be printed in the command line window when the application is built:

Bluetooth Mesh Composition metadata generated:
  Encoded metadata: 020000000000000094cf24017c26f3710100
  Full metadata written to: APPLICATION_FOLDER\build\zephyr\dfu_application.zip

Note

It is required that the Composition Data is declared with the const qualifier. If the application contains more than one Composition Data structure (for example, when the structure to be used is picked at runtime), the script will not print any encoded metadata. In this case, use the JSON file to find the encoded metadata matching the Composition Data to be used by the device after the update. Additionally, the script is hardcoded to produce a metadata string where the firmware is targeted for the application core.

A separate west command can be utilized to print the metadata to the console, given that it is already generated by the build system. This gives the user easy access to this information, without having to enter the .json file in the build folder or to rebuild the application:

west build -t ble_mesh_dfu_metadata

For this particular example, the following output is generated:

{
  "sign_version": {
    "major": 2,
    "minor": 0,
    "revision": 0,
    "build_number": 0
  },
  "binary_size": 241236,
  "composition_data": {
    "cid": 89,
    "pid": 0,
    "vid": 0,
    "crpl": 10,
    "features": 7,
    "elements": [
      {
        "location": 1,
        "sig_models": [
          0,
          2,
          48962,
          48964
        ],
        "vendor_models": []
      }
    ]
  },
  "composition_hash": "0x71f3267c",
  "encoded_metadata": "020000000000000094cf24017c26f3710100"
}

Manual metadata generation

The Bluetooth Mesh DFU subsystem provides a set of shell commands that can be used to compose a firmware metadata. The format of metadata is defined in the bt_mesh_dfu_metadata structure. For the complete list of commands, see DFU metadata.

To start composing metadata, issue the mesh models dfu metadata comp-add shell command that encodes a Composition Data header. For example, for a Target node with product ID 0x0059, zero company and version IDs, 10 entries in the replay list, and with Relay, Proxy and Friend features enabled, the command will be the following:

mesh models dfu metadata comp-add 0x59 0 0 10 7

Now you need to encode elements that are present on a new image. For each element to encode, issue the mesh models dfu metadata comp-elem-add shell command specifying the location of the element, number of Bluetooth SIG and vendor models and their IDs. For example, for Bluetooth Mesh: Device Firmware Update (DFU) target sample, which has only one element containing Configuration and Health Server models as well as DFU and BLOB Transfer Server models, the command will be the following:

mesh models dfu metadata comp-elem-add 1 4 0 0x0000 0x0002 0xBF42 0xBF44

Note

In case of any mistakes during the encoding of the Composition Data, use the mesh models dfu metadata comp-clear command to clear the cached value, then start composing the metadata from the beginning.

When all elements are added, generate a hash of the Composition Data using the mesh models dfu metadata comp-hash-get shell command. For example, using the inputs from the commands above, the output of this command should be the following:

Composition data to be hashed:
        CID: 0x0059
        PID: 0x0000
        VID: 0x0000
        CPRL: 10
        Features: 0x7
        Elem: 1
                NumS: 4
                NumV: 0
                SIG Model ID: 0x0000
                SIG Model ID: 0x0002
                SIG Model ID: 0xbf42
                SIG Model ID: 0xbf44
Composition data hash: 0x71f3267c

The generated hash will then be encoded into the metadata. Use the mesh models dfu metadata encode shell command to encode the metadata. For example, using the Composition Data hash generated above, the command to encode the metadata for firmware version 2.0.0+0, with a size of 241236 bytes and targeted to application core, will be the following:

mesh models dfu metadata encode 2 0 0 0 241236 1 0x71f3267c 1

The output of the command will be the following:

Metadata to be encoded:
        Version: 2.0.0+0
        Size: 241236
        Core Type: 0x1
        Composition data hash: 0x71f3267c
        Elements: 1
        User data length: 0
Encoded metadata: 020000000000000094cf24017c26f3710100