This post is older than 2 years and might not be relevant anymore
More Info: Consider searching for newer posts

Nordic SDK boilerplate code size

I am still somewhat of a beginner to development with nRF51, but it seems to be that the SDK, specifically all the boilerplate code in the app_template example just to initialize the softdevice and so on generates almost 30 KB of code (using SDK v10, S110 and ARM's GCC 4.9.3 distribution with optimizing with -O3). It also consumes almost 2 KB of RAM already, leaving only 6 KB of RAM for the 16 KB RAM variant (xxaa I believe) of the chip.

Why is the boilerplate already so big? Were the older versions much smaller? This looks to me like one can only use the biggest 256 KB flash and 32 KB RAM variant with the current SDK.

Or are my GCC settings or something like that wrong?

Update: I checked the specific app_template code size. So when compiling the app_template in /nRF51_SDK_10.0.0/examples/ble_peripheral/ble_app_template/pca10028/s110/armgcc with gnu make and the makefile supplied by Nordic (i.e. I compile the exact app_template as it comes with the SDK distribution and with ARM GCC 4.9.3 installed on my system) I get the following output about the sizes (Nordic's makefile uses -O3):

  text    data     bss     dec     hex filename
  27120     112    1884   29116    71bc _build/nrf51422_xxac_s110.out

So we can clearly see that the "boilerplate", i.e. what I consider the least amount of setup code even without actually setting up the BLE services, but just calling ble_stack_init() and the other stuff from the app_template, you need 30 KB already.

Even when using -Os instead of -O3 it's still 20 KB, so 10 KB less, but still a lot:

text    data     bss     dec     hex filename
  17176     112    1876   19164    4adc _build/nrf51422_xxac_s110.out
Parents
  • You are right, let's stick to the topic and let the others research performance of different compilers (from my experience GCC for ARM did great job over past 2 years so I'm very happy with optimizations at -O3 and -Os levels). By looking into the main.c we get some answers:

    • It's using full device_manager module for storing and serving bonding&security (+ advertising and connection wrapper functions which are probably more convenient to use then calling SD calls directly).
    • It's using pstorage module which stores parts of the data/configuration persistently in flash (probably used by device manager but usually useful for business logic as well).
    • It's using BSP (board support package) including event dispatcher for LEDs and BUTTONs.
    • It's using app_timer package.

    If you then tweak makefile a little bit you can see sizes of all compiled modules as well as ELF dump (DMP) and LSS files. Together with MAP file you can see more details, such as GPIO/GPIOTE/UART functions and interrupt handlers being linked (not sure if these are ever used - UART might be for instance just left from app_trace and app_assert modules which helps in DEBUG mode to output some checkpoints into serial console). Here is one of such output examples for examples\ble_peripheral\ble_app_template project in discussion:

       text    data     bss     dec     hex filename
         92       0       0      92      5c _build/gcc_startup_nrf51.o
        972       6     529    1507     5e3 _build/main.o
        588       0      49     637     27d _build/app_button.o
         24       0       0      24      18 _build/app_error.o
       2392       0      29    2421     975 _build/app_timer.o
          0       0       0       0       0 _build/app_trace.o
          0       0       0       0       0 _build/nrf_assert.o
         48       0     208     256     100 _build/retarget.o
        372       0       7     379     17b _build/app_uart.o
         60       0       0      60      3c _build/nrf_delay.o
        128       0       0     128      80 _build/nrf_drv_common.o
       2732       0      72    2804     af4 _build/nrf_drv_gpiote.o
       1496       0      24    1520     5f0 _build/nrf_drv_uart.o
       5948       0     264    6212    1844 _build/pstorage.o
       3876       0     130    4006     fa6 _build/bsp.o
        368       0       8     376     178 _build/bsp_btn_ble.o
       3008       0       0    3008     bc0 _build/ble_advdata.o
       3024       2     284    3310     cee _build/ble_advertising.o
        696       0      80     776     308 _build/ble_conn_params.o
       1404       0       0    1404     57c _build/ble_srv_common.o
       6784       0     355    7139    1be3 _build/device_manager_peripheral.o
        172       4       0     176      b0 _build/system_nrf51.o
        480       0      19     499     1f3 _build/softdevice_handler.o
      34664      12    2058   36734    8f7e (TOTALS)
    
    Size of target .elf file:
    arm-none-eabi-size -B _build/ble_app_template_s110_pca10028.elf
       text    data     bss     dec     hex filename
      27432     112    1888   29432    72f8 _build/ble_app_template_s110_pca10028.elf
    
    Size of target .bin file:
    arm-none-eabi-size -B --target=binary _build/ble_app_template_s110_pca10028.bin
       text    data     bss     dec     hex filename
          0   27544       0   27544    6b98 _build/ble_app_template_s110_pca10028.bin
    

    As I've written in previous exchange I believe that this is great template for fully equipped BLE Peripheral application if you want to move development fast. It's definitely good place to learn for newcomers. Also resulting size isn't end of the world (I assume usage of 256kB nRF51 variants), you have still good chance to put nice business logic there are even integrate OTA DFU functionality.

    If you think there is a lot of unnecessary overhead I totally agree with you. I'd not go with this template for product of my own company, every skilled embedded (C) programmer can do better then this. However these SDK modules are written as generic to serve majority of use cases and they are tested and proven to work well. So maybe some of them might be good choice for your app in the end (you might be able to write something 10-20% more efficient in terms of code and RAM size but it's question if 1-2 weeks of your life are worth of these few hundreds of bytes). Optimized code for your particular use case (working directly on top of HW peripherals) will be of course always smaller and even device manager might be exchanged with your smaller manager of LE Security layer (especially if you are not using it or you have limited number of bonds&keys by design).

    This answer is just opinion of regular nRF51 SDK user, I hope that someone from Nordic team will give you better explanation of what this particular template project is targeting.

    Cheers Jan

