Eclipse & nRF52 create a native project

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

One thought on “Eclipse & nRF52 create a native project

Leave a Reply

Your email address will not be published. Required fields are marked *

This site uses Akismet to reduce spam. Learn how your comment data is processed.