Multi-Image FOTA on nRF5340 Using External NAND Flash (App + Net Core)

Hi Nordic team,

We’ve implemented a custom firmware update flow for our nRF5340-based device, which supports a robust single-image FOTA process using external NAND flash. The update is downloaded via HTTPS (using fota_download), written to NAND via stream_flash, and installed using MCUboot on the next reboot.

Now we want to extend this flow to support coordinated multi-image updates — specifically App Core and Network Core firmware — with atomic validation and rollback behavior.


Current Setup

  • Device: nRF5340 (custom hardware)

  • Storage: External NAND flash via QSPI

  • Transport: Firmware is downloaded via HTTPS using fota_download

  • Bootloader: MCUboot

  • Flow:

    • Image is stored in NAND (not internal flash)

    • Reboot is triggered via sys_reboot(SYS_REBOOT_COLD)

    • MCUboot detects new image in NAND and swaps it on boot

    • Image is confirmed using boot_write_img_confirmed() if successful

We also have a manual firmware_reswap() function using boot_request_upgrade() for triggering updates when needed, but this is not part of our automated FOTA path.


Multi-Image FOTA Goal

We want to:

  • Download two images (App Core and Net Core) and store both in external NAND

  • Validate both images before allowing any upgrade

  • Only proceed if both are valid

  • Trigger a coordinated update through MCUboot

  • Ensure that if either image fails to install or boot, both are rolled back


Open Questions

  1. MCUboot + External Flash + Multi-Image:
    Can MCUboot handle multi-image updates from external NAND using:

    kconfig
    KopierenBearbeiten
    CONFIG_PM_EXTERNAL_FLASH_MCUBOOT_SECONDARY=y CONFIG_NRF53_MULTI_IMAGE_UPDATE=y CONFIG_NRF53_UPGRADE_NETWORK_CORE=y

    Is this officially supported in conjunction with stream_flash and external slots?

  2. Download strategy:
    Would you recommend:

    • Downloading and storing two separate images independently?

    • Or combining them into a single bundle to unpack after download?

  3. Partitioning and mapping:
    What’s the cleanest way to define partition layout (e.g., via pm_static.yml) to store both images in NAND and allow MCUboot to find them?

  4. Image validation:
    What’s the best practice to ensure both images are valid before rebooting?
    Should we compute and compare hashes manually, or use image manager APIs?

  5. Rollback consistency:
    How do we ensure both images are rolled back if one fails post-upgrade?
    Does MCUboot handle this natively in multi-image mode, or do we need additional coordination?

  6. General advice:
    Are there known limitations, recommended patterns, or pitfalls when doing multi-image OTA updates from NAND flash on the nRF5340?


We’re open to customizing parts of this logic ourselves if needed, but would prefer to stick to supported MCUboot patterns where possible.

Thanks in advance for your help and insights!

Best regards,
Lucas

