JTAG and SWD

JTAG and SWD tips for Particle Devices.

JTAG ("Joint Test Action Group") is a standard for testing and verifying electronic circuit boards. It can be used with Photon, P1 and Electron devices and this document will describe using it for tasks like programming flash and saving configurations.

JTAG can also be used with a source-level debugger (gdb and OpenOCD), but that's a big topic and will get its own tutorial.

There is also a variation known as Serial Wire Debug (SWD), used with ARM devices, of which the Photon/P1/Electron are. It's also used with the mesh devices (nRF52840). This is helpful because it only requires two pins (D6 and D7).

Occasionally you'll see SWIM was well, but that's generally for STM8 processors. It won't hurt if your programmer supports SWD and SWIM, but a SWIM-only programmer can't program STM32 Particle devices.

Programmers

Particle Debugger

The Particle Debugger is the easiest way to use SWD on mesh devices. It connects easily with the included ribbon cable.

Debugger

It can also be used with the Photon, P1, Electron, and E Series using the debugging header.

Another common programmer is the ST-LINK/V2. It connects to your computer using USB and to the board using JTAG or SWD.

ST-LINK/V2

It can only be used with 1st and 2nd generation devices (Photon, P1, Electron, E Series, and Core), not with mesh devices.

There are also "ST-LINK/V2 Mini" devices. These also connect by USB but only use the SWD interface. These inexpensive clone devices are available on Amazon and eBay for US$12 or even less.

ST-LINK/V2 Mini

It can only be used with 1st and 2nd generation devices (Photon, P1, Electron, E Series, and Core), not with mesh devices.

Particle Photon Programmer Shield

Finally, there's the Particle Programmer Shield, primarily designed for the Photon but can be used with the Electron.

Particle Programmer Shield

It can only be used with 1st and 2nd generation devices (Photon, Elecron, and Core), not with mesh devices.

Connecting to the Photon/Electron/P1

Since the JTAG/SWD interface uses the same pins as your project may use, it will probably be necessary to stop your code from running so it won't reinitialize the pins needed for JTAG/SWD. The easiest way is to enable DFU mode (blinking yellow). This works even if you have a P1 without a USB port.

Even if you don't use the pins, you will likely have problems using SWD in normal operating mode (breathing cyan).

JTAG

Pins:

  • D7: TMS
  • D6: TCK
  • D5: TDI
  • D4: TDO
  • D3: TRST
  • GND

SWD

Pins:

  • D7: SWDIO
  • D6: SWCLK
  • GND

Particle Debugger

With the Particle Debugger positioned like this, USB connector toward you and the headers facing up:

Debugger

Left Header Right Header
VDD SWCLK
RTS SWDIO
RX NC
TX NC
CTS GND
GND VUSB

In order to use SWD debugging you need to connect:

  • D7: SWDIO
  • D6: SWCLK
  • GND

You can optionally connect the serial TX and RX pins for Serial1 serial debugging.

Programmer shield

Since you plug the Photon into the programmer shield, there's nothing to connect.

Select computer operating system:

Installing OpenOCD - Standalone Installation

If you've already set up Particle Debugging with Eclipse you can use the installation of OpenOCD included with that and skip to the next section.

OpenOCD is more complicated to install, but works on Mac and Linux as well as Windows, and also is a command-line interface which may be helpful if you're automating the setup of devices on an assembly line.

Installing OpenOCD - Using Eclipse OpenOCD Installation

If you've already set up Particle Debugging with Eclipse you can use the installation of OpenOCD included with that. The only difference is the path to the scripts and executable.

Using OpenOCD

General Instructions

You generally run OpenOCD in one of three ways:

  • To execute a preset list of commands
  • To start up an interactive session via telnet
  • To start up a debugging session via gdb

The first option makes something you can copy and paste into a terminal window, but because there are so many options and the lines are so long it gets a little unwieldy, especially when something goes wrong. The examples here will use the second option.

For example, using the ST-LINK/V2 Mini on the Mac, you might use a command like this to start OpenOCD:

$ cd /usr/local/share/openocd/scripts
$ openocd -f interface/stlink-v2.cfg -f target/stm32f2x.cfg -c "telnet_port 4444"

Then in a separate terminal window, you'd issue commands. The command prompt is the greater than symbol ">" so the commands you type are after that.

