Running the DFU process

This user guide introduces basic information of the DFU and provides an example procedure for running it on your application.

The DFU process in this SDK uses MCUboot, a secure bootloader for 32-bit microcontrollers. MCUboot allows for safe firmware updates with minimal overhead.

Firmware updates are transferred to a device using MCUmgr, which has transports for Bluetooth Low Energy® and UART.

More detailed information about specific concepts can be found in Memory Partitioning for DFU and Bootloader keys sections.

Partition Configuration

The memory of your device must be partitioned appropriately to accommodate the bootloader, application, and firmware update mechanisms. Bare Metal uses Zephyr’s DTS system for memory partitioning.

For details on memory partitioning and related concepts, see Memory Partitioning for DFU. If you are not using a DK board target, refer to Preparing the DFU-ready variant of your board for an example of how to partition the memory using DTS.

Firmware loader

The firmware loader is a crucial application for updating the main application via a transport layer, such as Bluetooth LE.

Note

When using Bluetooth LE as transport, make sure to enable the SB_CONFIG_BM_FIRMWARE_LOADER_BT_MCUMGR sysbuild Kconfig option.

The firmware loader can be activated by the bootloader using the following methods:

  • Using a button (GPIO)

    Set the SB_CONFIG_BM_BOOTLOADER_MCUBOOT_FIRMWARE_LOADER_ENTRANCE_GPIO sysbuild Kconfig option to use this mode.

  • Using the reset pin

    Set the SB_CONFIG_BM_BOOTLOADER_MCUBOOT_FIRMWARE_LOADER_ENTRANCE_PIN_RESET sysbuild Kconfig option to use this mode.

  • Buttonless entry through the retention register from the application

    Set the SB_CONFIG_BM_BOOTLOADER_MCUBOOT_FIRMWARE_LOADER_ENTRANCE_BOOT_MODE sysbuild Kconfig option to use this mode.

Installer Application

The installer application is automatically generated by the build system. It updates the firmware loader and SoftDevice images on the device.

Output build files (image files)

When DFU is enabled in the application, the build system outputs the following files.

File

Description

Programming scenario

<build_dir>/firmware_loader/zephyr/zephyr.signed.hex

Firmware loader image.

Programming board targets.

<build_dir>/mcuboot/zephyr/zephyr_signed_softdevice_flash_metadata.hex

MCUBoot image with SoftDevice.

<build_dir>/<app_name>/zephyr/zephyr.signed.hex

Application image.

<build_dir>/production.hex

Production hex file, containing: MCUboot, firmware loader, SoftDevice and main application images.

Production device programming.

<build_dir>/installer_softdevice_firmware_loader.bin

Installer Update image (DFU) with SoftDevice and firmware loader updates.

DFU process for board targets.

<build_dir>/<app_name>/zephyr/zephyr.signed.bin

Application Update image (DFU).

Running DFU in your application

The following is the workflow for testing the DFU mechanism on an application developed with Bare Metal.

Note

The preparation below here describes how to add a MCUboot board variant to a custom board, for Bare Metal there already are MCUboot board variants for the bm_nrf54l15dk board:

  • bm_nrf54l15dk/nrf54l05/cpuapp/s115_softdevice/mcuboot for nRF54L15 (emulating nRF54L05) with S115 softdevice

  • bm_nrf54l15dk/nrf54l10/cpuapp/s115_softdevice/mcuboot for nRF54L15 (emulating nRF54L10) with S115 softdevice

  • bm_nrf54l15dk/nrf54l15/cpuapp/s115_softdevice/mcuboot for nRF54L15 with S115 softdevice

To test DFU with one of these default board targets, skip to the Building and running section.

Preparing the DFU-ready variant of your board

Before enabling DFU in your application, you must first add an MCUboot variant of your board.

Assuming that your board is bm_nrf54l15dk and using the S115 SoftDevice with the existing board variant name of bm_nrf54l15dk/nrf54l15/cpuapp/s115_softdevice, then you can use the bm_nrf54l15dk/nrf54l15/cpuapp/s115_softdevice/mcuboot board variant to enable DFU support in your application.

