6min read

Polidea Labs #1: A Minimal Toolchain Setup for nRF5x Chips

The most basic need

Taking control of the build process is one of the most basic needs a programmer has to satisfy in order to succeed. It’s not only about the obvious translation of source code into binary. In most cases, build scripts also include tooling that take the burden of repetitive tasks from the developer. Simply put: if the process of flashing a developer board with new firmware always requires the same 10 parameters command, why would you want to type it each time by hand? Consequently, the choice of the right build system and setup has a tremendous influence on your productivity. In this article, I will present our build setup for nRF5x targeted firmware projects. You will learn all about the components involved - why we chose them and how it ended.

How did we arrive here?

Historically, here at Polidea, we had been focusing on writing only the mobile-app part of the projects that included peripheral devices. The natural border line had been marked by the Bluetooth Low Energy schema. Over the years, many of our customers had been asking if we could also help with firmware development. We had usually hesitated as this was “not in our DNA”. Finally 2017 came and we decided to cross the border into a yet unexplored land. It seemed like a natural thing to do since we had already gained some experience in BLE projects. The first platform we set to explore is the nRF5 series by Nordic Semiconductor. This was dictated by both the market situation (it’s very popular) and the needs of our clients (almost all of our past and present BLE projects use it).

Key ingredients

The most important part of the setup is of course the SDK provided by Nordic Semiconductor. It makes a very good first impression, and more importantly, does support various toolchains across multiple operating systems including a GCC variant provided by ARM that runs just fine on a plain macOS system. This is not something taken for granted in a world dominated by Windows only tools. All in all, we only need 4 software packages to start: 1. arm-none-eabi-gcc by the Free Software Foundation and ARM – this is a variant of the popular GCC compiler targeting ARM processors running without a OS (hence none-eabi), 2. nRF5 SDK by Nordic Semiconductor – the actual SDK containing libraries, bootstrap code, and examples, 3. J-Link by SEGGER – interfacing software for the J-Link family of programmers and debuggers, 4. nrfjprog utility by Nordic Semiconductor – wrapper utility for the J-Link software.

Installation is a snap. J-Link is provided as a standard macOS installer. The rest just needs to be downloaded and unpacked in a convenient place. After that, only two last polishing touches are necessary: 1. setting the PATH to include the nrfjprog directory, 2. editing the Makefile.posix file found in the toolchains/gcc directory of the SDK the point to the right compiler install directory and version.

The examples

To check if everything is set up correctly so far, we can access the SDK’s extensive example catalog. It shows various aspects of the platform. From basic GPIO access, through peripherals like timers, up to high-level Bluetooth Low Energy services. They supplement the documentation nicely. Let’s start with the “hello world” equivalent for embedded apps, and make some LED’s blink. The ‘blinky’ example is located under ‘examples/peripheral/blinky’. At its root there is the main source file (main.c), a license, and a IAR Workbench project file. Then, in individual sub-directories there are makefiles/project files for the different compiler and board combinations. We also have a selection of a bare-metal and a softdevice based configuration (we will talk about softdevices shortly). So, assuming we want to build for the nRF51 DK (model name PCA10028) with softdevice under arm-none-eabi-gcc, we would go to the ./pca10028/s130/armgcc subdirectory. Nordic decided to stick with the standard UNIX make tool for their build scripts. This makes building very easy. Just type:

  1. make – builds the firmware,
  2. make erase – clears the SoC flash,
  3. make flash_softdevice – writes the softdevice into the SoC flash,
  4. make flash – writes the actual firmware into the SoC flash,
  5. make clean – removes all build products. Can be used to force a complete fresh build cycle.

Invoking 1—4 in order will compile and flash the development board with the firmware. If you did everything correctly during setup, you should now observe LED1 cycling in an infinite on-off loop.

The Softdevice

