Tags

,

 

I spent a couple more days getting my head around setting up nRF51822 projects in Eclipse.

The Goal

The goal of this post is to document “best practices” in setting up nRF51822 projects in Eclipse.  Through many (many) attempts, I was able to successfully build projects based on starting with an example project from the nRF51 SDK. 

Stuff to Know

It’s like “they” say – when you peel an onion you get a new bag of onions (although I am not sure who the “they” is).  In this case, the onion is the Eclipse environment.  In a previous post I mentioned the importance of the workspace and the project folder.  After more play, I have a better handle on the practical implications of these concepts.

Workspace

The workspace is a path within the file system that roots where the Projects where be located.  Eclipse allows us to change the workspace location which probably makes sense for larger projects, but for my current needs and abilities, changing the workspace location would cause confusion.

Project space

The key is to understand the purpose of the .project – Project Description File –  and .cproject files (link to Stackoverflow discussion on what these files are).  

Prior to realizing the .project and .cproject files would be in the folder that is tied to a Project in Eclipse, I was setting up the Project within a location within my file system outside of the workspace path.  Ultimately, I found this confusing so now all projects are contained within the folder that is tied to the workspace.

Bottom line: Once a project is initially set up, I check the folder in the filesystem to make sure the .project and .cproject are where I expect them to be.

Setting up a Project

The ways I could set up a project include:

  • starting new – either using a makefile or using managed makefiles.  I decided to not go this route because the nRF51 SDK has many, many header and libraries.  Plus, I do not have the skills to masterfully set up a makefile – or in the case of a managed makefile – set all the parameters.
  • starting from an example – this is my preferred way to start. 
  • starting from a project – doable, but I could only find one project and then there is a step that involves tweaking the file paths in the .project path.  Also, it brings in more libraries and the code is more complex than other examples.  Ideally, the nRF51 SDK would come with both Keil Packs and Eclipse Projects for each example.

Starting From an Example

note: modifying Makefile.posix must be done every time an updated nRF51 SDK is used.

The very first step is to update Makefile.posix file located within the<filepath to root of SDK folders> /components/toolchain/gcc directory.  Update the variables to reflect the GNU version that is installed.  The version of GNU I am using is 4.9.3.  Here’s the contents of my updated file:

GNU_INSTALL_ROOT := /usr/local/gcc-arm-none-eabi-4_9-2015q1
GNU_VERSION := 4.9.3
GNU_PREFIX := arm-none-eabi

I’ll use the ble_app_template example from the SDK.  Here are the steps to set up the example within a folder of a workspace.  Doing the steps in this ordered ensured the most success:

  • go to the workspace folder in the file system.  For example, my Eclipse workspace folder is /Users/margaret/Documents/EHAL/ARM/Nordic/nRF51
  • create a folder that will be the same name as what you will name the project in Eclipse.  In this example, I named the folder test2 E.G.: /Users/margaret/Documents/EHAL/ARM/Nordic/nRF51/test2
  • copy the config folder, Makefile and ble_app_template_gcc_nrf51.ld from the folder where it resides in the nRF51 SDK E.G.: /Users/margaret/Documents/nRF51_SDK_8.1.0/examples/ble_peripheral/ble_app_template/pca10028/s110/armgcc into the project folder created in the second step
  • create a folder to hold main.c.  I created one called Application.  Then copy the main.c program from the examples into the folder.
  • in Eclipse create a new project that starts with the Makefile (i.e.: Makefile Project with Existing Code).  On the “New Project” Dialog box, browse to the project folder you created above.  ALSO choose Cross ARM GCC under Toolchain for Indexer settings.  When I did not select the toolchain, CDT did not discover the gcc include files which is an important step that happens in a bit.  

Pasted Image 7 22 15 9 18 AM

However, later on debugging won’t work because an environment variable, which is a prefix to the gdb client isn’t set.  SO the environment variable cross-prefix needs to be set to arm-none-eabi-  since the gdb client is named arm-none-eabi-gdb.exe.  To set the cross-prefix variable, go into project properties->C/C++ Build/Build Variables, check the box Show system variables and scroll down to the cross_prefix.  While setting cross-prefix also check cross-make to make sure it is set to make.

Pasted Image 7 22 15 1 01 PM

  • Don’t enter a project name but browse to the folder within the workspace that will contain the project files E.G.: test2.
  • check that the .project and .cproject have been created within the project folder within the filesystem.  If they are not there, Eclipse does not think the project is contained in that folder.
  • check to make sure the build command = make.  I was having challenges getting the Build command to use the Makefile.  It turned out make was not being called.  Check Project -> Properties->C/C++ Build->Builder Settings  Build command is make.  If not, uncheck the Use default build command and type in make.
