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.
Thread Secure DFU does not use a SoftDevice, but the bootloader requires the Master Boot Record (MBR). The example provides a stand-alone MBR as a .hex file. To program the MBR, perform the following steps:
<InstallFolder>\examples\thread\experimental\dfu\mbr
.nrfjprog -f nrf52 -r --program mbr_nrf52_2.2.0_mbr.hex --chiperase
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:
armgcc
folder of the example at <InstallFolder>\examples\thread\experimental\dfu\bootloader\pca10056\blank\armgcc
.make
to build the project._build
folder to the board. For example, nrfjprog -f nrf52 -r --program _build\nrf52840_xxaa_blank.hex --sectoranduicrerase
.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.
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:
coap_dfu_init()
function, the DFU client binds to DFU_UDP_PORT
(by default 5683).-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.
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.
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
.
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.
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.
--sd-req
option is required for compatibility reasons. You can provide any value for the option as it is ignored during DFU.Thread Secure DFU uses the same validation algorithm as BLE Secure DFU Bootloader. Refer to Validation for details of the validation algorithm.
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 will be 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\experimental\dfu
.
Test the Thread Secure DFU application by performing the following steps:
dfu_public_key.c:
dfu_public_key.c
file to the project folder <InstallFolder>\examples\dfu\dfu_req_handling
, replacing the existing file. <InstallFolder>\examples\thread\experimental\dfu
. Use the path provided above.main()
function: COM3
is the DFU Server DK serial port: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.-a
option. For more information about nrfutil parameters, enter nrfutil dfu thread --help
.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) | 0x0001 F000 - 0x000F 4000 (852 kB) |
Reserved | 0x0000 1000 - 0x0001 F000 (120 kB) |
Master Boot Record (MBR) | 0x0000 0000 - 0x0000 1000 (4 kB) |