In many cases, telnet is not installed by default. You may want to use nc (netcat) instead of telnet.

$ telnet localhost 4444
Connected to localhost.
Escape character is '^]'.
Open On-Chip Debugger
> reset halt
target state: halted
target halted due to debug-request, current mode: Thread 
xPSR: 0x01000000 pc: 0x08002f1c msp: 0x20020000
> flash list
{name stm32f2x base 0 size 0 bus_width 0 chip_width 0}
> flash info 0
device id = 0x20036411
flash size = 1024kbytes
 #0 : stm32f2x at 0x08000000, size 0x00100000, buswidth 0, chipwidth 0
    #  0: 0x00000000 (0x4000 16kB) protected
    #  1: 0x00004000 (0x4000 16kB) not protected
    #  2: 0x00008000 (0x4000 16kB) not protected
    #  3: 0x0000c000 (0x4000 16kB) not protected
    #  4: 0x00010000 (0x10000 64kB) not protected
    #  5: 0x00020000 (0x20000 128kB) protected
    #  6: 0x00040000 (0x20000 128kB) protected
    #  7: 0x00060000 (0x20000 128kB) protected
    #  8: 0x00080000 (0x20000 128kB) protected
    #  9: 0x000a0000 (0x20000 128kB) not protected
    # 10: 0x000c0000 (0x20000 128kB) not protected
    # 11: 0x000e0000 (0x20000 128kB) not protected
STM32F2xx - Rev: X

With the Particle Debugger (3rd generation)

Using the Particle debugger and mesh devices (Argon, Boron, Xenon):

You'll need the nrf52 board file. Download the file nrf52-var.cfg and put it in your install location, typically one of:

  • /usr/local/share/openocd/scripts/target (Mac using HomeBrew)
  • /Applications/GNU ARM Eclipse/OpenOCD/0.10.0-201510281129-dev/scripts/target (Mac using GNU ARM Eclipse)
  • C:\Program Files\GNU ARM Eclipse\OpenOCD\0.10.0-201610281609-dev\scripts\target (Windows using GNU ARM Eclipse)
  • /cygdrive/c/Program Files/GNU ARM Eclipse/OpenOCD/0.10.0-201610281609-dev/scripts/target (Windows using using GNU ARM Eclipse and Cygwin)
  • /opt/gnuarmeclipse/openocd/0.10.0-201610281609-dev/scripts/target (Linux using using GNU ARM Eclipse)

Then use the command:

$ cd /usr/local/share/openocd/scripts
$ openocd -f interface/cmsis-dap.cfg -f target/nrf52-var.cfg -c "telnet_port 4444"

With the Particle Debugger (2nd generation)

Using the Particle debugger and a Photon, P1, or Electron:

$ cd /usr/local/share/openocd/scripts
$ openocd -f interface/cmsis-dap.cfg -f target/stm32f2x.cfg -c "telnet_port 4444"

The difference is that you use the cmsis-dap.cfg interface instead of stlink-v2.cfg or particle-ftdi.cfg.

With the Particle Programmer Shield

On the Mac, I use this command to connect OpenOCD to the Particle Programmer Shield.

$ cd /usr/local/share/openocd/scripts
$ openocd -f interface/ftdi/particle-ftdi.cfg -f target/stm32f2x.cfg -c "telnet_port 4444"

It's possible to use the ST-LINK/V2 Mini with OpenOCD as well as ST-LINK. You need to use the stlink-v2.cfg interface file.

$ cd /usr/local/share/openocd/scripts
$ openocd -f interface/stlink-v2.cfg -f target/stm32f2x.cfg -c "telnet_port 4444"
Open On-Chip Debugger 0.9.0 (2016-10-13-17:05)
Licensed under GNU GPL v2
For bug reports, read
    http://openocd.org/doc/doxygen/bugs.html
Info : auto-selecting first available session transport "hla_swd". To override use 'transport select <transport>'.
adapter speed: 1000 kHz
adapter_nsrst_delay: 100
Info : The selected transport took over low-level target control. The results might differ compared to plain JTAG/SWD
none separate
Info : Unable to match requested speed 1000 kHz, using 950 kHz
Info : Unable to match requested speed 1000 kHz, using 950 kHz
Info : clock speed 950 kHz
Info : STLINK v2 JTAG v23 API v2 SWIM v4 VID 0x0483 PID 0x3748
Info : using stlink api v2
Info : Target voltage: 3.258847
Info : stm32f2x.cpu: hardware has 6 breakpoints, 4 watchpoints