Reply
  • You are right, let's stick to the topic and let the others research performance of different compilers (from my experience GCC for ARM did great job over past 2 years so I'm very happy with optimizations at -O3 and -Os levels). By looking into the main.c we get some answers:

    • It's using full device_manager module for storing and serving bonding&security (+ advertising and connection wrapper functions which are probably more convenient to use then calling SD calls directly).
    • It's using pstorage module which stores parts of the data/configuration persistently in flash (probably used by device manager but usually useful for business logic as well).
    • It's using BSP (board support package) including event dispatcher for LEDs and BUTTONs.
    • It's using app_timer package.

    If you then tweak makefile a little bit you can see sizes of all compiled modules as well as ELF dump (DMP) and LSS files. Together with MAP file you can see more details, such as GPIO/GPIOTE/UART functions and interrupt handlers being linked (not sure if these are ever used - UART might be for instance just left from app_trace and app_assert modules which helps in DEBUG mode to output some checkpoints into serial console). Here is one of such output examples for examples\ble_peripheral\ble_app_template project in discussion:

       text    data     bss     dec     hex filename
         92       0       0      92      5c _build/gcc_startup_nrf51.o
        972       6     529    1507     5e3 _build/main.o
        588       0      49     637     27d _build/app_button.o
         24       0       0      24      18 _build/app_error.o
       2392       0      29    2421     975 _build/app_timer.o
          0       0       0       0       0 _build/app_trace.o
          0       0       0       0       0 _build/nrf_assert.o
         48       0     208     256     100 _build/retarget.o
        372       0       7     379     17b _build/app_uart.o
         60       0       0      60      3c _build/nrf_delay.o
        128       0       0     128      80 _build/nrf_drv_common.o
       2732       0      72    2804     af4 _build/nrf_drv_gpiote.o
       1496       0      24    1520     5f0 _build/nrf_drv_uart.o
       5948       0     264    6212    1844 _build/pstorage.o
       3876       0     130    4006     fa6 _build/bsp.o
        368       0       8     376     178 _build/bsp_btn_ble.o
       3008       0       0    3008     bc0 _build/ble_advdata.o
       3024       2     284    3310     cee _build/ble_advertising.o
        696       0      80     776     308 _build/ble_conn_params.o
       1404       0       0    1404     57c _build/ble_srv_common.o
       6784       0     355    7139    1be3 _build/device_manager_peripheral.o
        172       4       0     176      b0 _build/system_nrf51.o
        480       0      19     499     1f3 _build/softdevice_handler.o
      34664      12    2058   36734    8f7e (TOTALS)
    
    Size of target .elf file:
    arm-none-eabi-size -B _build/ble_app_template_s110_pca10028.elf
       text    data     bss     dec     hex filename
      27432     112    1888   29432    72f8 _build/ble_app_template_s110_pca10028.elf
    
    Size of target .bin file:
    arm-none-eabi-size -B --target=binary _build/ble_app_template_s110_pca10028.bin
       text    data     bss     dec     hex filename
          0   27544       0   27544    6b98 _build/ble_app_template_s110_pca10028.bin
    

    As I've written in previous exchange I believe that this is great template for fully equipped BLE Peripheral application if you want to move development fast. It's definitely good place to learn for newcomers. Also resulting size isn't end of the world (I assume usage of 256kB nRF51 variants), you have still good chance to put nice business logic there are even integrate OTA DFU functionality.

    If you think there is a lot of unnecessary overhead I totally agree with you. I'd not go with this template for product of my own company, every skilled embedded (C) programmer can do better then this. However these SDK modules are written as generic to serve majority of use cases and they are tested and proven to work well. So maybe some of them might be good choice for your app in the end (you might be able to write something 10-20% more efficient in terms of code and RAM size but it's question if 1-2 weeks of your life are worth of these few hundreds of bytes). Optimized code for your particular use case (working directly on top of HW peripherals) will be of course always smaller and even device manager might be exchanged with your smaller manager of LE Security layer (especially if you are not using it or you have limited number of bonds&keys by design).

    This answer is just opinion of regular nRF51 SDK user, I hope that someone from Nordic team will give you better explanation of what this particular template project is targeting.

    Cheers Jan

Children
No Data
Related