Reducing ROM size for the nRF52833

I think I've followed practically every "minimal configuration" example I could find, and implemented as many Kconfig options as possible, but our firmware image is still too large for DFU. I also created a static partition scheme and reduced MCU boot partition to 32 kilobytes and NVS partition to 8 kilobytes.

Despite this, our ROM size comes out to be around 13 kilobytes too large for MCU boot.

Here's my full project configuration file, with the Kconfig options I've found that actually reduce ROM size at the top. Please let me know if there's any Kconfig options I'm missing or anything else I can do to reduce the ROM size.

# not yet sure if this is helpful, harmful, or just unnecessary... but it actually decreases the project size!
CONFIG_NCS_SAMPLES_DEFAULTS=y

# to reduce image size
CONFIG_CBPRINTF_NANO=y
CONFIG_CBPRINTF_LIBC_SUBSTS=n
CONFIG_MINIMAL_LIBC=y
CONFIG_SIZE_OPTIMIZATIONS=y
CONFIG_BT_ASSERT=n
CONFIG_BT_DATA_LEN_UPDATE=n
#CONFIG_BT_GATT_SERVICE_CHANGED=n # unfortunately this is required by DFU
CONFIG_BT_GATT_READ_MULTIPLE=n
CONFIG_BT_GATT_READ_MULT_VAR_LEN=n
CONFIG_BT_GAP_PERIPHERAL_PREF_PARAMS=n
CONFIG_BT_PHY_UPDATE=n
CONFIG_BT_CTLR_LE_PING=n
CONFIG_BT_CTLR_PRIVACY=n
CONFIG_BT_CTLR_PHY_2M=n
CONFIG_TIMEOUT_64BIT=n
CONFIG_TIMESLICING=n
CONFIG_LOG=n
CONFIG_FPU=y # despite guidance from "Minimal" examples, enabling this actually decreases ROM size
CONFIG_SPI=n
CONFIG_ASSERT=n # should be enabled while developing, disabled for production
CONFIG_CONSOLE=n # should be enabled while developing, disabled for production
CONFIG_SERIAL=n # should be enabled while developing, disabled for production
CONFIG_USE_SEGGER_RTT=n # is this required for development? what does this really do?

# for DFU (remote firmware upgrades)
CONFIG_BOOTLOADER_MCUBOOT=y
CONFIG_NCS_SAMPLE_MCUMGR_BT_OTA_DFU=y

# for reading / writing to flash
CONFIG_FLASH=y
CONFIG_FLASH_PAGE_LAYOUT=y
CONFIG_FLASH_MAP=y
CONFIG_NVS=y
CONFIG_MPU_ALLOW_FLASH_WRITE=y

# software resets
CONFIG_REBOOT=y

# for button, LED, accelerometer
CONFIG_GPIO=y
CONFIG_I2C=y

# for printing heap usage stats
CONFIG_SYS_HEAP_RUNTIME_STATS=y

# for bluetooth (general)
CONFIG_BT=y

# for bluetooth (advertising)
CONFIG_BT_PERIPHERAL=y # technically our application only requires "broadcaster" but "peripheral" is required for DFU
CONFIG_BT_DEVICE_APPEARANCE=512
CONFIG_BT_DEVICE_NAME="AirA7v100"
CONFIG_BT_EXT_ADV=y
CONFIG_BT_EXT_ADV_MAX_ADV_SET=3

# for bluetooth (tx power control)
CONFIG_BT_HCI_VS_EXT=y
CONFIG_BT_CTLR_TX_PWR_DYNAMIC_CONTROL=y

# for bluetooth (scanning)
CONFIG_BT_CENTRAL=y
CONFIG_BT_SCAN=y
CONFIG_BT_ID_MAX=1
CONFIG_BT_SCAN_FILTER_ENABLE=y
CONFIG_BT_SCAN_NAME_CNT=2

# for bluetooth (connecting)
CONFIG_BT_SMP=y
CONFIG_BT_SMP_SC_ONLY=n
CONFIG_BT_SMP_APP_PAIRING_ACCEPT=n
CONFIG_BT_SMP_ENFORCE_MITM=y
CONFIG_BT_BONDABLE=n

# for blueooth (GATT)
CONFIG_BT_GATT_CLIENT=y
CONFIG_BT_GATT_DM=y
CONFIG_BT_GATT_DM_DATA_PRINT=y