This board target will always enable DFU support when it is used to build the application.

  1. Go to the board directory.

  2. Edit the board.yml file to define the new board variant and flash the runner configuration:

    board:
      name: bm_nrf54l15dk
      full_name: Bare Metal nRF54L15 DK
      vendor: nordic
      socs:
        - name: nrf54l15
          variants:
            - name: s115_softdevice
              cpucluster: cpuapp
              variants:
                - name: mcuboot
    
    runners:
      run_once:
        '--recover':
           - runners:
              - nrfjprog
              - nrfutil
            run: first
            groups:
              - boards:
                  - bm_nrf54l15dk/nrf54l15/cpuapp
                  - bm_nrf54l15dk/nrf54l15/cpuapp/s115_softdevice
                  - bm_nrf54l15dk/nrf54l15/cpuapp/s115_softdevice/mcuboot
        '--erase':
          - runners:
              - nrfjprog
              - jlink
              - nrfutil
            run: first
            groups:
              - boards:
                  - bm_nrf54l15dk/nrf54l15/cpuapp
                  - bm_nrf54l15dk/nrf54l15/cpuapp/s115_softdevice
                  - bm_nrf54l15dk/nrf54l15/cpuapp/s115_softdevice/mcuboot
        '--reset':
          - runners:
              - nrfjprog
              - jlink
              - nrfutil
            run: last
            groups:
              - boards:
                  - bm_nrf54l15dk/nrf54l15/cpuapp
                  - bm_nrf54l15dk/nrf54l15/cpuapp/s115_softdevice
                  - bm_nrf54l15dk/nrf54l15/cpuapp/s115_softdevice/mcuboot
    
  3. Copy the existing SoftDevice board variant files for the new board variant:

    • bm_nrf54l15dk_nrf54l15_cpuapp_s115_softdevice.dts -> bm_nrf54l15dk_nrf54l15_cpuapp_s115_softdevice_mcuboot.dts

    • bm_nrf54l15dk_nrf54l15_cpuapp_s115_softdevice.yaml -> bm_nrf54l15dk_nrf54l15_cpuapp_s115_softdevice_mcuboot.yaml

    • bm_nrf54l15dk_nrf54l15_cpuapp_s115_softdevice_defconfig -> bm_nrf54l15dk_nrf54l15_cpuapp_s115_softdevice_mcuboot_defconfig

  4. Edit the bm_nrf54l15dk_nrf54l15_cpuapp_s115_softdevice_mcuboot.dts file to add the partitions used for MCUboot and ensure that the chosen node is set to slot0_partition:

    / {
            chosen {
                    zephyr,code-partition = &slot0_partition;
            };
    };
    
    ...
    
    &cpuapp_rram {
            status = "okay";
    
            partitions {
                    compatible = "fixed-partitions";
                    #address-cells = <1>;
                    #size-cells = <1>;
    
                    boot_partition: partition@0 {
                            label = "boot";
                            reg = <0x00000000 DT_SIZE_K(32)>;
                    };
    
                    storage_partition: partition@8000 {
                            compatible = "fixed-subpartitions";
                            label = "storage";
                            reg = <0x00008000 DT_SIZE_K(8)>;
                            ranges = <0x0 0x8000 DT_SIZE_K(8)>;
                            #address-cells = <1>;
                            #size-cells = <1>;
    
                            storage0_partition: partition@0 {
                                    label = "storage0";
                                    reg = <0x00000000 DT_SIZE_K(4)>;
                            };
    
                            storage1_partition: partition@1000 {
                                    label = "storage1";
                                    reg = <0x00001000 DT_SIZE_K(4)>;
                            };
                    };
    
                    slot0_partition: partition@a000 {
                            label = "slot0";
                            reg = <0x0000a000 DT_SIZE_K(1290)>;
                    };
    
                    slot1_partition: partition@14c800 {
                            label = "slot1";
                            reg = <0x0014c800 DT_SIZE_K(64)>;
                    };
    
                    softdevice_partition: partition@15c800 {
                            label = "softdevice";
                            reg = <0x0015c800 (DT_SIZE_K(129) + 0x200)>;
                    };
    
                    metadata_partition: partition@17ce00 {
                            label = "metadata";
                            reg = <0x0017ce00 0x200>;
                    };
            };
    };
    
  5. Edit the bm_nrf54l15dk_nrf54l15_cpuapp_s115_softdevice_mcuboot.yaml file to set the name and flash size:

    identifier: bm_nrf54l15dk/nrf54l15/cpuapp/s115_softdevice/mcuboot
    name: Bare_Metal-nRF54L15-DK-nRF54L15-Application-S115-SoftDevice-MCUboot
    type: mcu
    arch: arm
    toolchain:
      - gnuarmemb
      - xtools
      - zephyr
    sysbuild: true
    ram: 238
    flash: 1298
    
  6. Add a Kconfig.defconfig file with the following:

    config ROM_START_OFFSET
            default 0x800 if BOOTLOADER_MCUBOOT
    
  7. Edit the Kconfig.sysbuild file with the following:

    if BOARD_BM_NRF54L15DK_NRF54L15_CPUAPP_S115_SOFTDEVICE_MCUBOOT
    
    choice BM_BOOTLOADER
            default BM_BOOTLOADER_MCUBOOT
    endchoice
    
    choice SOFTDEVICE_SELECTION
            default SOFTDEVICE_S115
    endchoice
    
    choice BM_FIRMWARE_LOADER
            default BM_FIRMWARE_LOADER_BT_MCUMGR
    endchoice
    
    endif # BOARD_BM_NRF54L15DK_NRF54L15_CPUAPP_S115_SOFTDEVICE_MCUBOOT
    
  8. Edit the Kconfig.bm_nrf54l15dk file with the following:

    config BOARD_BM_NRF54L15DK
            select SOC_NRF54L15_CPUAPP if BOARD_BM_NRF54L15DK_NRF54L15_CPUAPP_S115_SOFTDEVICE || BOARD_BM_NRF54L15DK_NRF54L15_CPUAPP_S115_SOFTDEVICE_MCUBOOT
    
  9. Ensure that BOARD_PIN_BTN_0 is defined in the include/board-config.h file:

    #define GPIO_ACTIVE_HIGH 1
    
    #ifndef BOARD_PIN_BTN_0
    #define BOARD_PIN_BTN_0 NRF_PIN_PORT_TO_PIN_NUMBER(13, 1)
    #endif
    