makeinbuildcommand
 
  • set up CDT to discover the toolchain paths and compiler settings.  This will add the gcc include files to the project and associate the makefile with CDT so the project uses the makefile.  Vidar describes how to do this in this post under “Enable auto discovery of symbols, include paths and compiler settings.”  I’m putting the steps here just in case the post goes away.
    • Enter project properties -> C/C++ General->Preprocessor Include Paths,etc.->Providers
    • Click on CDT GCC Build Output Parser and change the compiler command pattern from (gcc)|([gc]++)|(clang) to (arm-none-eabi-gcc)|([gc]++)|(clang)
    • Click apply button
    • Click on CDT Built-in Compiler Settings Cross ARM and replace ${COMMAND} with arm-none-eabi-gcc
    • Click apply button.
    • if the CDT discovered the gcc paths, there will now be an include folder within the project folder that include the gcc paths. I’m using gcc version 4.9.3.   Six include paths were located.
  • Make changes to the Makefile:
    • Add the following variables near the top of the Makefile and set the path to whatever you used. Mine are shown as examples:
      PROJECT_PATH = /Users/margaret/Documents/EHAL/ARM/Nordic/nRF51/test2
      SDK_PATH = /Users/margaret/Documents/EHAL/ARM/Nordic/nRF51/nrf51_sdk
    • update TEMPLATE_PATH e.g.: TEMPLATE_PATH = $(SDK_PATH)/components/toolchain/gcc
    • Do a Find/Replace all for Find: ../../../../../../..  Replace All: $(SDK_PATH)
    • Delete the line:  INC_PATHS += -I$(SDK_PATH)/../components/drivers_nrf/config
    • Modify the line: INC_PATHS  = -I../../../config  to the location of the config folder within the project: -I$(PROJECT_PATH)/config
    • change the path to main.c within the C_SOURCE_FILES variable from: ../../../main.c \ to $(PROJECT_PATH)/Application/main.c .  I put the main.c within the Application folder.
    • change the location of the INC_PATHS for the config directory to  -I$(PROJECT_PATH)/config
    • if the makefile compiles bsp.c, change the path to bsp.c within the C_SOURCE_FILES variable from: $(SDK_PATH)/bsp/bsp.c \ to $(SDK_PATH)/examples/bsp/bsp.c \
    • change the bsp path to:  INC_PATHS += -I$(SDK_PATH)/examples/bsp
    • set up the options for debugging.  Vidar covers this in his tutorial post.  I repeat his steps here:
      • Open makefile from project explorer and find the ‘-O3’ option in the CFLAGS variable and replace it with ‘-O0’. This will turn off compiler optimization.
      • Add ‘-g3’ option to CFLAGS to produce debugging information.
      • Link time optimization is then turned off by removing “CFLAGS += -flto -fno-builtin”
      • CDT has a build output parser that can parse include paths and symbols from the build output. To use this tool we need the Makefile to print the compiler commands.Search for the $(NO_ECHO)$(CC) $(CFLAGS) $(INC_PATHS) -c -o $@ $< line in the makefile.Add @echo arm-none-eabi-gcc $(CFLAGS) $(INC_PATHS) -c -o $@ $< on the line above to echo the symbols and include paths used when compiling the source files.
    • Replace this section of the Makefile from:

finalize: genbin genhex echosize

 

genbin:

@echo Preparing: $(OUTPUT_FILENAME).bin

$(NO_ECHO)$(OBJCOPY) -O binary $(OUTPUT_BINARY_DIRECTORY)/$(OUTPUT_FILENAME).out $(OUTPUT_BINARY_DIRECTORY)/$(OUTPUT_FILENAME).bin

 

## Create binary .hex file from the .out file

genhex: 

@echo Preparing: $(OUTPUT_FILENAME).hex

$(NO_ECHO)$(OBJCOPY) -O ihex $(OUTPUT_BINARY_DIRECTORY)/$(OUTPUT_FILENAME).out $(OUTPUT_BINARY_DIRECTORY)/$(OUTPUT_FILENAME).hex

 

echosize:

-@echo “”

$(NO_ECHO)$(SIZE)$(OUTPUT_BINARY_DIRECTORY)/$(OUTPUT_FILENAME).out

-@echo “”

 

clean:

$(RM)$(BUILD_DIRECTORIES)

 

cleanobj:

$(RM)$(BUILD_DIRECTORIES)/*.o

 

flash: $(MAKECMDGOALS)

@echo Flashing: $(OUTPUT_BINARY_DIRECTORY)/$<.hex

nrfjprog –reset –program $(OUTPUT_BINARY_DIRECTORY)/$<.hex

 

## Flash softdevice

flash_softdevice: 

@echo Flashing: s110_softdevice.hex

nrfjprog –reset –program $(SDK_PATH)/../components/softdevice/s110/hex/s110_softdevice.hex

to: 

#don’t need .bin so I took it out.

#finalize: genbin genhex echosize

finalize: genhex echosize

 

#genbin:

#@echo Preparing: $(OUTPUT_FILENAME).bin

#$(NO_ECHO)$(OBJCOPY) -O binary $(OUTPUT_BINARY_DIRECTORY)/$(OUTPUT_FILENAME).out $(OUTPUT_BINARY_DIRECTORY)/$(OUTPUT_FILENAME).bin

 

## Create binary .hex file from the .out file

genhex: 

@echo Preparing: $(OUTPUT_FILENAME).hex

$(NO_ECHO)$(OBJCOPY) -O ihex $(OUTPUT_BINARY_DIRECTORY)/$(OUTPUT_FILENAME).out $(OUTPUT_BINARY_DIRECTORY)/$(OUTPUT_FILENAME).hex

 

echosize:

-@echo “”

$(NO_ECHO)$(SIZE)$(OUTPUT_BINARY_DIRECTORY)/$(OUTPUT_FILENAME).out

-@echo “”

 

clean:

$(RM)$(BUILD_DIRECTORIES)

 

cleanobj:

$(RM)$(BUILD_DIRECTORIES)/*.o

 

#############################################################################

# Set up variables to run SEGGER’s JLINK utility

#############################################################################

JLINK_OPTS = -device nrf51422_xxac 

JLINK = JLinkExe $(JLINK_OPTS)

#############################################################################

# Target: erase

# remove all binaries from the nRF51

#############################################################################

erase: erase.jlink

$(JLINK) erase.jlink

erase.jlink:

printf “erase\nr\nexit\n” > erase.jlink

#############################################################################

# Target: flash_softdevice

# load the s110 softdevice onto the nRF51

#############################################################################

flash_softdevice: flash_softdevice.jlink

$(JLINK) flash_softdevice.jlink

flash_softdevice.jlink:

printf “loadfile /Users/margaret/Documents/EHAL/ARM/Nordic/nRF51/nrf51_sdk/components/softdevice/s110/hex/s110_softdevice.hex\nr\ng\nexit\n” >flash_softdevice.jlink

#############################################################################

# Target: flash

# load app onto the nRF51

#############################################################################

flash: flash.jlink

$(JLINK) flash.jlink

flash.jlink:

printf “loadfile /Users/margaret/Documents/EHAL/ARM/Nordic/nRF51/EC_Test_1/_build/nrf51422_xxac_s110.hex\nr\ng\nexit\n” > flash.jlink

      change the loadfile path under flash.jlink to match the path of the project.  E.g.: above has EC_Test_1.  Replace this with whatever the project name is, e.g.: test2

    • now it’s time to load up the include file paths in Eclipse so Eclipse can help with source line debugging. 
      • open up the Makefile and copy the INC_PATHS lines to an editor.  E.g.:
        INC_PATHS += -I$(PROJECT_PATH)/SimpleTimer/config
        INC_PATHS += -I$(SDK_PATH)/examples/bsp
        INC_PATHS += -I$(SDK_PATH)/components/RTT
        INC_PATHS += -I$(SDK_PATH)/components/drivers_nrf/nrf_soc_nosd
        INC_PATHS += -I$(SDK_PATH)/components/device
        INC_PATHS += -I$(SDK_PATH)/components/drivers_nrf/hal
        INC_PATHS += -I$(SDK_PATH)/components/libraries/button
        INC_PATHS += -I$(SDK_PATH)/components/drivers_nrf/timer
        INC_PATHS += -I$(SDK_PATH)/components/libraries/util
        INC_PATHS += -I../..
        INC_PATHS += -I$(SDK_PATH)/components/libraries/simple_timer
        INC_PATHS += -I$(SDK_PATH)/components/drivers_nrf/timer
        INC_PATHS += -I$(SDK_PATH)/components/drivers_nrf/common
        INC_PATHS += -I$(SDK_PATH)/components/toolchain
        INC_PATHS += -I$(SDK_PATH)/components/libraries/timer
        INC_PATHS += -I$(SDK_PATH)/components/drivers_nrf/gpiote
        INC_PATHS += -I$(SDK_PATH)/components/toolchain/gcc

 

      add these paths to Project Properties -> C/C++ General->Paths and Symbols-> GNU C
  • add make targets erase, flash_softdevice, flash
  • run the erase make target (assuming the flash on the nRF51 DK needs to be erased)
  • run the flash_softdevice make target (assuming the flash on the nRF51 DK does not have the s110 soft device)
  • run the flash make target to load the binary onto the nRF51 DK
I covered debugging in this post.  Since then, I’ve bumbled a few times setting up the Debug Configuration correctly.  Make sure to create the debug configuration under the GDB SEGGER J-Link Debugging folder.  
 

Pasted Image 7 23 15 9 51 AM

 
If you get an error message about file not found, most likely this is caused because the arm-none-eabi-gdb.exe client is not being used.  Check the build variables noted above as well as the Debug Configuration.
 

If You Get A Build Error Like This..

.

‘RTC0_INSTANCE_INDEX’ undeclared here (not in a function)

          .instance_id =  RTC##id##_INSTANCE_INDEX

 where there is a ##id## you most likely did not copy the config folder into the workspace and/or change the INC_PATHS for the config to point to the config folder in the workspace.  I addressed these steps above.  I mention them here because I’ve forgotten to do this a few times.
 

Whew!

Well, I got this far from repetition until I *think* I had somewhat of an idea what was going on within the Eclipse environment.  I’ll share anything else I learn. 
 
 
Thanks for reading this far.  Please find many things to smile about.
Advertisements