This tutorial demonstrates how to flash CircuitPython onto an inexpensive nRF52840 dongle using OpenOCD and a Raspberry Pi. The Bluefruit LE Connect app will also be used to control the dongle from a mobile phone using BLE.
This is my 2nd CircuitPython tutorial. The first one demonstrated getting started with the Adafruit Feather nRF52840 Express which is very easy because it comes preloaded with a CircuitPython compatible bootloader.
For this tutorial, I’ll be using the nRF52840 dongle from Nordic Semiconductor. The part number is PCA10059.
The dongle is very inexpensive and stocked by most of the large online electronics distributers. It’s similar to the Adafruit Feather except it doesn’t have a battery connector or charging circuit. The board is designed by Nordic to help develop wireless solutions such as Bluetooth Low Energy.
The main chip is an nRF52840 SoC. The board has a card edge USB connector so it can be plugged directly into a computer without a cable. There are 20 castellated mounting holes which can be used to solder directly to another board or accept common 2.54 mm pin headers. They expose 15 GPIO pins. There is a user switch (SW1), a reset button, an RGB LED (LD2) and a regular green LED (LD1).
On the bottom side of the board is an unpopulated 10 pin solder pad (P1). It is for a standard 1.27 mm pitch Serial Wire Debug interface (SWD) which can be used for debugging or programming. The SWD interface also exposes a plug of nails adapter for use with a spring-pin connector.
The bottom center of the board contains solder pads for an additional 9 GPIO’s. There are also 2 more castellated mounting holes inset from the others that provide easy access to the SWD clock (SWDCLK) and bi-directional data input/output (SWDIO). This is convenient because the dongle’s bootloader is not compatible with CircuitPython. Nordic provides utilities for DFU programming over USB, but they won’t let you overwrite the bootloader unless it’s vendor signed. As far as I can tell the dongle’s existing bootloader can only be overwritten using an SWD compatible debugging probe such as Segger J-link.
I like the J-Link because it just works. It’s supported by most IDEs and compatible with most MCUs. It’s very popular and well documented. I’ve used it many times to recover bricked boards. A convenient way to connect the J-link to the nRF52840 dongle is with a Tag-Connect 2050 plug-of-nails connector.
It mates well with the nRF52840 dongle. The 3 outer pins slide through the board while the spring pins make contact with the SWD interface. You can physically hold it in place during programming or use a retaining clip sold separately to secure it. My Tag-Connect 2050 came with a 10 pin plug so I etched a small adapter board. Here are the eagle files.
The J-link is a great tool for debugging and programming. Unfortunately it’s expensive. Therefore, I’ve come up with an alternative low cost solution for this tutorial.
OpenOCD which is short for Open On-Chip Debugger, is an open source project designed to provide debugging, in-system programming and boundary-scan testing for embedded target devices. It has support for the nRF52 chips and it supports using the Raspberry Pi’s GPIO as a debug adapter.
Currently OpenOCD requires manual installation to get the necessary features. I recommend you use a freshly wiped Raspberry Pi 3 running the latest updated version of Raspbian. A few necessary libraries including autoconf, libtool and libusb-dev will be required. These prerequisites may vary if you’re using a different OS. Install the libraries using apt-get install.
CD into the home directory and use git clone to download the OpenOCD repository into a folder called openocd-code. The recursive parameter is used to pull any necessary submodules. Afterwards, CD into the new folder.
Run the bootstrap script to begin the configuration.
Next run the configure script. The –enable-BCM2835GPIO parameter is passed to enable Raspberry Pi GPIO support. This allows the Pi’s GPIO pins to be used as a bit bang debugger. Afterwards a configuration summary is displayed. Don’t worry if it doesn’t mention the Raspberry GPIO. It still works.
The make utility is used to compile the source code. It takes around 20 minutes to complete on a Pi3 and will probably take a lot longer on an older Pi.
Sudo make install is used to install OpenOCD.
When OpenOCD is run, it looks for a config file to set the interface and target. The interface is the hardware debug adapter which will be the Raspberry Pi GPIO. The target device is the nRF52840 chip. Create a new folder in the home directory called openocd-config and use Nano to create a blank openocd.cfg file.
Here’s the contents of the openocd.cfg file. Uncomment lines appropriate to your Raspberry Pi. If you encounter errors, try uncommenting adapter_khz and set it to a lower speed.
I relied heavily on a post to the Linux Device Hacking forum by Joerg999 to derive the settings for the openocd.cfg file. The SWD GPIO pins are specified for the clock and the data input output as GPIO 25 and 24 respectively. The transport is set to SWD as opposed to JTAG. Chipname is set to the nRF52840. OpenOCD comes with a configuration file for the nRF52 chips so source can be used to specify the target. Init to initialize. Targets, should display the single target status for the nRF52840. Reset halt, halts the target.
Before using OpenOCD the SWD wiring needs to be set up between the Pi and the nRF52840 dongle. The SWDIO pin on the dongle is connected to GPIO 24. The SWDCLK pin is connected to GPIO 25. Power and ground are connected by plugging the dongle into the Pi. The nRF52840 has an on-chip regulator that can be set from 1.8 to 3.3 V. My board came set to 3.3 V so its GPIO’s are Pi friendly.
I recommend you disconnect power to the Pi before making any connections.
Make sure you are in the openocd-cfg folder and type sudo openocd to start the program. The summary should look as follows. If you get errors check your wiring and try lowering the clock speed.
The summary should indicate OpenOCD is listening for telnet connections on port 4444. Next install a telnet client such as the following:
Telnet into OpenOCD using localhost on port 4444.
Adafruit’s GitHub site contains an nRF52 bootloader repo that’s compatible with the PCA10059 dongle and CircuitPython. Click releases and scroll down to the PCA10059 bootloader and download the most recent hex file. Once the hex file is downloaded, the nRF52840 dongle can be erased and the hex flashed.WARNING: wiping the chip will reset the voltage regulator.
When you erase the chip, it clears the User Information Configuration Registers (UICR). This includes the RegOut0 register which controls the chip’s voltage regulator output. This was set to 3.3 V at the factory, but when it’s cleared, the default value is 1.8 V which is too low to be compatible with the Pi’s 3.3 V GPIO pins. Fortunately the settings don’t take effect until the chip is reset and when the Adafruit bootloader is flashed it will set the regulator back to 3.3 V. However, if the dongle is reset , unplugged or something goes wrong before flashing then the chip will basically be bricked and there would only be 2 recovery options.
You can modify the dongle to use an external 3.3 V power supply through the VDDOUT pin. This is accomplished by cutting the SB2 trace on the bottom of the board and soldering together SB1. .
Alternatively, you could use a debugger that supports level shifting such as the J-link EDU which has a target voltage range of 1.2 to 5 V. The J-link Mini won’t work because its minimum target voltage is 3.3 V. Another option is to use a level shifter board between the Pi and the nRF52840 dongle such as this 4 channel Adafruit board.When using a level shifter, it will probably be necessary to reduce the clock speed.
The following Open OCD commands will erase the chip, flash the new firmware and verify. Please make sure you specify the full path of the hex file. For example: /home/pi/Downloads/pca10059_bootloader-123.hex
If there are no errors then it should be safe to reset the chip.
Afterwards, a new device folder called NRF52BOOT should be detected by the Pi.
To install CircuitPython, just download the most recent UF2 file for the PCA10059 from the CircuitPython repo and copy it to the NRF52BOOT folder.
The demo program in this tutorial will use the free Adafruit Bluefruit LE Connect app which has versions for both Android and iOS devices. The app provides a variety of tools to communicate with BLE devices. The demo will use the color picker feature to control the dongle’s RGB LED.
Two libraries from the Adafruit CircuitPython Bundle will be required to communicate with the Bluefruit LE Connect app:
Download the latest bundle and extract the two folders to the /media/pi/CIRCUITPY device folder.UPDATE: Adafruit has made extensive changes to the CircuitPython BLE library. I have revised the code below appropriately.
The code sets up pulse width modulation (PWM) for the GPIO pins of the board’s RGB LED. A BLE UART server is set up to start advertising. The program waits for a connection. Then while connected it monitors the UART server packet stream for color packets. Upon receipt, the RGB color values (0 to 255) are scaled to the duty cycle range (0 to 65535). The values are also inverted because the onboard RGB LED sinks the cathodes. Therefore a zero pulse is full on and a 65535 pulse is off. Finally the PWM duty cycle values are updated which sets the RGB to the specified color packet.
The Bluefruit LE Connect app color picker can now be used to control the nRF52840 dongle’s RGB LED.
In case you want to restore the nRF52840 to its factory bootloader:
My next tutorial demonstrates how to use CircuitPython with LCD displays and introduces the DisplayIO library.