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; };