Size of build image for mcuboot with serial or usb DFU enabled?

Working on a nrf5340 project, and running into limits of the size of the flash to store my application image along with mcuboot bootloader.

I had a mucboot setup that fitted into 56Kb (signed images, secondary slot on external flash). This did NOT include the serial DFU however, and (of course) one of my first units out in the field got bricked during a DFU (using dfu_target lib to update the secondary slot from a file loaded on USB FAT FS mounted on the external flash... not yet got the unit to see what got corrupted...)

I expose the USB interface, so would like to enable the serial DFU functionality in mcuboot so that at least I have a method to DFU even if my main app image gets corrupted...Some questions to get this to work:

1/ The buttons on the device are via a gpio expander on the i2c interface, it seems mcuboot likes a 'dfu button' to be a direct gpio (at least if I set the alias:

mcuboot-button0 = &button2;
then it doesn't build because button2 is 
button2: button_2 {
            gpios = <&ioexp0 4 (GPIO_ACTIVE_LOW)>;    // GPA4
). Is this correct or should it work via a ioexpander?
BTW This is not a deal breaker as I see I can have a 'DFU delay' at boot to always check if the dfu is to be activated on the serial/USB
2/ serial DFU (virtual com port on USB) vs USB DFU : which is better to use? Which gives me a smaller mcuboot image?
3/ Image size : mcuboot with DFU_USB is now 76+Kb
Is this normal? Are there ways to slim this down? also, the mcuboot child_image build has its own mcuboot.conf - does this addon to the usual prj.conf, or replace it completely?
The image size is an issue because my main app uses https over wifi networking (nrf7002) and the wifi code+networking+TLS takes up a LOT of space....
thanks for any tips to get a solid mcuboot in the least flash space!
  • SB_CONFIG_BOOT_SIGNATURE_KEY_FILE seems to be ignored now with sysbuild? So, I added this to my sysbuild.conf:
    SB_CONFIG_SECURE_BOOT_SIGNING_KEY_FILE="\${APPLICATION_CONFIG_DIR}/../keys/bootloader_priv-ecdsa256.pem"
     
    My sysbuild.conf in full:
    # MCU boot config now handled by sysbuild
    SB_CONFIG_BOOTLOADER_MCUBOOT=y
    
    # build HCI-IPC image for CPU-NET
    SB_CONFIG_NETCORE_HCI_IPC=y
    
    # we allow secure update of images, but not of mcuboot itself.
    # allow update of CPU-NET? Only if SECURE_BOOT which we don't want
    # Not using "secure boot" as this has 2 bootloaders...
    SB_CONFIG_SECURE_BOOT=y
    SB_CONFIG_SECURE_BOOT_NETCORE=y
    SB_CONFIG_NETCORE_APP_UPDATE=y
    
    #SB_CONFIG_BOOT_SIGNATURE_TYPE_ECDSA_P256=y
    #SB_CONFIG_BOOT_SIGNATURE_KEY_FILE="\${APPLICATION_CONFIG_DIR}/../keys/bootloader_priv-ecdsa256.pem"
    #SB_CONFIG_BOOT_SIGNATURE_KEY_FILE="/work/dev/if-device-nrf53/keys/bootloader_priv-ecdsa256.pem"
    #CONFIG_MCUBOOT_SIGNATURE_KEY_FILE="/work/dev/if-device-nrf53/keys/bootloader_priv-ecdsa256.pem"
    
    SB_CONFIG_SECURE_BOOT_SIGNING_KEY_FILE="/work/dev/if-device-nrf53/keys/bootloader_priv-ecdsa256.pem"
    #SB_CONFIG_SECURE_BOOT_SIGNING_KEY_FILE="\${APPLICATION_CONFIG_DIR}/../keys/bootloader_priv-ecdsa256.pem"
    
    SB_CONFIG_MCUBOOT_MODE_SWAP_WITHOUT_SCRATCH=y
    
    # nrf7002 firmware handled by sysbuild
    SB_CONFIG_WIFI_NRF70=y
    SB_CONFIG_WIFI_NRF70_SYSTEM_MODE=y
    SB_CONFIG_WIFI_PATCHES_EXT_FLASH_STORE=y
    
    SB_CONFIG_MCUBOOT_UPDATEABLE_IMAGES=3
    #SB_CONFIG_MCUBOOT_APPLICATION_IMAGE_NUMBER=0
    #SB_CONFIG_MCUBOOT_NETWORK_CORE_IMAGE_NUMBER=1
    #SB_CONFIG_MCUBOOT_WIFI_PATCHES_IMAGE_NUMBER=2
    
    #SB_CONFIG_DFU_ZIP=y
    #SB_CONFIG_DFU_ZIP_APP=y
    #SB_CONFIG_DFU_ZIP_NET=y
    #SB_CONFIG_DFU_ZIP_WIFI_FW_PATCH=y
    
    # put application secondary slot in external flash
    SB_CONFIG_PARTITION_MANAGER=y
    SB_CONFIG_PM_MCUBOOT_PAD=0x200
    SB_CONFIG_PM_EXTERNAL_FLASH_MCUBOOT_SECONDARY=y
    
    But still, in nrf/cmake/sysbuild/debug_keys.cmake, it complains that 
    SB_CONFIG_SECURE_BOOT_SIGNING_KEY_FILE=""
    and so it generates the debug only keys and seems to sign all the images iwth this...
    Even weirder, it says SB_CONFIG_BOOT_SIGNATURE_KEY_FILE has the right path even though its commented out in my sysbuild.conf!!! (and also in the sysbuild/mcuboot/prj.conf)
    log output from cmake (I added some warning logs to see what values it gets):
    -- Configuring done
    -- Generating done
    -- Build files have been written to: C:/work/dev/if-device-nrf53/cc1-med/build/cc1-med
    CMake Warning at C:/ncs/v2.9.0/nrf/cmake/sysbuild/provision_hex.cmake:10 (message):


    -- provision_hex:
    -- SB_CONFIG_SECURE_BOOT_SIGNING_KEY_FILE =
    -- SB_CONFIG_BOOT_SIGNATURE_KEY_FILE = ${APPLICATION_CONFIG_DIR}/../keys/bootloader_priv-ecdsa256.pem
    -- SB_CONFIG_BOOT_SIGNATURE_TYPE_ECDSA_P256 = y


    Call Stack (most recent call first):
    C:/ncs/v2.9.0/nrf/sysbuild/CMakeLists.txt:55 (include)
    C:/ncs/v2.9.0/nrf/sysbuild/CMakeLists.txt:667 (include_provision_hex)
    cmake/modules/sysbuild_extensions.cmake:583 (nrf_POST_CMAKE)
    cmake/modules/sysbuild_extensions.cmake:583 (cmake_language)
    cmake/modules/sysbuild_images.cmake:23 (sysbuild_module_call)
    cmake/modules/sysbuild_default.cmake:20 (include)
    C:/ncs/v2.9.0/zephyr/share/zephyr-package/cmake/ZephyrConfig.cmake:75 (include)
    C:/ncs/v2.9.0/zephyr/share/zephyr-package/cmake/ZephyrConfig.cmake:92 (include_boilerplate)
    C:/ncs/v2.9.0/zephyr/share/sysbuild-package/cmake/SysbuildConfig.cmake:8 (include)
    template/CMakeLists.txt:10 (find_package)


    CMake Warning at C:/ncs/v2.9.0/nrf/cmake/sysbuild/debug_keys.cmake:21 (message):


    --------------------------------------------------------------
    --- WARNING: Using generated NSIB public/private key-pair. ---
    --- It should not be used for production. ---
    --- See SB_CONFIG_SECURE_BOOT_SIGNING_KEY_FILE ---
    --------------------------------------------------------------

    What is the correct setup to get signed & validated images for mcuboot?
  • Ok : with the sysbuild.conf below I have successfully managed to get a valid multi-image hex, to flash this to my device (including to the external flash for the wifi), it runs, and can be updated by dfu_target calls (my app code copies a file from the usb-fs disk to the secondary slot for this) using the zephyr.signed.bin image from a subsequent build... (which I hope means that the private key used for signing is indeed my configured one...)

    And mcumgr shows 3 known slots for updates in serial recovery mode (over USB VCOM).

    Haven't yet tested update of either CPU-NET or wifi-fw slots however, but its looking better.... 

    # MCU boot config now handled by sysbuild
    SB_CONFIG_BOOTLOADER_MCUBOOT=y
    
    # build HCI-IPC image for CPU-NET
    SB_CONFIG_NETCORE_HCI_IPC=y
    
    # we allow secure update of images, but not of mcuboot itself.
    # allow update of CPU-NET? Only if SECURE_BOOT which we don't want
    # Not using "secure boot" as this has 2 bootloaders...
    SB_CONFIG_SECURE_BOOT_NETCORE=y
    SB_CONFIG_NETCORE_APP_UPDATE=y
    
    SB_CONFIG_BOOT_SIGNATURE_TYPE_ECDSA_P256=y
    SB_CONFIG_BOOT_SIGNATURE_KEY_FILE="\${APPLICATION_CONFIG_DIR}/../keys/bootloader_priv-ecdsa256.pem"
    #SB_CONFIG_BOOT_SIGNATURE_KEY_FILE="/work/dev/if-device-nrf53/keys/bootloader_priv-ecdsa256.pem"
    #SB_CONFIG_SECURE_BOOT_SIGNING_KEY_FILE="/work/dev/if-device-nrf53/keys/bootloader_priv-ecdsa256.pem"
    SB_CONFIG_SECURE_BOOT_SIGNING_KEY_FILE="\${APPLICATION_CONFIG_DIR}/../keys/bootloader_priv-ecdsa256.pem"
    
    SB_CONFIG_MCUBOOT_MODE_SWAP_WITHOUT_SCRATCH=y
    
    # nrf7002 firmware handled by sysbuild
    SB_CONFIG_WIFI_NRF70=y
    SB_CONFIG_WIFI_NRF70_SYSTEM_MODE=y
    SB_CONFIG_WIFI_PATCHES_EXT_FLASH_STORE=y
    
    SB_CONFIG_MCUBOOT_UPDATEABLE_IMAGES=3
    #SB_CONFIG_MCUBOOT_APPLICATION_IMAGE_NUMBER=0
    #SB_CONFIG_MCUBOOT_NETWORK_CORE_IMAGE_NUMBER=1
    #SB_CONFIG_MCUBOOT_WIFI_PATCHES_IMAGE_NUMBER=2
    
    #SB_CONFIG_DFU_ZIP=y
    #SB_CONFIG_DFU_ZIP_APP=y
    #SB_CONFIG_DFU_ZIP_NET=y
    #SB_CONFIG_DFU_ZIP_WIFI_FW_PATCH=y
    
    # put application secondary slot in external flash
    SB_CONFIG_PARTITION_MANAGER=y
    SB_CONFIG_PM_MCUBOOT_PAD=0x200
    SB_CONFIG_PM_EXTERNAL_FLASH_MCUBOOT_SECONDARY=y
    

  • Small update : even though I can get an mcuboot with the required features to squeeze into 64kB, its within a few 10s of bytes of not fitting. Given this is the CRITICAL partition for the offsets for all the others, I'm worried that a future zephyr version or patch could push mcuboot over that size, and mean I lose build compaitiblity with older devices (so no DFU is possible...)

    I have therefore added 4Kb to MCUBoot, for 'future' space (and then put back my hack for INF level logs too). 68kB for the bootloader.... 

  • Hi,

    Reading over this ticket: It has gone a bit back and forth now.
    Thanks for the updates on the progress!

    I can not see any specific questions in your previous messages. However, I might have missed something, so:
    Let me know if you need anything from me, or got any questions!

  • Hi Sigurd

    Well, I have managed to get a good serially recoverable sysbuildable project using NCS 2.9, with the required 3 images to do the application/CPU-NET/wifi fw DFUs, and my mcuboot is 'only' 68kB (albeit with either no log output, or with a hack to map the logs directly to printk).

    So I will flag my post with the sysbuild that works as the answer for this issue....

    I am now fighting with mcuboot about DFU and confirmation of an updated image (to stop it reverting after a dfu_target_xxx() update).

    This ticket has the details.

     DFU using USB file system (not serial emulation)? 

    But a CRITICAL thing I have discovered, which is not IMHO well documented, is that it is essential that your slot partitions for mcuboot (primary, secondary) are both aligned at their start address on a flash erase sector boundry AND that their size is ALSO aligned on a erase boundry (0x1000=4Kb for my flash device for example).

    And that the 'mcuboot_pad' partition (for the 1st image ie the app) is the oneto align on the boundry, not the following 'app' partition (so that the 'mcuboot_primary' ends up on the boundary).

    Also, its the 'mcuboot_primary' size that must be aligned, and the 'mcuboot_secondary' must be this size, not the app size....

    If you don't align the start : after a mcuboot swap, the resulting primary image is unreadable for booting (presumably because it couldn't erase the start sector properly?)

    If you don't align the size of the primary/secondary : the swap procedure fails to clear the mcuboot trailer (because its size is not aligned for erase?), and your 2 slots will flip-flop on reboot....

    When you are trying to use every last byte of the internal flash for your app (eg because the wifi stack is taking up 3/4 of the flash....) then the temptation is to avoid any wasted space... but the alignment needs to be there as the mcuboot code doesn't cope otherwise....

Related