Nordic uses the concept of softdevices in their SDK. Simply put, those are ready to use implementations of higher level radio stacks. They come in numerous versions for different chip families (nRF51 vs. nRF52), and various radio protocols (Bluetooth Low Energy, ANT, etc). In contrast to the rest of the SDK, they are provided in a binary form and without source code. Designing the firmware has a number of implications:

  1. the softdevice can be certified to conform to a target protocol, and as such, it’s easier to pass certification with the final device,
  2. the Over-The-Air Device Firmware Update process can be simplified, as the actual application binary can be swapped out separately from the softdevice,
  3. Nordic protects their IP.

The only real downside for the developers is the need to choose the right softdevice for the job.

Yearn to be more

So far so good. I applaud Nordic for choosing standard makefiles for their example projects. This reduces the number of dependencies, and is well known among programmers. But they have their downsides. Some of them are inherent to make. Others are the consequences of design decisions made by Nordic. To name a few:

  1. The scripts contain a number of long and ugly relative paths. For example SDK_ROOT := ../../../../../...
  2. The sources and headers for different components of the SDK are intermixed with each other. It’s not immediately apparent which of them belong together, depend on each other or are unused at all.
  3. For each target SoC there is a separate makefile.
  4. They are tightly coupled with a makefile bundled with the SDK.
  5. They assume the nrfjprog tool is in the PATH.
  6. Makefiles have more in common with bash scripts, than with programming languages.

Can we do better? Of course we can. Enter CMake. The build script tool that generates build scripts. It provides a nice syntax, and enables organizing code into smaller modules. Exactly what we would expect in 2017. The only problem is that we need to port the makefiles to it.

The process is straightforward, although time consuming. The basic idea is to enable verbose output in the original makefiles (using VERBOSE=1) and save the build output. Then iterate on your cmake files, until you get exactly the same compiler and linker calls. Of course once done this work can be reused, with minimal modification, for other examples and completely new projects.

My starting point was the BLE Heart Rate service example for the nRF51 DK board. In the first step I copied over the source file and header lists directly from the makefiles. Thanks to this, I could concentrate on compiler and linker flags. This was easy with only one exception. By default CMake appends CMAKECFLAGS to the linker call. Which in case of ARM GCC is not a good idea. Luckily the CMAKECLINKEXECUTABLE and CMAKECXXLINKEXECUTABLE variables can be overridden to change this behaviour. As soon as the firmware compiled and burned successfully to the board, I went on removing excess source files and headers. The last touch was to compare the nRF51 and nRF52 makefiles, and incorporate the differences (like the Cortex-M0 vs. Cortex-M4 CPU architecture) into our cmake script. The end result is on Polidea’s GitHub (MIT license) found here.

To sum up, by moving to cmake we:

  1. achieved a clear separation of project and platform sources,
  2. can switch quickly between different Nordic Semiconductor SoCs,
  3. have predefined macros for adding common SDK libraries.

Last missing part

Ok, there is one last part missing. The IDE. One option is Eclipse CDT. In fact, you will find it in most of the instructions for using the nRF+GCC combo available online. But as I’m a huge fan of Jetbrains, I decided to go with CLion instead. In fact, I originally learned CMake due to CLion.

And there you have it. A setup for building nRF based firmware projects using GCC on macOS with support for a decent IDE.


AntoniPrincipal Software Engineer


Sign in and expect sharp insights, recommendations, ebooks and fascinating project stories delivered to your inbox

The controller of the personal data that you are about to provide in the above form will be Polidea sp. z o.o. with its registered office in Warsaw at ul. Przeskok 2, 00-032 Warsaw, KRS number: 0000330954, tel.: 0048 795 536 436, email: (“Polidea”). We will process your personal data based on our legitimate interest and/or your consent. Providing your personal data is not obligatory, but necessary for Polidea to respond to you in relation to your question and/or request. If you gave us consent to call you on the telephone, you may revoke the consent at any time by contacting Polidea via telephone or email. You can find detailed information about the processing of your personal data in relation to the above contact form, including your rights relating to the processing, HERE.

Data controller:

