Skip to content

Commit

Permalink
doc: suit: Push scenario and DFU caches documentation
Browse files Browse the repository at this point in the history
Added documentation for SUIT DFU cache partitions
and how to use them to push detached payloads for DFU
to the device.

Signed-off-by: Artur Hadasz <artur.hadasz@nordicsemi.no>
  • Loading branch information
ahasztag committed Oct 11, 2024
1 parent ffebf6f commit 30466ea
Show file tree
Hide file tree
Showing 5 changed files with 237 additions and 28 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,7 @@ For a list of available SUIT samples, see the :ref:`suit_samples` page.
ug_nrf54h20_suit_customize_qsg.rst
ug_nrf54h20_suit_customize_dfu.rst
ug_nrf54h20_suit_fetch
ug_nrf54h20_suit_push
ug_nrf54h20_suit_external_memory
ug_nrf54h20_suit_components
ug_nrf54h20_suit_hierarchical_manifests
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -12,8 +12,8 @@ However, the application domain can implement an IPC service, which allows the S
This guide explains how to prepare the application domain firmware and the SUIT envelope to perform SUIT firmware upgrade using external memory.

.. note::
The prerequisite to this guide is the :ref:`ug_nrf54h20_suit_fetch` user guide, as this guide assumes that the application uses the fetch model to obtain the candidate images.
See the :ref:`ug_nrf54h20_suit_fetch` for more details on how to migrate from push to fetch model.
To use external memory with SUIT, you can either use the push model-based or the fetch model-based firmware upgrade.
See :ref:`ug_nrf54h20_suit_push` for details about the push model and :ref:`ug_nrf54h20_suit_fetch` for details on how to migrate from the push to fetch model.

The following terms are used in this guide:

Expand All @@ -25,12 +25,10 @@ The following terms are used in this guide:
Overview of external memory in SUIT firmware updates
****************************************************

To use external memory with SUIT, the fetch model-based firmware upgrade is required.
The SUIT envelope must always be stored in the non-volatile memory in the MCU.
The SUIT manifests stored in the envelope contain instructions that the device must perform to fetch other required payloads.
To store payloads in the external memory, a Device Firmware Update (DFU) cache partition must be defined in the external memory's devicetree node.
In the SUIT manifest, you can define a component representing the cache partition in the external memory.
Within the ``suit-payload-fetch`` sequence, you can then store fetched payload(s) into a ``CACHE_POOL`` component.
The push model-based update and the fetch model-based update differ in the way the cache partition is filled with the images.

When the Secure Domain processes the ``suit-install`` sequence, issuing ``suit-directive-fetch`` on any non-integrated payload will instruct the Secure Domain firmware to search for a given URI in all cache partitions in the system.
However, when such a cache partition is located in the external memory, the Secure Domain is unable to access the data directly.
Expand All @@ -43,13 +41,54 @@ The companion image consists of two main parts:
* IPC service exposed towards the Secure Domain

When the companion image is booted and a directive that accesses the data on the external memory is issued, such as the ``suit-directive-fetch`` or ``suit-directive-copy`` directives, the Secure Domain firmware uses the IPC service provided by the companion image to access the contents of the external memory.
Beyond the booting of the companion image, the update process does not differ from regular fetch model-based update.
Apart from booting the companion image, the update process does not differ from regular push model-based or fetch model-based updates.

Difference between push and fetch models
========================================

Push model
----------

In the push model, the cache partition contents are created on the building machine and pushed to the device without modifications.
The images are extracted to the cache partition files using the :kconfig:option:`CONFIG_SUIT_DFU_CACHE_EXTRACT_IMAGE` Kconfig option.

No additional sequences are required in the SUIT manifest.

For more details, see :ref:`ug_nrf54h20_suit_push`.

Fetch model
-----------

In the fetch model, the SUIT processor runs on the application core.

In the SUIT manifest, you can define a component that represents the cache partition in the external memory.
Within the ``suit-payload-fetch`` sequence, you can then store fetched payloads into a ``CACHE_POOL`` component.
The device then pulls the images from external sources and manages their storage in the cache partitions.

For more details, see :ref:`ug_nrf54h20_suit_fetch`.

Enabling external flash support in SUIT DFU
*******************************************

The :ref:`nrf54h_suit_sample` sample contains a premade configuration enabling the external memory in SUIT DFU.
To enable the external memory, you must add the ``-DFILE_SUFFIX="extflash"`` argument to the build, or complete the following steps:
The :ref:`nrf54h_suit_sample` sample contains several example configurations that enable the external memory for SUIT DFU.

The configurations using the push model are the following:

* ``sample.suit.smp_transfer.cache_push.extflash``
* ``sample.suit.smp_transfer.cache_push.extflash.bt``

The configurations using the fetch model are following:

* ``sample.suit.smp_transfer.full_processing.extflash``
* ``sample.suit.smp_transfer.full_processing.extflash.bt``

You can find these configurations defined in the :file:`samples/suit/smp_transfer/sample.yaml` file.
This file specifies which options need to be enabled.

Alternatively, you can follow the following steps to manually enable external memory in SUIT DFU.

Common steps for both push and fetch models
===========================================

1. Turn on the external flash chip on the nRF54H20 DK using the `nRF Connect Board Configurator`_ app within `nRF Connect for Desktop`_ .

Expand All @@ -59,8 +98,6 @@ To enable the external memory, you must add the ``-DFILE_SUFFIX="extflash"`` arg
#. Enable the ``SB_CONFIG_SUIT_BUILD_FLASH_COMPANION`` sysbuild Kconfig option, which enables the build of the reference companion image.
See the :ref:`suit_flash_companion` user guide for instructions on how to configure the companion image using sysbuild.

#. Enable the :kconfig:option:`CONFIG_SUIT_STREAM_SOURCE_FLASH` Kconfig option, which enables SUIT processor on the application core to read and parse DFU cache partitions.

#. Define a new DFU cache partition in the external memory in the DTS file:

.. code-block:: devicetree
Expand All @@ -86,18 +123,7 @@ To enable the external memory, you must add the ``-DFILE_SUFFIX="extflash"`` arg

#. Modify the application manifest file :file:`app_envelope.yaml.jinja2` by completing the following steps:

a. Modify the ``CACHE_POOL`` identifier in the SUIT manifest:

.. code-block:: yaml
suit-components:
...
- - CACHE_POOL
- 1
The ``CACHE_POOL`` identifier must match the identifier of the cache partition defined in the DTS file.

#. Append the ``MEM`` type component that represents the companion image in the same SUIT manifest file:
a. Append the ``MEM`` type component that represents the companion image in the same SUIT manifest file:

.. code-block:: yaml
Expand All @@ -111,7 +137,7 @@ To enable the external memory, you must add the ``-DFILE_SUFFIX="extflash"`` arg
In this example, the component index is ``3``.
In the following steps, the companion image component is selected with ``suit-directive-set-component-index: 3``.

#. Modify the ``suit-install`` sequence to boot the companion image before accessing the candidate images, which are stored in the external memory:
#. Modify the ``suit-install`` sequence in the application manifest file (:file:`app_envelope.yaml.jinja2`) to boot the companion image before accessing the candidate images stored in the external memory:

.. code-block:: yaml
Expand All @@ -122,12 +148,63 @@ To enable the external memory, you must add the ``-DFILE_SUFFIX="extflash"`` arg
The companion image can be optionally upgraded and have its integrity checked.

#. |open_terminal_window_with_environment|
Steps specific for the push model
=================================

1. Enable the :kconfig:option:`CONFIG_SUIT_DFU_CANDIDATE_PROCESSING_PUSH_TO_CACHE` option to allow the application core to modify cache partitions.

#. Enable the :kconfig:option:`CONFIG_SUIT_DFU_CACHE_EXTRACT_IMAGE` Kconfig option for every image that needs to be updated from external memory.

#. Modify the manifest files for all domains by completing the following steps:

a. Ensure that the URI used by the ``suit-payload-fetch`` sequence to fetch a given image matches the :kconfig:option:`CONFIG_SUIT_DFU_CACHE_EXTRACT_IMAGE_URI` Kconfig option.

#. Ensure that the envelope integrates the specified image within the envelope integrated payloads section.
This is ensured by default if you use the provided SUIT envelope templates.

Steps specific for the fetch model
==================================

1. Enable the :kconfig:option:`CONFIG_SUIT_DFU_CANDIDATE_PROCESSING_FULL` Kconfig option to allow the application core to process SUIT manifests.

#. Enable the :kconfig:option:`CONFIG_SUIT_STREAM_SOURCE_FLASH` Kconfig option, which allows the SUIT processor on the application core to read and parse DFU cache partitions.

#. Modify the application manifest file :file:`app_envelope.yaml.jinja2` by completing the following steps:

a. Modify the ``CACHE_POOL`` identifier in the SUIT manifest:

.. code-block:: yaml
suit-components:
...
- - CACHE_POOL
- 1
The ``CACHE_POOL`` identifier must match the identifier of the cache partition defined in the DTS file.

#. Add the ``suit-payload-fetch`` sequence:

.. code-block:: yaml
suit-payload-fetch:
- suit-directive-set-component-index: 2
- suit-directive-override-parameters:
suit-parameter-uri: 'file://{{ app['binary'] }}'
- suit-directive-fetch:
- suit-send-record-failure
This snippet assumes that ``CACHE_POOL`` is the third component on the manifest's components list (so its component index is 2)

Testing the application with external flash support
===================================================

1. |open_terminal_window_with_environment|

#. Build and flash the application by completing the following commands:

.. code-block:: console
west build -b nrf54h20dk/nrf54h20/cpuapp
west build ./ -b nrf54h20dk/nrf54h20/cpuapp -T <configuration_name>
west flash
The build system will automatically use :ref:`configuration_system_overview_sysbuild` and generate a :file:`build/zephyr/dfu_suit.zip` archive, which contains the SUIT envelope and candidate images.
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,108 @@
.. _ug_nrf54h20_suit_push:

How to push SUIT payloads to multiple partitions
################################################

.. contents::
:local:
:depth: 2

In the Software Updates for Internet of Things (SUIT), you can push certain payloads separately from the SUIT envelope.
The envelope can find them in the device and use them as part of the firmware upgrade process.

In Nordic Semiconductor's implementation, this functionality is provided by a mechanism called *DFU cache partitions*.

This guide explains how DFU cache partitions work, and how to configure the build system and SUIT manifests to use them for pushing detached payloads.


Reasons to push images separately from the SUIT envelope
********************************************************

Pushing images separately from the SUIT envelope can be useful in the following scenarios:

* Pushing parts of an image to external memory.
* Storing portions of the update package in non-contiguous memory areas, separated by other data.
* Reducing the amount of data that needs to be resent after a communication failure, allowing the update to continue.
* Sending different parts of the image through multiple communication channels.

DFU Cache Partitions
********************

The payloads pushed to the device must be placed in so called “DFU cache partitions”, numbered 0..n.
The DFU cache partitions hold data using a CBOR map format, where the keys are URI strings and the values are binary images.

When the Secure Domain processes the manifest and encounters a ``suit-directive-fetch`` directive it first checks if a given URI is present in its ``suit-integrated-payloads`` section.
If it is not, it goes through all the DFU cache partitions defined in the device.
If the given URI is found as a map key, the binary data stored in the value field corresponding to that URI is fetched.

The DFU cache partition 0 is always present in the device.
It takes all of the remaining space from the ``dfu_partition`` that is not occupied by the envelope.
This partition has a limitation:
it can only be used after storing the SUIT envelope.

The DFU cache partitions from ``1`` to ``n`` are defined in the devicetree, by using the ``dfu_cache_partition_x`` node name, where x is the partition number.
The partitions can be placed both in the internal MRAM as well as in the external flash.

Extracting images
*****************

The :ref:`nrf54h_suit_sample` sample uses the SMP protocol for uploading new envelopes and is by default configured to use the push model for firmware upgrades.
To reconfigure the sample to allow for pushing images into DFU cache partitions, complete the following steps:

1. Enable the :kconfig:option:`CONFIG_SUIT_DFU_CANDIDATE_PROCESSING_PUSH_TO_CACHE` Kconfig option.
This enables the writing to the DFU cache partitions.
Alternatively, you can enable the :kconfig:option:`CONFIG_SUIT_DFU_CANDIDATE_PROCESSING_FULL` option to enable the SUIT envelope processing in the application firmware.
This will enable a superset of options enabled by :kconfig:option:`CONFIG_SUIT_DFU_CANDIDATE_PROCESSING_PUSH_TO_CACHE`, but will occupy more space in both MRAM and RAM memories.

#. If you intend to use any other cache partition than 0, add the DFU cache partition in the appropriate memory area in the device tree overlay:

.. code-block:: dts
dfu_cache_partition_N: partition@a000 {
reg = <0xa000 DT_SIZE_K(1024)>;
};

Replace ``N`` with the partition number, ``a000`` with the proper offset inside the memory area, and ``1024`` with the proper size of the cache partition.

For example, you could add the cache partition 1 with the size of 1024 kilobytes in the external flash at an offset of 0 by adding:

.. code-block:: dts
&mx25uw63 {
status = "okay";
partitions {
compatible = "fixed-partitions";
#address-cells = <1>;
#size-cells = <1>;
dfu_cache_partition_1: partition@0 {
reg = <0x0 DT_SIZE_K(1024)>;
};
};
};
#. For each image that you want to push separately to the device, do the following:

* Enable the :kconfig:option:`CONFIG_SUIT_DFU_CACHE_EXTRACT_IMAGE` Kconfig option.
* Optionally, modify :kconfig:option:`CONFIG_SUIT_DFU_CACHE_EXTRACT_IMAGE_PARTITION` to select the partition where the image will be pushed (default is partition 1).
* Optionally, modify the :kconfig:option:`CONFIG_SUIT_DFU_CACHE_EXTRACT_IMAGE_URI` to modify the URI used as key for the given image in the DFU cache.

#. Ensure that the URI used by the ``suit-payload-fetch`` sequence to fetch a given image matches the :kconfig:option:`CONFIG_SUIT_DFU_CACHE_EXTRACT_IMAGE_URI` Kconfig option.
This is done by default when using the manifest templates provided by Nordic Semiconductor.
For the application image URI, you can do that as follows (assuming the target name ``application`` for the image):

.. code-block:: yaml
- suit-directive-override-parameters:
suit-parameter-uri: '{{ application['config']['CONFIG_SUIT_DFU_CACHE_EXTRACT_IMAGE_URI'] }}'
- suit-directive-fetch:
- suit-send-record-failure
#. Ensure that the envelope does not integrate the given image inside the envelope integrated payloads section.
This is ensured by default when using the provided default SUIT envelope templates.


Pushing the images to device
****************************

See the :ref:`SUIT SMP Sample documentation <nrf54h_suit_sample>` for an example of how to push an image to a device.
Original file line number Diff line number Diff line change
Expand Up @@ -1110,6 +1110,7 @@ Documentation
* The :ref:`peripheral_sensor_node_shield` page.
* The :ref:`dfu_tools_mcumgr_cli` page after it was removed from the Zephyr repository.
* The :ref:`ug_nrf54h20_suit_soc_binaries` page.
* The :ref:`ug_nrf54h20_suit_push` page documentating the SUIT push model-based update process.

* Restructured the :ref:`app_bootloaders` documentation and combined the DFU and bootloader articles.
Additionally, created a new bootloader :ref:`bootloader_quick_start`.
Expand Down
28 changes: 25 additions & 3 deletions samples/suit/smp_transfer/README.rst
Original file line number Diff line number Diff line change
Expand Up @@ -107,22 +107,30 @@ See :ref:`app_build_output_files_suit_dfu` for a full table of SUIT-generated ou
If you want to make modifications to how the DFU is executed in this sample, you can do so by editing the manifest templates, or generating your own custom manifests.
See the :ref:`ug_nrf54h20_suit_customize_dfu` user guide for instructions and examples.

.. _nrf54h_suit_sample_extflash:

External flash support
======================

You can enable the external flash support by setting the following ``FILE_SUFFIX=extflash`` parameter:
You can build the application with external flash support by running the following command from the sample directory:

.. code-block:: console
west build -p -b nrf54h20dk/nrf54h20/cpuapp -- -DFILE_SUFFIX="extflash"
west build ./ -b nrf54h20dk/nrf54h20/cpuapp -T sample.suit.smp_transfer.cache_push.extflash
With this configuration, the sample is configured to use UART as the transport and the external flash is enabled.
To see which Kconfig options are needed to achieve that, see the ``sample.suit.smp_transfer.cache_push.extflash`` configuration in the :file:`samples/suit/sample.yaml` file.

To enable both the external flash and the BLE transport, use the following command:

.. code-block:: console
west build -p -b nrf54h20dk/nrf54h20/cpuapp -- -DFILE_SUFFIX="extflash" -DOVERLAY_CONFIG="sysbuild/smp_transfer_bt.conf" -DSB_OVERLAY_CONFIG="sysbuild_bt.conf"
west build ./ -b nrf54h20dk/nrf54h20/cpuapp -T sample.suit.smp_transfer.cache_push.extflash.bt
.. note::
This way of building the application will enable the push scenario for updating from external flash.
It will also extract the image to a DFU cache partition file.
For more information, see :ref:`How to push SUIT payloads to multiple partitions <ug_nrf54h20_suit_push>`.

Building and running
********************
Expand Down Expand Up @@ -313,6 +321,20 @@ After programming the sample to your development kit and updating the sequence n
197.40 KiB / 244.57 KiB [==============================================================================================================================>------------------------------] 80.71% 20.51 KiB/s 00m02s
241.16 KiB / 244.57 KiB [=================================================================================================================================================================>--] 98.60% 20.74 KiB/s
Done
#. If you have built the application with :ref:`external flash support <nrf54h_suit_sample_extflash>`, upload the cache partition to the external flash using the following command:

.. code-block:: console
mcumgr --conntype serial --connstring "dev=/dev/ttyACM0,baud=115200" image upload -n 2 build/DFU/dfu_cache_partition_1.bin
.. note::
the ``-n 2`` parameter uploads to DFU cache partition 1 (where image 0 is the envelope and image 1 is the cache partition 0).
#. Start the installation of the new firmware as follows:

.. code-block:: console
mcumgr --conntype serial --connstring "dev=/dev/ttyACM0,baud=115200" image confirm
#. Read the version and digest of the uploaded root manifest with MCUmgr:

Expand Down

0 comments on commit 30466ea

Please sign in to comment.