简体中文 | English
Variable Oscilloscope · Online Value Modification · Data Export · Log Output
This application directly interfaces hardware debuggers with microcontrollers, parses compiled symbol files to obtain a variable table, and enables non-intrusive debugging of target chips (no need to modify the chip’s firmware).
The program is developed with Qt, and utilizes OpenOCD to support a wide range of debuggers and MCUs.
Additionally, serial port connection is supported for any chip with a UART—simply port a provided firmware stub.
Main Features
-
Real-time variable read and modification
-
Real-time waveform plotting for variable values
-
Data export
-
Formatted log output
Connection Methods
The software provides two ways to connect to the target chip:
-
Via debugger:
-
Non-intrusive: no changes required to the target’s firmware
-
In principle, supports all debuggers and MCUs compatible with OpenOCD, such as STLink, JLink, CMSIS-DAP, STM32 series, etc.
See official OpenOCD docs: Supported Debug Adapters, Supported CPUs
-
For chips that require dedicated OpenOCD drivers (e.g. ESP32C3), external OpenOCD processes can be started manually and connected to afterward
-
Maximum sampling rate: ~100Hz
-
-
Via serial port:
-
Intrusive: requires porting a firmware stub to the target chip
-
Supports any chip with a UART
-
Maximum sampling rate: ~80Hz
-
-
If using a serial connection, or if you need logging, please refer to the Serial Port Porting Instructions and Log Porting Instructions to port the corresponding firmware to your target device.
-
Download the latest release, extract it, and double-click
LinkScope.exeto run. -
Set your compiled symbol file (such as AXF or ELF), then specify variables to view.
-
Add variables:
-
Via the variable selection window
-
Or enter them manually in the last row of the main table, under the variable name column
-
-
Remove variables:
-
Right-click the variable name
-
Or select it and press Del
-
Note: The variable name can be any legal C expression supported by GDB. See Advanced Usage. Compound types like structs can be viewed only, not edited or plotted.
-
-
Select a connection mode and connect; once connected, sampling begins.
-
In debugger mode, select your debugger and target chip from the dropdown, then click Connect. Or check “External Process” to link to an already running OpenOCD process.
-
In serial mode, click “Refresh Serial Ports” to list available ports, select the correct one, and click Connect.
-
-
Edit the
Modify Variablecolumn to change variable values. Double-click thePlot Colorcolumn to select a plot color. -
Click on a
Variable Namecell to highlight its plotted waveform; its current and selected values (mouse hover) are displayed in the lower left. -
In the plot window, use the mouse wheel with
Ctrl,Shift, orAltfor zooming and panning.
-
Refresh Connection Config: Reload configuration files you’ve edited or created into the dropdown lists. See Advanced Usage. -
Save Config: Save the configured connection mode, debugger type, MCU model, symbol file path, and variable setup to a config file. -
Import Config: Reload a previously saved config file. -
Export Data: Export all sampled variable data to a CSV file. -
Advanced Settings: Open the advanced settings dialog, with options for serial configuration, sample rate, GDB port, etc.
-
Variable expressions can be any C expressions supported by GDB.
Assuming the following global variables in
main.cof your target program:static int g_int = 0; // static global variable int g_arr[10] = {0}; // global array struct Pack { int var1, var2; } g_pack = {0}; // global struct variable
Example expressions:
g_int // value of g_int &g_int // address of g_int g_pack.var1 // value of g_pack.var1 g_pack.var1+g_pack.var2 // sum of two variables g_arr[0] or *g_arr // value of first element in g_arr g_pack // the whole struct (view only) g_arr[2]@3 // g_arr[2] through g_arr[4] (view only) 'main.c'::g_int // specifically g_int from main.c *(int*)0x20005c5c // value at address 0x20005c5c (works even without a symbol file)
-
Custom OpenOCD configurations for debugger connection:
-
Files are located under
openocd/share/openocd/scripts/targetandinterface; you can modify or add your configs there. -
See OpenOCD Config File Guidelines for syntax.
-
After adding, load them into the software via
Refresh Connection Config.
-
-
Without a symbol file, variable names are unavailable; only absolute addresses can be monitored.
-
If you change the symbol file path, reconnect is required.
-
This software does not perform flash programming—make sure your firmware has already been flashed before connecting. If you use a different debugger, even with the same MCU firmware, re-flashing is recommended.
-
Serial and log firmware stubs should match the LinkScope version. Update the firmware after updating the PC software.
-
If the application crashes in debugger mode, it may not reconnect on next startup. If so, manually end any lingering
openocd.exeprocesses. -
In serial mode, reading a single byte from address 0 always returns 0.
About Sampling Rate
-
Sampling rate depends on CPU load, number of variables, log output frequency, etc. The application samples as fast as possible.
-
The rates in the introduction were measured on an
i5-8265UCPU under nearly idle load, with a single variable and logging disabled. -
In debugger mode, fetching one log entry takes about 50ms; about 90ms in serial mode. Sampling is interrupted during log retrieval; many logs will reduce sampling rate.
About Supported Hardware
-
While all OpenOCD-supported devices are theoretically compatible, real-world issues may prevent correct operation on some platforms.
-
Verified/tested devices so far include:
-
Debuggers: STLINK-V2, CMSIS-DAP
-
Target MCUs: STM32F103RCT6, STM32F103C8T6, STM32F407ZGT6, STM32F407IGH6, ESP32C3 (built-in JTAG + dedicated OpenOCD)
-
Note: If you'd like to contribute, please read this section. If you only wish to use the software, you can ignore it.
Development Environment
-
IDE: Qt Creator
-
Qt Version: 5.9.9
Runtime Architecture
-
In debugger mode, when connecting, the program launches an OpenOCD process in the background and has GDB connect to it. In serial mode, OpenOCD is replaced by a TCP server that interprets GDB’s RSP protocol and forwards it over UART.
-
The main process communicates with GDB via stdin/stdout. When you add a variable, it sends a
display exprcommand to GDB’s display list. It sendsdisplayevery 10ms, parses output via regex, and updates the UI. -
A microsecond timer records timestamps for each received variable sample, tagging data for plotting; the graph window continuously renders historied data.
-
GDB does not accept non-ASCII paths for symbol files. Therefore, before connecting, the symbol file is copied to the GDB directory with an ASCII name and loaded via a relative path; the temp file is deleted on disconnect.
-
The variable selection window uses a separate GDB process to parse the symbol file, storing variable structures as a tree. When you expand a node, it queries GDB with
info variables,whatis, orptypeas needed, parses results via regex, and builds the hierarchy. -
The logging firmware stub maintains a queue; logs are output into the buffer, and the main program routinely dequeues and displays them via a GDB print command.
Repository File Structure
-
mainwindow.cpp/h: Main window -
graphwindow.cpp/h: Plot window -
listwindow.cpp/h: Variable selection window -
logwindow.cpp/h: Log window -
aboutwindow.cpp/h: About dialog -
helpwindow.cpp/h: Help dialog -
openocd.cpp/h: OpenOCD process control -
serialocd.cpp/h: Serial server logic (receives GDB TCP, communicates with firmware via serial port) -
gdbprocess.cpp/h: GDB process control and output parsing -
vartype.h: Variable type definitions -
qss: QSS style files -
gdb/openocd: GDB and OpenOCD binaries/configs (not built, must be manually placed beside the executable after build) -
lower/log/lower/serial: Firmware code for logging/serial connection
TODO
-
Increase sampling rate
-
Add support for native (host) debugging