Parents
  • Hi,

    MCUboot + External Flash + Multi-Image:
    Can MCUboot handle multi-image updates from external NAND using:

    kconfig
    KopierenBearbeiten
    CONFIG_PM_EXTERNAL_FLASH_MCUBOOT_SECONDARY=y CONFIG_NRF53_MULTI_IMAGE_UPDATE=y CONFIG_NRF53_UPGRADE_NETWORK_CORE=y

    Is this officially supported in conjunction with stream_flash and external slots?

    Specifically, MCUboot calls nrf53_hooks.c when doing the dual core swapping. Here, it will perform PCD swap to netcore when the data is swapped from mcuboot_secondary to mcuboot_primary.

    I cannnot see any flash operations here, so I guess that will be handled by mcuboot itself. I think MCUboot uses boot_copy_region(), which uses flash_area_write().

    So I guess the answer would be "no, stream_flash is not supported as such".

    Would you recommend:

    • Downloading and storing two separate images independently?

    • Or combining them into a single bundle to unpack after download?

    Our existing solutions stores two separate images (mcuboot_secondary and mcuboot_secondary_1). See https://academy.nordicsemi.com/courses/nrf-connect-sdk-intermediate/lessons/lesson-9-bootloaders-and-dfu-fota/topic/dfu-for-the-nrf5340/ for an explanation.

    What’s the cleanest way to define partition layout (e.g., via pm_static.yml) to store both images in NAND and allow MCUboot to find them?

    The partition manager has support for multi-image DFU.

    What’s the best practice to ensure both images are valid before rebooting?
    Should we compute and compare hashes manually, or use image manager APIs?

    I dont think i got a specific recommendation here. Just verify, in whatever way you find best.

    How do we ensure both images are rolled back if one fails post-upgrade?
    Does MCUboot handle this natively in multi-image mode, or do we need additional coordination?

    We do not support rollback for nRF5340 multi-image DFU. Ref Simultaneous multi-image DFU with nRF5340 DK.

    Are there known limitations, recommended patterns, or pitfalls when doing multi-image OTA updates from NAND flash on the nRF5340?

    Here is what I can think of:

    nRF5340 multi-image DFU as support status: Experimental
    Rollback is not supported for nRF5340 multi-image DFU.
    We do not have integrated support for NAND flash, so you will have to figure out the NAND part yourself.
    Check out Known Issues in general

    Regards,
    Sigurd Hellesvik

  • Hi Sigurd,

    just to understand what you stated in your last message:

    We do not have integrated support for NAND flash, so you will have to figure out the NAND part yourself.
    Check out Known Issues in general

    i am using nowadays the SDK 2.7.0 and it seems the bug NCSDK-21379 still exists even if it has been removed from the list of known anomalies.

    According to the link here , the bug NCSDK-21379 should be solved from 2.5.3, but it seems not. Could I please have a feedback from you ?

    Thanks in advance !

    Kind regards

    Riccardo 

  • I just found this post, where it reported this for the sdk 2.7.0:

    Unfortunately, one of the developers has confirmed that it's currently not possible to update the network core from external flash unless simultaneous updates are enabled. Do you have any existing devices that need to be updated? The reason I ask is that it's not possible to change the memory layout through DFU

    This confirms the scenario i am having.

  • We transitioned to using Sysbuild in v2.7.0 and this lead to some breaking changes around the non-sim. DFU support, but I did manage work around this in the sample I posted here:  RE: Bug in Secure Boot / b0n related partition configuration for nRF5340 under sysbuild in SDK v2.9.0? and figured the same approach would work in v2.7.0 since both are using the same build mechanism. Did you try building the sample I uploaded? 

  • Hi Vidar,

    i apologize for the delay in replying to you.

    you mean the example project located here ?

    I am not using the sysbuild yet with sdk 2.7.0, but still the multi image build.

    And in my project the mcuboot_secondary (mcuboot_secondary_1 is not used yet) stand in the external flash.

    Does your example uses the external flash ?

    I will have a look asap. Thanks for the help !

     

  • Hi,

    Vidar is out, looking at the linked devzone case and discussion I get the impression that it uses external flash yes.

    Kenneth

  • Hi,

    sorry for the delay.

    I actually moved to SDK 2.9.2, still with multi image build, but i can see that the problem is still there.
    I am using one single slot in the external flash to upgrade the netcore. With this configuration, this code  (similar to the screen shoot i posted in the previous message) is executed:

    secondary_fa->fa_off contains the start offset from the beginning of the external flash memory and the hdr pointer is accessing this address, which does not exist within the memory address of the nrf5340.

    The upgrade of the appcore works properly.

    Thanks in advance !

    Kind regards

    Riccardo Gaiati

Reply
  • Hi,

    sorry for the delay.

    I actually moved to SDK 2.9.2, still with multi image build, but i can see that the problem is still there.
    I am using one single slot in the external flash to upgrade the netcore. With this configuration, this code  (similar to the screen shoot i posted in the previous message) is executed:

    secondary_fa->fa_off contains the start offset from the beginning of the external flash memory and the hdr pointer is accessing this address, which does not exist within the memory address of the nrf5340.

    The upgrade of the appcore works properly.

    Thanks in advance !

    Kind regards

    Riccardo Gaiati

Children
Related