How to reduce the size of an executable file?

Hello,

I have modified the central_uart example to make the nRF52832 communicate with an ESP32 in MessagePack. After having disabled the logger configuration in the proj.conf file the size of the *.bin file is 225.8 kB which is too large for an nRF52805 (flash of 192 kB). Is there any way to reduce the bin file size?

Below the proj.conf file:

#
# Copyright (c) 2018 Nordic Semiconductor
#
# SPDX-License-Identifier: LicenseRef-Nordic-5-Clause
#

# Enable the UART driver
CONFIG_UART_ASYNC_API=y
CONFIG_NRFX_UARTE0=y
CONFIG_SERIAL=y
CONFIG_CONSOLE=y
CONFIG_UART_CONSOLE=y

# Enable the BLE stack with GATT Client configuration
CONFIG_BT=y
CONFIG_BT_CENTRAL=y
CONFIG_BT_SMP=y
CONFIG_BT_GATT_CLIENT=y

# Enable the BLE modules from NCS
CONFIG_BT_NUS_CLIENT=y
CONFIG_BT_SCAN=y
CONFIG_BT_SCAN_FILTER_ENABLE=y
CONFIG_BT_SCAN_UUID_CNT=1
CONFIG_BT_SCAN_ADDRESS_CNT=1
CONFIG_BT_GATT_DM=y
CONFIG_HEAP_MEM_POOL_SIZE=2048
CONFIG_BT_MAX_PAIRED=1
CONFIG_BT_MAX_CONN=1

# This example requires more workqueue stack
CONFIG_SYSTEM_WORKQUEUE_STACK_SIZE=2048

# Enable bonding
CONFIG_BT_SETTINGS=y
CONFIG_FLASH=y
CONFIG_FLASH_PAGE_LAYOUT=y
CONFIG_FLASH_MAP=y
CONFIG_NVS=y
CONFIG_SETTINGS=y

# Enable use of the non-minimal C functionality (stdio.h).
CONFIG_NEWLIB_LIBC=y

# Config logger
CONFIG_LOG=n
CONFIG_USE_SEGGER_RTT=y
CONFIG_LOG_BACKEND_RTT=n
CONFIG_LOG_BACKEND_UART=n
CONFIG_LOG_PRINTK=n
CONFIG_BT_DEBUG_LOG=n
CONFIG_BT_GATT_DM_DATA_PRINT=n

CONFIG_ASSERT=y

# Config I2C
CONFIG_GPIO=y
CONFIG_I2C=y
CONFIG_I2C_NRFX=y

CONFIG_SHELL=y
CONFIG_I2C_SHELL=y

Regards,

Marco

