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!
Parents
  • Hi,

    Which version of nRF Connect SDK are you using?

    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?

    I will have to look closer into this.

    2/ serial DFU (virtual com port on USB) vs USB DFU : which is better to use? Which gives me a smaller mcuboot image?

    Which is better to use: That depends on the design of your product. W.r.t to size you would have to build your project for either configurations and see the build results.

    3/ Image size : mcuboot with DFU_USB is now 76+Kb
    Is this normal?

    If you've done optimizations, then that might be the default size, yes. Without DFU_USB MCUboot defaults to 48kB, but can be shrunk depending on what features you need.

    Are there ways to slim this down?

    The optimization page here might give you some more information w.r.t shrinking the size of the bootloader: https://docs.nordicsemi.com/bundle/ncs-latest/page/nrf/test_and_optimize.html 

    In addition you can have a look at the minimal mcuboot confiugration such as discussed here in the Matter applications: https://docs.nordicsemi.com/bundle/ncs-latest/page/nrf/protocols/matter/end_product/bootloader.html 

    also, the mcuboot child_image build has its own mcuboot.conf - does this addon to the usual prj.conf, or replace it completely?

    If my understanding is correct it adds configurations that are just defined for said child image (MCUboot in this case).

    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....

    The optimization links as well as this https://docs.nordicsemi.com/bundle/ncs-latest/page/nrf/app_dev/device_guides/nrf70/fw_patches_ext_flash.html and to use external flash for general DFU (which I assume you already do) is hopefully a good starting place, but let me know if you have any more specific questions.

    Kind regards,
    Andreas

  • Which version of nRF Connect SDK are you using?

    2.6.x

    2/ serial DFU (virtual com port on USB) vs USB DFU : which is better to use? Which gives me a smaller mcuboot image?

    Which is better to use: That depends on the design of your product. W.r.t to size you would have to build your project for either configurations and see the build results.

    Yes, I was rather hoping for some experience rather than having to explore all the possible options myself... But hving tried the 'USB DFU' option, I have decided against, as it requires installing the WinUSB driver for the device to let dfu-util see it, but this then breaks the USB FS operation (at least on my PC)...

    Trying serial DFU, but it doesn't like my dfu zip it seems: 

    This is the zip created directly by the west build. Any idea what it is objecting to?

    In addition you can have a look at the minimal mcuboot confiugration such as discussed here in the Matter applications: https://docs.nordicsemi.com/bundle/ncs-latest/page/nrf/protocols/matter/end_product/bootloader.html

    This claims you can get down to 24kB. I have managed to reduce the basic mcuboot to about 40kB, but with the serial loader option it is still up at over 64kB... 

    The optimization links as well as this https://docs.nordicsemi.com/bundle/ncs-latest/page/nrf/app_dev/device_guides/nrf70/fw_patches_ext_flash.html and to use external flash for general DFU (which I assume you already do) is hopefully a good starting place, but let me know if you have any more specific questions.

    Yes, my DFU secondary slots are in the external flash already.

    I will need to try to "nrf7002 firmware in external flash" option, even if it looks complex, as that will save 64kB I guess.

    I have switched to tinyCrypt instead of mbedtls, which seems to save some 30kB or so. However, I haven't managed (with either) to get a TLS connection (for https) to work yet... what are the impacts of using tinyCrypt?

  • Noted. I'm also helping you out in #337838. I think 336663 is better of with waiting until the migration is successfully done.

    As I've written in the other case, activity here will unfortunately be slow until early january from now on due to holidays. I will pick up  both cases again when I am back in office early January

    Kind regards,
    Andreas

  • hi, I'm back trying to get this project finalised. I have moved to NCS2.9.0, although still struggling with sysbuild... ( (Missing Forum Thread) 

    ). I want to get mcuboot to enable serial DFU over the USB virtual com port (as the USB port is accessible on my device, the debug uart is not). I'd really like to get the size to be 64kB, but can't get it to be less than 79kB.

    Discussing with some colleagues they say that it can get down to ~40-48k with USB and a minimal configuration, but I've not succeeded in recreating that.

    Can you get the config used by your colleagues so I can try it? I don't need secure boot, but I do want signed boot images.

  • Hi,

    I have some good news since last we talked. Since then the bootloader course has been updated to support NCS 2.9.0 https://academy.nordicsemi.com/courses/nrf-connect-sdk-intermediate/lessons/lesson-9-bootloaders-and-dfu-fota/ 

    There might be some steps here that can help you reduce the size of MCUboot in the 4th exercise's solution. https://github.com/NordicDeveloperAcademy/ncs-inter/tree/main/v2.9.0-v2.7.0/l9 where the size is set to 0x10000 for MCUboot (65k). If you combine this with removing any additional features that you don't need in the bootloader per similarity with the Matter samples https://docs.nordicsemi.com/bundle/ncs-latest/page/nrf/protocols/matter/end_product/bootloader.html 

    W.r.t the configuration we talked about 3 months ago, I fear this information is gone as they don't have this sample available any more. I will do some more digging, but I can't promise anything other than the abovementioned resources.

    Kind regards,
    Andreas

  • Hi,

    Here's a slightly more optimized version of lesson9 exercise 4 (Dfu with USB from application). Disclaimer, I've only verified that it builds, and I have not tested the sample itself.

    The skeleton is the solution for the exercise previously linked with optimization added to sysbuild/mcuboot.conf, such as disabling logging and adding LTO and sysbuild/mcuboot.overlay. Solution was reduced from  66k to 54k

    L9E4_solution for nrf5340dk/nrf5340

    With modifications for nrf5340dk/nrf5340:

    dfu_uart_minimal.zip

    Kind regards,
    Andreas

  • Great! I confirm it builds to around 56kB for me, without logs, using 2.9.0 with the depreciated multi-image build system (no-sysbuild). It boots the app image ok which is a big step forwards.

    I will try this now building with sysbuild...

    thanks

