nRF5 SDK for Thread and Zigbee v1.0.0
Thread Secure DFU Example

The Thread Secure DFU example consists of two components: a bootloader and a DFU client. The bootloader is used to verify application integrity and to install a new application image. The DFU client is a module that is typically incorporated into the user application. This allows for downloading a new image while the user application is running. This mechanism differs from the one in the BLE Secure DFU Bootloader where a new image is downloaded and installed in the bootloader.

Thread Secure DFU accepts images that contain a new bootloader or application, which contains the Thread network stack. To protect the target device against malicious attackers trying to impersonate the rightful sender of the firmware update, the init packet of the firmware package must be signed.

Thread Secure DFU supports two modes of firmware updates - unicast or multicast. In unicast mode, each DFU client requests consecutive firmware blocks from the server individually. In multicast mode, the server sends consecutive firmware blocks with a multicast message, and clients interested in a new firmware receive and process them.

MBR setup

Thread Secure DFU does not use a SoftDevice, but the bootloader requires the Master Boot Record (MBR). The example uses a stand-alone MBR provided as a hex file. To program the MBR, perform the following steps:

  1. Open a command prompt and navigate to <InstallFolder>\components\softdevice\mbr\nrf52840\hex.
  2. Ensure that the path to nrfjprog (from nRF5x Command Line Tools v9.2.0 or newer) is in the PATH environment variable.
  3. Run the following command: nrfjprog -f nrf52 -r --program mbr_nrf52_2.3.0_mbr.hex --chiperase

Bootloader setup

The bootloader for the Thread Secure DFU is implemented using Bootloader modules. The main role of the bootloader is to check application integrity and, in case of dual bank updates (see Dual-bank and single-bank updates), to transfer the new image to the active bank. Unlike the BLE Secure DFU Bootloader, the bootloader for Thread Secure DFU does not initialize any transports. Therefore, DFU is not possible in the bootloader. If a valid application is missing, the bootloader enters an infinite loop.

During system startup, the Master Boot Record (MBR) is responsible for starting the bootloader. To do this, the MBR must know the start address of the bootloader. This start address is defined in UICR.BOOTLOADERADDR, which is located at address 0x10001014 (see NRF_UICR_BOOTLOADER_START_ADDRESS). Therefore, you must set UICR.BOOTLOADERADDR to the correct value when you program the bootloader.

Programming the bootloader requires the following steps:

  1. Navigate to the armgcc folder of the example at <InstallFolder>\examples\thread\dfu\bootloader\pca10056\blank\armgcc.
  2. Open a command prompt and run make to build the project.
  3. Use nrfjprog (from nRF5x Command Line Tools v9.2.0 or newer) to program the .hex file that was created in the _build folder to the board. For example, nrfjprog -f nrf52 -r --program _build\nrf52840_xxaa_blank.hex --sectoranduicrerase.

nrfutil

nrfutil is a PC tool which allows for creating and signing firmware packages, as well as for performing the firmware update process using a PC. Support for multicast DFU over Thread has been added to nrfutil in version 3.4.0. Refer to nrfutil installation section for details on possible ways to install the tool.

Note
Thread Secure DFU example behavior was modified in Thread SDK v0.11.0. The current example is not compatible with older versions of nrfutil. Therefore, you must use nrfutil v3.5.0 with the current version of this example. Older versions of Thread Secure DFU (Thread SDK 0.10.0 and older) are compatible with nrfutil v3.2.0.

DFU client

The DFU process flow in the Thread Secure DFU is slightly different from, for example, the BLE Secure DFU Bootloader DFU process flow.

The are two entities which participate in the Thread Secure DFU process: a DFU client and a DFU server. The DFU client runs on a DFU target, which is the device that is being upgraded, and is responsible for downloading and installing the new firmware. The DFU client incorporates a DFU controller (see Device Firmware Update process) which manages the DFU process. This means that each DFU target might be in a different state regarding the DFU process at a given point of time. The DFU server is a server which provides a firmware package. For example, the DFU server could be a cloud service, an nRF52840 Development Kit in conjunction with nrfutil, or a mobile phone running an application.