Parents
  • Hey Marco,

    Just curious, have you tried using CONFIG_SIZE_OPTIMIZATIONS=y so GCC optimizes for size? That may work. Also, have you tried using the minimal C library (CONFIG_MINIMAL_LIBC=y) instead of Newlib (CONFIG_NEWLIB_LIBC=y)?

  • Hello James,

    Yes, I'm using CONFIG_SIZE_OPTIMIZATIONS=y but I have not tried CONFIG_MINIMAL_LIBC=y yet. Should this be configured in the prj.conf file?

  • You could also try setting these configs too, just to see where all of your stacks are at:

    CONFIG_THREAD_NAME=y
    CONFIG_THREAD_MONITOR=y
    
    CONFIG_THREAD_STACK_INFO=y
    CONFIG_THREAD_RUNTIME_STATS=y
    CONFIG_SCHED_THREAD_USAGE=y
    CONFIG_SCHED_THREAD_USAGE_ALL=y
    CONFIG_THREAD_ANALYZER=y
    CONFIG_THREAD_ANALYZER_AUTO=y
    CONFIG_THREAD_ANALYZER_USE_LOG=y
    CONFIG_THREAD_ANALYZER_ISR_STACK_USAGE=y
    CONFIG_THREAD_ANALYZER_AUTO_STACK_SIZE=2048

  • Hi James,

    Thank you for the tips on stack analysis.

    When I added the stack config items you suggested I got this error when loading the project in Segger Embedded Studio (SES) v5.60. Note, I am using zephyr v1.7.0.

    error: cmake failed
    create_nordic_project.py failed (1)

    So, I removed them and started adding one at the time and the first one that triggered the error was CONFIG_SCHED_THREAD_USAGE=y, these other two also caused the same error, CONFIG_THREAD_ANALYZER_USE_LOG=y
    CONFIG_THREAD_ANALYZER_ISR_STACK_USAGE=y

    So, this is the config I am using for stack analysis,

    ### THREAD STACK ANALYSIS - start ###
    #
    CONFIG_THREAD_ANALYZER=y
    #CONFIG_THREAD_ANALYZER_USE_PRINTK=y
    CONFIG_THREAD_ANALYZER_AUTO=y
    CONFIG_THREAD_ANALYZER_AUTO_INTERVAL=5
    CONFIG_THREAD_ANALYZER_AUTO_STACK_SIZE=2048
    CONFIG_THREAD_NAME=y

    #CONFIG_INIT_STACKS=y
    CONFIG_THREAD_STACK_INFO=y

    CONFIG_RESET_ON_FATAL_ERROR=n
    #CONFIG_SYSTEM_WORKQUEUE_STACK_SIZE=8192
    CONFIG_SYSTEM_WORKQUEUE_STACK_SIZE=4096


    CONFIG_THREAD_MONITOR=y
    CONFIG_THREAD_RUNTIME_STATS=y
    #CONFIG_SCHED_THREAD_USAGE=y
    #CONFIG_SCHED_THREAD_USAGE_ALL=y
    CONFIG_THREAD_ANALYZER_USE_LOG=y
    #CONFIG_THREAD_ANALYZER_ISR_STACK_USAGE=y
    #
    ### THREAD STACK ANALYSIS - end ###

    The complete trace leading up to the error is shown below.

    Back to the MPU FAULT crash, the stack analysis is not showing much because up until just before the crash occurs the stack usage looks good then the crash occurs and the program breaks in fault_s.S before the stack analyser had a chance to display its statistics.

    See trace from SES

    *** First, before BLE activity starts,

    [00:01:00.071,136] <inf> thread_analyzer: Thread analyze:
    [00:01:00.071,441] <inf> thread_analyzer: thread_analyzer : STACK: unused 1788 usage 260 / 2048 (12 %); CPU: 0 %
    [00:01:00.072,143] <inf> thread_analyzer: sysworkq : STACK: unused 3936 usage 160 / 4096 (3 %); CPU: 0 %
    [00:01:00.072,204] <inf> thread_analyzer: logging : STACK: unused 264 usage 504 / 768 (65 %); CPU: 0 %
    [00:01:00.072,265] <inf> thread_analyzer: idle 00 : STACK: unused 248 usage 72 / 320 (22 %); CPU: 99 %
    [00:01:00.073,425] <inf> thread_analyzer: main : STACK: unused 7408 usage 784 / 8192 (9 %); CPU: 0 %

    [00:01:05.073,516] <inf> thread_analyzer: Thread analyze:
    [00:01:05.073,822] <inf> thread_analyzer: thread_analyzer : STACK: unused 1788 usage 260 / 2048 (12 %); CPU: 0 %
    [00:01:05.074,462] <inf> thread_analyzer: sysworkq : STACK: unused 3936 usage 160 / 4096 (3 %); CPU: 0 %
    [00:01:05.074,523] <inf> thread_analyzer: logging : STACK: unused 264 usage 504 / 768 (65 %); CPU: 0 %
    [00:01:05.074,584] <inf> thread_analyzer: idle 00 : STACK: unused 248 usage 72 / 320 (22 %); CPU: 99 %
    [00:01:05.075,775] <inf> thread_analyzer: main : STACK: unused 7408 usage 784 / 8192 (9 %); CPU: 0 %

    [00:01:10.075,836] <inf> thread_analyzer: Thread analyze:
    [00:01:10.076,141] <inf> thread_analyzer: thread_analyzer : STACK: unused 1788 usage 260 / 2048 (12 %); CPU: 0 %
    [00:01:10.076,782] <inf> thread_analyzer: sysworkq : STACK: unused 3936 usage 160 / 4096 (3 %); CPU: 0 %
    [00:01:10.076,843] <inf> thread_analyzer: logging : STACK: unused 264 usage 504 / 768 (65 %); CPU: 0 %
    [00:01:10.076,904] <inf> thread_analyzer: idle 00 : STACK: unused 248 usage 72 / 320 (22 %); CPU: 99 %
    [00:01:10.078,094] <inf> thread_analyzer: main : STACK: unused 7408 usage 784 / 8192 (9 %); CPU: 0 %

    *** Then after BLE activity starts. Notice, the extra stack stats in blue. I am not suggesting the BLE activity is causing this crash.

    [00:02:15.370,788] <inf> thread_analyzer: Thread analyze:
    [00:02:15.370,880] <inf> thread_analyzer: BT RX : STACK: unused 384 usage 640 / 1024 (62 %); CPU: 0 %
    [00:02:15.370,941] <inf> thread_analyzer: BT RX pri : STACK: unused 208 usage 240 / 448 (53 %); CPU: 0 %
    [00:02:15.371,215] <inf> thread_analyzer: BT TX : STACK: unused 240 usage 400 / 640 (62 %); CPU: 0 %
    [00:02:15.371,520] <inf> thread_analyzer: thread_analyzer : STACK: unused 1776 usage 272 / 2048 (13 %); CPU: 0 %
    [00:02:15.372,131] <inf> thread_analyzer: sysworkq : STACK: unused 2904 usage 1192 / 4096 (29 %); CPU: 16 %
    [00:02:15.372,222] <inf> thread_analyzer: logging : STACK: unused 264 usage 504 / 768 (65 %); CPU: 0 %
    [00:02:15.372,283] <inf> thread_analyzer: idle 00 : STACK: unused 248 usage 72 / 320 (22 %); CPU: 59 %
    [00:02:15.373,535] <inf> thread_analyzer: main : STACK: unused 7408 usage 784 / 8192 (9 %); CPU: 23 %

    [00:02:16.781,951] <inf> uart: UART RX processing
    [00:02:16.782,043] <inf> uart: -> ProcessRxByte: 0x31
    [00:02:17.261,688] <inf> uart: UART RX processing
    [00:02:17.261,779] <inf> uart: -> ProcessRxByte: 0x0D


    [00:03:06.555,358] <err> os: ***** MPU FAULT *****
    [00:03:06.555,358] <err> os: Instruction Access Violation
    [00:03:06.555,358] <err> os: r0/a1: 0x00000001 r1/a2: 0x00000003 r2/a3: 0x20009662
    [00:03:06.555,389] <err> os: r3/a4: 0x20009664 r12/ip: 0x20009662 r14/lr: 0x00000000
    [00:03:06.555,389] <err> os: xpsr: 0x21000000
    [00:03:06.555,389] <err> os: Faulting instruction address (r15/pc): 0x2000440c
    [00:03:06.555,419] <err> os: >>> ZEPHYR FATAL ERROR 0: CPU exception on CPU 0
    [00:03:06.555,419] <err> os: Current thread: 0x20001ef0 (main)
    [00:03:06.959,045] <err> os: Halting system

    This is proving to be a tricky bug to track down. Do you want to join in the fun?

    Kind regards

    Mohamed

    Creating solution HomeBeacon_dev_sb.emProject
    C:/Zypher/v1.7.0/toolchain/opt/bin/cmake.exe -GNinja -DBOARD=nrf52833dk_nrf52833 -DBOARD_DIR=C:\Zypher\v1.7.0\zephyr\boards\arm\nrf52833dk_nrf52833 -BC:\Sandbox\HomeBeacon_dev_sb\build_nrf52833dk_nrf52833_v149_tuning -SC:\Sandbox\HomeBeacon_dev_sb -DNCS_TOOLCHAIN_VERSION=1.7.0 -DDTC_OVERLAY_FILE=C:/Sandbox/HomeBeacon_dev_sb/nrf52833dk_nrf52833.overlay -DEXTRA_KCONFIG_TARGETS=menuconfig_ses -DEXTRA_KCONFIG_TARGET_COMMAND_FOR_menuconfig_ses=C:\Zypher\v1.7.0\toolchain\segger_embedded_studio/html/configure_nordic_project_menuconfig.py
    -- Application: C:/Sandbox/HomeBeacon_dev_sb
    -- Zephyr version: 2.6.99 (C:/Zypher/v1.7.0/zephyr), build: v2.6.99-ncs1
    -- Found Python3: C:/Zypher/v1.7.0/toolchain/opt/bin/python.exe (found suitable exact version "3.8.2") found components: Interpreter
    -- Found west (found suitable version "0.11.1", minimum required is "0.7.1")
    -- Board: nrf52833dk_nrf52833
    -- Cache files will be written to: C:/Zypher/v1.7.0/zephyr/.cache
    -- Found dtc: C:/Zypher/v1.7.0/toolchain/opt/bin/dtc.exe (found suitable version "1.4.7", minimum required is "1.4.6")
    -- Found toolchain: gnuarmemb (C:/Zypher/v1.7.0/toolchain/opt)
    -- Found BOARD.dts: C:/Zypher/v1.7.0/zephyr/boards/arm/nrf52833dk_nrf52833/nrf52833dk_nrf52833.dts
    -- Found devicetree overlay: C:/Sandbox/HomeBeacon_dev_sb/nrf52833dk_nrf52833.overlay
    -- Generated zephyr.dts: C:/Sandbox/HomeBeacon_dev_sb/build_nrf52833dk_nrf52833_v149_tuning/zephyr/zephyr.dts
    -- Generated devicetree_unfixed.h: C:/Sandbox/HomeBeacon_dev_sb/build_nrf52833dk_nrf52833_v149_tuning/zephyr/include/generated/devicetree_unfixed.h
    -- Generated device_extern.h: C:/Sandbox/HomeBeacon_dev_sb/build_nrf52833dk_nrf52833_v149_tuning/zephyr/include/generated/device_extern.h
    -- Including generated dts.cmake file: C:/Sandbox/HomeBeacon_dev_sb/build_nrf52833dk_nrf52833_v149_tuning/zephyr/dts.cmake
    Parsing C:/Sandbox/HomeBeacon_dev_sb/Kconfig
    Loaded configuration 'C:/Zypher/v1.7.0/zephyr/boards/arm/nrf52833dk_nrf52833/nrf52833dk_nrf52833_defconfig'
    Merged configuration 'C:/Sandbox/HomeBeacon_dev_sb/prj_debug.conf'
    -- Configuring incomplete, errors occurred!
    Including boilerplate (Zephyr base): C:/Zypher/v1.7.0/zephyr/cmake/app/boilerplate.cmake
    -- Using NCS Toolchain 1.7.0 for building. (C:/Zypher/v1.7.0/toolchain/cmake)

    warning: NEWLIB_LIBC_FLOAT_PRINTF (defined at C:/Zypher/v1.7.0/modules/lib/pelion-
    dm/zephyr\Kconfig.pal:74, lib/libc/Kconfig:89) was assigned the value 'y' but got the value 'n'.
    Check these unsatisfied dependencies: ((PELION_SOURCES && PELION_CLIENT) || NEWLIB_LIBC) (=n). See
    docs.zephyrproject.org/.../CONFIG_NEWLIB_LIBC_FLOAT_PRINTF.html and/or
    look up NEWLIB_LIBC_FLOAT_PRINTF in the menuconfig/guiconfig interface. The Application Development
    Primer, Setting Configuration Values, and Kconfig - Tips and Best Practices sections of the manual
    might be helpful too.


    warning: UART_CONSOLE (defined at drivers/console/Kconfig:47) was assigned the value 'y' but got the
    value 'n'. Check these unsatisfied dependencies: SERIAL (=n), SERIAL_HAS_DRIVER (=n). See
    docs.zephyrproject.org/.../CONFIG_UART_CONSOLE.html and/or look up
    UART_CONSOLE in the menuconfig/guiconfig interface. The Application Development Primer, Setting
    Configuration Values, and Kconfig - Tips and Best Practices sections of the manual might be helpful
    too.


    warning: I2C_0 (defined at drivers/i2c/Kconfig.esp32:15) was assigned the value 'y' but got the
    value 'n'. Check these unsatisfied dependencies: I2C_ESP32 (=n). See
    docs.zephyrproject.org/.../CONFIG_I2C_0.html and/or look up I2C_0 in the
    menuconfig/guiconfig interface. The Application Development Primer, Setting Configuration Values,
    and Kconfig - Tips and Best Practices sections of the manual might be helpful too.


    C:/Sandbox/HomeBeacon_dev_sb/prj_debug.conf:180: warning: attempt to assign the value 'y' to the undefined symbol SCHED_THREAD_USAGE

    error: Aborting due to Kconfig warnings

    CMake Error at C:/Zypher/v1.7.0/zephyr/cmake/kconfig.cmake:268 (message):
    command failed with return code: 1
    Call Stack (most recent call first):
    C:/Zypher/v1.7.0/zephyr/cmake/app/boilerplate.cmake:554 (include)
    C:/Zypher/v1.7.0/zephyr/share/zephyr-package/cmake/ZephyrConfig.cmake:24 (include)
    C:/Zypher/v1.7.0/zephyr/share/zephyr-package/cmake/ZephyrConfig.cmake:35 (include_boilerplate)
    CMakeLists.txt:34 (find_package)

    error: cmake failed
    create_nordic_project.py failed (1)

  • Hey Mohamed,

    Hope your morning is going well. I would start by getting rid of the compiler warnings. You can remove CONFIG_NEWLIB_LIBC_FLOAT_PRINTF since you're using the minimal library now. UART_CONSOLE requires that CONFIG_SERIAL is enabled, do you have that enabled? I'm not sure about the I2C one. Those won't resolve your issues, but it's always good to have a clean compile. 

    Another idea is to try and use Ozone. When you run your code from Ozone it will give you a stack trace when it crashes. This may point to where to core issue lies. You can also set a breakpoint on the address where it's faulting, you can look at the disassembly where that address is to pinpoint where it's crashing, etc. Ozone has helped me figure a lot of obscure bugs out. You should also be able to step through your code, which is always helpful. It's very simple to setup in VS Code, but I'm not sure about SES since I don't use it. Also, it should give you a free license since you're using Nordic.

    As mentioned, I unfortunately do not use SES (I use VS Code). I would try the above and see what happens. If that doesn't work I would open a new ticket and then hopefully a Nordic engineer can jump on and give some ideas too. A lot of people may not be seeing this since the original question was answered and we're buried in the depths of comment land.

  • Thank you James for the valuable pointers.

    UART_CONSOLE requires that CONFIG_SERIAL is enabled, do you have that enabled?
    No, it is not. This is because of a hardware constraint I think.
    #CONFIG_UART_CONSOLE=n
    CONFIG_SERIAL=n
    Notice, UART_CONSOLE is commented out in my prj.conf. Does it default to 'y' or 'n'?
    Another idea is to try and use Ozone.

    Ozone was going to be my next move because SES does not support data breakpoints.

    I Will keep you posted.

    Kind regards
    Mohamed
  • Here is the definition for it:

    config UART_CONSOLE
    	bool "Use UART for console"
    	depends on SERIAL && SERIAL_HAS_DRIVER
    	select CONSOLE_HAS_DRIVER
    	help
    	  Enable this option to use one UART for console.

    So it's possible that the console isn't defined. I would check the dts file and see if it's defined there. Here is a snippit of what I use. We use a custom board that's based on the nRF52840 SoC, but it should be the same for yours as well. I'm not 100% sure if this is the issue, but I would try this:

    / {
        chosen {
            zephyr,console = &uart0;
        };
    };

    If you're using the DK and it's not defined, then you can always add it to your overlay file (or create an overlay file).

Reply
  • Here is the definition for it:

    config UART_CONSOLE
    	bool "Use UART for console"
    	depends on SERIAL && SERIAL_HAS_DRIVER
    	select CONSOLE_HAS_DRIVER
    	help
    	  Enable this option to use one UART for console.

    So it's possible that the console isn't defined. I would check the dts file and see if it's defined there. Here is a snippit of what I use. We use a custom board that's based on the nRF52840 SoC, but it should be the same for yours as well. I'm not 100% sure if this is the issue, but I would try this:

    / {
        chosen {
            zephyr,console = &uart0;
        };
    };

    If you're using the DK and it's not defined, then you can always add it to your overlay file (or create an overlay file).

Children
Related