DFU target

The DFU target library provides an API that supports different types of firmware upgrades against a single interface.

Overview

The DFU target library collects sequentially the image data received from a transport protocol. It then saves the data using buffered writes, resulting in fewer write operations and faster response times seen by the application. The library also takes away, from the application, the responsibility of calculating the data-chunk write offset.

Common application flow

Each of the supported upgrade types follow the common DFU flow.

  1. Initialize the specific DFU target by calling the dfu_target_init() function.

    Internally, it uses the image type and image number to decide which target to initialize.

  2. Ask the offset of already downloaded blocks by calling the dfu_target_offset_get() function.

    This step is optional, but it allows the application to skip the blocks that are already downloaded. All targets do not necessarily support it.

  3. Write a block of DFU image into the target by calling the dfu_target_write() function.

    Repeat until all blocks have been downloaded.

  4. When all downloads have completed, call the dfu_target_done() function to tell the DFU library that the process has completed.

  5. When the application is ready to install the image, call the dfu_target_schedule_update() function to mark it as ready for update.

    Some targets perform the installation automatically on next boot.

To cancel an ongoing operation, call the dfu_target_reset() function. This clears up any images that have already been downloaded or even marked to be updated. This is different than aborting a download by calling the dfu_target_done() function, in which case the same download can be resumed later by initializing the same target.

Supported upgrade types

The DFU target library supports the following types of firmware upgrades:

  • MCUboot-style upgrades

  • Modem delta upgrades

  • Full modem firmware upgrades

MCUboot-style upgrades

You can use MCUboot-style firmware upgrades for updates to the application and to the upgradable bootloader. This type of DFU writes the data given to the dfu_target_write() function into the secondary slot specified by MCUboot’s flash memory partitions. Depending on the type of upgrade, it has the following behavior:

  • For application updates, the new image replaces the existing application.

  • For bootloader updates, the new firmware is placed in the non-active partition (slot 0 or slot 1, see Second-stage Upgradable bootloader).

The MCUboot target type supports multiple image pairs, like the application core image pair and the network core image pair, to support multi-image updates where the device contains two or more executable images at once.

Note

When updating the bootloader, ensure that the provided bootloader firmware is linked against the correct partition. This is handled automatically by the FOTA download library.

When the image data transfer is completed, the application using the DFU target library must do the following:

  1. Call the dfu_target_done() function to finish the image data collection.

  2. Call the dfu_target_schedule_update() function to mark the firmware as ready to be booted. On the next reboot, the device will run with the new firmware.

After that, the application can call the dfu_target_init() function for another image pair index.

Note

The application can schedule the upgrade of all the image pairs at once using the dfu_target_schedule_update() function.

Modem delta upgrades

This type of firmware upgrade is used for delta upgrades to the modem firmware (see: Delta firmware updates). The modem stores the data in the memory location reserved for firmware patches. If there is already a firmware patch stored in the modem, the library requests the modem to delete the old firmware patch to make space for the new patch.

When the transfer has completed, the application must call the dfu_target_done() function to release modem resources and then call dfu_target_schedule_update() to request the modem to apply the patch. On the next reboot, the modem tries to apply the patch.

If an existing image needs to be removed, even if it is marked to be updated, the application may call the dfu_target_reset() function, which erases the DFU area and prepares it for next download.

Full modem upgrades

Note

An external flash memory with minimum 4 MB is required for this type of upgrade.

This type of firmware upgrade supports updating the modem firmware using the serialized firmware bundled in the zip file of the modem firmware release. The serialized firmware file uses the .cbor extension.

This DFU target downloads the serialized modem firmware to an external flash memory. Once the modem firmware has been downloaded, the application should use Full modem firmware update from flash device to write the firmware to the modem. The DFU target library does not perform the upgrade and calling the dfu_target_schedule_update() function has no effect.

Configuration

Configuring the library requires making edits to your component and using Kconfig options.

Enabling the library

Every supported DFU target must implement the set of functions defined in subsys/dfu/src/dfu_target.c.

When initializing the DFU target library, you must provide information about the type of firmware upgrade. To do so automatically, send the first fragment of the firmware to the function dfu_target_img_type(). This function can identify all supported firmware upgrade types. The result of this call can then be given as input to the dfu_target_init() function.

Note

