Recently I came across an interesting little ARM Cortex M0 microcontroller nrf51822, which has an integrated low energy Bluetooth (BLE) and overall is a very capable to do other tasks besides BLE especially due to its immense FLASH memory and RAM which is 256kb and 32kb accordingly (varies between models). Immediately I thought of trying to make a simple smart-watch for various reasons like low energy mode, which I think was 0.1µA in sleep mode. Only drawback compared to other ARM Cortex series microcontrollers is that it’s not really the fastest in the market, however a new one will be coming soon by first quarter of 2016, which will be more efficient, faster and overall more capable SOC. Luckily for us, their SDKs are pretty much identical, and once you learn and understand how nrf51 series SDK is structured and how to use it then switching to nrf52 shouldn’t be a problem. In any case I bought the development board BLE400 which is pictured above to play around; nonetheless I highly recommend buying the original nrf51-DK board just to support Nordic for developing an awesome micro.
This tutorial is intended for windows users, however setting up the environment in linux shouldn’t be much different and where I can I’ll try to warn about platform specific steps you need to take.
Also I’ll assume you have j-link programmer, which comes embedded on the original development board but does not come on the BLE400, if you don’t have one unfortunately you’ll need to hack a programmer from stm32 or just buy the edu version of j-link.
Setting up compiling environment
Disclaimer, I don’t claim that the information provided here is my own; merely it’s a summary of what I’ve learned so far by playing with the micro as future reference for setting up another environment.
In this section we will try to set up the compiling environment for the nrf51 SOC. Here are the first things you’ll need to download and install/unpack:
- GCC ARM Embedded
- CoreUtils for Windows
- Make for Windows
- nRF51 SDK 10
- nRF5x-Tools you’ll need to put softdevice and DFU. Also you can upload your application via this tool. I’ll explain what a softdevice is in another article.
- J-link windows tools
- Python 2.7.x, it will be necessary for GDB in Qt Creator
GCC ARM Embedded and GNU Utils
Once you have finished installing the GCC ARM tools, make sure it is added to the PATH variable in your environment. To test whether it is, you can open CMD and just type:
This obviously should return you something similar as pictured below:
If it doesn’t and complains about not finding the command or something along those lines, then most likely ARM GCC is not in your PATH variable. Normally, you’d need to add this line to your PATH variable:
C:/Program Files (x86)/GNU Tools ARM Embedded/4.9 2015q3/bin
One way to do it is to use command line even though I prefer to use GUI:
set PATH=%PATH%;C:/Program Files (x86)/GNU Tools ARM Embedded/4.9 2015q3/bin
While you are still in CMD, you can also check whether your “make” command can be executed
This should return you something like this:
If it doesn’t then again something is wrong with your PATH variable. Check if the following is in your PATH variable:
C:/Program Files (x86)/GnuWin32/bin
nRF51 SDK 10
At this point you should have a working environment and be able to actually initiate compiling. Now unpack the SDK somewhere on your computer. First step is to test whether you are able to compile anything. If you followed previous step correctly you should be able to compile any example in the SDK.
Before we can actually compile SDK examples we must update the Makefile.windows or your corresponding systems file to reflect the location of GCC ARM directory
Navigate to “your sdk path/components/toolchain/gcc” and edit the file Makefile.windows
Technically you just have to update the version number of your GCC ARM, however on my Windows 10 machine it didn’t seem to work and it couldn’t resolve whether I have 64bit system or not, so I just got rid of the check and ended up with the following Makefile.windows:
PROGFILES := C:/Program Files (x86) GNU_INSTALL_ROOT := $(PROGFILES)/GNU Tools ARM Embedded/4.9 2015q3 GNU_VERSION := 4.9.3 GNU_PREFIX := arm-none-eabi
But it might work for you as it was intended, but if it doesn’t you can just do what I did.
Compiling first example
Once that is done, let’s try to actually compile something. As a symbolic “hello world” let’s compile blinking LED example
With your CMD navigate to “your SDK path/examples/peripheral/blinky/pca10028/blank/armgcc”
Unrelated tip: You can navigate to the folder with your explorer window and then by clicking the URL bar and typing CMD will open it in the path your explorer is currently in.
Once you have opened the path in your CMD, just type “make” and it should be able to compile the example:
Usually it will create a folder “_build” which contains the hex file you can upload to the board. However, note that we compiled it for board pca10028 it probably won’t work on BLE400, the board I have pictured at the start of the article. I’ll get to that in a moment; we will need to define a new BOARD in SDK. Or redefine pca10028 for easier compilation.
But, if you do have pca10028 board, feel free to upload the compiled hex file and you should have LEDs blinking. You can upload the hex file via the nRF tools, more precisely nRFGo Studio.
Important: Notice that I have only a single region; there is no soft device present on my nRF at the moment. Make sure you have it as such, because we compiled the example for a blank nRF which has a different offset where your application will begin in the memory.
If you are using the board I have, download the BLE400 BSP: Download: ble400_bsp.zip (1.72K)
and replace boards.h file and add ble400.h file in “your sdk dir/examples/bsp”. Also edit your Makefile for blinky example and find where it defines the -DBOARD_PCA10028 in CFLAGS and replace it with -DBOARD_BLE400 like so:
Recompile, by executing “make” and you should have HEX file in your “_build” directory for the BLE400 board. Feel free to upload and you should have LEDs blinking properly.
By following the steps above you can compile any example just using “make” command. However, when it comes to Bluetooth examples you have to also flash the micro with the corresponding softdevice for it to work.
Setting up Qt Creator
Now that we have successfully set up build environments, we need to have some sort of IDE to properly debug and write software for the nRF51. I prefer Qt Creator, because from my experience it’s a very fast and most importantly stable C/C++ IDE compared to eclipse. I don’t want to bash eclipse, but I can promise you, that setting up Qt Creator will be easier and more straight forward than eclipse. Back to the topic, Qt Creator was designed obviously to work in junction with some version of Qt, but with plugins like “Bare Metal” and the new QBS “project file” we are now able to set up full development IDE with debugging and code uploading etc. in it itself. Note we will be setting up Qt Creator with j-link.
First things first, download open source version of Qt from https://www.qt.io/download-open-source/ and install the latest version of Qt Creator, if you don’t already have it.
Once you have it installed, go to “Help -> About Plugins…” and enable “BareMetal”
Afterwards go into “Tools -> Options”. Select “BareMetal” in the left hand side menu and add a new GDB Server provider.
I’m using the following init command, even though you can get away with only “load”:
mon speed 1000 mon endian little mon flash download = 1 mon flash device = NRF51822 mon reset 0 load mon reset 0
This is how my BareMetal configuration looks like:
Next we need to add the nRF51822 device to the “Devices” list. Select the corresponding tab in left hand side menu:
Now that we have our device setup, we can add the debugger. Select “Build & Run” in the left hand side menu and then “Debuggers” tab. Just add a new entry and browse to your GNU ARM tools and select arm-none-eabi-gdb-py.exe. It is important to select the python version; unfortunately that is the only version Qt Creator supports. Once you select the python debugger, it should auto detect its version number and look something like this:
Next step is to add the compiler, just select “Compilers” tab. Add a new entry and select either arm-none-eabi-g++ or if you don’t want warnings about C99 flag and you think you won’t be using C++ then select arm-none-eabi-gcc. I prefer using C++ over pure C, even though the SDK is written in C99 and you will have some compatibility issues, fortunately for us the Qt Creator with g++ is smart enough to compile *.c files with C99 flag enabled and *.cpp files without it, which makes the compilation very easy compared to writing your own makefile where you need to have G++ and GCC compiling their own sources and linking them together (which probably is a better way to do it anyway).
Off topic aside, your compiler entry should look something like this:
After we have Debugger and compiler added to the Qt Creator we need to add the nRF51822 kit, by selecting the “Kits” tab. Just as before just add a new entry, and configure it as I have it in the picture with our defined compiler and debugger:
There is one additional step you have to take if you are running Windows. As far as I know the bug is not present in Linux. You have to run the debugger in asynchronous mode, otherwise when you try to debug your ARM micro, Qt Creator will just crash. Which is simple to do, select “Debugger” in left hand side menu, and then “GDB Extended” tab. Tick the “User Asynchronous mode to control the inferior”.
That’s actually all you have to do to have Qt Creator set up for programming nRF51822, compared to eclipse you don’t need to specify where are all the includes for GCC ARM, and other fancy configurations I was doing and I can’t recall at the moment.
Creating a project in Qt Creator
So the next step is to create a project and run the blinky example using Qt Creator. Normally in Qt Creator you would use .pro file to describe your compiler flags and overall project structure and etc. Now for our convenience people behind Qt have released a QBS “project definition structure”. With it, we can easily set up a project with all the necessary modules from nRF51 SDK. I’ve used multiple examples of people already defining the QBS file for nrf51822 and made some changes for my convenience, any of them should work. Nonetheless in the article and as example code I’ll be using my qbs template. What I have done compared to other qbs templates is that I’ve defined each module in a structure where it is easy to enable or disable them by just commenting or uncommenting specific modules in an array at the top of the file. Also I allow warnings, because I’m using G++ with C99 flag.
Note: at the moment I haven’t included any BLE drivers in the QBS file and I’m still rewriting and refining it. If you don’t want to have all BLE modules defined in the qbs file you can use this one.
First of all to continue, you must download the QBS: Download: nrf_blinky_example.zip (6.84K) file and extract it somewhere on your computer. Once you have extracted the files and have Qt installed and configured, just double click the qbs file “blinky_template.qbs” and the project should open. Then, on left hand side project tree double click the qbs file again to open for editing.
First thing we must do for you to be able to compile the blinky example we must specify where your Nordic SDK v10.x.x resides by changing line 7:
property string sdk: "../sdk_10/"
And also if you’re using any other board than the one pictured in the title, change “BOARD_BLE400” on line 40 to your board for example “BOARD_PCA10028”.
Technically you can already build the project at this stage, however, I like to also configure the build directory for both release and debug version. To do so, on the left hand side select “Projects” tab and edit build configuration for both modes to what you prefer like pictured below:
As you can see in the picture I’ve specified the build directory for debug mode to
I also do the same for release mode, by selecting it in the dropdown menu you can see in the screenshot and just changing directory “debug” to “release”. That’s pretty much it, at this point we can try to build the example by pressing “Ctrl+B” or the hammer icon on bottom-left corner
Running the blinky example
Once you have managed to compile the blinky example the next logical step would be to try and upload it to the board, we already configured Qt Creator for it to be able to connect to j-link and before we can run it directly from Qt you have to start the gdb server. I’m not sure how it is done in linux environment you can just look it up, but in windows just open the J-Link GDB Server and change the configuration to match what I have in the screenshot below:
Press OK, and you should get a dialog stating that GDB server is up and running:
Now in Qt Creator just press Ctrl+R or the arrow button on the bottom left corner to compile and upload the application to your board. And there you have it, you should have blinking LEDs on your board.
QBS template structure
Now that we have managed to compile and run a simple blinky example on our board it’s worth understanding how I have structured the QBS file. Once again let me remind that this doesn’t include BLE and is not fully finished but should do the trick for now.
First thing what you should notice is an array called “modules” on line 15. Here you are able to enable to or disable individual modules for your project. In our case you can see, that only one additional module “DELAY” was required for blinky example. If you want to also use “UART” or any other module enable them accordingly. If a module is dependent on another one and I haven’t screwed up it will enable it automatically. In case of “UART” it will also include the “FIFO” module even if you don’t enable it.
Once you enable the module in your project tree it will become green and on the contrary gray means it is disabled (captain obvious).
commonDefines are just your compiler definitions, some modules add definitions automatically to this array.
If you want to add additional files to your project, just create them in the root of your project directory and it should get automatically added to the project tree under “app header files” or “app source files” group.
Also important to note, by default it will use linker script which assumes you have S110 softdevice on your board. If you want to compile for a version without s110 on board just change s110_gcc_nrf51.ld to blank_gcc_nrf51.ld on line 83 in qbs file.
After all this hassle setting up the environment we should be able to write simple applications for nRF51 series microcontrollers. This should be enough to make yourself familiar with the very basics of the micro and later on move to the more advanced uses by writing Bluetooth application. Which I’ll try to cover in another article, but before that you can play around with the basic peripherals. For me normally next step is to get the UART working, which is actually really simple in nRF51, I’ll let you to work through the example code provided by nRF and by enabling the necessary module to run the UART example. Nonetheless if you are unable to I will quickly go through the necessary steps in the next article and how to get FreeRTOS up and running on this micro. Luckily for us SDK 10.x.x comes with all the hardware specific files for FreeRTOS.
Skywavedesign. (2015). swd_nrf51_s110_qt_template. Available: https://github.com/skywavedesign/swd_nrf51_s110_qt_template. Last accessed 12.12.2015.
Marcel Mulder . (2015). ST-LINK nrf51822 and QT Creator. Available: https://devzone.nordicsemi.com/question/24109/st-link-nrf51822-and-qt-creator/. Last accessed 12.12.2015.
wim . (2015). Debugging using QtCreator on Mac. Available: https://devzone.nordicsemi.com/blogs/702/debugging-using-qtcreator-on-mac/. Last accessed 12.12.2015.
Vidar Berg . (2015). Development with GCC and Eclipse. Available: https://devzone.nordicsemi.com/tutorials/7/development-with-gcc-and-eclipse/. Last accessed 10.11.2015.
Tim Hutt. (2014). Remote GDB debugging.. Available: http://lists.qt-project.org/pipermail/qt-creator/2014-June/003749.html. Last accessed 10.11.2015.