Using Segger Studio, Nordic SDK and Arduino with Particle Xenon
The Particle Xenon is a nice CPU module based on the brand new Nordic Semiconductor NRF52840. Last I looked, retail price was $15 so it’s very compelling. This article is about ignoring the Particle firmware and using a totally different operating system and development chain for it.
I waited months for my Xenons in order to replace some Adafruit NRF52 boards. They have the exact same pinout and mechanics. The Xenon uses the newer processor (with twice the ram and flash), is FCC certified, and has a 4MB spi flash for extra storage. It’s also about half the cost!
Unfortunately the Xenon also comes with very incomplete software. The firmware doesn’t yet support traditional Bluetooth and it’s missing features like sleep. I have great faith in Particle and expect the firmware to add these features but I have a project waiting for this.
Adafruit is also working on their Arduino for the chips but they don’t yet have the Xenon files in their Arduino port. There’s a section at the end of this article about using Arduino with the Xenon.
So, I decided to try developing on the Xenon using the Nordic Semi NRF5 SDK, instead of the particle firmware. It seems to be working fine.
To get started you need Segger Embedded Studio (free for Nordic development).
SES requires a Segger device for connection. If you’re a hobbyist that would be the Segger JLink EDU (purchase here) for about $60 or the JLink Mini EDU for about $20. You can develop without debugging using the SDK but getting a JLink is totally worth it.
This also needs an SWD adapter cable.
Also install the Nordic NRF5 SDK. This is a zip file that I unzipped into a root folder with a short name (no spaces or funny characters in the folder name).
Segger Studio installs the rest of the toolchain (gcc-arm).
Once the prerequisites are installed, run Segger Embedded Studio (SES). The top menu has a command Tools / Package Manager … Click this and refresh the package list then find the Nordic tools package and install it.
I personally use Visual Studio Code for development, but I use SES for building, debugging, and quick edits. Normally I keep both windows open simultaneously. Nothing special about the VSCode installation.
Connection requires two USB ports. Use this order:
- Connect the JLink to the Xenon using the debug port.
- Connect the JLink to a USB port.
- Connect the Xenon USB input to a USB port.
It’s easy to do the first test. Start up SES and select File / New Project…
SES has strange definitions of project and solution. I treat them as the same. When you create a new project it builds a project file (foo.emProject) that you load using “Open Solution”. Huh?
Put it in a new solution and for project settings change the Target Processor to the NRF52840_xxAA.
This will create a simple hello world application. You can build and download in one step by doing a Go (F5) or you can build then download then go…
When you run it the Debug Terminal will show Hello World nns.
A Serious NRF52840 Application with Bluetooth
To move on to a more serious application, the best thing to do is start with a Nordic-supplied example program. To use a Nordic sample program go to the folder (C:\nrf5_sdk\examples\ble_central\ble_app_hrs_c in my case) and then dive into the pca10056\s140\ses folder where the Segger Embedded Studio (ses) project file lives. Double-click the emProject file to load the project.
The pca10056 is the codeid for the Nordic NRF52840-DK board, which is a pretty slim board and seems to work fine as a starting point for the Xenon. The code also won’t deal with the Particle Lipo charging system nor the antenna selector.
This will produce a working bluetooth application (in my case) but all of the dependencies require the app being in the nrf5 sdk folder — which sucks.
Move the app by moving the entire folder somewhere useful (e.g. Documents) and then edit the emProject file with better paths. I added a macro for the base SDK path then updated the relative paths to the SDK code in the emProject file. Also look at the emSession file and remove any prior paths.
At one point SES was convinced the firmware on the chip was up to date (it wasn’t). I think it uses a CRC to verify the flash has changed so there is a small possibility the CRC is unchanged I guess. I finally ended up clearing the flash and then it failed crc and downloaded and worked.
The SES project settings require all individual include paths for the SDK. This is a lot of paths. I worked through failed compiles, adding paths as required, until it compiled. Some care is required as the SDK has multipath options for their different chips (so the same file in multiple places). Apparently you also have to point to each individual c/c++ file used by the source code (including the nrf5 sdk). Rather tedious.
It’s not at all clear where the Nordic soft-device (the API library for the chip) and the bootloader live in the SES processing. More detective work.
In the Weeds
I’m a newbie but here are some helpful hints. Feedback is welcome.
Code To Look At
Two repositories are critical. Open source smile.
This is a really nice Arduino layer over the nRF52 SDK. It provides examples and good working code. Clone it locally.
Here you can download the current SDK tree. Unzip it and put it somewhere.
The Nordic Semiconductor documentation is abysmal. No, it’s worse than that. Their examples, however, are very illustrative and they have a user forum. So, all is not lost. Also, there’s the working Adafruit layer for additional examples. Please buy something at Adafruit.
There are two key files you have to create in your project (or start with samples more likely).
- config/sdk_config.h — this contains all of the DEFINES for sdk modules that you will include (pwm, gpio, spi, …). It also defines default config values when you create instance objects. Otherwise default may come from the generic file in the sdk for the processor.
- flash_placement.xml — if you use the SoftDevice (the Bluetooth and ? library) this locates stuff. See the doc.
It’s also nice to add the Xenon to the sdk board list (the equivalent of variant.h in Arduino). Follow up by changing the BOARD’s preprocessor definition in the emProject to BOARD_PARTICLE_XENON. Add
- board.h in components/boards contains the list and I also added a
- particle_xenon.h with pin definitions
I use VSCode to edit the .emProject file. Especially with a project macro for the sdk folder it’s efficient. SES auto-reloads the project on save by VSCode. You get three common build errors:
- Can’t find header file: they don’t support recursive include paths, so find the file in the nrf5-sdk folder tree and add the path to the project file.
- Undefined method linked-to. Add the sdk’s xxxx.c file to the project tree (use Add Existing File…).
- Constant with very strange name doesn’t exist. Like NRFX_RTC0_INST_XXX or something. This means either you need to enable an instance (here NRFX_RTC0) or the legacy politely-stuff is interfering and should be commented out.
For source files the projects do support recursion. This is done by creating a new folder (with the path name imho) and making it dynamic linked to the folder you want (example ./Utility) and recursion is a checkbox.
The Sdk_Config.h File
If you’re familiar with tiny processors this file is familiar. It contains all of the on/off of the individual modules within the processor as well as structure defaults. It also has legacy stuff that tends to interfere and just generally it’s painful. If you can avoid editing this that’s a good thing because it’s formatted and read/written by an editor (if you have one). The costly (Keil and IAR) compilers support the format better than Segger.
Segger recommends a useful but primitive third-party app named CMSIS Configuration Wizard. Since the code is available I improved it noticeably.
See below for my spin on it. I hate java so I run this in a VM but it works well. You just run it on the config file and it reads/writes it.
Power Usage when Debugging
I’m debugging a system with usage in the single digit mA range. I couldn’t figure out why my power usage was 1.5mA in sleep mode when I randomly disconnected (in software) the debugger and the power dropped way down. It’s not the SWD port power (which is minimal) but the CPU supporting the debugger. Oops.
I’ve been working with SES for a a short while. I really like it. The IDE (interface) is ok, but worse than Visual Studio Code, except for two things.
- When there’s a build error it opens the file and scrolls to the first error and shows error lines with a red x-circle. That’s nice.
- The debugger is very similar to Visual Studio (real) and that’s a wonderful thing. It has breakpoints and shows local values and lets you step in and out and … yay.
SES builds like Visual Studio, not like Arduino — on my system a typical build takes <1 sec. Full build is maybe 5 seconds. Sweet!
So, highly recommended as a nRF52840 development environment. I run Visual Studio Code at the exact same time for serious editing — the apps synchronize extremely well.
I ported about 5,000 lines of Arduino code to the nRF5 SDK in under a week.
Adafruit Bootloader and Arduino
If you’d rather use Arduino instead of nrf5 SDK directly, the code is starting to become available.
Adafruit is starting to support the Xenon, as expected. The board files were added on Dec 4th (two days ago as I write this). See sdk-root/boards/particle_xenon.h for example.
Update: as of Jan 1, 2019 I was able to build and run an Arduino application on the Particle Xenon. For my application (which uses none of the standard Xenon pinout :) ) the bootloader works ok as-is because it only uses internal pin definitions for the Xenon. The reset pin is incorrect but it doesn’t seem to matter.
As of Jan 19, 2019 the latest Arduino build (0.9.3) seemed to work on my Feather nrf52832 and mostly worked on my Xenon - I couldn’t get Serial to work.
So, use the Arduino IDE to upload the latest bootloader to the Xenon, then…
Add a folder named particle_xenon here (version numbers may change):
Add two files to the folder: variant.h and variant.cpp. I started with the pca10056 variant files. The variant.cpp is unchanged, set the Particle-specific mappings in variant.h using internal pin numbers: e.g.
#define PIN_SPI_MISO (46)
#define PIN_SPI_MOSI (45)
#define PIN_SPI_SCK (47)
#define PIN_WIRE_SDA (26)
#define PIN_WIRE_SCL (27)
Then, add a section in the boards.txt file to support the xenon, modeled after the 52840 express. Here’s an extract of parts to show what’s needed. I copied the 52840 express and renamed stuff. Mainly the Build section needs to be changed.
# Particle Xenon Board
# DFU Mode with CDC only
# ---- (stuff left out here)
Note that when you use Arduino to update the board library it will wipe this stuff out so save it elsewhere.
Once you’ve added the two files and updated the boards.txt file you can run VSCode (or the Arduino IDE) and select Particle Xenon from the board manager list.
Debugging Arduino with the JLink debugger
It turns out to be really easy to debug Arduino code using the JLink debugger and Ozone or Segger Studio. Because Arduino builds a monolithic application either debugger can just be dropped into the build folder as follows.
I use Visual Studio Code to create Arduino applications but you can use the standard Arduino IDE if you hate yourself.
Create your Arduino application and upload it to the Xenon as usual. This will require also uploading the Arduino bootloader — which the Arduino application can easily do. Note the build folder path.
Comment: for some reason the Adafruit build options don’t turn off optimization in debug which makes it painful to debug. The option can be changed in the boards.txt file.
Run Segger’s Ozone application and create a new project
- for the nrf52840_xxAA
- no peripherals
- interface SWD, USB, 1MHz
- elf file can be found in the root of your build folder
Now, when you attach to a running application and halt (break) it will show all source code and let you fully debug. Very cool.
Segger Studio Setup
In Segger Studio create a new project in a new solution. Use the Nordic externally built option:
Use section placement of Flash (I guess) and pick your target processor. The Xenon would be nrf52840_xxAA. The Feather nrf52 would be nrf52832_xxAA. Select your xx.elf in the build folder as the Load File.
At this point things are more or less working.