nRF5340: SMP Server with external XIP

This sample demonstrates how to split an application that partially resides on internal flash and Quad Serial Peripheral Interface (QSPI) flash by using Execute in place (XIP) and the Simple Management Protocol (SMP) server.

Requirements

The sample supports the following development kits:

Hardware platforms

PCA

Board name

Board target

Thingy:53

PCA20053

thingy53

thingy53/nrf5340/cpuapp

nRF5340 DK

PCA10095

nrf5340dk

nrf5340dk/nrf5340/cpuapp

The sample requires a connection to a computer with mcumgr command-line tool’s or a compatible MCUmgr client tool.

Overview

SMP is a basic transfer protocol used by the MCUmgr management library. This sample shows how to divide an application into internal and external parts using the SMP server. The internal part operates from the SoC’s built-in storage, and the external part runs directly from external memory, using the XIP capability through a QSPI peripheral.

For more information about MCUmgr and SMP, see Device Management.

The sample enables the splitting by:

  • Enabling the split XIP image feature through the CONFIG_XIP_SPLIT_IMAGE Kconfig option. This Kconfig option sets a build-system level support for image division and adapts the image-signing support for MCUboot.

  • Using the project’s CMake file which describes relocation of certain libraries or objects to an external XIP area.

  • Using a linker script that describes the external QSPI area. (The execution code from the external memory should link to it.)

  • Using the static partition manager description for appropriate memory mapping.

For details on SMP features implemented by the sample, see the Zephyr SMP server documentation.

Building and running

This sample can be found under samples/nrf5340/extxip_smp_svr in the nRF Connect SDK folder structure.

To build the sample, follow the instructions in Building an application for your preferred building environment. See also Programming an application for programming steps and Testing and optimization for general information about testing and debugging in the nRF Connect SDK.

Note

When building repository applications in the SDK repositories, building with sysbuild is enabled by default. If you work with out-of-tree freestanding applications, you need to manually pass the --sysbuild parameter to every build command or configure west to always use it.

west build -b board_target

The nRF Connect SDK build system generates all essential binaries, including the application for internal and external QSPI flash, the networking stack, and MCUboot. The build process involves signing all the application binaries except for MCUboot which does not require signing in this configuration.

To upload MCUboot and a bundle of images to the nRF5340 SoC, use the west flash command.

Testing

The smp_svr app is now ready to run. Reset your board and test the app with the mcumgr command-line tool’s echo functionality. This will send a string to the remote target device and have it echo it back:

sudo mcumgr --conntype ble --connstring ctlr_name=hci0,peer_name='Zephyr' echo hello
hello

Note

The mcumgr command-line tool requires a connection string in order to identify the remote target device. The Bluetooth version of the sample uses a Bluetooth LE-based connection string. You might need to modify it depending on the Bluetooth LE controller you are using.

In the following sections, <connection string> is used to represent the --conntype <type> and --connstring=<string> mcumgr parameters.

Upload and map image to MCUboot slot

For this sample configuration, MCUmgr supports the uploading of three target images, which allows you to update all parts of the firmware.

The MCUmgr image upload command has the optional -e -n <image> parameter, which lets you select the target image for upload. When this parameter is not provided, 0 is assumed (interpreted as the default behavior), and MCUmgr uploads to image-1 (MCUboot’s secondary slot).

See the Partition manager (PM) label for slot-to-<image> translation:

PM label

Slot

-n <image>

Firmware part

mcuboot_secondary

slot-1

0

Internal application part

mcuboot_secondary_1

slot-3

1

Networking

mcuboot_secondary_2

slot-5

2

QSPI application part

Note

The -e option means “no erase”, and is provided to the MCUmgr to prevent it from sending the erase command to the target before updating the image. This option is always needed when -n is used for image selection, as the erase command is hardcoded to erase slot-1 (image-1), regardless of which slot is uploaded at the time.

Upload the signed image

To upload the signed image, run the following command:

sudo mcumgr <connection string> image upload build/zephyr/<signed_upload.bin> -e -n <image>

Adjust the command depending on the case:

  • Use the internal_flash_update.bin file and <image> = 0 to update the internal application image.

  • Use the net_core_app_update.bin file and <image> = 1 to update the networking core image.

  • Use the qspi_flash_update.bin file and <image> = 2 to update the QSPI application image.

Note

The <image> values correspond to the internally (0) and externally (2) linked parts of the application. These two images are linked and must always be uploaded together.

Test the image

To initiate the image swap with MCUboot, first you must test the image by obtaining its SHA with the following command:

imgtool verify build/zephyr/<signed_upload.bin>

Ensure it boots using the image digest fetched by running the following command:

sudo mcumgr <connection string> image test <hash of image>

The selected mode in this test case must be applied to all images that constitute the complete application. Once applied, MCUboot will swap these images during the next reset.

Note

The sample supports the MCUboot overwrite-only mode. This means that regardless of how the image is marked for the update (either as test or confirm), the process is not affected. The old image is still overwritten by the content of the incoming image during the firmware update process.

Reset remotely

To check how MCUboot has upgraded the images, you can reset the device remotely by running the following command:

sudo mcumgr <connection string> reset

Dependencies

The sample uses the following Zephyr library:

It also uses the following nRF Connect SDK library: