As seen in a previous post, working with nRF52 and Eclipse is not the easiest challenge !
This post will detail how to create a template project for a BLE project using a softdevice working on the PCA10040 board and using my ble library.
This can be apply to most of ble starting project with nRF52. I assume you configured Eclipse IDE as described in this post. As a pre-requisite you also need git. The tutorial works with SDK 12.3
Prerequisites
Ensure you have the last version of the different tools
- nRF52 command line tools v9 – from here.
- SDK Version 12.3 – from here.
- SoftDevice 132 V3.1
- Seeger tools >= V6.14h
Create a new project
- Go to File >> New >> C project
- In the project create the following directory structure
Inc >> will contain all the header files specific to your project
Src >> will contain all the source files specific to your project
- Clone the dsk_ble project
- Now the project have a new folder ble_dsk_library
- Now we can create a simple main.c file by moving the ble_dsk_library/main.c file to src/main.c
- Now we need a sdk_config.h file. You can take the one of the sdk in C:\nrf52\sdk\examples\ble_peripheral\ble_app_hrs\pca10040\s132\sdk_config.h and copy it into the inc folder.
Configure compiler
Create some Build Variable
- SDK_PATH with value c:/nrf52/sdk
Create Preprocessor entries
you can manually create all the entries but it is really long … so I recommend to close the Eclipse project and edit cproject file and add the following lines
<option id="ilg.gnuarmeclipse.managedbuild.cross.option.c.compiler.defs.914749029" superClass="ilg.gnuarmeclipse.managedbuild.cross.option.c.compiler.defs" useByScannerDiscovery="true" valueType="definedSymbols"> <listOptionValue builtIn="false" value="NRF52_PAN_1"/> <listOptionValue builtIn="false" value="NRF52_PAN_2"/> <listOptionValue builtIn="false" value="NRF52_PAN_3"/> <listOptionValue builtIn="false" value="NRF52_PAN_4"/> <listOptionValue builtIn="false" value="NRF52_PAN_7"/> <listOptionValue builtIn="false" value="NRF52_PAN_8"/> <listOptionValue builtIn="false" value="NRF52_PAN_9"/> <listOptionValue builtIn="false" value="NRF52_PAN_10"/> <listOptionValue builtIn="false" value="NRF52_PAN_11"/> <listOptionValue builtIn="false" value="NRF52_PAN_12"/> <listOptionValue builtIn="false" value="NRF52_PAN_15"/> <listOptionValue builtIn="false" value="NRF52_PAN_16"/> <listOptionValue builtIn="false" value="NRF52_PAN_17"/> <listOptionValue builtIn="false" value="NRF52_PAN_20"/> <listOptionValue builtIn="false" value="NRF52_PAN_23"/> <listOptionValue builtIn="false" value="NRF52_PAN_24"/> <listOptionValue builtIn="false" value="NRF52_PAN_25"/> <listOptionValue builtIn="false" value="NRF52_PAN_26"/> <listOptionValue builtIn="false" value="NRF52_PAN_27"/> <listOptionValue builtIn="false" value="NRF52_PAN_28"/> <listOptionValue builtIn="false" value="NRF52_PAN_29"/> <listOptionValue builtIn="false" value="NRF52_PAN_30"/> <listOptionValue builtIn="false" value="NRF52_PAN_31"/> <listOptionValue builtIn="false" value="NRF52_PAN_32"/> <listOptionValue builtIn="false" value="NRF52_PAN_33"/> <listOptionValue builtIn="false" value="NRF52_PAN_34"/> <listOptionValue builtIn="false" value="NRF52_PAN_35"/> <listOptionValue builtIn="false" value="NRF52_PAN_36"/> <listOptionValue builtIn="false" value="NRF52_PAN_37"/> <listOptionValue builtIn="false" value="NRF52_PAN_38"/> <listOptionValue builtIn="false" value="NRF52_PAN_39"/> <listOptionValue builtIn="false" value="NRF52_PAN_40"/> <listOptionValue builtIn="false" value="NRF52_PAN_41"/> <listOptionValue builtIn="false" value="NRF52_PAN_42"/> <listOptionValue builtIn="false" value="NRF52_PAN_43"/> <listOptionValue builtIn="false" value="NRF52_PAN_44"/> <listOptionValue builtIn="false" value="NRF52_PAN_46"/> <listOptionValue builtIn="false" value="NRF52_PAN_47"/> <listOptionValue builtIn="false" value="NRF52_PAN_48"/> <listOptionValue builtIn="false" value="NRF52_PAN_49"/> <listOptionValue builtIn="false" value="NRF52_PAN_51"/> <listOptionValue builtIn="false" value="NRF52_PAN_54"/> <listOptionValue builtIn="false" value="NRF52_PAN_55"/> <listOptionValue builtIn="false" value="NRF52_PAN_58"/> <listOptionValue builtIn="false" value="NRF52_PAN_63"/> <listOptionValue builtIn="false" value="NRF52_PAN_64"/> <listOptionValue builtIn="false" value="NRF52_PAN_65"/> <listOptionValue builtIn="false" value="BLE_DFU_APP_SUPPORT"/> <listOptionValue builtIn="false" value="BLE_STACK_SUPPORT_REQD"/> <listOptionValue builtIn="false" value="CONFIG_GPIO_AS_PINRESET"/> <listOptionValue builtIn="false" value="BOARD_PCA10040"/> <listOptionValue builtIn="false" value="NRF52"/> <listOptionValue builtIn="false" value="SOFTDEVICE_PRESENT"/> <listOptionValue builtIn="false" value="S132"/> <listOptionValue builtIn="false" value="NRF_SD_BLE_API_VERSION=3"/> <listOptionValue builtIn="false" value="SWI_DISABLE0"/> <listOptionValue builtIn="false" value="BLE_STACK_SUPPORT_REQD"/> <listOptionValue builtIn="false" value="DEBUG"/> <listOptionValue builtIn="false" value="NRF_LOG_USES_RTT=1"/> </option>
You may copy the blue et pink part in the different option entries for C and ASM preprocessor then for debug and normal build.
The two last #Defines can be included by default only in the Debug build part.
The different NRF52_PAN_XX correspond to hardware issues fixed in the sdk. I’m not sure how to get the right list to be used based on sdk version and hw version.
Softdevice reference are
SOFTDEVICE_PRESENT
S132
NRF_SD_BLE_API_VERSION=3
Add the Include directories
For including the header the best way is also to edit the cproject file directly and add them to the two build option : Release & debug
<option id="ilg.gnuarmeclipse.managedbuild.cross.option.c.compiler.include.paths.1037856738" name="Include paths (-I)" superClass="ilg.gnuarmeclipse.managedbuild.cross.option.c.compiler.include.paths" useByScannerDiscovery="true" valueType="includePath"> <listOptionValue builtIn="false" value="${ProjDirPath}/inc"/> <listOptionValue builtIn="false" value="."/> <listOptionValue builtIn="false" value="${ProjDirPath}/ble_dsk_library"/> <listOptionValue builtIn="false" value="${SDK_PATH}/components/drivers_nrf/comp"/> <listOptionValue builtIn="false" value="${SDK_PATH}/components/drivers_nrf/twi_master"/> <listOptionValue builtIn="false" value="${SDK_PATH}/components/ble/ble_services/ble_ancs_c"/> <listOptionValue builtIn="false" value="${SDK_PATH}/components/ble/ble_services/ble_ias_c"/> <listOptionValue builtIn="false" value="${SDK_PATH}/components/libraries/pwm"/> <listOptionValue builtIn="false" value="${SDK_PATH}/components/softdevice/s132/headers/nrf52"/> <listOptionValue builtIn="false" value="${SDK_PATH}/components/libraries/usbd/class/cdc/acm"/> <listOptionValue builtIn="false" value="${SDK_PATH}/components/libraries/usbd/class/hid/generic"/> <listOptionValue builtIn="false" value="${SDK_PATH}/components/libraries/usbd/class/msc"/> <listOptionValue builtIn="false" value="${SDK_PATH}/components/libraries/usbd/class/hid"/> <listOptionValue builtIn="false" value="${SDK_PATH}/components/libraries/log"/> <listOptionValue builtIn="false" value="${SDK_PATH}/components/ble/ble_services/ble_gls"/> <listOptionValue builtIn="false" value="${SDK_PATH}/components/libraries/fstorage"/> <listOptionValue builtIn="false" value="${SDK_PATH}/components/drivers_nrf/i2s"/> <listOptionValue builtIn="false" value="${SDK_PATH}/components/libraries/gpiote"/> <listOptionValue builtIn="false" value="${SDK_PATH}/components/drivers_nrf/gpiote"/> <listOptionValue builtIn="false" value="${SDK_PATH}/components/boards"/> <listOptionValue builtIn="false" value="${SDK_PATH}/components/drivers_nrf/common"/> <listOptionValue builtIn="false" value="${SDK_PATH}/components/ble/ble_advertising"/> <listOptionValue builtIn="false" value="${SDK_PATH}/components/drivers_nrf/adc"/> <listOptionValue builtIn="false" value="${SDK_PATH}/components/ble/ble_services/ble_bas_c"/> <listOptionValue builtIn="false" value="${SDK_PATH}/components/ble/ble_services/ble_hrs_c"/> <listOptionValue builtIn="false" value="${SDK_PATH}/components/libraries/queue"/> <listOptionValue builtIn="false" value="${SDK_PATH}/components/ble/ble_dtm"/> <listOptionValue builtIn="false" value="${SDK_PATH}/components/toolchain/cmsis/include"/> <listOptionValue builtIn="false" value="${SDK_PATH}/components/ble/ble_services/ble_rscs_c"/> <listOptionValue builtIn="false" value="${SDK_PATH}/components/drivers_nrf/uart"/> <listOptionValue builtIn="false" value="${SDK_PATH}/components/ble/common"/> <listOptionValue builtIn="false" value="${SDK_PATH}/components/ble/ble_services/ble_lls"/> <listOptionValue builtIn="false" value="${SDK_PATH}/components/drivers_nrf/wdt"/> <listOptionValue builtIn="false" value="${SDK_PATH}/components/libraries/bsp"/> <listOptionValue builtIn="false" value="${SDK_PATH}/components/ble/ble_services/ble_bas"/> <listOptionValue builtIn="false" value="${SDK_PATH}/components/libraries/experimental_section_vars"/> <listOptionValue builtIn="false" value="${SDK_PATH}/components/softdevice/s132/headers"/> <listOptionValue builtIn="false" value="${SDK_PATH}/components/ble/ble_services/ble_ans_c"/> <listOptionValue builtIn="false" value="${SDK_PATH}/components/libraries/slip"/> <listOptionValue builtIn="false" value="${SDK_PATH}/components/libraries/mem_manager"/> <listOptionValue builtIn="false" value="${SDK_PATH}/external/segger_rtt"/> <listOptionValue builtIn="false" value="${SDK_PATH}/components/libraries/csense_drv"/> <listOptionValue builtIn="false" value="${SDK_PATH}/components/drivers_nrf/hal"/> <listOptionValue builtIn="false" value="${SDK_PATH}/components/ble/ble_services/ble_nus_c"/> <listOptionValue builtIn="false" value="${SDK_PATH}/components/drivers_nrf/rtc"/> <listOptionValue builtIn="false" value="${SDK_PATH}/components/ble/ble_services/ble_ias"/> <listOptionValue builtIn="false" value="${SDK_PATH}/components/libraries/usbd/class/hid/mouse"/> <listOptionValue builtIn="false" value="${SDK_PATH}/components/drivers_nrf/ppi"/> <listOptionValue builtIn="false" value="${SDK_PATH}/components/ble/ble_services/ble_dfu"/> <listOptionValue builtIn="false" value="${SDK_PATH}/components/drivers_nrf/twis_slave"/> <listOptionValue builtIn="false" value="${SDK_PATH}/components"/> <listOptionValue builtIn="false" value="${SDK_PATH}/components/libraries/scheduler"/> <listOptionValue builtIn="false" value="${SDK_PATH}/components/ble/ble_services/ble_lbs"/> <listOptionValue builtIn="false" value="${SDK_PATH}/components/ble/ble_services/ble_hts"/> <listOptionValue builtIn="false" value="${SDK_PATH}/components/drivers_nrf/delay"/> <listOptionValue builtIn="false" value="${SDK_PATH}/components/libraries/crc16"/> <listOptionValue builtIn="false" value="${SDK_PATH}/components/drivers_nrf/timer"/> <listOptionValue builtIn="false" value="${SDK_PATH}/components/libraries/util"/> <listOptionValue builtIn="false" value="${SDK_PATH}/components/drivers_nrf/pwm"/> <listOptionValue builtIn="false" value="${SDK_PATH}/components/libraries/usbd/class/cdc"/> <listOptionValue builtIn="false" value="${SDK_PATH}/components/libraries/csense"/> <listOptionValue builtIn="false" value="${SDK_PATH}/components/drivers_nrf/rng"/> <listOptionValue builtIn="false" value="${SDK_PATH}/components/libraries/low_power_pwm"/> <listOptionValue builtIn="false" value="${SDK_PATH}/components/libraries/hardfault"/> <listOptionValue builtIn="false" value="${SDK_PATH}/components/ble/ble_services/ble_cscs"/> <listOptionValue builtIn="false" value="${SDK_PATH}/components/libraries/uart"/> <listOptionValue builtIn="false" value="${SDK_PATH}/components/libraries/hci"/> <listOptionValue builtIn="false" value="${SDK_PATH}/components/libraries/usbd/class/hid/kbd"/> <listOptionValue builtIn="false" value="${SDK_PATH}/components/drivers_nrf/spi_slave"/> <listOptionValue builtIn="false" value="${SDK_PATH}/components/drivers_nrf/lpcomp"/> <listOptionValue builtIn="false" value="${SDK_PATH}/components/libraries/timer"/> <listOptionValue builtIn="false" value="${SDK_PATH}/components/drivers_nrf/power"/> <listOptionValue builtIn="false" value="${SDK_PATH}/components/libraries/usbd/config"/> <listOptionValue builtIn="false" value="${SDK_PATH}/components/toolchain"/> <listOptionValue builtIn="false" value="${SDK_PATH}/components/libraries/led_softblink"/> <listOptionValue builtIn="false" value="${SDK_PATH}/components/drivers_nrf/qdec"/> <listOptionValue builtIn="false" value="${SDK_PATH}/components/ble/ble_services/ble_cts_c"/> <listOptionValue builtIn="false" value="${SDK_PATH}/components/drivers_nrf/spi_master"/> <listOptionValue builtIn="false" value="${SDK_PATH}/components/ble/ble_services/ble_nus"/> <listOptionValue builtIn="false" value="${SDK_PATH}/components/ble/ble_services/ble_hids"/> <listOptionValue builtIn="false" value="${SDK_PATH}/components/drivers_nrf/pdm"/> <listOptionValue builtIn="false" value="${SDK_PATH}/components/libraries/crc32"/> <listOptionValue builtIn="false" value="${SDK_PATH}/components/libraries/usbd/class/audio"/> <listOptionValue builtIn="false" value="${SDK_PATH}/components/libraries/sensorsim"/> <listOptionValue builtIn="false" value="${SDK_PATH}/components/ble/peer_manager"/> <listOptionValue builtIn="false" value="${SDK_PATH}/components/drivers_nrf/swi"/> <listOptionValue builtIn="false" value="${SDK_PATH}/components/ble/ble_services/ble_tps"/> <listOptionValue builtIn="false" value="${SDK_PATH}/components/ble/ble_services/ble_dis"/> <listOptionValue builtIn="false" value="${SDK_PATH}/components/device"/> <listOptionValue builtIn="false" value="${SDK_PATH}/components/ble/nrf_ble_qwr"/> <listOptionValue builtIn="false" value="${SDK_PATH}/components/libraries/button"/> <listOptionValue builtIn="false" value="${SDK_PATH}/components/libraries/usbd"/> <listOptionValue builtIn="false" value="${SDK_PATH}/components/drivers_nrf/saadc"/> <listOptionValue builtIn="false" value="${SDK_PATH}/components/ble/ble_services/ble_lbs_c"/> <listOptionValue builtIn="false" value="${SDK_PATH}/components/ble/ble_racp"/> <listOptionValue builtIn="false" value="${SDK_PATH}/components/toolchain/gcc"/> <listOptionValue builtIn="false" value="${SDK_PATH}/components/libraries/fds"/> <listOptionValue builtIn="false" value="${SDK_PATH}/components/libraries/twi"/> <listOptionValue builtIn="false" value="${SDK_PATH}/components/libraries/bsp"/> <listOptionValue builtIn="false" value="${SDK_PATH}/components/drivers_nrf/clock"/> <listOptionValue builtIn="false" value="${SDK_PATH}/components/ble/ble_services/ble_rscs"/> <listOptionValue builtIn="false" value="${SDK_PATH}/components/drivers_nrf/usbd"/> <listOptionValue builtIn="false" value="${SDK_PATH}/components/softdevice/common/softdevice_handler"/> <listOptionValue builtIn="false" value="${SDK_PATH}/components/ble/ble_services/ble_hrs"/> <listOptionValue builtIn="false" value="${SDK_PATH}/components/libraries/log/src"/> <listOptionValue builtIn="false" value="${SDK_PATH}/components/drivers_nrf/nrf_soc_nosd"/> </option>
Configure Compilation options (CFLAGS)
The final list of option should be :
arm-none-eabi-gcc -mcpu=cortex-m4 -mthumb -mfloat-abi=hard -mfpu=fpv4-sp-d16 -mabi=aapcs -O3 -ffunction-sections -fdata-sections -fno-builtin -fno-strict-aliasing -Werror -Wall -Wno-unused-variable -Wno-unused-function -Wno-unused-but-set-variable -g3 --short-enums --std=gnu99
For ASM compiler an option is added
-x assembler-with-cpp
Configure Linker options
Add the sdk module dependency
Create a virtual folder with name sdk, going to File >> New >> Folder
Then for each of the needed sdk component you can add it creating a new folder based on an alternate location targeting the SDK
To assign all the folder you can also base your list on an existing Makefile and use a regex to modify the .project file :
search : \$\(SDK_ROOT\)(/.+/)([^/]+)(/[^/]+.[cS]) \\ replace : <link><name>sdk/$2</name><type>2</type><location>C:/nrf52/sdk$1$2</location></link>
The list is here for a basic ble project
<linkedResources> <link> <name>sdk</name> <type>2</type> <locationURI>virtual:/virtual</locationURI> </link> <link><name>sdk/util</name><type>2</type><location>C:/nrf52/sdk/components/libraries/util</location></link> <link><name>sdk/log</name><type>2</type><location>C:/nrf52/sdk/components/libraries/log/src</location></link> <link><name>sdk/util</name><type>2</type><location>C:/nrf52/sdk/components/libraries/util</location></link> <link><name>sdk/timer</name><type>2</type><location>C:/nrf52/sdk/components/libraries/timer</location></link> <link><name>sdk/hardfault</name><type>2</type><location>C:/nrf52/sdk/components/libraries/hardfault</location></link> <link><name>sdk/boards</name><type>2</type><location>C:/nrf52/sdk/components/boards</location></link> <link><name>sdk/clock</name><type>2</type><location>C:/nrf52/sdk/components/drivers_nrf/clock</location></link> <link><name>sdk/nrf_common</name><type>2</type><location>C:/nrf52/sdk/components/drivers_nrf/common</location></link> <link><name>sdk/gpiote</name><type>2</type><location>C:/nrf52/sdk/components/drivers_nrf/gpiote</location></link> <link><name>sdk/uart</name><type>2</type><location>C:/nrf52/sdk/components/drivers_nrf/uart</location></link> <link><name>sdk/bsp</name><type>2</type><location>C:/nrf52/sdk/components/libraries/bsp</location></link> <link><name>sdk/button</name><type>2</type><location>C:/nrf52/sdk/components/libraries/button</location></link> <link><name>sdk/segger_rtt</name><type>2</type><location>C:/nrf52/sdk/external/segger_rtt</location></link> <link><name>sdk/ble_common</name><type>2</type><location>C:/nrf52/sdk/components/ble/common</location></link> <link><name>sdk/toolchain</name><type>2</type><location>C:/nrf52/sdk/components/toolchain</location></link> <link><name>sdk/softdevice_handler</name><type>2</type><location>C:/nrf52/sdk/components/softdevice/common/softdevice_handler</location></link> </linkedResources>
Some of the file in the imported directory won’t compile (this SDK is really a mess), you can manually remove them from build by right clicking on the file and select Property menu entry.
You have to do it for all the Configurations
The list of file to remove from build is :
timer/app_timer_freertos.c timer/app_timer_rtx.c toolchain/system_nrf52840.c toolchain/system_nrf51422.c toolchain/system_nrf51.c toolchain/gcc/gcc_startup_nrf51.S toolchain/gcc/gcc_startup_nrf52840.S segger_rtt/RTT_Syscalls_IAR.c segger_rtt/RTT_Syscalls_KEIL.c bsp/bsp_btn_ant.c timer/app_timer_ble_gzll.c
Flash the compiled firmware
The first step is to flash the softdevice. I’m using softdevice S132 version 3.1.0.
To flash it I recommend to use nRFGo Studio, since I add some trouble to start a project where the softdevice has been programmed using nrfjprog called by the given Makefile.
Debug Firmware
Console debugging
You can create a Flash Launch button to automatically send built firmware to the device using nrfjprog tool.
- Add a post build action to ensure the .hex file will always be the sameplace whatever the build mode you choose:
Apply it to all build configuration
- Then you can create an external tool launcher configuration
- One done, by clicking on the External Tool Launcher the firmware will be uploaded to the device automatically
GDB Debugger
The first time you need to create a configuration for the project
Once done you can start debugging, the program will be automatically downloaded to the board and executed.
Resources
You can download in the attached zip file an empty project with the .cproject file and .project file. template_ble
You can have a look at Segger Embedded Studio. Its free to use with Nordic Semiconductor Products.