Skip to content

Latest commit

 

History

History
271 lines (154 loc) · 9.66 KB

File metadata and controls

271 lines (154 loc) · 9.66 KB

简体中文 | English

LinkScope

Non-intrusive Hardware Debugging Tool
Variable Oscilloscope · Online Value Modification · Data Export · Log Output


Project Overview

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

Demo Running


Getting Started

  1. 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.

  2. Download the latest release, extract it, and double-click LinkScope.exe to run.

  3. 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.

  4. 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.

  5. Edit the Modify Variable column to change variable values. Double-click the Plot Color column to select a plot color.

  6. Click on a Variable Name cell to highlight its plotted waveform; its current and selected values (mouse hover) are displayed in the lower left.

  7. In the plot window, use the mouse wheel with Ctrl, Shift, or Alt for zooming and panning.

Operation Demo

Log Output


Main Menu Items

  • 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.


Advanced Usage

  • Variable expressions can be any C expressions supported by GDB.

    Assuming the following global variables in main.c of 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/target and interface; 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.


Notes

  • 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.


Known Issues

  • If the application crashes in debugger mode, it may not reconnect on next startup. If so, manually end any lingering openocd.exe processes.

  • In serial mode, reading a single byte from address 0 always returns 0.


Additional Information

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-8265U CPU 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)


Developer Notes

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.

    Process Block Diagram

  • The main process communicates with GDB via stdin/stdout. When you add a variable, it sends a display expr command to GDB’s display list. It sends display every 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, or ptype as 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