The controller of your personal data is Polidea sp. z o.o. with its registered office in Warsaw at ul. Przeskok 2, 00-032 Warsaw, KRS number: 0000330954, tel.: [0048795536436], email: [] (“Polidea”)

Purpose and legal bases for processing:


Used abbreviations:

GDPR – Regulation (EU) 2016/679 of the European Parliament and of the Council of 27 April 2016
on the protection of natural persons with regard to the processing of personal data and on the free movement
of such data, and repealing Directive 95/46/EC (General Data Protection Regulation)

ARES – Polish Act on Rendering Electronic Services dated 18 July 2002

TL – Polish Telecommunications Law dated 16 July 2004

1)        sending to the given email address a newsletter including information on Polidea’s new projects, products, services, organised events and/or general insights from the mobile app business world |art. 6.1 a) GDPR, art. 10.2 ARES and art. 172.1 TL (upon your consent)

Personal data:name, email address

2)       statistical, analytical and reporting purposes |art. 6. 1 f) GDPR (based on legitimate interests pursued by Polidea, consisting in analysing the way our services are used and adjusting them to our clients’ needs, as well as developing new services)

Personal data:name, email address

Withdrawal of consent:

You may withdraw your consent to process your personal data at any time.

Withdrawal of the consent is possible solely in the scope of processing performed based on the consent. Polidea is authorised to process your personal data after you withdraw your consent if it has another legal basis for the processing, for the purposes covered by that legal basis.

Categories of recipients:

Your personal data may be shared with:

1)       authorised employees and/or contractors of Polidea

2)       persons or entities providing particular services to Polidea (accounting, legal, IT, marketing and advertising services) – in the scope required for those persons or entities to provide those services to Polidea


Retention period:

1)       For the purpose of sending newsletter to the given email address – for as long as the relevant consent is not withdrawn

2)       For statistical, analytical and reporting purposes – for as long as the relevant consent is not withdrawn

Your rights:


Used abbreviation:

GDPR – Regulation (EU) 2016/679 of the European Parliament and of the Council of 27 April 2016
on the protection of natural persons with regard to the processing of personal data and on the free movement
of such data, and repealing Directive 95/46/EC (General Data Protection Regulation)

According to GDPR, you have the following rights relating to the processing of your personal data, exercised by contacting Polidea via [e-mail, phone].

1)       to access to your personal data (art. 15 GDPR) by requesting sharing and/or sending a copy of all your personal data processed by Polidea

2)       to request rectification of inaccurate personal data
(art. 16 GDPR) by indicating the data requiring rectification

3)       to request erasure of your persona data (art. 17 GDPR); Polidea has the rights to refuse erasing the personal data in specific circumstances provided by law

4)       to request restriction of processing of your personal data (art. 18 GDPR) by indicating the data which should be restricted

5)       to move your personal data (art. 20 GDPR) by requesting preparation and transfer by Polidea of the personal data that you provided to Polidea to you or another controller in a structured, commonly used machine-readable format

6)       to object to processing your personal data conducted based on art. 6.1 e) or f) GDPR, on grounds relating to your particular situation (art. 21 GDPR)

7)       to lodge a complaint with a supervisory authority,
in particular in the EU member state of your habitual residence, place of work or place of the alleged infringement if you consider that the processing
of personal data relating to you infringes the GDPR
(art. 77.1 GDPR)

No obligation to provide data:

Providing your personal data is not obligatory, but necessary for Polidea to provide you the newsletter service

Refusal to provide the above data will result in inability to receive the newsletter service.


In the process of providing the newsletter service, we make decisions in an automated way, including profiling, based on the data you provide.


“Profiling” means automated processing of personal data consisting of the use of your personal data to evaluate certain personal aspects relating to you, in particular to analyze or predict aspects concerning your personal preferences and interests.


The automated decisions are taken based on the analysis of clicked and viewed content. They affect the targeting of specific newsletter content to selected users registered to receive the newsletter service, based on the anticipated interests of the recipient.