diff --git a/config/nrfconnect/app/overlay-dfu_support.conf b/config/nrfconnect/app/overlay-dfu_support.conf
new file mode 100644
index 00000000000000..f12343fa847e5c
--- /dev/null
+++ b/config/nrfconnect/app/overlay-dfu_support.conf
@@ -0,0 +1,40 @@
+#
+# Copyright (c) 2021 Project CHIP Authors
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+#
+
+CONFIG_BOOTLOADER_MCUBOOT=y
+
+# QSPI configuration
+CONFIG_NORDIC_QSPI_NOR=y
+CONFIG_NORDIC_QSPI_NOR_FLASH_LAYOUT_PAGE_SIZE=4096
+CONFIG_NORDIC_QSPI_NOR_STACK_WRITE_BUFFER_SIZE=4
+
+# External flash memory configuration
+CONFIG_PM_EXTERNAL_FLASH=y
+CONFIG_PM_EXTERNAL_FLASH_DEV_NAME="MX25R64"
+CONFIG_PM_EXTERNAL_FLASH_SIZE=0xf2000
+CONFIG_PM_EXTERNAL_FLASH_BASE=0
+
+# MCU Manager and SMP configuration
+CONFIG_MCUMGR=y
+CONFIG_MCUMGR_CMD_IMG_MGMT=y
+CONFIG_MCUMGR_CMD_OS_MGMT=y
+CONFIG_MCUMGR_SMP_BT=y
+CONFIG_MCUMGR_SMP_BT_AUTHEN=n
+
+# Increase BT MTU and RX buffer for big size DFU messages
+CONFIG_BT_L2CAP_TX_MTU=252
+CONFIG_BT_L2CAP_RX_MTU=252
+CONFIG_BT_RX_BUF_LEN=260
diff --git a/examples/lighting-app/nrfconnect/README.md b/examples/lighting-app/nrfconnect/README.md
index a26135120ad89f..e51f6c5010b780 100644
--- a/examples/lighting-app/nrfconnect/README.md
+++ b/examples/lighting-app/nrfconnect/README.md
@@ -22,6 +22,7 @@ into an existing CHIP network and can be controlled by this network.
- [Overview](#overview)
- [Bluetooth LE advertising](#bluetooth-le-advertising)
- [Bluetooth LE rendezvous](#bluetooth-le-rendezvous)
+ - [Device Firmware Upgrade](#device-firmware-upgrade)
- [Requirements](#requirements)
- [Supported devices](#supported_devices)
- [Device UI](#device-ui)
@@ -32,10 +33,12 @@ into an existing CHIP network and can be controlled by this network.
- [Removing build artifacts](#removing-build-artifacts)
- [Building with release configuration](#building-with-release-configuration)
- [Building with Pigweed RPCs](#building-with-pigweed-rpcs)
+ - [Building with Device Firmware Upgrade support](#building-with-device-firmware-upgrade-support)
- [Configuring the example](#configuring-the-example)
- [Flashing and debugging](#flashing-and-debugging)
- [Testing the example](#testing-the-example)
- [Testing using CHIPTool](#testing-using-chiptool)
+ - [Testing Device Firmware Upgrade](#testing-device-firmware-upgrade)
@@ -61,6 +64,9 @@ default settings by pressing button manually. However, this mode does not
guarantee that the device will be able to communicate with the CHIP controller
and other devices.
+The example can be configured to use the secure bootloader and utilize it for
+performing over-the-air Device Firmware Upgrade using Bluetooth LE.
+
### Bluetooth LE advertising
To commission the device onto a CHIP network, the device must be discoverable
@@ -86,6 +92,45 @@ sending the Thread network credentials from the CHIP controller to the CHIP
device. As a result, device is able to join the Thread network and communicate
with other Thread devices in the network.
+### Device Firmware Upgrade
+
+The example allows enabling the over-the-air Device Firmware Upgrade feature. In
+this process, the device hosting new firmware image sends the image to the CHIP
+device using Bluetooth LE transport and
+[Simple Management Protocol](https://developer.nordicsemi.com/nRF_Connect_SDK/doc/latest/zephyr/guides/device_mgmt/index.html#device-mgmt).
+The
+[MCUboot](https://developer.nordicsemi.com/nRF_Connect_SDK/doc/latest/mcuboot/index.html)
+bootloader solution then replaces the old firmware image with the new one.
+
+#### Bootloader
+
+MCUboot is a secure bootloader used for swapping firmware images of different
+versions and generating proper build output files that can be used in the device
+firmware upgrade process.
+
+The bootloader solution requires an area of flash memory to swap application
+images during the firmware upgrade. The Nordic devices use an external memory
+chip for this purpose. The memory chip communicates with the microcontroller
+through the QSPI bus.
+
+See the
+[Building with Device Firmware Upgrade support](#building-with-device-firmware-upgrade-support)
+section to learn how to change MCUboot and flash configuration in this example.
+
+#### Simple Management Protocol
+
+Simple Management Protocol (SMP) is a basic transfer encoding that is used for
+device management purposes, including application image management. SMP supports
+using different transports, such as Bluetooth LE, UDP, or serial USB/UART.
+
+In this example, the CHIP device runs the SMP Server to download the application
+update image using the Bluetooth LE transport.
+
+See the
+[Building with Device Firmware Upgrade support](#building-with-device-firmware-upgrade-support)
+section to learn how to enable SMP and use it for the DFU purpose in this
+example.
+
@@ -150,7 +195,10 @@ following states are possible:
initiated.
- _Pressed for less than 3 s_ — Initiates the OTA software update
- process. This feature is not currently supported.
+ process. This feature is disabled by default, but can be enabled by
+ following the
+ [Building with Device Firmware Upgrade support](#building-with-device-firmware-upgrade-support)
+ instruction.
**Button 2** — Pressing the button once changes the lighting state to the
opposite one.
@@ -318,6 +366,43 @@ kit you own:
$ west build -b build-target -- -DOVERLAY_CONFIG=rpc.overlay
+### Building with Device Firmware Upgrade support
+
+To build the example with configuration that enables DFU, run the following
+command with _build-target_ replaced with the build target name of the Nordic
+Semiconductor's kit you own (for example `nrf52840dk_nrf52840`):
+
+> **_WARNING:_** Please do remember about replacing _build-target_ also in the
+> PM_STATIC_YML_FILE path.
+
+ $ west build -b build-target -- -DOVERLAY_CONFIG=third_party/connectedhomeip/config/nrfconnect/app/overlay-dfu_support.conf -DPM_STATIC_YML_FILE="configuration/build-target/pm_static.yml"
+
+#### Changing bootloader configuration
+
+To change the default MCUboot configuration, edit the `overlay-dfu_support.conf`
+overlay file that contains bootloader configuration options. The file is located
+in the `config/nrfconnect/app` directory. You can also define the desired
+options in your example's `prj.conf` file.
+
+Make sure to apply the same configuration changes in the
+`child_image/mcuboot.conf` file. This is necessary for the configuration to
+work, as the bootloader image is a separate application from the user
+application and it has its own configuration file. The contents of this file
+must be consistent with the application configuration.
+
+#### Changing flash memory settings
+
+In the default configuration, the MCUboot uses the
+[Partition Manager](https://developer.nordicsemi.com/nRF_Connect_SDK/doc/latest/nrf/scripts/partition_manager/partition_manager.html#partition-manager)
+to configure flash partitions used for the bootloader application image slot
+purposes. You can change these settings by defining
+[static partitions](https://developer.nordicsemi.com/nRF_Connect_SDK/doc/latest/nrf/scripts/partition_manager/partition_manager.html#ug-pm-static).
+This example uses this option to define using an external flash.
+
+To modify the flash settings of your board (that is, your _build-target_, for
+example `nrf52840dk_nrf52840`), edit the `pm_static.yml` file located in the
+`configuration/build-target/` directory.
+
@@ -374,3 +459,10 @@ Read the
to see how to use [CHIPTool](../../../src/android/CHIPTool/README.md) for
Android smartphones to commission and control the application within a
CHIP-enabled Thread network.
+
+### Testing Device Firmware Upgrade
+
+Read the section about downloading the new image to a device on the
+[FOTA upgrades](https://developer.nordicsemi.com/nRF_Connect_SDK/doc/latest/nrf/ug_nrf52.html#fota-upgrades)
+page in the nRF Connect documentation to see how to upgrade your device firmware
+over Bluetooth LE using a smartphone.
diff --git a/examples/lighting-app/nrfconnect/child_image/mcuboot.conf b/examples/lighting-app/nrfconnect/child_image/mcuboot.conf
new file mode 100644
index 00000000000000..7097c7c93260dd
--- /dev/null
+++ b/examples/lighting-app/nrfconnect/child_image/mcuboot.conf
@@ -0,0 +1,29 @@
+#
+# Copyright (c) 2021 Project CHIP Authors
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+#
+
+# QSPI configuration
+CONFIG_NORDIC_QSPI_NOR=y
+CONFIG_NORDIC_QSPI_NOR_FLASH_LAYOUT_PAGE_SIZE=4096
+CONFIG_NORDIC_QSPI_NOR_STACK_WRITE_BUFFER_SIZE=4
+
+CONFIG_MULTITHREADING=y
+CONFIG_BOOT_MAX_IMG_SECTORS=256
+
+# External flash memory configuration
+CONFIG_PM_EXTERNAL_FLASH=y
+CONFIG_PM_EXTERNAL_FLASH_DEV_NAME="MX25R64"
+CONFIG_PM_EXTERNAL_FLASH_SIZE=0xf2000
+CONFIG_PM_EXTERNAL_FLASH_BASE=0
diff --git a/examples/lighting-app/nrfconnect/configuration/nrf52840dk_nrf52840/pm_static.yml b/examples/lighting-app/nrfconnect/configuration/nrf52840dk_nrf52840/pm_static.yml
new file mode 100644
index 00000000000000..b194f921be3b26
--- /dev/null
+++ b/examples/lighting-app/nrfconnect/configuration/nrf52840dk_nrf52840/pm_static.yml
@@ -0,0 +1,38 @@
+mcuboot:
+ address: 0x0
+ size: 0xc000
+ region: flash_primary
+mcuboot_pad:
+ address: 0xc000
+ size: 0x200
+app:
+ address: 0xc200
+ size: 0xf1e00
+mcuboot_primary:
+ orig_span: &id001
+ - mcuboot_pad
+ - app
+ span: *id001
+ address: 0xc000
+ size: 0xf2000
+ region: flash_primary
+mcuboot_primary_app:
+ orig_span: &id002
+ - app
+ span: *id002
+ address: 0xc200
+ size: 0xf1e00
+settings_storage:
+ address: 0xfe000
+ size: 0x2000
+ region: flash_primary
+mcuboot_secondary:
+ address: 0x0
+ size: 0xf2000
+ device: MX25R64
+ region: external_flash
+external_flash:
+ address: 0xf2000
+ size: 0x0
+ device: MX25R64
+ region: external_flash
diff --git a/examples/lighting-app/nrfconnect/main/AppTask.cpp b/examples/lighting-app/nrfconnect/main/AppTask.cpp
index b29a238b4b9a2c..e072a7c8b308a4 100644
--- a/examples/lighting-app/nrfconnect/main/AppTask.cpp
+++ b/examples/lighting-app/nrfconnect/main/AppTask.cpp
@@ -37,6 +37,20 @@
#include
#include
+// MCUMgr BT FOTA includes
+#ifdef CONFIG_MCUMGR_CMD_OS_MGMT
+#include "os_mgmt/os_mgmt.h"
+#endif
+#ifdef CONFIG_MCUMGR_CMD_IMG_MGMT
+#include "img_mgmt/img_mgmt.h"
+#endif
+#ifdef CONFIG_MCUMGR_SMP_BT
+#include
+#endif
+#ifdef CONFIG_BOOTLOADER_MCUBOOT
+#include
+#endif
+
#include
#include
#include
@@ -92,6 +106,22 @@ int AppTask::Init()
k_timer_init(&sFunctionTimer, &AppTask::TimerEventHandler, nullptr);
k_timer_user_data_set(&sFunctionTimer, this);
+#ifdef CONFIG_BOOTLOADER_MCUBOOT
+ // Check if the image is run in the REVERT mode and eventually
+ // confirm it to prevent reverting on the next boot.
+ if (mcuboot_swap_type() == BOOT_SWAP_TYPE_REVERT)
+ {
+ if (boot_write_img_confirmed())
+ {
+ LOG_ERR("Confirming firmware image failed, it will be reverted on the next boot.");
+ }
+ else
+ {
+ LOG_INF("New firmware image confirmed.");
+ }
+ }
+#endif
+
ret = LightingMgr().Init(LIGHTING_PWM_DEVICE, LIGHTING_PWM_CHANNEL);
if (ret != 0)
return ret;
@@ -293,6 +323,14 @@ void AppTask::FunctionTimerEventHandler(AppEvent * aEvent)
}
}
+int AppTask::SoftwareUpdateConfirmationHandler(uint32_t offset, uint32_t size, void * arg)
+{
+ // For now just print update progress and confirm data chunk without any additional checks.
+ LOG_INF("Software update progress %d B / %d B", offset, size);
+
+ return 0;
+}
+
void AppTask::FunctionHandler(AppEvent * aEvent)
{
if (aEvent->ButtonEvent.PinNo != FUNCTION_BUTTON)
@@ -319,7 +357,26 @@ void AppTask::FunctionHandler(AppEvent * aEvent)
{
sAppTask.CancelTimer();
sAppTask.mFunction = kFunction_NoneSelected;
- LOG_INF("Software update is not implemented");
+
+#if defined(CONFIG_MCUMGR_SMP_BT) && defined(CONFIG_MCUMGR_CMD_IMG_MGMT) && defined(CONFIG_MCUMGR_CMD_OS_MGMT)
+ if (!sAppTask.mSoftwareUpdateEnabled)
+ {
+ sAppTask.mSoftwareUpdateEnabled = true;
+ os_mgmt_register_group();
+ img_mgmt_register_group();
+ img_mgmt_set_upload_cb(SoftwareUpdateConfirmationHandler, NULL);
+ smp_bt_register();
+
+ LOG_INF("Enabled software update");
+ }
+ else
+ {
+ LOG_INF("Software update is already enabled");
+ }
+
+#else
+ LOG_INF("Software update is disabled");
+#endif
}
else if (sAppTask.mFunctionTimerActive && sAppTask.mFunction == kFunction_FactoryReset)
{
diff --git a/examples/lighting-app/nrfconnect/main/include/AppTask.h b/examples/lighting-app/nrfconnect/main/include/AppTask.h
index 59443ed3aa4e35..e98921183eb1d5 100644
--- a/examples/lighting-app/nrfconnect/main/include/AppTask.h
+++ b/examples/lighting-app/nrfconnect/main/include/AppTask.h
@@ -61,6 +61,8 @@ class AppTask
static void ButtonEventHandler(uint32_t button_state, uint32_t has_changed);
static void TimerEventHandler(k_timer * timer);
+ static int SoftwareUpdateConfirmationHandler(uint32_t offset, uint32_t size, void * arg);
+
void StartTimer(uint32_t aTimeoutInMs);
enum Function_t
@@ -72,8 +74,9 @@ class AppTask
kFunction_Invalid
};
- Function_t mFunction;
- bool mFunctionTimerActive;
+ Function_t mFunction = kFunction_NoneSelected;
+ bool mFunctionTimerActive = false;
+ bool mSoftwareUpdateEnabled = false;
static AppTask sAppTask;
};
diff --git a/examples/lock-app/nrfconnect/README.md b/examples/lock-app/nrfconnect/README.md
index 75b1ff1b621cf9..5d452f0fa6a06b 100644
--- a/examples/lock-app/nrfconnect/README.md
+++ b/examples/lock-app/nrfconnect/README.md
@@ -22,6 +22,7 @@ into an existing CHIP network and can be controlled by this network.
- [Overview](#overview)
- [Bluetooth LE advertising](#bluetooth-le-advertising)
- [Bluetooth LE rendezvous](#bluetooth-le-rendezvous)
+ - [Device Firmware Upgrade](#device-firmware-upgrade)
- [Requirements](#requirements)
- [Supported devices](#supported_devices)
- [Device UI](#device-ui)
@@ -29,10 +30,14 @@ into an existing CHIP network and can be controlled by this network.
- [Using Docker container for setup](#using-docker-container-for-setup)
- [Using native shell for setup](#using-native-shell-for-setup)
- [Building](#building)
+ - [Removing build artifacts](#removing-build-artifacts)
+ - [Building with release configuration](#building-with-release-configuration)
+ - [Building with Device Firmware Upgrade support](#building-with-device-firmware-upgrade-support)
- [Configuring the example](#configuring-the-example)
- [Flashing and debugging](#flashing-and-debugging)
- [Testing the example](#testing-the-example)
- [Testing using CHIPTool](#testing-using-chiptool)
+ - [Testing Device Firmware Upgrade](#testing-device-firmware-upgrade)
@@ -58,6 +63,9 @@ default settings by pressing button manually. However, this mode does not
guarantee that the device will be able to communicate with the CHIP controller
and other devices.
+The example can be configured to use the secure bootloader and utilize it for
+performing over-the-air Device Firmware Upgrade using Bluetooth LE.
+
### Bluetooth LE advertising
In this example, to commission the device onto a CHIP network, it must be
@@ -83,6 +91,45 @@ sending the Thread network credentials from the CHIP controller to the CHIP
device. As a result, device is able to join the Thread network and communicate
with other Thread devices in the network.
+### Device Firmware Upgrade
+
+The example allows enabling the over-the-air Device Firmware Upgrade feature. In
+this process, the device hosting new firmware image sends the image to the CHIP
+device using Bluetooth LE transport and
+[Simple Management Protocol](https://developer.nordicsemi.com/nRF_Connect_SDK/doc/latest/zephyr/guides/device_mgmt/index.html#device-mgmt).
+The
+[MCUboot](https://developer.nordicsemi.com/nRF_Connect_SDK/doc/latest/mcuboot/index.html)
+bootloader solution then replaces the old firmware image with the new one.
+
+#### Bootloader
+
+MCUboot is a secure bootloader used for swapping firmware images of different
+versions and generating proper build output files that can be used in the device
+firmware upgrade process.
+
+The bootloader solution requires an area of flash memory to swap application
+images during the firmware upgrade. The Nordic devices use an external memory
+chip for this purpose. The memory chip communicates with the microcontroller
+through the QSPI bus.
+
+See the
+[Building with Device Firmware Upgrade support](#building-with-device-firmware-upgrade-support)
+section to learn how to change MCUboot and flash configuration in this example.
+
+#### Simple Management Protocol
+
+Simple Management Protocol (SMP) is a basic transfer encoding that is used for
+device management purposes, including application image management. SMP supports
+using different transports, such as Bluetooth LE, UDP, or serial USB/UART.
+
+In this example, the CHIP device runs the SMP Server to download the application
+update image using the Bluetooth LE transport.
+
+See the
+[Building with Device Firmware Upgrade support](#building-with-device-firmware-upgrade-support)
+section to learn how to enable SMP and use it for the DFU purpose in this
+example.
+
@@ -150,7 +197,10 @@ states are possible:
initiated.
- _Pressed for less than 3 s_ — Initiates the OTA software update
- process. This feature is not currently supported.
+ process. This feature is disabled by default, but can be enabled by
+ following the
+ [Building with Device Firmware Upgrade support](#building-with-device-firmware-upgrade-support)
+ instruction.
**Button 2** — Pressing the button once changes the lock state to the
opposite one.
@@ -308,6 +358,43 @@ features like logs and command-line interface, run the following command:
Remember to replace _build-target_ with the build target name of the Nordic
Semiconductor's kit you own.
+### Building with Device Firmware Upgrade support
+
+To build the example with configuration that enables DFU, run the following
+command with _build-target_ replaced with the build target name of the Nordic
+Semiconductor's kit you own (for example `nrf52840dk_nrf52840`):
+
+> **_WARNING:_** Please do remember about replacing _build-target_ also in the
+> PM_STATIC_YML_FILE path.
+
+ $ west build -b build-target -- -DOVERLAY_CONFIG=third_party/connectedhomeip/config/nrfconnect/app/overlay-dfu_support.conf -DPM_STATIC_YML_FILE="configuration/build-target/pm_static.yml"
+
+#### Changing bootloader configuration
+
+To change the default MCUboot configuration, edit the `overlay-dfu_support.conf`
+overlay file that contains bootloader configuration options. The file is located
+in the `config/nrfconnect/app` directory. You can also define the desired
+options in your example's `prj.conf` file.
+
+Make sure to apply the same configuration changes in the
+`child_image/mcuboot.conf` file. This is necessary for the configuration to
+work, as the bootloader image is a separate application from the user
+application and it has its own configuration file. The contents of this file
+must be consistent with the application configuration.
+
+#### Changing flash memory settings
+
+In the default configuration, the MCUboot uses the
+[Partition Manager](https://developer.nordicsemi.com/nRF_Connect_SDK/doc/latest/nrf/scripts/partition_manager/partition_manager.html#partition-manager)
+to configure flash partitions used for the bootloader application image slot
+purposes. You can change these settings by defining
+[static partitions](https://developer.nordicsemi.com/nRF_Connect_SDK/doc/latest/nrf/scripts/partition_manager/partition_manager.html#ug-pm-static).
+This example uses this option to define using an external flash.
+
+To modify the flash settings of your board (that is, your _build-target_, for
+example `nrf52840dk_nrf52840`), edit the `pm_static.yml` file located in the
+`configuration/build-target/` directory.
+
@@ -364,3 +451,10 @@ Read the
to see how to use [CHIPTool](../../../src/android/CHIPTool/README.md) for
Android smartphones to commission and control the application within a
CHIP-enabled Thread network.
+
+### Testing Device Firmware Upgrade
+
+Read the section about downloading the new image to a device on the
+[FOTA upgrades](https://developer.nordicsemi.com/nRF_Connect_SDK/doc/latest/nrf/ug_nrf52.html#fota-upgrades)
+page in the nRF Connect documentation to see how to upgrade your device firmware
+over Bluetooth LE using a smartphone.
diff --git a/examples/lock-app/nrfconnect/child_image/mcuboot.conf b/examples/lock-app/nrfconnect/child_image/mcuboot.conf
new file mode 100644
index 00000000000000..7097c7c93260dd
--- /dev/null
+++ b/examples/lock-app/nrfconnect/child_image/mcuboot.conf
@@ -0,0 +1,29 @@
+#
+# Copyright (c) 2021 Project CHIP Authors
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+#
+
+# QSPI configuration
+CONFIG_NORDIC_QSPI_NOR=y
+CONFIG_NORDIC_QSPI_NOR_FLASH_LAYOUT_PAGE_SIZE=4096
+CONFIG_NORDIC_QSPI_NOR_STACK_WRITE_BUFFER_SIZE=4
+
+CONFIG_MULTITHREADING=y
+CONFIG_BOOT_MAX_IMG_SECTORS=256
+
+# External flash memory configuration
+CONFIG_PM_EXTERNAL_FLASH=y
+CONFIG_PM_EXTERNAL_FLASH_DEV_NAME="MX25R64"
+CONFIG_PM_EXTERNAL_FLASH_SIZE=0xf2000
+CONFIG_PM_EXTERNAL_FLASH_BASE=0
diff --git a/examples/lock-app/nrfconnect/configuration/nrf52840dk_nrf52840/pm_static.yml b/examples/lock-app/nrfconnect/configuration/nrf52840dk_nrf52840/pm_static.yml
new file mode 100644
index 00000000000000..b194f921be3b26
--- /dev/null
+++ b/examples/lock-app/nrfconnect/configuration/nrf52840dk_nrf52840/pm_static.yml
@@ -0,0 +1,38 @@
+mcuboot:
+ address: 0x0
+ size: 0xc000
+ region: flash_primary
+mcuboot_pad:
+ address: 0xc000
+ size: 0x200
+app:
+ address: 0xc200
+ size: 0xf1e00
+mcuboot_primary:
+ orig_span: &id001
+ - mcuboot_pad
+ - app
+ span: *id001
+ address: 0xc000
+ size: 0xf2000
+ region: flash_primary
+mcuboot_primary_app:
+ orig_span: &id002
+ - app
+ span: *id002
+ address: 0xc200
+ size: 0xf1e00
+settings_storage:
+ address: 0xfe000
+ size: 0x2000
+ region: flash_primary
+mcuboot_secondary:
+ address: 0x0
+ size: 0xf2000
+ device: MX25R64
+ region: external_flash
+external_flash:
+ address: 0xf2000
+ size: 0x0
+ device: MX25R64
+ region: external_flash
diff --git a/examples/lock-app/nrfconnect/main/AppTask.cpp b/examples/lock-app/nrfconnect/main/AppTask.cpp
index b043e088bf15c2..bc4dc067d079dd 100644
--- a/examples/lock-app/nrfconnect/main/AppTask.cpp
+++ b/examples/lock-app/nrfconnect/main/AppTask.cpp
@@ -32,6 +32,20 @@
#include
+// MCUMgr BT FOTA includes
+#ifdef CONFIG_MCUMGR_CMD_OS_MGMT
+#include "os_mgmt/os_mgmt.h"
+#endif
+#ifdef CONFIG_MCUMGR_CMD_IMG_MGMT
+#include "img_mgmt/img_mgmt.h"
+#endif
+#ifdef CONFIG_MCUMGR_SMP_BT
+#include
+#endif
+#ifdef CONFIG_BOOTLOADER_MCUBOOT
+#include
+#endif
+
#include
#include
#include
@@ -87,6 +101,22 @@ int AppTask::Init()
k_timer_init(&sFunctionTimer, &AppTask::TimerEventHandler, nullptr);
k_timer_user_data_set(&sFunctionTimer, this);
+#ifdef CONFIG_BOOTLOADER_MCUBOOT
+ // Check if the image is run in the REVERT mode and eventually
+ // confirm it to prevent reverting on the next boot.
+ if (mcuboot_swap_type() == BOOT_SWAP_TYPE_REVERT)
+ {
+ if (boot_write_img_confirmed())
+ {
+ LOG_ERR("Confirming firmware image failed, it will be reverted on the next boot.");
+ }
+ else
+ {
+ LOG_INF("New firmware image confirmed.");
+ }
+ }
+#endif
+
BoltLockMgr().Init();
BoltLockMgr().SetCallbacks(ActionInitiated, ActionCompleted);
@@ -287,6 +317,14 @@ void AppTask::FunctionTimerEventHandler(AppEvent * aEvent)
}
}
+int AppTask::SoftwareUpdateConfirmationHandler(uint32_t offset, uint32_t size, void * arg)
+{
+ // For now just print update progress and confirm data chunk without any additional checks.
+ LOG_INF("Software update progress %d B / %d B", offset, size);
+
+ return 0;
+}
+
void AppTask::FunctionHandler(AppEvent * aEvent)
{
if (aEvent->ButtonEvent.PinNo != FUNCTION_BUTTON)
@@ -313,7 +351,26 @@ void AppTask::FunctionHandler(AppEvent * aEvent)
{
sAppTask.CancelTimer();
sAppTask.mFunction = kFunction_NoneSelected;
- LOG_INF("Software update is not implemented");
+
+#if defined(CONFIG_MCUMGR_SMP_BT) && defined(CONFIG_MCUMGR_CMD_IMG_MGMT) && defined(CONFIG_MCUMGR_CMD_OS_MGMT)
+ if (!sAppTask.mSoftwareUpdateEnabled)
+ {
+ sAppTask.mSoftwareUpdateEnabled = true;
+ os_mgmt_register_group();
+ img_mgmt_register_group();
+ img_mgmt_set_upload_cb(SoftwareUpdateConfirmationHandler, NULL);
+ smp_bt_register();
+
+ LOG_INF("Enabled software update");
+ }
+ else
+ {
+ LOG_INF("Software update is already enabled");
+ }
+
+#else
+ LOG_INF("Software update is disabled");
+#endif
}
else if (sAppTask.mFunctionTimerActive && sAppTask.mFunction == kFunction_FactoryReset)
{
diff --git a/examples/lock-app/nrfconnect/main/include/AppTask.h b/examples/lock-app/nrfconnect/main/include/AppTask.h
index 507bce09f0b281..83c25665bbf7fa 100644
--- a/examples/lock-app/nrfconnect/main/include/AppTask.h
+++ b/examples/lock-app/nrfconnect/main/include/AppTask.h
@@ -58,6 +58,8 @@ class AppTask
static void ButtonEventHandler(uint32_t buttons_state, uint32_t has_changed);
static void TimerEventHandler(k_timer * timer);
+ static int SoftwareUpdateConfirmationHandler(uint32_t offset, uint32_t size, void * arg);
+
void StartTimer(uint32_t aTimeoutInMs);
enum Function_t
@@ -69,8 +71,9 @@ class AppTask
kFunction_Invalid
};
- Function_t mFunction;
- bool mFunctionTimerActive;
+ Function_t mFunction = kFunction_NoneSelected;
+ bool mFunctionTimerActive = false;
+ bool mSoftwareUpdateEnabled = false;
static AppTask sAppTask;
};