Aaron Christiansen

Flashing your PineTime using an ST-Link and OpenOCD


The PineTime development kits are now shipping out, and to do anything interesting with yours, you’ll probably be looking to flash a firmware on to it.

With open-source tool OpenOCD and a cheap ST-Link programmer, it’s really easy to flash firmware once you know what to do!


There are a few things you need to do before you can follow this guide:

  • You’ll need to solder wires onto your PineTime’s SWD pins so that you can connect it to a programmer (or a Pi to unlock it - see below). See the wiki page for a diagram of which pin is which. (Some people have had success with just resting the pins in the holes on the board and not soldering them there, but I haven’t tried this.)

  • You must remove the flash protection your PineTime before you can flash it. It’s possible to do this using a J-Link, but they are very expensive. Fortunately, you can also do it with a Raspberry Pi; follow the Remove nRF52 Flash Protection with Raspberry Pi section of Lup Yuen Lee’s fantastic guide.

  • You need an ST-Link programmer; I use this cheap clone from Amazon UK. If you haven’t yet used an ST-Link on your Linux installation, you’ll need udev rules: I followed this guide to add mine.

Building OpenOCD

The build of OpenOCD you can get from your package manager might not work for our purposes, as it probably hasn’t been built with CMSIS-DAP support. We’ll build it from source using a GitHub mirror instead.

On Linux:

git clone https://github.com/ntfreak/openocd
cd openocd
./configure --enable-cmsis-dap

This will give you an OpenOCD executable inside the repo at src/openocd.

Configuring OpenOCD

You’ll need a configuration file to tell OpenOCD to connect to your ST-Link, and tell it what kind of chip we’ll be debugging. Save this in nrf52.cfg, at the root of your OpenOCD repo:

source [find interface/stlink.cfg]
transport select hla_swd
source [find target/nrf52.cfg]

Starting OpenOCD

Now we can start an OpenOCD server with our configuration! Run this in the repo root:

./src/openocd -s tcl -f nrf52.cfg -d3

-s tcl tells OpenOCD to look for files it needs in the tcl directory, such as the interface/stlink.cfg we specified in our config. -f nrf52.cfg runs our configuration file on OpenOCD, and -d3 prints the maximum amount of debugging information so it’s easier to diagnose any issues.

Connecting to OpenOCD

After starting OpenOCD, we now have a telnet server on port 4444 which we can connect to in order to issue commands to our ST-Link. Connect with:

telnet localhost 4444

You’ll get some preamble and a prompt which should look something like this:

Trying ::1...
Connection failed: Connection refused
Connected to localhost.
Escape character is '^]'.
Open On-Chip Debugger

There are two commands to check to ensure your chip is detected. targets should show one device, and flash banks should show two results.

> targets
    TargetName         Type       Endian TapName            State       
--  ------------------ ---------- ------ ------------------ ------------
 0* nrf52.cpu          hla_target little nrf52.cpu          running

> flash banks
#0 : nrf52.flash (nrf5) at 0x00000000, size 0x00000000, buswidth 1, chipwidth 1
#1 : nrf52.uicr (nrf5) at 0x10001000, size 0x00000000, buswidth 1, chipwidth 1

Looks good!


Flashing a firmware is now pretty easy. First, we want to ensure that our PineTime is stopped:

> reset halt
target halted due to debug-request, current mode: Thread 
xPSR: 0x01000000 pc: 0x00000462 msp: 0x20000800

You may want to clear the PineTime’s firmware before flashing a new one. This should happen as part of the programming process, but if you want to do it explicitly:

> nrf51 mass_erase
nRF52832-QFAA(build code: E0) 512kB Flash, 64kB RAM

Now for the actual flash! Give the path you’d like to program. Note that this path is relative from where you ran OpenOCD, not where you ran telnet, so you’ll probably want to give an absolute path here. Make sure you also include the verify reset at the end.

> program /home/aaron/projects/pinetime/app.bin verify reset
target halted due to debug-request, current mode: Thread 
xPSR: 0x01000000 pc: 0xfffffffe msp: 0xfffffffc
** Programming Started **
Adding extra erase range, 0x00005d2c .. 0x00005fff
** Programming Finished **
** Verify Started **
** Verified OK **
** Resetting Target **

You’re all done! If your PineTime didn’t restart for some reason, you can always reset it and kick it off with a command:

> reset run

Need a pre-built firmware?

Want to make sure you can flash your PineTime, but haven’t got round to building a firmware yet? I’ve built a simple firmware on go-smartwatch which should show “Hello!” on your PineTime’s display.

Download the pre-built firmware here!