CMake scripts for developing projects with Nordic Semiconductor nRF5 series SoCs, utilising the CMake scripts found in the Nordic nRF5 Mesh SDK.
This project originally forked from cmake-nRF5x which is a self-contained nRF5 CMake solution. As this project takes a different approach (using Nordic Mesh SDK) it was set up as a new project.
Currently supports:
- nRF5 SDK v17.0.2
- nRF5 Mesh SDK v4.2.0
The script makes use of the following dependencies which are downloaded by the script:
- nRF5 SDK by Nordic Semiconductor - SoC specific drivers and libraries (also includes a lot of examples)
- nRF5 mesh SDK by Nordic Semiconductor - A mesh SDK which uses CMake, and is used for its CMake configuration
The script depends on the following external dependencies:
- JLink by Segger - interface software for the JLink familiy of programmers
- Nordic command line tools (
nrfjprog
andmergehex
) by Nordic Semiconductor - Wrapper utility around JLink - Python
- Nordic nrfutil by Nordic Semiconductor - a utility for generating DFU packages. Install with
pip install nrfutil
. - ARM GNU Toolchain by ARM and the GCC Team - compiler toolchain for embedded (= bare metal) ARM chips. On Windows, download directly. On a Mac, can be installed with homebrew:
brew tap ArmMbed/homebrew-formulae brew install arm-none-eabi-gcc
The script depends on the nRF5 SDK and the nRF5 mesh SDK. It can download these dependencies for you.
After setting up your CMakeLists.txt as described below, or using the example project, to download the dependencies run:
cmake -Bcmake-build-download -G "Unix Makefiles"
cmake --build cmake-build-download/ --target download
cmake -Bcmake-build-debug -G "Unix Makefiles" -DCMAKE_BUILD_TYPE=Debug
This will download the dependencies and then generate the build files using the toolchain.
Note: You can also follow the tutorial on the NRB Tech blog.
-
Download this repo (or add as submodule) to the directory
nRF5-cmake-scripts
in your project -
It is recommended that you copy the example
CMakeLists.txt
andsrc/CMakeLists.txt
into your project, but you can inspect these and change the structure or copy as you need -
Search the SDK
example
directory for asdk_config.h
,main.c
and a linker script (normally named<project_name>_gcc_<chip familly>.ld
) that fits your chip and project needs -
Copy the
sdk_config.h
and the projectmain.c
into a new directorysrc
. Modify them as required for your project -
Copy the linker script from the example's
armgcc
directory into your project -
Adjust the example
CMakeList.txt
files for your requirements, and to point at your source filesNote: By default, C and assembly languages are enabled. You can add C++ with
enable_language(C ASM)
-
Optionally add additional libraries:
Many drivers and libraries are wrapped with macros to include them in your project, see
includes/libraries.cmake
. If you need one isn't implemented, please create an issue or pull request.To include BLE services, use
nRF5_addBLEService(<service name>)
.
After setup you can use cmake as usual:
-
Generate the build files:
cmake -Bcmake-build-debug -G "Unix Makefiles" -DCMAKE_BUILD_TYPE=Debug
-
Build your app:
cmake --build cmake-build-debug --target <your target name>
There are also other targets available:
merge_<your target name>
: Builds the application and merges the SoftDevicesecure_bootloader_<your target name>
: Builds the secure bootloader for this targetuECC
: Builds the uECC librarybl_merge_<your target name>
: Builds your application and the secure bootloader, merges these and the softdevicepkg_<your target name>
: Builds and packages your application for DFUpkg_bl_sd_<your target name>
: Builds and packages your application, the SoftDevice, and bootloader for DFU.
Immediately after the call to nRF5_setup()
in your root CMakeLists.txt
, add the line:
enable_language(CXX)
By default, SEGGER RTT will be init in the bootloader, and then re-init in the app at a different memory location. The RTT client reads memory directly from RAM, so will only pick up on the App's RTT memory. To make RTT work across bootloader and app you need to only init in the bootloader and ensure the App continues to use the same RAM location for RTT.
To do this, create a new header rtt_config.h
, add:
#define SEGGER_RTT_SECTION ".rtt"
and also copy in all the SEGGER_RTT_CONFIG_...
defines from sdk_config.h
/app_config.h
. Include this file in your sdk_config.h
/app_config.h
and the bootloader sdk_config.h
/app_config.h
.
In the nRF52 SDK, modules/nrfx/mdk/nrf_common.ld
, add the following before .data : AT (__etext)
:
.rtt:
{
} > RAM
This symbol must be removed from the hex file, to do this ensure ".rtt" is in the list of symbols to remove from hex passed to nRF5_addExecutable
(see example project).
Ensure the RAM start and size are aligned in the app and bootloader linker scripts.
In the nRF52 SDK, external/segger_rtt/SEGGER_RTT.c
, change the SEGGER_RTT_Init
function to:
void SEGGER_RTT_Init (void) {
if(_SEGGER_RTT.acID[0] != 'S') {
_DoInit();
}
}
This ensures that RTT is not re-init in the App if already init in the bootloader.
Ensure all the SEGGER files are compiled in your bootloader – refer to the _debug
makefiles to see what is required.
Ensure the bootloader sdk_config.h
/app_config.h
is configured to use RTT.
You should then see continuous RTT output from the bootloader and App.
In addition to the build targets the script adds some support targets:
FLASH_SOFTDEVICE
: Flashes the nRF softdevice to the SoC (typically done only once for each SoC if not using DFU flash target)flash_<your target name>
: Builds and flashes your applicationflash_bl_merge_<your target name>
: Builds the bootloader and application, and flashes both and the softdeviceFLASH_ERASE
: Erases the SoC flash
To start the gdb server and RTT terminal, build the target START_JLINK_ALL
:
cmake --build "cmake-build" --target START_JLINK_ALL
There are also the targets START_JLINK_RTT
and START_JLINK_GDBSERVER
to start these independently.
MIT.
Please note that the nRF5 SDK and mesh SDK by Nordic Semiconductor are covered by their own licenses and shouldn't be re-distributed.