Exceeding flash partition size while using mcuboot for FOTA (NCS SDK V1.4.2)

Dear DevZone support team

I'm facing the following problem:
My application uses the Zephyr's BLE stack and basically does not much beside parsing JSON-messages received via BLE and passing them over UART to a second MCU and vice versa.
So it's basically a relays, which enables connecting via BLE and serves another MCU (however, the latter is required for safety reasons).
The current build is surprisingly high, despite the fact, that the Zephyr RTOS and it's BLE stack are involved, most of the flash space is not occupied by the custom application code itself.
Thus, I tried to optimize the code size, but it seems that it's already as small as it can get with the limited / disabled debugging support. However, the "debug information" is still visible in the .map file. Could it be, that it is just treated as optional "filler" in case there's is some available flash space left?

I'm using the following configurationin "prj.conf":

CONFIG_UART_ASYNC_API=y
CONFIG_SERIAL=y
CONFIG_GPIO=y
CONFIG_NRFX_UARTE0=y # This will also enable NRFX_UARTE
CONFIG_UART_0_NRF_TX_BUFFER_SIZE=64

CONFIG_UART_0_NRF_HW_ASYNC=y
CONFIG_UART_0_NRF_HW_ASYNC_TIMER=4
CONFIG_NRFX_TIMER=y
CONFIG_NRFX_TIMER4=y
CONFIG_NRFX_PPI=y

# Use RTT as Console, not UART -> printk are directed to RTT Viewer
CONFIG_CONSOLE=y
CONFIG_PRINTK=y
CONFIG_RTT_CONSOLE=y
CONFIG_USE_SEGGER_RTT=y
CONFIG_UART_CONSOLE=n

CONFIG_HEAP_MEM_POOL_SIZE=4096

CONFIG_MAIN_STACK_SIZE=11000
CONFIG_SYSTEM_WORKQUEUE_STACK_SIZE=2048

CONFIG_HW_STACK_PROTECTION=y # Catch Stackoverflow

CONFIG_BT=y
CONFIG_BT_LL_SW_SPLIT=y
CONFIG_BT_PERIPHERAL=y
CONFIG_BT_SETTINGS=y
CONFIG_BT_SETTINGS_CCC_STORE_ON_WRITE=y
CONFIG_BT_DEVICE_NAME_DYNAMIC=y
CONFIG_BT_DEVICE_APPEARANCE=967
CONFIG_BT_MAX_CONN=1
CONFIG_BT_MAX_PAIRED=2
CONFIG_BT_CTLR_TX_PWR_PLUS_4=y # Choose max Tx Power
CONFIG_BT_PHY_UPDATE=n
CONFIG_BT_DEVICE_NAME_MAX=10

CONFIG_BT_WHITELIST=y
CONFIG_BT_CTLR_FILTER=y # This is enabled in default

# Enable bonding: Flash required, to store permanently
CONFIG_FLASH=y
CONFIG_FLASH_PAGE_LAYOUT=y
CONFIG_FLASH_MAP=y
CONFIG_NVS=y
CONFIG_SETTINGS=y
CONFIG_BT_BONDABLE=y # This is enabled in default

# Enable the NUS service
CONFIG_BT_NUS=y
CONFIG_BT_DEBUG_MONITOR=n
CONFIG_BT_DEBUG_ATT=n # Will log stuff related to ATT / GATT
CONFIG_BT_DEBUG_GATT=n
CONFIG_BT_SMP=y
CONFIG_BT_SMP_ALLOW_UNAUTH_OVERWRITE=y
CONFIG_BT_DEBUG_LOG=n # Will also print stack size for bluetooth thread

# Connection Parameter
CONFIG_BT_CREATE_CONN_TIMEOUT=60
# Connection Interval in 1.25ms units
CONFIG_BT_PERIPHERAL_PREF_MIN_INT=24
CONFIG_BT_PERIPHERAL_PREF_MAX_INT=40
CONFIG_BT_PERIPHERAL_PREF_SLAVE_LATENCY=0
CONFIG_BT_PERIPHERAL_PREF_TIMEOUT=2000
# Parameter update timeout in ms
CONFIG_BT_CONN_PARAM_UPDATE_TIMEOUT=5000
# Debug Logging
CONFIG_BT_DEBUG_CONN=n
CONFIG_BT_DEBUG_SETTINGS=n
CONFIG_BT_NUS_LOG_LEVEL_DBG=n
CONFIG_BT_DEBUG_HCI_CORE=n

# Enable DK LED and Buttons library
CONFIG_DK_LIBRARY=y

