Skip to content

Commit

Permalink
[nrfconnect] Added support for DFU in light and lock examples. (#6575)
Browse files Browse the repository at this point in the history
* Added overlay enabling:
	* MCUboot bootloader
	* Use of external flash
	* SMP transactions over BLE that allows performing DFU
* MCUboot and flash partitions configuration files for nRF52840DK
* Extended documentation by desrciption how to perform DFU
  • Loading branch information
kkasperczyk-no authored and pull[bot] committed Jul 13, 2021
1 parent 17ebe03 commit 8221580
Show file tree
Hide file tree
Showing 11 changed files with 488 additions and 8 deletions.
40 changes: 40 additions & 0 deletions config/nrfconnect/app/overlay-dfu_support.conf
Original file line number Diff line number Diff line change
@@ -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
94 changes: 93 additions & 1 deletion examples/lighting-app/nrfconnect/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -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)
Expand All @@ -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)

<hr>

Expand All @@ -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
Expand All @@ -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.

<hr>

<a name="requirements"></a>
Expand Down Expand Up @@ -150,7 +195,10 @@ following states are possible:
initiated.

- _Pressed for less than 3 s_ &mdash; 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** &mdash; Pressing the button once changes the lighting state to the
opposite one.
Expand Down Expand Up @@ -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.

<hr>

<a name="configuring"></a>
Expand Down Expand Up @@ -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.
29 changes: 29 additions & 0 deletions examples/lighting-app/nrfconnect/child_image/mcuboot.conf
Original file line number Diff line number Diff line change
@@ -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
Original file line number Diff line number Diff line change
@@ -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
59 changes: 58 additions & 1 deletion examples/lighting-app/nrfconnect/main/AppTask.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -37,6 +37,20 @@
#include <support/ErrorStr.h>
#include <system/SystemClock.h>

// 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 <mgmt/mcumgr/smp_bt.h>
#endif
#ifdef CONFIG_BOOTLOADER_MCUBOOT
#include <dfu/mcuboot.h>
#endif

#include <dk_buttons_and_leds.h>
#include <logging/log.h>
#include <zephyr.h>
Expand Down Expand Up @@ -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;
Expand Down Expand Up @@ -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)
Expand All @@ -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)
{
Expand Down
7 changes: 5 additions & 2 deletions examples/lighting-app/nrfconnect/main/include/AppTask.h
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand All @@ -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;
};

Expand Down
Loading

0 comments on commit 8221580

Please sign in to comment.