OpenOCD telnet commands (3rd generation)

These commands are for 3rd-generation (mesh) devices including the Argon, Boron, and Xenon.

Programming the boot loader (3rd generation)

Download the appropriate bootloader bin file from the release site.

Then connect to the server with telnet or nc:

nc localhost 4444
> adapter_khz 1000
> transport select swd
> init
> program /Users/rickk/Downloads/bootloader-0.8.0-rc.25-xenon.bin 0xf4000 verify reset exit

If you flash the bootloader and get no status LED on, you may need to flash the soft device as well. You will definitely need to do this if:

  • You erased the whole flash
  • You accidentally flashed the bootloader to 0 instead of 0xf4000

Download s140_nrf52_6.0.0_softdevice.hex, then:

nc localhost 4444
> adapter_khz 1000
> transport select swd
> init
> program /Users/rickk/Downloads/s140_nrf52_6.0.0_softdevice.hex verify reset exit

This is not necessary in most cases.

OpenOCD telnet commands (2nd generation)

These are only for the Photon, P1, Electron and E Series.

Programming the boot loader (2nd generation)

After you're connected OpenOCD to your hardware device and opened the telnet session, you can program the boot loader via telnet as follows:

> reset halt
> flash protect 0 0 0 off
> program /Users/rickk/Downloads/bootloader-photon.bin verify 0x08000000
> flash protect 0 0 0 on

You'll need to edit the path to the bootloader-photon.bin file. You need to specify a full path to the directory as well as filename.

Programming system and user firmware (2nd generation)

To program Device OS, use a set of commands like this for the Photon:

> reset halt
> flash protect 0 5 8 off
> program /Users/rickk/Downloads/system-part1-0.4.9-photon.bin verify 0x08020000
> program /Users/rickk/Downloads/system-part2-0.4.9-photon.bin verify 0x08060000
> flash protect 0 5 8 on

For the P1, the addresses are the same:

> reset halt
> flash protect 0 5 8 off
> program /Users/rickk/Downloads/system-part1-0.4.9-p1.bin verify 0x08020000
> program /Users/rickk/Downloads/system-part2-0.4.9-p1.bin verify 0x08060000
> flash protect 0 5 8 on

For user firmware on the Photon and P1:

> reset halt
> program /Users/rickk/Downloads/firmware.bin verify 0x80A0000

For the Electron running 0.5.x or earlier:

> reset halt
> flash protect 0 5 8 off
> program /Users/rickk/Downloads/system-part1-0.5.3-electron.bin verify 0x08020000
> program /Users/rickk/Downloads/system-part2-0.5.3-electron.bin verify 0x08040000
> flash protect 0 5 8 on

For the Electron running 0.6.0 or later, there are three system parts, and note that the address are not sequential with the part numbers:

> reset halt
> flash protect 0 5 8 off
> program /Users/rickk/Downloads/system-part1-0.6.0-electron.bin verify 0x08060000
> program /Users/rickk/Downloads/system-part2-0.6.0-electron.bin verify 0x08020000
> program /Users/rickk/Downloads/system-part3-0.6.0-electron.bin verify 0x08040000
> flash protect 0 5 8 on

For user firmware on the Electron:

> reset halt
> program /Users/rickk/Downloads/firmware.bin verify 0x8080000

Saving and erasing configuration (2nd generation)

To save a copy of your configuration using OpenOCD:

> reset halt
> dump_image /Users/rickk/Documents/config.bin 0x08004000 0x8000

To restore the configuration image:

> reset halt
> program /Users/rickk/Documents/config.bin verify 0x08004000

To erase all of your configuration and start from scratch:

> reset halt
> flash erase_sector 0 1 2

That's bank 0, sectors 1 and 2 (starting at 0x08004000 and 0x080008000).

Note that when you erase the configuration flash your device ID is preserved but your device private key will be lost. This means you won't be able to connect to the cloud until you upload your keys using the CLI command particle keys doctor.