The upload approach via USB-C used in [[Blinking an LED]] is a quick way to get firmware onto a µC, but is of limited use during development: there is no way to see "debug output" and there is no way to investigate complex problems with a debugging tool such as [gdb](https://en.wikipedia.org/wiki/GNU_Debugger). Both of these issue can be addressed by connecting a "debug probe". As described on the [[Hardware]] page, I'm using a WeAct "Mini Debugger", which is equivalent to STM's [ST-Link](https://www.st.com/en/development-tools/st-link-v2.html): ![[weact-stlink.png|400]] This is a bridge with two different purposes: a Virtual Communication Port (VCP) to connect a serial port on the development board, and an [SWD](https://en.wikipedia.org/wiki/JTAG#Similar_interface_standards) low-level interface to the CPU. There are 10 pins with jumper wires to connect to the development board: ![[weact-minidbg-pinout.png|500]] - Three pins are used to upload and debug via this unit: SWDIO, SWCLK, and GND. - Another three are used for serial communication: TXD, RXD, and GND (same connection). - The NRST pin can force the dev board into reset, which is very useful when it's asleep. - The SWO pin provides another mechanism to collect information from the dev board. - The 3V3 (i.e. 3.3V) and 5V pins can supply power to the board when not connected to USB. ## Step 1: Solder pin headers I'm going to use the STM32F411 "Black Pill" as initial dev board. Many other boards can be used in a similar way, but they simply can't all be described here. The F411 board has 44 pin connections: two rows of 20 on the side and 4 at the end. The one at the end is the SWD connection which can be used to power, upload, and debug the board. It needs to have a [pin header](https://en.wikipedia.org/wiki/Pin_header) soldered on, as follows: ![[swd-front.jpg|250]]![[swd-back.jpg|250]] And let's solder the other two headers as well, to allow placing it on a [breadboard](https://en.wikipedia.org/wiki/Breadboard) later on. ## Step 2: Upload via SWD With these four wires we can power the board and upload to it, instead of plugging in via USB: ![[swd-probe.jpg|500]] By removing the line `upload_protocol = dfu` from `platformio.ini`, this automatically switches back to SWD via the `stlink` protocol, since that's the default for STM32. ## Step 3: Connect more pins The remaining six pins (one is merely a second "GND" connection) can be hooked up with jumper wires, using a breadboard to bring it all together - turning this into a bit of a rat's nest: ![[breadboard.jpg|500]] These six wires are connected as follows, with the jumper colours used in this setup: | Jumpers | Dev board | Debug probe | Comments | | ------- | --------- | ----------- | ------------------------- | | white | R | RST | µC reset (on the top row) | | green | A9 | RX | from STM32 to probe | | orange | A10 | TX | from probe to STM32 | | blue | B3 | SWO | Serial Wire Output | | red | 5V | 5V | same as attaching USB | | black | G | GND | 2nd GND (redundant) | The USB port is not used here, neither for power nor otherwise. ## Tidying it up Jumper wires are very useful to figure out how to connect everything together. Once it all works, those jumpers can be replaced by properly sized wires and make the debug setup look like this: ![[tidied-up.jpg|500]]. ## That's it The debug probe adds several developer conveniences through these connections: 1. supply power to the dev board: both 5V and 3.3V (via the SWD header) 2. allow quick uploading over SWD, without having to push buttons each time 3. provide a serial console connection, capable of running at up to 2 million baud 4. support the `gdb` debugger to single-step, set breakpoints, and examine variables 5. add an additional serial output over SWO for capturing low-level execution traces The next step will verify that everything works as expected: adding [[Serial console output]].