Arduino In-circuit Debugging with PlatformIO

Manuel Bl.
5 min readAug 18, 2019

--

Some Arduino boards have debugging signals exposed on the bottom side. With an inexpensive adapter you can start using the PlatformIO debugger — a tool far more powerful than print statements to track down bugs in your software.

The Board

The Arduino Nano 33 IoT is a recently released Arduino board. It comes in the typical Nano form factor and offers unique features: powerful Atmel SAMD21 micro controller, Bluetooth, WiFi, crypto chip and a 6 axis IMU (acceleration and gyroscope).

Arduino Nano 33 IoT

What really caught my attention were the exposed pads on the bottom side:

Bottom side of Arduino Nano 33 IoT

These aren’t just test points. They are debug signals. And for the first time, they are described on the Arduino web site (see last section of technical specification).

The description is confusing though. So here is a visual pinout:

Debug port pads

SWD and SWCLK are the relevant signals: they are a debug port called Serial Wire Debug (abbreviated as SWD), available on all ARM-based micro controllers. And the Atmel SAMD21 is ARM-based of course. The remaining signals are less important as they are also available as regular pins.

The Debug Adapter

There are plenty of debug adapters available for Serial Wire Debug or SWD. I have used a J-Link adapter from uncle Ali for about USD 12.

J-Link Debug Adapter

The adapter is a clone of Segger J-Link Debug Probes. Many clones even carry the Segger logo although they are not a genuine product. Several variants are available and difficult to distinguish. This is the least expensive one, and it worked.

Connecting the Adapter

In order to connect the Arduino board to the debug adapter, wires need to be soldered to the debug pads. I’ve soldered wires to all five of them but in the end did not use the 3.3V wire. The GND and RST pins can also be soldered to regular pins, or if you have a board with headers pins, just connect them to the header pins. The minimum are the SWD and SWCLK wires.

Wires soldered to the debug port

I then crimped Dupont connectors onto the other end of the wires. You can also start with ready-made Dupont wires, cut off the connectors on one side and solder them to the board.

The wires need to be connected to the J-Link adapter to the following pins:

J-Link Pinout for Serial Wire Debug (SWD)

The SWD pin is called SWDIO here as this is the official J-Link label. It is sufficient to connect as single GND pin. The 3.3V wire is not connected as the board will be powered via USB.

Dupont connectors can be directly plugged onto the J-Link pins. I have used an intermediate adapter board as it simplifies plugging and unplugging the adapter. The pinout is the same.

Debug Your Program

If everything is plugged in (J-Link to computer, Arduino board to computer, Arduino board to J-Link), debugging with PlatformIO can start. J-Link is not the default debugger for the Arduino Nano 33 IoT. Therefore, the debug_tool needs to be specified in platformio.ini:

[env:nano_33_iot]
platform = atmelsam
board = nano_33_iot
framework = arduino
debug_tool = jlinklib_deps =
Arduino_LSM6DS3

The example program (main.cpp) reads gyroscope values from the IMU and prints them to the serial port:

#include <Arduino.h>
#include <Arduino_LSM6DS3.h>
void setup() {
Serial.begin(9600);
// Wait for serial connection to be ready
while (!Serial);
if (!IMU.begin()) {
Serial.println("Failed to initialize IMU");
while (1);
}

Serial.print("Gyroscope sample rate = ");
Serial.print(IMU.gyroscopeSampleRate());
Serial.println(" Hz");
Serial.println();
Serial.println("Gyroscope in degrees/second");
Serial.println("X, Y, Z");
}
void loop() {
float x, y, z;

if (IMU.gyroscopeAvailable()) {
IMU.readGyroscope(x, y, z);

Serial.print(x);
Serial.print(", ");
Serial.print(y);
Serial.print(", ");
Serial.println(z);
}
}

To start debugging, go to the debug view (1), select the PIO Debug configuration of your project (2) and click the arrow icon next to it (3). It will take a moment to compile your code again and start the debugger in the background. Then your program is started and immediately stopped in the main function in another main.cpp file (4):

PlatformIO debugging session: debug view, configuration selection, start, first breakpoint

You can then open your own main.cpp file and set a breakpoint by clicking next to the line number (1). A small red dot will appear. The blue array icon (2) continues the execution. The program will then likely be stuck at the check for the serial connection (3). To unlock it a serial terminal program needs to connect to the Arduino board, e.g. by running PlatformIO’s Serial Monitor. The program will run to your breakpoint and stop again. By clicking the arrow button again, the program completes an iteration of the loop function and again stops at the breakpoint in the next iteration.

PlatformIO debug session: breakpoint, continue execution, serial connection check, variable inspection

Variables can easily be inspected in the debugger’s Variables view (4). There is no need anymore for adding print statements and recompiling your program to analyze your program.

Other Arduino Boards

Two further Arduino boards expose their debug signals in exactly the same way as the Arduino Nano 33 IoT: Arduino Nano 33 BLE and Arduino Nano 33 BLE Sense. They use a Nordic Semiconductor nRF52840 microcontroller and a new Mbed OS based Arduino core. This combination is now supported by PlatformIO (with a few hick-ups though).

Further Arduino boards can be connected to a debugger in the same way:

The debug pads are also on the bottom side but look slightly different:

Debug Port Pads on Arduino MKR Boards

Additional boards with exposed debug pads are available from Adafruit and SparkFun. They all have in common that they use an Atmel SAMD21 microcontroller.

Happy debugging…

--

--