Debugging with CMSIS-DAP
This tutorial covers setting up hardware debugging for NanoVNA-H firmware development using a CMSIS-DAP debug probe and OpenOCD.
What You Will Learn
Section titled “What You Will Learn”- Connecting a CMSIS-DAP debug probe
- Configuring OpenOCD for NanoVNA-H
- Using GDB for firmware debugging
- Setting breakpoints and inspecting variables
Prerequisites
Section titled “Prerequisites”- Build Environment Setup completed
- Building and Flashing working
- A CMSIS-DAP compatible debug probe
Debug Probe Options
Section titled “Debug Probe Options”CMSIS-DAP is a standard debug interface. Compatible probes include:
| Probe | Notes |
|---|---|
| DAP-Link | Common, inexpensive |
| DAPLink (official) | Open-source reference design |
| J-Link | Professional, also supports CMSIS-DAP mode |
| ST-Link v2 | Can be converted to CMSIS-DAP with firmware |
| Black Magic Probe | Built-in GDB server, no OpenOCD needed |
Hardware Connection
Section titled “Hardware Connection”NanoVNA-H Debug Pins
Section titled “NanoVNA-H Debug Pins”The NanoVNA-H has SWD (Serial Wire Debug) pads on the PCB:
| Pin | Function | Connect To |
|---|---|---|
| SWDIO | Data | Probe SWDIO |
| SWCLK | Clock | Probe SWCLK |
| GND | Ground | Probe GND |
| 3V3 | Power (optional) | Probe VRef |
Connection Diagram
Section titled “Connection Diagram”NanoVNA-H Debug Probe---------- ----------- SWDIO <-------------> SWDIO SWCLK <-------------> SWCLK GND <-------------> GND 3V3 <--- optional -> VRef-
Locate the debug pads
Look for small test points or pads labeled SWD, SWDIO, SWCLK on the NanoVNA PCB.
-
Solder connection wires
Use thin wire (30 AWG recommended) to connect the debug pads to your probe.
-
Connect grounds first
Always connect GND before other signals.
-
Verify connections
Use a multimeter to check for shorts between SWDIO, SWCLK, and GND.
Installing OpenOCD
Section titled “Installing OpenOCD”sudo apt install openocdsudo pacman -S openocdbrew install openocdDownload from OpenOCD releases or use Chocolatey:
choco install openocdVerify installation:
openocd --versionOpenOCD Configuration
Section titled “OpenOCD Configuration”The NanoVNA-H repository includes a configuration file: NanoVNA_DAP.cfg
If not present, create it with this content:
# NanoVNA-H (STM32F072) OpenOCD configuration
source [find interface/cmsis-dap.cfg]transport select swd
source [find target/stm32f0x.cfg]
adapter speed 4000
# Reset configurationreset_config srst_nogate
inittargets# NanoVNA-H4 (STM32F303) OpenOCD configuration
source [find interface/cmsis-dap.cfg]transport select swd
source [find target/stm32f3x.cfg]
adapter speed 4000
# Reset configurationreset_config srst_nogate
inittargetsStarting OpenOCD
Section titled “Starting OpenOCD”-
Connect the debug probe
Connect the probe to your computer via USB and to the NanoVNA via SWD.
-
Power the NanoVNA
Connect the NanoVNA via USB or battery.
-
Start OpenOCD
Terminal window openocd -f NanoVNA_DAP.cfg -
Verify connection
Successful output:
Open On-Chip Debugger 0.11.0Info : CMSIS-DAP: SWD supportedInfo : CMSIS-DAP: Atomic commands supportedInfo : CMSIS-DAP: FW Version = 1.0Info : SWCLK/TCK = 1 SWDIO/TMS = 1 TDI = 0 TDO = 0 nRSET = 1Info : CMSIS-DAP: Interface readyInfo : clock speed 4000 kHzInfo : SWD DPIDR 0x0bb11477Info : stm32f0x.cpu: hardware has 4 breakpoints, 2 watchpointsInfo : starting gdb server for stm32f0x.cpu on 3333
OpenOCD now runs a GDB server on port 3333.
Using GDB
Section titled “Using GDB”Starting GDB
Section titled “Starting GDB”-
Open a new terminal
-
Navigate to build directory
Terminal window cd /path/to/NanoVNA-H -
Start GDB with the ELF file
Terminal window arm-none-eabi-gdb build/H.elf -
Connect to OpenOCD
In GDB:
(gdb) target extended-remote localhost:3333 -
Reset and halt the target
(gdb) monitor reset halt
Common GDB Commands
Section titled “Common GDB Commands”| Command | Description |
|---|---|
target extended-remote localhost:3333 | Connect to OpenOCD |
monitor reset halt | Reset and stop at beginning |
monitor reset run | Reset and run |
load | Flash the firmware (alternative to dfu-util) |
continue or c | Continue execution |
break main | Set breakpoint at main() |
break ui.c:100 | Set breakpoint at line 100 of ui.c |
step or s | Step into function |
next or n | Step over function |
print variable | Print variable value |
info registers | Show CPU registers |
backtrace or bt | Show call stack |
quit or q | Exit GDB |
Example Debug Session
Section titled “Example Debug Session”(gdb) target extended-remote localhost:3333Remote debugging using localhost:33330x08001234 in main () at main.c:150
(gdb) monitor reset halttarget halted due to debug-request, current mode: Thread
(gdb) break sweepBreakpoint 1 at 0x8002468: file main.c, line 256.
(gdb) continueContinuing.Breakpoint 1, sweep () at main.c:256256 static bool sweep(bool break_on_operation, uint16_t ch_mask) {
(gdb) print sweep_points$1 = 101
(gdb) backtrace#0 sweep () at main.c:256#1 0x08001a34 in Thread1 () at main.c:243#2 0x08000f90 in _port_thread_start ()
(gdb) continueFlashing via Debug Probe
Section titled “Flashing via Debug Probe”You can flash firmware without entering DFU mode:
(gdb) monitor reset halt(gdb) loadLoading section .text, size 0x1c234 lma 0x8000000Loading section .data, size 0x2e4 lma 0x801c234Start address 0x8000000, load size 115992Transfer rate: 42 KB/sec, 9666 bytes/write.(gdb) monitor reset runThis is faster for iterative development than DFU mode.
IDE Integration
Section titled “IDE Integration”VS Code
Section titled “VS Code”-
Install Cortex-Debug extension
Search for “Cortex-Debug” in VS Code extensions.
-
Create launch.json
Create
.vscode/launch.json:{"version": "0.2.0","configurations": [{"name": "NanoVNA-H Debug","type": "cortex-debug","request": "launch","servertype": "openocd","cwd": "${workspaceFolder}","executable": "${workspaceFolder}/build/H.elf","configFiles": ["${workspaceFolder}/NanoVNA_DAP.cfg"],"svdFile": "${workspaceFolder}/STM32F0x2.svd","runToEntryPoint": "main","showDevDebugOutput": "raw"}]} -
Download SVD file (optional)
SVD files provide register definitions for the Peripherals view. Download from STM32 SVD files.
-
Start debugging
Press F5 or click the Debug icon.
Eclipse
Section titled “Eclipse”Similar configuration is possible with Eclipse CDT and the GNU MCU Eclipse plugins.
Troubleshooting
Section titled “Troubleshooting””Error: unable to find a matching CMSIS-DAP device”
Section titled “”Error: unable to find a matching CMSIS-DAP device””- Check USB connection
- Verify probe appears in
lsusb(Linux) or Device Manager (Windows) - Try different USB port
- Check probe firmware
”Error: connect failed”
Section titled “”Error: connect failed””- Verify SWD connections (especially GND)
- Check for shorts
- Ensure NanoVNA is powered
- Try reducing adapter speed in config file
”Error: target not halted”
Section titled “”Error: target not halted””- The MCU may be running and ignoring halt request
- Try
monitor reset haltbefore other commands - Check reset line connection if available
Breakpoints not working
Section titled “Breakpoints not working”- The F072 has only 4 hardware breakpoints
- Software breakpoints require writable flash (not always possible)
- Remove unused breakpoints
Variables show as “optimized out”
Section titled “Variables show as “optimized out””-
The default build uses -O2 optimization
-
For debugging, edit Makefile to use -O0:
USE_OPT = -O0 -ggdb ... -
Rebuild and reflash
Advanced Topics
Section titled “Advanced Topics”Semihosting
Section titled “Semihosting”Enable printf output via the debug probe:
(gdb) monitor arm semihosting enableRequires semihosting support in firmware (not enabled by default).
Real-time Tracing
Section titled “Real-time Tracing”The F303 (NanoVNA-H4) supports ITM/SWO tracing for non-intrusive debugging. This requires additional hardware setup.
Watchpoints
Section titled “Watchpoints”Monitor memory access:
(gdb) watch measured[0][0][0]Hardware watchpoint 2: measured[0][0][0](gdb) continueHardware watchpoint 2: measured[0][0][0]Old value = 0.5New value = 0.75The F072 has 2 watchpoints, F303 has 4.
Next Steps
Section titled “Next Steps”- Build Environment Setup - Toolchain configuration
- Building and Flashing - DFU flashing method