After starting a DFU procedure for a given target, you cannot initialize a new DFU procedure with a different firmware file for the same target until the pending DFU procedure has completed successfully or the device has been restarted.

Disabling support for specific DFU targets

You can disable support for specific DFU targets using the following options:

Maintaining writing progress after reboot

You can let the application maintain the writing progress in case the device reboots. To do so, enable the following options:

The MCUboot target will then use the Settings subsystem in Zephyr to store the current progress used by the dfu_target_write() function across power failures and device resets.

API documentation

Header file: include/dfu/dfu_target.h
Source files: subsys/dfu/dfu_target/src/
group dfu_target

DFU Target.

Typedefs

typedef void (*dfu_target_callback_t)(enum dfu_target_evt_id evt_id)

Enums

enum dfu_target_image_type

DFU image type.

Bitmasks of different image types.

Values:

enumerator DFU_TARGET_IMAGE_TYPE_NONE

Not a DFU image

enumerator DFU_TARGET_IMAGE_TYPE_MCUBOOT

Application image in MCUBoot format

enumerator DFU_TARGET_IMAGE_TYPE_MODEM_DELTA

Modem delta-update image

enumerator DFU_TARGET_IMAGE_TYPE_FULL_MODEM

Full update image for modem

enumerator DFU_TARGET_IMAGE_TYPE_ANY_APPLICATION

Any application image type

enumerator DFU_TARGET_IMAGE_TYPE_ANY_MODEM

Any modem image

enumerator DFU_TARGET_IMAGE_TYPE_ANY

Any DFU image type

enum dfu_target_evt_id

Values:

enumerator DFU_TARGET_EVT_TIMEOUT
enumerator DFU_TARGET_EVT_ERASE_DONE

Functions

enum dfu_target_image_type dfu_target_img_type(const void *const buf, size_t len)

Find the image type for the buffer of bytes received. Used to determine what DFU target to initialize.

Parameters
  • buf[in] A buffer of bytes which are the start of a binary firmware image.

  • len[in] The length of the provided buffer.

Returns

Identifier for a supported image type or DFU_TARGET_IMAGE_TYPE_NONE if image type is not regognized.

int dfu_target_init(int img_type, int img_num, size_t file_size, dfu_target_callback_t cb)

Initialize the resources needed for the specific image type DFU target.

If a target update is in progress, and the same target is given as input, then calling the ‘init()’ function of that target is skipped.

To allow continuation of an aborted DFU procedure, call the ‘dfu_target_offset_get’ function after invoking this function.

Parameters
  • img_type[in] Image type identifier.

  • img_num[in] Image pair index. Value different than 0 are supported only for DFU_TARGET_IMAGE_TYPE_MCUBOOT image type currently.

  • file_size[in] Size of the current file being downloaded.

  • cb[in] Callback function in case the DFU operation requires additional procedures to be called.

Returns

0 for a supported image type or a negative error code indicating reason of failure.

int dfu_target_offset_get(size_t *offset)

Get offset of the firmware upgrade.

Parameters
  • offset[out] Returns the offset of the firmware upgrade.

Returns

0 if success, otherwise negative value if unable to get the offset

int dfu_target_write(const void *const buf, size_t len)

Write the given buffer to the initialized DFU target.

Parameters
  • buf[in] A buffer of bytes which contains part of an binary firmware image.

  • len[in] The length of the provided buffer.

Returns

Positive identifier for a supported image type or a negative error code indicating reason of failure.

int dfu_target_done(bool successful)

Release the resources that were needed for the current DFU target.

Parameters
  • successful[in] Indicate whether the process completed successfully or was aborted.

Returns

0 for a successful deinitialization or a negative error code indicating reason of failure.

int dfu_target_reset(void)

Release the resources that were needed for the current DFU target if any and resets the current DFU target.

Returns

0 for an successful deinitialization and reset or a negative error code indicating reason of failure.

int dfu_target_schedule_update(int img_num)

Schedule update of one or more images.

This call requests images update. Time of update depends on image type.

Parameters
  • img_num[in] For DFU_TARGET_IMAGE_TYPE_MCUBOOT image type: given image pair index or -1 for all of image pair indexes. Disregard otherwise.

Returns

0 for a successful request or a negative error code indicating reason of failure.

struct dfu_target
#include <dfu_target.h>

Functions which needs to be supported by all DFU targets.