# for reading voltage
CONFIG_NRFX_SAADC=y
CONFIG_NRFX_TIMER2=y
CONFIG_NRFX_PPI=y

# for power management
CONFIG_PM_DEVICE=y

# for power-off state
CONFIG_POWEROFF=y

Parents
  • Hi,

    There are some resources which might help you in reducing ROM usage. For example, there are some general recommendations how to optimize memory footprint, how to optimize Zephyr for footprint, and minimal footprint sample. On the Bluetooth side, you can look at configuration options which deal with stack sizes and buffers. Finally, you can look at minimal configuration given in minimal.conf file of the Peripheral LBS and Peripheral UART samples.

    Best regards,
    Dejan

  • Thanks Dejan, however I believe I've gone through everything you've linked.

    My question is, outside of what you've posted, are there any additional Kconfig parameters or guidance to reduce ROM size? Because I've found some on my own, and I imagine there are more, but I'm not an expert in Zephyr so I'm sort-of shooting in the dark.

    We need to reduce the ROM size by at least 10 more kilobytes for DFU to be functional, so mainly I'm wondering: does that seem feasible based on the information I've given you?

    Thanks for your help,
    Cal


    "For example, there are some general recommendations how to optimize memory footprint, how to optimize Zephyr for footprint, and minimal footprint sample."

    Yes, I've looked through those and I believe I've implemented everything possible (i.e. didn't break our application, actually reduced ROM size, and wasn't already disabled by default). Unfortunately most of the guidance combines ROM and RAM reduction tips, however I spent a bunch of time going through each one to see which Kconfigs actually reduced ROM size.

    Also, I've even found some more Kconfigs that weren't mentioned the documentation you listed. For instance, today I just found a couple more that reduced ROM size in this Github issue

    "On the Bluetooth side, you can look at configuration options which deal with stack sizes and buffers."

    I've found that none of those configuration options reduce the ROM size. They reduce the RAM size. 

    "Finally, you can look at minimal configuration given in minimal.conf file of the Peripheral LBS and Peripheral UART samples."

    Yes, this is where I found many of the Kconfig options that reduced ROM size.

  • Hi,

    There are two more discussions that you may want to look at - build file size optimization and how to resize mcuboot partition in Zephyr.

    In addition, you could try to use this config option which could decrease footprint by around 4 KB. 

    Best regards,
    Dejan


  • "There are two more discussions that you may want to look at - build file size optimization and how to resize mcuboot partition in Zephyr."

    The guidance in the first link discusses NEWLIB_LIBC optimizations which don't apply to me, because I'm already using MINIMAL_LIBC (which is far leaner than NEWLIB_LIBC). It also references a few other Kconfig options that I've already disabled if you look at my original post. 

    The guidance in the second link I've already utilized to shrink my MCU Boot partition. I've been able to shrink the MCU boot image to a little less than 19 kilobytes, which allowed me to resize the MCU boot partition 20 kilobytes.

    "In addition, you could try to use this config option which could decrease footprint by around 4 KB."

    If you look at my original post, you can see I already have that config option in my prj.conf file.


    Just so we're clear, here is my latest project configuration environment. Note that this morning I found a few more Bluetooth options I could disable, so I'm now even closer: only 1.5 Kilobytes above the ROM size limitation!

    app/prj.conf (application configuration)

    # not yet sure if this is helpful, harmful, or just unnecessary... but it actually decreases the project size!
    CONFIG_NCS_SAMPLES_DEFAULTS=y
    
    # to reduce image size
    CONFIG_CBPRINTF_NANO=y
    CONFIG_CBPRINTF_LIBC_SUBSTS=n # untested
    CONFIG_MINIMAL_LIBC=y
    CONFIG_MINIMAL_LIBC_OPTIMIZE_STRING_FOR_SIZE=y
    CONFIG_SIZE_OPTIMIZATIONS=y
    CONFIG_BT_ASSERT=n
    CONFIG_BT_DATA_LEN_UPDATE=n
    #CONFIG_BT_GATT_SERVICE_CHANGED=n # unfortunately this is required by DFU
    CONFIG_BT_GATT_READ_MULTIPLE=n
    CONFIG_BT_GATT_READ_MULT_VAR_LEN=n
    CONFIG_BT_GAP_PERIPHERAL_PREF_PARAMS=n
    CONFIG_BT_PHY_UPDATE=n
    CONFIG_BT_CTLR_LE_PING=n
    CONFIG_BT_CTLR_PRIVACY=n
    CONFIG_BT_CTLR_PHY_2M=n
    CONFIG_TIMEOUT_64BIT=n
    CONFIG_TIMESLICING=n
    CONFIG_LOG=n
    CONFIG_SPI=n
    CONFIG_ASSERT=n # should be enabled while developing, disabled for production
    CONFIG_CONSOLE=n # should be enabled while developing, disabled for production
    CONFIG_SERIAL=n # should be enabled while developing, disabled for production
    
    # to reduce image size even more (everything below doesn't break the application, but unknown how it affects DFU!)
    CONFIG_BT_ATT_RETRY_ON_SEC_ERR=n
    CONFIG_BT_GATT_AUTO_RESUBSCRIBE=n
    CONFIG_BT_GATT_CACHING=n
    CONFIG_BT_GATT_ENFORCE_SUBSCRIPTION=n
    
    # for DFU (remote firmware upgrades)
    CONFIG_BOOTLOADER_MCUBOOT=y # should be disabled while developing, enabled for production
    CONFIG_NCS_SAMPLE_MCUMGR_BT_OTA_DFU=y # should be disabled while developing, enabled for production
    
    # for reading / writing to flash
    CONFIG_FLASH=y
    CONFIG_FLASH_PAGE_LAYOUT=y
    CONFIG_FLASH_MAP=y
    CONFIG_NVS=y
    CONFIG_MPU_ALLOW_FLASH_WRITE=y
    
    # software resets
    CONFIG_REBOOT=y
    
    # for button, LED, accelerometer
    CONFIG_GPIO=y
    CONFIG_I2C=y
    
    # for printing heap usage stats
    CONFIG_SYS_HEAP_RUNTIME_STATS=y
    
    # for bluetooth (general)
    CONFIG_BT=y
    
    # for bluetooth (advertising)
    CONFIG_BT_PERIPHERAL=y # used to be CONFIG_BT_BROADCASTER=y but DFU BLE implementation requires peripheral
    CONFIG_BT_DEVICE_APPEARANCE=512
    CONFIG_BT_DEVICE_NAME="AirA7v100"
    CONFIG_BT_EXT_ADV=y
    CONFIG_BT_EXT_ADV_MAX_ADV_SET=3
    
    # for bluetooth (tx power control)
    CONFIG_BT_HCI_VS_EXT=y
    CONFIG_BT_CTLR_TX_PWR_DYNAMIC_CONTROL=y
    
    # for bluetooth (scanning)
    CONFIG_BT_CENTRAL=y
    CONFIG_BT_SCAN=y
    CONFIG_BT_ID_MAX=1
    CONFIG_BT_SCAN_FILTER_ENABLE=y
    CONFIG_BT_SCAN_NAME_CNT=2
    
    # for bluetooth (connecting)
    CONFIG_BT_SMP=y
    CONFIG_BT_SMP_SC_ONLY=n
    CONFIG_BT_SMP_APP_PAIRING_ACCEPT=n
    CONFIG_BT_SMP_ENFORCE_MITM=y
    CONFIG_BT_BONDABLE=n
    
    # for blueooth (GATT)
    CONFIG_BT_GATT_CLIENT=y
    CONFIG_BT_GATT_DM=y
    CONFIG_BT_GATT_DM_DATA_PRINT=y
    
    # for reading voltage
    CONFIG_NRFX_SAADC=y
    CONFIG_NRFX_TIMER2=y
    CONFIG_NRFX_PPI=y
    
    # for power management
    CONFIG_PM_DEVICE=y
    #CONFIG_PM_DEVICE_RUNTIME=y
    
    # for power-off state
    CONFIG_POWEROFF=y

    app/child_image/mcuboot.conf (bootloader configuration)

    CONFIG_MAIN_STACK_SIZE=10240
    CONFIG_MBEDTLS_CFG_FILE="mcuboot-mbedtls-cfg.h"
    
    CONFIG_FLASH=y
    CONFIG_FPROTECT=y
    CONFIG_PM=n
    
    CONFIG_BOOT_SWAP_SAVE_ENCTLV=n
    CONFIG_BOOT_ENCRYPT_IMAGE=n
    
    CONFIG_BOOT_BOOTSTRAP=n
    CONFIG_BOOT_UPGRADE_ONLY=n
    
    ### Minimal Configurations ###
    CONFIG_BOOT_USE_MIN_PARTITION_SIZE=y
    CONFIG_ASSERT=n
    CONFIG_ASSERT_VERBOSE=n
    CONFIG_BOOT_BANNER=n
    CONFIG_CLOCK_CONTROL=n
    CONFIG_CONSOLE=n
    CONFIG_CONSOLE_HANDLER=n
    CONFIG_GPIO=n
    CONFIG_KERNEL_MEM_POOL=n
    CONFIG_LOG=n
    CONFIG_MINIMAL_LIBC_CALLOC=n
    CONFIG_MINIMAL_LIBC_MALLOC=n
    CONFIG_MINIMAL_LIBC_REALLOCARRAY=n
    CONFIG_NCS_SAMPLES_DEFAULTS=n
    CONFIG_NO_RUNTIME_CHECKS=y
    CONFIG_NRF_RTC_TIMER=n
    CONFIG_PRINTK=n
    CONFIG_SECURE_BOOT_DEBUG=n
    CONFIG_SERIAL=n
    CONFIG_SIZE_OPTIMIZATIONS=y
    CONFIG_SYS_CLOCK_EXISTS=n
    CONFIG_UART_CONSOLE=n
    
    # trying out some more (doesn't do much)
    CONFIG_MPU=n
    CONFIG_ARM_MPU=n
    CONFIG_CBPRINTF_NANO=y
    CONFIG_CBPRINTF_LIBC_SUBSTS=n
    CONFIG_MINIMAL_LIBC=y
    
    # trying out some more (doesn't do anything)
    CONFIG_SPI=n
    CONFIG_TIMEOUT_64BIT=n
    CONFIG_TIMESLICING=n
    CONFIG_MINIMAL_LIBC_OPTIMIZE_STRING_FOR_SIZE=y

    app/pm_static.yml (static partition configuration, mcu == 20 kilobytes, nvs == 8 kilobytes)

    app:
      address: 0x5200
      end_address: 0x41800
      region: flash_primary
      size: 0x3C600
    mcuboot:
      address: 0x0
      end_address: 0x5000
      placement:
        before:
        - mcuboot_primary
      region: flash_primary
      size: 0x5000
    mcuboot_pad:
      address: 0x5000
      end_address: 0x5200
      placement:
        align:
          start: 0x1000
        before:
        - mcuboot_primary_app
      region: flash_primary
      size: 0x200
    mcuboot_primary:
      address: 0x5000
      end_address: 0x41800
      orig_span: &id001
      - mcuboot_pad
      - app
      region: flash_primary
      sharers: 0x1
      size: 0x3C800
      span: *id001
    mcuboot_primary_app:
      address: 0x5200
      end_address: 0x41800
      orig_span: &id002
      - app
      region: flash_primary
      size: 0x3C600
      span: *id002
    mcuboot_secondary:
      address: 0x41800
      end_address: 0x7E000
      placement:
        after:
        - mcuboot_primary
        align:
          start: 0x1000
      region: flash_primary
      share_size:
      - mcuboot_primary
      size: 0x3C800
    nvs_storage:
      address: 0x7E000
      end_address: 0x80000
      placement:
        align:
          start: 0x1000
        before:
        - end
      region: flash_primary
      size: 0x2000
    sram_primary:
      address: 0x20000000
      end_address: 0x20020000
      region: sram_primary
      size: 0x20000

  • Hi,

    I hope you will find a way to reduce the size of your application even further. However, even if you manage to decrease the size of your application/mcuboot so that your application flashes successfully, you might not have a functional DFU. It is desirable to have at least 5% of spare space, and preferably 10% to be able to accommodate future DFU upgrades.
    If you have some features which are good to have but not necessary you should consider omitting them. In addition, consider disabling everything that you do not really need. Alternatively, consider upgrading to nrf52840 which has more flash space.

    Best regards,
    Dejan

  • Looks like we're going with the nRF52840. Thanks! Feel free to close this!

  •    

    Stumbled across this post whilst essentially trying to achieve the same goal - my image size is too big for me to be able to enable logging.  I've been having an ongoing discussion about how to reduce my image size in this ticket

    The above changes enabled me to reduce my mcuboot by 10kB, and my application size by 4kB :-)

    So now I can get logging enabled.

    Even with the CONFIG_LOG_MINIMAL=y setting, logging seems to require 23kB of memory.

    Thanks!

Reply Children
No Data
Related