Upping STM32 debugging
Lately a major part of my day job has been writing software running on STM32 microcontroller. Up until this point my only debugging tools were limited to:
- printf-littering code and looking at output in serial console;
- Stepping through code with debugger (gdb together with OpenOCD or stlink);
Both of the approaches have their uses and limitations. Serial output is easier to transmit over unusual physical layers (think wireless debugging) and easier to log data over longer period of time. However it takes up an extra UART which is not always available and software UART is not up to the task in terms of bandwidth and effect on program execution.
Using a standard debugger interface (setting breakpoints, stepping through code and examining memory) is more flexible if the problem is not localized yet. On the other hand it is not trivial to do this wirelessly and (obviously) without stopping program.
So I wanted a better way to debug a relatively large codebase with little effect on program under test without using hardware UART.
Enter ARM's ITM block and, often unused, SWO pin. While ITM is more complex than I'm going to describe, it can essentially be used as high-speed serial data (8N1 UART or Manchester-encoded) debug output.
Data going out via this debug interface can be grouped in 32 groups (called stimulus ports) and active ports can be enabled/disabled while the program is running (either fiddling with registers in program itelf or having connected debugger do that).
To my amazement, inexpensive STLink-V2 (and compatible) debuggers actually support access to this data over USB. This means I can program and see debug output of STM32Discovery board without having to connect additional USB-UART adapter (some of the newer, STM32 Nucleo branded development boards actually have USB-CDC support in the programmer-side so this isn't as important with those).
Once we have the code which writes data to ITM registers (see examples for libopencm3, mbed, chibios, next step is actually receiving this data.
OpenOCD allows to do this with the following configuration:
source [find interface/stlink-v2.cfg] source [find target/stm32f4x.cfg] reset_config srst_only srst_nogate tpiu config internal swo-trace-output.log uart off <SYS_CLK> <SWO BAUD RATE>
However I was only able to receive data at ~10KiB/s (with maximum SWO baud rate supported by STLink, 2 Mbaud/s).
Another option is swopy by KarlP. As it rarely is with open-source, it works better than advertised and could easily log 150KiB/s of debugging data.
Yet another option (not limited by 2 Mbaud/s limitation of STLink-V2) is to use FT232L like it's described in OpenOCD docs.
For more advanced (alas, more involved) debugging on STM32, see Execution tracing on Cortex-M microcontrollers.