This guide will show you, step by step, how to add Device Firmware Update (DFU) support to your application using the nRF Connect SDK. First it will demonstrate how to add BLE DFU support to the Peripheral LBS sample and how to perform a DFU using the nRF Connect Device Manager app. The next section will show you how to add Serial DFU support to the Hello World sample and how to perform a DFU from a computer using mcumgr. The code snippets used in this guide are inspired by the SMP Server sample.
Check out the source code for the mcumgr management library for more information about the library and the underlying protocols. It contains a README explaining mcumgr and a README explaining the Simple Management Protocol (SMP).
Before starting, make sure you have installed the nRF Connect SDK and are familiar with nRF Connect for VS code. Check out the nRF Connect for VS Code series on YouTube for help with this. The west command is used to build and flash the samples, but if you're not familiar with the command line, you can build and flash the sample using nRF Connect for VS Code instead.
The samples in this guide are tested with nRF Connect SDK v1.8.0-rc1 and the nRF52840 DK.

In the above image, Linux is used. If you're using Windows, make sure the nRF Connect Toolchain points to the folder <ncs location>/<ncs version>/toolchain
# Enable mcumgr.
CONFIG_MCUMGR=y
# Enable most core commands.
CONFIG_MCUMGR_CMD_IMG_MGMT=y
CONFIG_MCUMGR_CMD_OS_MGMT=y
# Ensure an MCUboot-compatible binary is generated.
CONFIG_BOOTLOADER_MCUBOOT=y
The first config (MCUMGR) will enable the mcumgr management library and the next two (MCUMGR_CMD_IMG_MGMT and MCU_MGR_CMD_OS_MGMT) enables the command handlers for image management and OS management. The image management command handlers makes it possible to upload, list, test and confirm the image(s), while the OS management command handlers makes it possible to reset the chip (and run the echo command). Since the DFU support is added to the application, the chip needs to be reset, to give control to MCUboot, which will validate the new uploaded image and swap it with the old image. Finally, BOOTLOADER_MCUBOOT includes MCUboot as a child image.
# Allow for large Bluetooth data packets.
CONFIG_BT_L2CAP_TX_MTU=252
CONFIG_BT_BUF_ACL_RX_SIZE=256
# Enable the Bluetooth (unauthenticated) and shell mcumgr transports.
CONFIG_MCUMGR_SMP_BT=y
CONFIG_MCUMGR_SMP_BT_AUTHEN=n
# Some command handlers require a large stack.
CONFIG_SYSTEM_WORKQUEUE_STACK_SIZE=4096
First we increase the L2CAP MTU (BT_L2CAP_TX_MTU) and the ACL size (BT_BUF_ACL_RX_SIZE) in order to be able to upload the binary. Next, the Bluetooth mcumgr SMP transport (MCUMGR_SMP_BT) is enabled and the need for an encrypted and authenticated connection to send messages over the BLE SMP transport layer (MCUMGR_SMP_BT_AUTHEN) is disabled (remember to change this value if your application has higher security requirements). The work queue stack size is increased to avoid stack overflow.
#include <mgmt/mcumgr/smp_bt.h>
#include "os_mgmt/os_mgmt.h"
#include "img_mgmt/img_mgmt.h"
BT_DATA_BYTES(BT_DATA_UUID128_ALL,
0x84, 0xaa, 0x60, 0x74, 0x52, 0x8a, 0x8b, 0x86,
0xd3, 0x4c, 0xb7, 0x1d, 0x1d, 0xdc, 0x53, 0x8d),
The reason this was done, is to make the advertising visible for the nRF Connect Device Manager app. The app will filter out all the devices that doesn't advertise with the SMP service UUID.
printk("build time: " __DATE__ " " __TIME__ "\n");
os_mgmt_register_group();
img_mgmt_register_group();
smp_bt_register();
Here we register the OS and Image group as well as the SMP Bluetooth service. A printk with the build date and time is added to make it easier to confirm that an update was successful.
If you've followed the above steps correctly, the sample should look like this: https://github.com/simon-iversen/sdk-nrf/tree/ble_dfu_peripheral_lbs/samples/bluetooth/peripheral_lbs
west build -b nrf52840dk_nrf52840 -p && west flash --erase
For example:
...
*** Booting Zephyr OS build v2.7.0-ncs1-rc1 ***
Starting Bluetooth Peripheral LBS example
build time: Nov 30 2021 17:14:25
...
west build -b nrf52840dk_nrf52840 -p
Due to the printk statement with the build date and time, a new and different binary will be created



The app will then transfer the image binary, and "UPLOAD COMPLETE" should be displayed when the whole binary is uploaded

The nRF Connect Device Manager app will reset the chip after the transfer is completed. If the date and time output on the terminal is different from the one seen earlier, it means a different image is running and the update was successful
For example:
...
*** Booting Zephyr OS build v2.7.0-ncs1-rc1 ***
Starting Bluetooth Peripheral LBS example
build time: Nov 30 2021 17:18:53
...
The new image will get confirmed from the app, so it should not revert back on the next reset.