Building and running

  1. Build an application using the new board target and with the desired option from Firmware loader set, and flash it to your device.

  2. To enter the firmware loader mode, hold down Button 0 and press the reset button.

  3. The device will be advertising with the name nRF_BM_MCUmgr displayed on the terminal output.

  4. Transfer the <build_dir>/installer_softdevice_firmware_loader.bin and <build_dir>/<app_name>/zephyr/zephyr.signed.bin files to your mobile device (see Output build files (image files) for details on output files)

  5. Open the nRF Device Manager application on your mobile device.

  6. Select the nRF_BM_MCUmgr named-device (or other name if the name has been changed) from the list.

  7. Tap the Image tab at the bottom to move to the image management tab.

  8. Under Image upgrade select the update file to load:

    • Choose installer_softdevice_firmware_loader.bin to update the Softdevice and firmware loader images, this is only needed if the SoftDevice or firmware loader images have been updated, this image should be loaded first if it is needed.

    • Choose zephyr.signed.bin to load the application update.

  9. Tap the Start button, then select the Upload only (no revert) option to begin the firmware update process.

  10. The mobile device will connect and load the firmware update to the device.

  11. Once completed, reboot the device. If the installer image was loaded, then it will apply the updates and reboot into firmware loader mode automatically and allow for loading the application firmware update using the same process. If an application update was loaded, then the new application will begin executing.

Signing keys

When building with an MCUboot board variant, it will use a default dummy MCUboot signing key which should not be used in production, see Bootloader keys for details on how to generate and use a custom signing key when building an application.

DFU samples

Any sample can be built for an MCUboot-enabled board target to add DFU support in. Applications can refer to the samples at nrf-bm/samples/boot/mcuboot_recovery_entry for a method to enter firmware loader mode by using the Bluetooth Low Energy® MCUmgr service, or nrf-bm/samples/boot/mcuboot_recovery_retention for how to reboot into firmware loader mode in a custom way from the user application. These samples demonstrate dummy buttonless entry to the firmware loader, allowing new firmware or installer updates to be loaded over Bluetooth Low Energy® using MCUmgr.