The DFU client is a module which is typically integrated with the user application. The module uses the IoT SDK CoAP library to implement a DFU algorithm which runs concurrently to the user application. The Thread Secure DFU example shows how the module should be initialized and triggered from a user application.

Thread Secure DFU supports two modes of operation - unicast mode and multicast mode. For more information about the specific mode of operation, refer to the relevant section.

The basic operation of the DFU client is as follows:

  1. Once initialized with the coap_dfu_init() function, the DFU client binds to DFU_UDP_PORT (by default 5683).
  2. The DFU client waits for a trigger packet. The trigger packet contains information about firmware size, checksum, and DFU mode.
  3. If the installed firmware size or checksum differs from the size or checksum sent in the trigger packet, the DFU client either requests the init packet from the DFU server which has sent the trigger packet or waits for multicast init packet transmission from the server (multicast mode).
  4. Once the init packet is downloaded, a validation procedure is performed (see Validation).
  5. If validation is successful, then the firmware image download starts.
  6. Once the firmware image is downloaded, the DFU client checks its integrity. If it is successful, the device is restarted (unless the nrfutil reset suppress option -rs was provided) and the new image is copied into the active bank.

The DFU client checks for availability of new firmware packages by sending a trigger packet using the coap_dfu_trigger() function. The trigger packet can be sent to a particular host or to a group of hosts using a multicast address. Sending the packet to a particular host is useful in a scenario where the DFU server is outside of the Thread network, for example, hosted in the cloud. The DFU initialized by the client is always performed in unicast mode.

Thread Secure DFU unicast mode

In unicast mode, the Thread DFU server sends a trigger packet with the mode bit set to 0. In this mode, the DFU server does not undertake any action on its own - it is the DFU client's responsibility to send appropriate requests to the server and download the image. All communication in this mode (with exception of the initial trigger packet) is sent through unicast messages. Therefore, each node must download the image individually. Use this mode when there is a single device to be updated. This mode is also used when the DFU process is initialized by the client.

Unicast mode is the default mode when no --address option is passed to nrfutil or when the passed address is a unicast address.

Thread Secure DFU multicast mode

In multicast mode, the Thread DFU server sends a trigger packet with the mode bit set to 1. In this mode, the DFU server sends consecutive blocks of init packet and firmware package through multicast messages. Every DFU client node that receives the multicast DFU trigger packet decides whether to participate in the DFU process and store the firmware blocks. A client that recognizes that it missed one or more of the firmware blocks can send a request to the server for retransmission of these specific blocks. Use this mode when the firmware should be updated on several nodes at once.

You can select this mode by passing a realm-local multicast address as a parameter to nrfutil, for example, --address FF03::1.

Init packet

Thread Secure DFU uses the same packet format as the BLE Secure DFU Bootloader. Refer to Init packet for details regarding the init packet customization.

Creating a firmware package

Firmware packages for Thread Secure DFU are created using the same method as in the BLE Secure DFU Bootloader. Refer to Creating a firmware package to find out how to create a firmware package.

Note
The Thread stack does not use the SoftDevice, but the --sd-req 0x00 option is required to indicate that no SoftDevice is used.

Validation

Thread Secure DFU uses the same validation algorithm as BLE Secure DFU Bootloader. Refer to Validation for details of the validation algorithm.

Testing

To test the DFU process, you need at least two nRF52840 Development Kit boards. One of these boards will be a DFU server that distributes the new firmware, while the others will play the role of DFU clients that are updated. When using more than one DFU client, you should use multicast DFU mode. Unless stated otherwise, run all of the presented commands in the main folder of the DFU Example: <InstallFolder>\examples\thread\dfu.