# sscanf is not supported in zephyr minimal libc
CONFIG_NEWLIB_LIBC=y

CONFIG_BT_RX_BUF_LEN=255
CONFIG_BT_ATT_TX_MAX=10
CONFIG_BT_ATT_PREPARE_COUNT=2
CONFIG_BT_CONN_TX_MAX=10
CONFIG_BT_L2CAP_TX_BUF_COUNT=10
CONFIG_BT_L2CAP_TX_MTU=247
CONFIG_BT_L2CAP_RX_MTU=247
CONFIG_BT_L2CAP_DYNAMIC_CHANNEL=y
CONFIG_BT_CTLR_RX_BUFFERS=2
CONFIG_BT_CTLR_TX_BUFFERS=10
CONFIG_BT_CTLR_TX_BUFFER_SIZE=251
CONFIG_BT_CTLR_DATA_LENGTH_MAX=251

CONFIG_ADC=y
CONFIG_ADC_ASYNC=y

CONFIG_I2C=y

# Enable monitoring
CONFIG_INIT_STACKS=n
CONFIG_THREAD_MONITOR=n # Disabled for testing
CONFIG_OBJECT_TRACING=n

# Enable PWM
CONFIG_PWM=y
CONFIG_NRFX_PWM1=y
CONFIG_NRFX_PWM2=y

# FOTA
CONFIG_MCUMGR=y # Enable mcumgr.
CONFIG_BOOTLOADER_MCUBOOT=y # Ensure an MCUboot-compatible binary is generated.

#CONFIG_DEBUG=n
#CONFIG_DEBUG_INFO=n
CONFIG_DEBUG_OPTIMIZATIONS=n # For better debugging
#CONFIG_SIZE_OPTIMIZATIONS=y

CONFIG_NFCT_PINS_AS_GPIOS=y # Disabling this option will not switch back pins to NFCT mode (UICR erase required)
CONFIG_SOC_LOG_LEVEL_DBG=n

# Power Management
CONFIG_DEVICE_POWER_MANAGEMENT=y
CONFIG_SYS_POWER_MANAGEMENT=y
CONFIG_SYS_POWER_DEEP_SLEEP_STATES=y
CONFIG_SYS_PM_STATE_LOCK=y

CONFIG_BOOT_BANNER=n # Reduces footprint size

So, with this configuration the following build output is generated:

1> Linking ‘zephyr_prebuilt.elf’
1> Memory region     Used Size  Region Size  %age Used
1>            FLASH:  222500 B     232960 B     95.51%
1>             SRAM:   59634 B        64 KB     90.99%
1>         IDT_LIST:     184 B         2 KB      8.98%

As apparent, the avaliable flash region size is given with 232960 B (227.5kB) which exceeds the forseen partition size according to nrf52dk_nrf52832.dts:

&flash0 {
/*
* For more information, see:
* docs.zephyrproject.org/.../legacy-macros.html
*/
    partitions {
        compatible = "fixed-partitions";
        #address-cells = <1>;
        #size-cells = <1>;

        boot_partition: partition@0 {
            label = "mcuboot";
            reg = <0x00000000 0xc000>;
        };
        slot0_partition: partition@c000 {
            label = "image-0";
            reg = <0x0000C000 0x32000>;
        };
        slot1_partition: partition@3e000 {
            label = "image-1";
            reg = <0x0003E000 0x32000>;
        };
        scratch_partition: partition@70000 {
            label = "image-scratch";
            reg = <0x00070000 0xa000>;
        };
        storage_partition: partition@7a000 {
            label = "storage";
            reg = <0x0007a000 0x00006000>;
        };
    };
};

There the specified partition size for the image is 0x32000 B (200kB). Why is this not matching the flash region size from the build output?

So in the end, I'm able to fit the application which occupies 217kB into the given flash region of 227.5kB, so the MCU will get flashed and also works.
But as soon as i want to upgrade the application via FOTA, it fails (with erratic behavior) and the application ends up being bricked.
This is reasonable, since the 217kB image exceeds the partition size of 200kB.

Long story short, is there a way to somehow bring down the image size? I'm not sure how 217kB can be filled with code for what the application actually does..
Did i miss some important points regarding the project configuration which could help?
FYI: I did not participate the project when it has been setup, the major part of the code base has already existed when I became responsible for its maintenance.
Furthermore, I'm not an expert on Zephyr either and did not have the chance yet to setup a project by myself (including all the learnings).

Thanks for your help!

Best regards
Manuel

Related