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. This is helpful because it only requires two pins (D6 and D7).

SWD is also used with the Gen 3 devices (Argon, Boron, and Xenon; nRF52840) via the 10-pin debugging connector.

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 Gen 3 devices (Argon, Boron, and Xenon). 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 Gen 1 (Core) and Gen 2 (Photon, P1, Electron, and E Series) devices, not with Gen 3 devices (Argon, Boron, Xenon).

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 Gen 3 (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, Electron, 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.

If you are want to program a Gen 2 device (Photon, P1, Electron, or E Series) using the ST/LINK under Windows, you can use the ST/LINK software.

Additional Details

Installing OpenOCD Manually

By far the easiest way to install openocd for Windows, Mac, and Linux is to install Particle Workbench.. If you really want to install it manually, expand the section below.

Additional Details

Using OpenOCD

General Instructions

This assumes you've installed OpenOCD using Particle Workbench. If you've installed it a different way, your path to the installation will be different.

Installation Path
Windows C:\Users\username\.particle\toolchains\openocd
Mac /Users/username/.particle/toolchains/openocd
Linux /home/username/.particle/toolchains/openocd

Open a Command Prompt or Terminal window and cd into the openocd directory, then cd into the version-specific directory. At the time of writing it was 0.10.0-particle.1 but could change.

Mac or Linux Terminal:

$ cd ~/.particle/toolchains/openocd/
$ ls
0.10.0-particle.1
$ cd 0.10.0-particle.1 

Windows Command Prompt:

C:\Users\rick>cd .particle\toolchains\openocd

C:\Users\rick\.particle\toolchains\openocd>dir
 Volume in drive C is Windows 10
 Volume Serial Number is 98E3-995C

 Directory of C:\Users\IEUser\.particle\toolchains\openocd

04/09/2019  09:08 AM    <DIR>          .
04/09/2019  09:08 AM    <DIR>          ..
04/09/2019  09:08 AM    <DIR>          0.10.0-particle.1
               0 File(s)              0 bytes
               3 Dir(s)  22,179,033,088 bytes free
C:\Users\rick\.particle\toolchains\openocd>cd 0.10.0-particle.1

With the Particle Debugger (3rd generation)

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

  • Connect the Particle Debugger ribbon cable between the debugger and device.
  • Connect the device by USB to your computer
  • Connect the Particle Debugger by USB to your computer
  • Put the device in DFU mode (blinking yellow) by holding down MODE. Tap RESET and continue to hold down MODE while the status LED blinks magenta (red and blue at the same time) until it blinks yellow, then release MODE.

Then use the command:

bin/openocd -f interface/cmsis-dap.cfg -f target/nrf52-particle.cfg \
-c "adapter_khz 1000" \
-c "transport select swd" \
-c "init" \
-c "flash list" \
-c "exit"
Open On-Chip Debugger 0.10.0 (2019-01-29-17:30)
Licensed under GNU GPL v2
For bug reports, read
    http://openocd.org/doc/doxygen/bugs.html
Warn : Interface already configured, ignoring
Info : auto-selecting first available session transport "swd". To override use 'transport select <transport>'.
adapter speed: 10000 kHz
cortex_m reset_config sysresetreq
adapter speed: 1000 kHz
Warn : Transport "swd" was already selected
swd
Info : CMSIS-DAP: SWD  Supported
Info : CMSIS-DAP: Interface Initialised (SWD)
Info : CMSIS-DAP: FW Version = 1.10
Info : SWCLK/TCK = 1 SWDIO/TMS = 1 TDI = 0 TDO = 0 nTRST = 0 nRESET = 1
Info : CMSIS-DAP: Interface ready
Info : clock speed 1000 kHz
Info : SWD DPIDR 0x2ba01477
Info : nrf52.cpu: hardware has 6 breakpoints, 4 watchpoints
{name nrf51 base 0 size 0 bus_width 1 chip_width 1} {name nrf51 base 268439552 size 0 bus_width 1 chip_width 1}

Note that the command line is very long and uses continuation lines (lines ending with a backslash \) to make it easier to read.

Command Purpose
bin/openocd Executable to run
-f interface/cmsis-dap.cfg Select the type of debugger
-f target/nrf52-particle.cfg Select the type of device
-c "adapter_khz 1000" Configure adapter speed
-c "transport select swd" Select SWD mode
-c "init" Initialize the adapter
-c "flash list" Run a command (in this case, list flash modules)
-c "exit" Exit openocd when done

The flash list command is done here for illustration purposes and to make sure the debugger can connect to the device. More useful commands are listed below.

With the Particle Debugger (2nd generation)

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

  • Connect the Particle Debugger to pin D6, D7, and GND as shown above.
  • Connect the device by USB to your computer
  • Connect the Particle Debugger by USB to your computer
  • Put the device in DFU mode (blinking yellow) by holding down MODE. Tap RESET and continue to hold down MODE while the status LED blinks magenta (red and blue at the same time) until it blinks yellow, then release MODE.

Then use the command:

bin/openocd -f interface/cmsis-dap.cfg -f target/stm32f2x.cfg \
-c "adapter_khz 1000" \
-c "transport select swd" \
-c "init" \
-c "flash list" \
-c "exit"

Note the use of target/stm32f2x.cfg for Gen 2 devices.

With the Particle Programmer Shield

bin/openocd -f interface/particle-ftdi.cfg -f target/stm32f2x.cfg \
-c "init" \
-c "flash list" \
-c "exit"

For the Particle Programmer Shield (Gen 2), use interface/particle-ftdi.cfg.

With the ST-LINK/V2 or Mini USB stick:

bin/openocd -f interface/stlink-v2.cfg -f target/stm32f2x.cfg \
-c "init" \
-c "flash list" \
-c "exit"

For the ST-LINK/V2 use interface/stlink-v2. The ST-LINK/V2 can only be used with Gen 2 devices.

OpenOCD 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.

bin/openocd -f interface/cmsis-dap.cfg -f target/nrf52-particle.cfg \
-c  "adapter_khz 1000" \
-c "transport select swd" \
-c "init" \
-c "program /Users/rickk/Downloads/bootloader-0.9.0-argon.bin 0xf4000 verify reset" \
-c "exit"

Note the addition of the command:

-c "program /Users/rickk/Downloads/bootloader-0.9.0-argon.bin 0xf4000 verify reset"

in place of the -c "flash list" in the example above.

Here's an example of a successful execution of the command:

$ bin/openocd -f interface/cmsis-dap.cfg -f target/nrf52-particle.cfg -c  "adapter_khz 1000" -c "transport select swd" -c "init" -c "program /Users/rickk/Downloads/bootloader-0.9.0-argon.bin 0xf4000 verify reset" -c "exit"
Open On-Chip Debugger 0.10.0 (2019-01-29-17:30)
Licensed under GNU GPL v2
For bug reports, read
    http://openocd.org/doc/doxygen/bugs.html
Warn : Interface already configured, ignoring
Info : auto-selecting first available session transport "swd". To override use 'transport select <transport>'.
adapter speed: 10000 kHz
cortex_m reset_config sysresetreq
adapter speed: 1000 kHz
Warn : Transport "swd" was already selected
swd
Info : CMSIS-DAP: SWD  Supported
Info : CMSIS-DAP: Interface Initialised (SWD)
Info : CMSIS-DAP: FW Version = 1.10
Info : SWCLK/TCK = 1 SWDIO/TMS = 1 TDI = 0 TDO = 0 nTRST = 0 nRESET = 1
Info : CMSIS-DAP: Interface ready
Info : clock speed 1000 kHz
Info : SWD DPIDR 0x2ba01477
Info : nrf52.cpu: hardware has 6 breakpoints, 4 watchpoints
target halted due to debug-request, current mode: Thread 
xPSR: 0x01000000 pc: 0x00000998 msp: 0x20000400
** Programming Started **
auto erase enabled
Warn : Unknown device (HWID 0x00000150)
Warn : using fast async flash loader. This is currently supported
Warn : only with ST-Link and CMSIS-DAP. If you have issues, add
Warn : "set WORKAREASIZE 0" before sourcing nrf51.cfg to disable it
wrote 36864 bytes from file /Users/rickk/Downloads/bootloader-0.9.0-argon.bin in 2.690096s (13.382 KiB/s)
** Programming Finished **
** Verify Started **
verified 33632 bytes in 0.286077s (114.807 KiB/s)
** Verified OK **
** Resetting Target **

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 use a -c option like:

-c program /Users/rickk/Downloads/s140_nrf52_6.0.0_softdevice.hex verify reset

This is not necessary in most cases.

OpenOCD commands (2nd generation)

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

Programming the boot loader (2nd generation)

Download the appropriate bootloader from the release site.

In place of the -c flash list command in the examples above, substitute the following commands:

-c "reset halt" \
-c "flash protect 0 0 0 off" \
-c "program /Users/rickk/Downloads/bootloader-1.0.1-photon.bin
 verify 0x08000000" \
-c "flash protect 0 0 0 on" \

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

If you get the error "Device Security Bit Set" you will also need to reset the RDP level.

-c "init" \
-c "reset halt" \
-c "stm32f2x unlock 0" \
-c "reset halt" \

After resetting the RDP level to 0 you'll need to flash the boot loader, system firmware, user firmware (or Tinker) and also do a particle keys server and particle keys doctor. This only applies to 2nd generation devices (Photon, P1, Electron, and E series).

Programming system and user firmware (2nd generation)

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

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

For the P1, the addresses are the same:

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

For user firmware on the Photon and P1:

-c "reset halt" \
-c "program /Users/rickk/Downloads/firmware.bin verify 0x80A0000" \

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:

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

For user firmware on the Electron:

-c "reset halt" \
-c "program /Users/rickk/Downloads/firmware.bin verify 0x8080000" \

Saving and erasing configuration (2nd generation)

To save a copy of your configuration using OpenOCD:

-c "reset halt" \
-c "dump_image /Users/rickk/Documents/config.bin 0x08004000 0x8000" \

To restore the configuration image:

-c "reset halt" \
-c "program /Users/rickk/Documents/config.bin verify 0x08004000" \

To erase all of your configuration and start from scratch on Gen 2:

-c "reset halt" \
-c "flash erase_sector 0 1 2 " \

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

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.