There is a simple and elegant way to debug an STM32 system without using any UART. It only requires an extra ST-Link pin.
Standard output peripherals, like UART, may be used to help with debugging MCUs. However, this solution can became intrusive for the following reasons:
- in interrupt mode, the frequency of interrupts may be very high, resulting in performance drop
- in polling mode, the waiting time for transmission affects the performance even more
The SWO (Serial Wire Output) trace pin is a hardware feature of the ARM Cortex-M3/M4/M7 processors that addresses this problem. It allows tracing of system activity and memory without significant impact on performance.
It uses the ITM (Instrumentation Trace Macrocell) module of the Cortex CoreSight technology, a part of the Cortex-M debugging infrastructure. It’s like a serial port built into the CPU that allows you to send data (for example, strings or variables) to a debugging tool via the SWO pin. You don't need any UART or extra pins. Only a standard SWD connection plus the SWO pin and some software settings are required.
The ITM has 32 communication channels. ITM Channel 0 is used for printf-style output via the debug interface.
Warning
Cortex-M0 and Cortex-M0+ based MCUs do not have SWO capabilities, nor do the boards on their base, such as Nucleo 32.
-
STM32 development board from the Black Pill or Nucleo series can be used. The WeActStudio BluePill Plus board is a good choice. It's an improved version of the popular Blue Pill board, featuring a genuine STM32F103C8T6 chip.
-
ST-Link debugger / programmer board, original or compatible. WeActStudio MiniDebugger is recommended for use with the BluePill Plus board. It is compatible with the original ST-Link and has both SWD and UART interfaces.
-
Jumper wires - 5 pieces in total may be needed: 4 for the SWD connector and 1 for the additional SWO pin. The amount and type of wires used depend on the board you have. For the BluePill Plus board, installed on the breadboard and connected to the MiniDebugger (as shown in the picture), you need one 10-cm-long male-to-male jumper wire for the SWO connection. Four SWD jumper wires are already combined with the debugger's connector and can be directly connected to the board's SWD connector. For the Nucleo board, no wires are needed, as all the connections are made inside the board. However, not all Nucleo boards support SWO.
-
USB Type-C cable is needed to connect the debugger to a PC. Choose the cable's length according to your needs.
Warning
Adding trace support to ST-Link clone dongles requires soldering a wire to the chip inside the dongle. See the references for details.
- Connect SWD connector of the STM32 board (4 pins) to the corresponding wires of the debugger (4 jumper wires).
- Connect SWO pin of the board (pin PB3 of the STM32F103C8T6 chip and pin B3 on the BluePill Plus board) to the SWO pin (jumper wire) of the debugger.
STM32CubeIDE has to be installed.
-
In the STM32CubeIDE Device Configuration Tool in Pinout & Configuration click on System Core -> SYS and set the Debug method to Trace Asynchronous Sw. This enables the SYS_JTDO-TRACESWO pin on your microcontroller (pin PB3 of the STM32F103C8T6 chip).
-
Enable SWV in STM32CubeIDE. Open the Debug Configurations... under the Debug icon (looking as a little beetle). In the Debugger tab, enable Serial Wire Viewer (SWV) and make sure the Core Clock is set to your system clock (which you can find in Device Configuration Tool -> Clock Configuration -> SYSCLK).
-
Click on Debug icon, switch to the Debug perspective, click on Window -> Show View -> SWV -> SWV ITM Data Console to be able to view the SWV output.
-
While the debugger is paused on the first breakpoint, bring up the SWV settings by clicking on the wrench icon in the upper-right corner of the SWV ITM Data Console tab. In the bottom part of the window, under ITM Stimulus Ports, check pin 0.
-
Press the red circle button in the SWV ITM Data Console and then press the Resume button on the Toolbar to run the code and start tracing.
-
You should see messages printed in the console.
-
Press the Suspend button on the Toolbar to pause the program and the Terminate button to exit the Debug perspective.
-
bluepill-plus_swv_putchar The simplest way to print something to the console seems to be using the ubiquitous
printffunction. But in the case of the code running on a microcontroller, it's won't be that easy. We should redirectprintfto SWO first.
To do this, we'll be usingITM_SendCharfunction, which transmits a character via the ITM channel 0. This function is part of the__io_putcharfunction, which is included in_writefunction in thesyscalls.cfile.
After including<stdio.h>and the__io_putcharto the code, we can start usingprintf, as we usually do in any C program. The code here outputs the counter's values to the console once per second in an endless loop. -
bluepill-plus_swv_write If the
syscalls.cfile is missing or not implemented, the entire_writefunction must be overwritten. In this caseITM_Send Charis inside this_writefunction, which we insert into the code instead of__io_putchar. The other parts of the code are the same.
Tip
To avoid losing the first character of the very first string being printed, a small delay of 0.1 seconds is inserted into the code before the start of the loop.