In the above image, Linux is used. If you're using Windows, make sure the nRF Connect Toolchain points to the folder <ncs location>/<ncs version>/toolchain
# Enable mcumgr.
CONFIG_MCUMGR=y
# Enable most core commands.
CONFIG_MCUMGR_CMD_IMG_MGMT=y
CONFIG_MCUMGR_CMD_OS_MGMT=y
# Ensure an MCUboot-compatible binary is generated.
CONFIG_BOOTLOADER_MCUBOOT=y
Check out Modify the Peripheral LBS sample for an explanations of these configs
# Enable the serial mcumgr transport. CONFIG_MCUMGR_SMP_UART=y # Disable UART Console and enable the RTT console CONFIG_UART_CONSOLE=n CONFIG_RTT_CONSOLE=y CONFIG_USE_SEGGER_RTT=y # Some command handlers require a large stack. CONFIG_SYSTEM_WORKQUEUE_STACK_SIZE=4096
We start by enabling the serial mcumgr SMP transport (MCUMGR_SMP_UART). Next, we use RTT for logging instead of UART, so that it doesn't interfere with the transfer (see Nordic nRF5x Segger J-Link -> RTT Console). Another option is to use the configs from smp_svr/overlay-serial-console.config to enable the UART console with mcumgr pass through. The work queue stack size is increased to avoid a stack overflow (SYSTEM_WORKQUEUE_STACK_SIZDE).
#include "os_mgmt/os_mgmt.h" #include "img_mgmt/img_mgmt.h"
printk("build time: " __DATE__ " " __TIME__ "\n");
os_mgmt_register_group();
img_mgmt_register_group();
We don't need to run any functions related to the SMP serial transport. This is because smp_uart_init() will run before main and set up an UART mcumgr ISR that handles the incoming mcumgr messages.
If you've followed the above steps correctly, the sample should look like this: https://github.com/simon-iversen/sdk-zephyr/tree/serial_dfu_hello_world/samples/hello_world
Before testing the sample, make sure mass storage is disabled. If not the upload command might stall at 0%
west build -b nrf52840dk_nrf52840 -p && west flash --erase
Use the USB connector connected to the Interface MCU, not the USB connector connected to the USB peripheral. This is because UART 0 is used for mcumgr UART, which is by default connected to the Interface MCU for the nRF52840 DK in nRF Connect SDK.

For example:
*** Booting Zephyr OS build v2.7.0-ncs1-rc1 ***
Hello World! nrf52840dk_nrf52840
build time: Nov 30 2021 17:39:13
west build -b nrf52840dk_nrf52840 -p
/dev/ttyACM0"), by running nrfjprog --com../home$ nrfjprog --com
683416774 /dev/ttyACM0 VCOM0
mcumgr --conntype serial --connstring "/dev/ttyACM0,baud=115200" echo hello
The string "hello" should be returned, if not the communication is not working properly
mcumgr --conntype serial --connstring "/dev/ttyACM0,baud=115200" image upload -e app_update.bin
mcumgr --conntype serial --connstring "/dev/ttyACM0,baud=115200" image list
This will list all the images located on the chip, and if the upload has been successful, you should see an image at slot 1, similar to below:
Images:
image=0 slot=0
version: 0.0.0
bootable: true
flags: active confirmed
hash: f8ebf4778aa17de10c24ea1a8fd7b3877672a934448d5193b89a0a60c37699cd
image=0 slot=1
version: 0.0.0
bootable: true flags:
hash: 31cc459b1ec1ac8e19f092caa860db8e377a7ab66234012bdb6a1dd522807269
Split status: N/A (0)
In order for mcuboot to swap the images on reset, the flag of the image in slot-1 has to be "pending". This can be done by running the mcumgr test command, with the hash of slot-1 image. For example:
mcumgr --conntype serial --connstring "/dev/ttyACM0,baud=115200" image test 31cc459b1ec1ac8e19f092caa860db8e377a7ab66234012bdb6a1dd522807269
The image in slot-1 should now be in a "pending" state
mcumgr --conntype serial --connstring "/dev/ttyACM0,baud=115200" reset
For example:
*** Booting Zephyr OS build v2.7.0-ncs1-rc1 ***
Hello World! nrf52840dk_nrf52840
build time: Nov 30 2021 17:42:56
mcumgr --conntype serial --connstring "/dev/ttyACM0,baud=115200" image confirm
This sample is similar to the one in Serial DFU, just that the secondary slot is located at the nRF52840 DK's onboard flash instead of the internal flash
This sample will download an app_update.bin file from a remote server and write it to the external flash. The nRF9160 DK needs to be used
-
user116519
-
Cancel
-
Vote Up
0
Vote Down
-
-
Sign in to reply
-
More
-
Cancel
Comment-
user116519
-
Cancel
-
Vote Up
0
Vote Down
-
-
Sign in to reply
-
More
-
Cancel
Children