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 Reply Children
  • Update: I was able to reduce the mcuboot size to 19 kilobytes using zephyr's "prj_minimal.conf" that I'm pasting below.

    I also resized my partitions accordingly. I'm still about 4 kilobytes over the image limit!

    child_image/mcuboot.conf

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

  • Hi,

    Which application do you use for testing? Do you use any of the NCS samples?

    Best regards,
    Dejan

  • I'm sorry but I'm a bit confused by the question.

    I've used various NCS samples, yes. Using those samples, I've developed an application that does everything we need it to do. The application works well, but the issue is there isn't enough space for the application when I enable everything required by DFU.

  • 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

Related