Reply Children
  • Oh, and when I hold down the defined button during boot, it starts the USB virtual comm ports. Haven't tried to run mcumgr yet, but thats the next step!

  • So, I applied the config to my test build using nrf70 wifi with the DFU images in the external flash... It built under multi-image system, but not with sysbuild (due to the 'hack' for the cpu-net primary slot it seems).

    If you have any insights for sysbuild, the ticket is here:

     (Missing Forum Thread) 

    thanks!. 

  • Great! It sounds like we've resolved the issue with reducing the size of MCUboot in this case.

    BrianW said:
    I will try this now building with sysbuild...

    I assume you refer to your sample with sysbuild specific, since the sample I supplied builds with sysbuild as a default, but I'm glad to hear you were able test it with the child/parent setup.

    I will have a look at your other case and give you a reply there shortly

    Kind regards,
    Andreas

  • I assume you refer to your sample with sysbuild specific, since the sample I supplied builds with sysbuild as a default, but I'm glad to hear you were able test it with the child/parent setup.

    yes, it has an issue with definition of the PRIMARY_1 slot for the CPU-NET DFU when built with sysbuild. 

  • I confirm it builds to around 56kB for me, without logs

    I hate not having logs on the UART especially given trying to get the various DFUs to work.

    But with CONFIG_LOG=y, its about 67kB.... even with 

    CONFIG_LOG_MODE_MINIMAL=y
    CONFIG_MCUBOOT_LOG_LEVEL_WRN=y
     
    However, if I leave CONFIG_LOG=n, and then hack bootloader/mcuboot/boot/bootutil/include/bootutil/bootutil_log.h (way too many 'boot's in that heirarchy..) like this:
    ...

    #ifdef MCUBOOT_HAVE_LOGGING
    #include <mcuboot_config/mcuboot_logging.h>

    #define BOOT_LOG_ERR(...) MCUBOOT_LOG_ERR(__VA_ARGS__)
    #define BOOT_LOG_WRN(...) MCUBOOT_LOG_WRN(__VA_ARGS__)
    #define BOOT_LOG_INF(...) MCUBOOT_LOG_INF(__VA_ARGS__)
    #define BOOT_LOG_DBG(...) MCUBOOT_LOG_DBG(__VA_ARGS__)
    #define BOOT_LOG_SIM(...) MCUBOOT_LOG_SIM(__VA_ARGS__)

    #define BOOT_LOG_MODULE_DECLARE(module)  MCUBOOT_LOG_MODULE_DECLARE(module)
    #define BOOT_LOG_MODULE_REGISTER(module) MCUBOOT_LOG_MODULE_REGISTER(module)

    #else
    // HACK: force log output using printk directly
    #include <zephyr/sys/printk.h>
    #define BOOT_LOG_ERR(...) printk(__VA_ARGS__);printk("\n")
    #define BOOT_LOG_WRN(...) printk(__VA_ARGS__);printk("\n")
    #define BOOT_LOG_INF(...) printk(__VA_ARGS__);printk("\n")
    #define BOOT_LOG_DBG(...) IGNORE(__VA_ARGS__)
    #define BOOT_LOG_SIM(...) IGNORE(__VA_ARGS__)

    #define BOOT_LOG_MODULE_DECLARE(module)
    #define BOOT_LOG_MODULE_REGISTER(module)

    #endif /* MCUBOOT_HAVE_LOGGING */
    I add back in the zephyr console to get printk to work, keep CONFIG_LOG as n (in child_image/mcuboot.conf)
    CONFIG_CONSOLE=y
    CONFIG_CONSOLE_HANDLER=n
    CONFIG_SERIAL=y
    CONFIG_UART_CONSOLE=y
    CONFIG_STDOUT_CONSOLE=y
    # turn off log to save image size
    CONFIG_LOG=n
     
    and voila: mcuboot error, warning, info logs :
    *** Booting MCUboot v2.1.0-dev-12e5ee106034 ***
    *** Using nRF Connect SDK v2.9.0-7787b2649840 ***
    *** Using Zephyr OS v3.7.99-1f8f3dc29142 ***
    Starting bootloader
    Primary image: magic=unset, swap_type=0x1, copy_done=0x3, image_ok=0x3
    Secondary image: magic=bad, swap_type=0x1, copy_done=0x2, image_ok=0x2
    Boot source: none
    Image index: 0, Swap type: none
    Bootloader chainload address offset: 0x10000
    and it builds to :
    Memory region Used Size Region Size %age Used
    FLASH: 61952 B 64 KB 94.53%
    RAM: 299560 B 440 KB 66.49%
    IDT_LIST: 0 GB 32 KB 0.00%
    Pity having to hack the mcuboot source though... I had hoped the CONFIG_LOG_MODE_MINIMAL would give me the same result, but it requires 8kB more for essentially the same output....
    If there is a better way to achieve this let me know...
Related