Test the Thread Secure DFU application by performing the following steps:

  1. Create cryptographic keys for the example. See Working with keys for information about key generation.
    1. Create a private key:
      nrfutil keys generate priv.pem
    2. Create a public key in code format and store it in a file named dfu_public_key.c:
      nrfutil keys display --key pk --format code priv.pem --out_file dfu_public_key.c
    3. Copy the dfu_public_key.c file to the project folder <InstallFolder>\examples\dfu, replacing the existing file.
      Note
      Do not copy the key to the folder <InstallFolder>\examples\thread\dfu. Use the path provided above.
  2. Build the bootloader by running the following command:
    make -C bootloader\pca10056\blank\armgcc
  3. Prepare the DFU Client:
    1. Install micro-ecc. This library is required by the Cryptography library , which is used by the Thread Secure DFU example.
    2. Compile the DFU client by running the following command:
      make -C client\pca10056\blank\armgcc
    3. Return to the DFU example main folder and generate a bootloader settings HEX file:
      nrfutil settings generate --family NRF52840 --application client\pca10056\blank\armgcc\_build\nrf52840_xxaa.hex --application-version 1 --bootloader-version 1 --bl-settings-version 1 settings.hex
    4. Use mergehex (part of the nRF5x Command Line Tools) to merge the client HEX file and the bootloader settings HEX file:
      mergehex -m client\pca10056\blank\armgcc\_build\nrf52840_xxaa.hex settings.hex -o dfu_client.hex
  4. Flash the DFU Client to the client boards:
    1. Connect one or more DFU Client boards to the computer.
    2. Flash the MBR as described in MBR setup:
      nrfjprog -f nrf52 -r --program ..\..\..\components\softdevice\mbr\nrf52840\hex\mbr_nrf52_2.3.0_mbr.hex --chiperase
    3. Flash the bootloader as described in Bootloader setup:
      nrfjprog -f nrf52 -r --program bootloader\pca10056\blank\armgcc\_build\nrf52840_xxaa_blank.hex --sectoranduicrerase
    4. Flash the merged DFU Client with the following command:
      nrfjprog -f nrf52 -r --program dfu_client.hex --sectorerase
    5. Make sure that the device connects to the Thread network. This is indicated by LED 1 being lit.
  5. Prepare the firmware package for the DFU process:
    1. To successfully perform the DFU process, you need to modify the DFU Client application, so that the new firmware has a different checksum. For example, add the following line to the main() function:
      LEDS_ON(BSP_LED_3_MASK);
    2. Compile the modified DFU Client by running the following command:
      make -C client\pca10056\blank\armgcc
    3. Return to the DFU example main folder and prepare a firmware package (in ZIP format) with the new firmware. See Creating a firmware package for more information:
      nrfutil pkg generate --hw-version 52 --sd-req 0x00 --application-version 2 --application client\pca10056\blank\armgcc\_build\nrf52840_xxaa.hex --key-file priv.pem app_dfu_package.zip
  6. Use nrfutil to run the DFU:
    1. Connect the DFU server nRF52840 Development Kit board to your computer. This board serves as the connectivity IC to the Thread network. This board does not require installation of any firmware. It will be flashed by nrfutil.
    2. Run the following command to start the DFU process over Thread, where COM3 is the DFU Server DK serial port:
      1. For unicast DFU:
        nrfutil dfu thread -f -pkg app_dfu_package.zip -p COM3 --channel 11 --panid 43981
      2. For multicast DFU:
        nrfutil dfu thread -f -pkg app_dfu_package.zip -p COM3 --channel 11 --panid 43981 -r 4 -rs 5000 -a FF03::1
        The -r rate parameter may need to be adjusted for a given network size. In general, larger networks will not be able to disseminate multicast messages at a higher rate.
    3. By default, DFU is performed on all conforming devices in the network. To choose a specific target device using its IPv6 address, use nrfutil's -a option. For more information about nrfutil parameters, enter nrfutil dfu thread --help.
  7. Observe that the device resets and runs the new application.

Memory Layout

When adding a bootloader to your device, you must be aware of where in the device memory the different firmware components are located. The following table shows the memory layout used by the Thread Secure DFU.

Usage Memory range nRF52840
Bootloader settings 0x000F F000 - 0x0010 0000 (4 kB)
MBR parameter storage 0x000F E000 - 0x000F F000 (4 kB)
Bootloader 0x000F 8000 - 0x000F E000 (24 kB)
OpenThread settings 0x000F 4000 - 0x000F 8000 (16 kB)
Application area (incl. free space) 0x0000 1000 - 0x000F 4000 (972 kB)
Master Boot Record (MBR) 0x0000 0000 - 0x0000 1000 (4 kB)

Documentation feedback | Developer Zone | Subscribe | Updated