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
  • I don't have much to add to Jan's excellent answer above. The generic template has grown in size over the releases of the SDKs, it used to be very small, but it didn't do very much, it advertised and had a hook for you to write a service handler, that was about it.

    That template now has everything you need to advertise, on a fast/slow/intermittent basis, connect, update connection parameters, perform bonding, store all the resulting keys for you and bring them back on reconnection with a bonded peripheral. It outputs debug information over the UART and has full support for the board including debounced button presses, blinking LEDs and some standard LED patterns for recognising errors. In fact the only thing it doesn't have is an actual service!

    The bonding/pairing stuff alone is big, because it's generically very complicated, that's 13kB of that image (including the pstorage module which it uses for persistence which you need for storing the keys). Nordic provides this very generic device management module which covers most of the use cases for bonding because, I think, many people either aren't able to write it themselves or just want a drop-in module which they can use to 'add bonding'. Can you do better? Of course you can if you don't need a generic bonding manager and have a simpler use-case, the code can be much smaller.

    Yes the reason that GPIOTE and UART code is linked is for the board support, the GPIOTE is for buttons (along with the timer module) and the UART code is for debugging, the fact that the IRQ handler is defined is enough to get a lot of the code linked even if it's never called, the compiler cannot know an interrupt handler is never called, so it has to put it in.

    If you want to see something smaller, try the beacon example, I think that's 12kB, and that also still has the board support package in it.

    I think you should look at that application template as an 'everything including the kitchen sink' template which you start with and then remove and comment out loads of things you don't need, or don't need a generic version of.

    Last point on the softdevice sizes. Yes they're not small, but that's the whole BTLE stack, and BTLE is getting fatter too with each revision of the spec. My feeling is that the release of the XXAC a couple of years ago and the nRF52 this year, was a recognition that 128k+16k was getting a bit skinny for the kind of BTLE devices people wanted to build. That said, if you have a simple peripheral it's easy to junk much of the boiler plate code and fit it on the smaller chips, even with the increased size of the S130 softdevice. That at least now has very configurable memory profiles to release more of the limited RAM when you're using the smaller chips.

Reply
  • I don't have much to add to Jan's excellent answer above. The generic template has grown in size over the releases of the SDKs, it used to be very small, but it didn't do very much, it advertised and had a hook for you to write a service handler, that was about it.

    That template now has everything you need to advertise, on a fast/slow/intermittent basis, connect, update connection parameters, perform bonding, store all the resulting keys for you and bring them back on reconnection with a bonded peripheral. It outputs debug information over the UART and has full support for the board including debounced button presses, blinking LEDs and some standard LED patterns for recognising errors. In fact the only thing it doesn't have is an actual service!

    The bonding/pairing stuff alone is big, because it's generically very complicated, that's 13kB of that image (including the pstorage module which it uses for persistence which you need for storing the keys). Nordic provides this very generic device management module which covers most of the use cases for bonding because, I think, many people either aren't able to write it themselves or just want a drop-in module which they can use to 'add bonding'. Can you do better? Of course you can if you don't need a generic bonding manager and have a simpler use-case, the code can be much smaller.

    Yes the reason that GPIOTE and UART code is linked is for the board support, the GPIOTE is for buttons (along with the timer module) and the UART code is for debugging, the fact that the IRQ handler is defined is enough to get a lot of the code linked even if it's never called, the compiler cannot know an interrupt handler is never called, so it has to put it in.

    If you want to see something smaller, try the beacon example, I think that's 12kB, and that also still has the board support package in it.

    I think you should look at that application template as an 'everything including the kitchen sink' template which you start with and then remove and comment out loads of things you don't need, or don't need a generic version of.

    Last point on the softdevice sizes. Yes they're not small, but that's the whole BTLE stack, and BTLE is getting fatter too with each revision of the spec. My feeling is that the release of the XXAC a couple of years ago and the nRF52 this year, was a recognition that 128k+16k was getting a bit skinny for the kind of BTLE devices people wanted to build. That said, if you have a simple peripheral it's easy to junk much of the boiler plate code and fit it on the smaller chips, even with the increased size of the S130 softdevice. That at least now has very configurable memory profiles to release more of the limited RAM when you're using the smaller chips.

Children
  • One more note to the RAM size: latest Soft Device S130 V2 needs bellow 8kB for full-throughput peripheral role (actually less then 7,200B if you go without security layer) and if 8kB isn't enough for your app you then need to go with nRF51 XXAC chip variant. 32kB of RAM is max for ARM Cortex-M0 design so if you need even more then invest into nRF52 (which is anyway recommended because price difference is small and you can save some external components + have longer support and better power efficiency for most of the applications).

Related