A non-invasive DAP-based tool for MCU data acquisition, monitoring, and visualization.
Project description
uCap
A non-invasive DAP-based tool for MCU data acquisition, monitoring, and visualization.
Features
- Non-invasive — reads/writes MCU memory via DAP (SWD/JTAG); no code changes or debug printf required
- Dual modes — headless CLI (
ucap rw) for fast batch acquisition, or GUI monitor (ucap mon) for live visualization - Multiple backends — pyOCD, pySWD, OpenOCD; works with ST-Link, DAP-Link, and more
- On-the-fly expressions — transform raw register values with math expressions (scaling, unit conversion, formulas)
- Struct-aware — unpack packed C structs into named fields automatically
- ELF symbol resolution — use variable names from your firmware instead of raw addresses
- Rich plotting — multi-figure / multi-axis layouts with line, stem, and scatter plot types
- Save & replay — captured data is saved and can be re-plotted offline
Installation
pip install python-ucap
If using ST-Link V3 with pyswd backend, you need to install the latest pyswd:
git clone https://github.com/cortexm/pyswd
cd pyswd
pip install .
Quick Start
Connect your MCU debugger (e.g. ST-Link, DAP-Link) to the target board, then create a config file my_config.toml. Set target to match your MCU (use pyocd list --targets to list supported chips; cortex_m is a generic fallback):
rw_freq = 100
[backend]
name = 'pyocd'
[backend.pyocd]
target = 'cortex_m'
[save]
enable = true
dir = 'data'
name = 'session1'
auto_name = false
[plot]
show = true
[[vars]]
name = 'sensor'
address = 0x20000000
format = '<f'
Run data acquisition (press Ctrl+C to stop):
ucap rw -c my_config.toml
A matplotlib window will open after completion.
Re-plot saved data anytime:
ucap show -d data/session1
See examples/simple.toml for a minimal config, docs/config-reference.toml for all available options, and docs/data-format.md for the captured data structure.
Concepts
Variables
A [[vars]] entry in config describes a variable in the target MCU's memory space that ucap will read and/or write. The address field accepts a raw hex address, a peripheral register name (e.g. ADC1->DR, TIM2->CNT), or a C global variable name — peripheral register and global variable symbols are all resolved from the ELF/DWARF debug info when an ELF file is specified via the --elf CLI option or the elf_file config key.
| Field | Description |
|---|---|
name |
Identifier used in saved data and plots |
address |
Hex address, peripheral register name, or C global variable name (resolved via --elf / elf_file in config) |
format |
struct format string for packing/unpacking bytes |
value |
If set, the variable is write-only (written every cycle); omit for read |
struct |
List of field names to unpack multi-field data into a dict |
expr |
Expression to transform the read value (e.g. 'x * 3.3 / 4096'); can reference other vars |
plot |
Axis assignment and plot type (line / stem / scatter) |
Read vs Write: Without value, the variable is read from the target each cycle. With value, it is written to the target each cycle.
Struct: When a variable occupies multiple fields (e.g. a C struct or packed flags), use struct to split it:
[[vars]]
name = 'status'
address = 0x20000040
format = '<BBH'
struct = ['flags', '_pad0', 'counter']
Fields starting with _ are discarded. The remaining fields become separately plottable.
Expression: Apply scaling or computation on the fly. See docs/expression.md for the full reference of supported math functions and expression modes:
[[vars]]
name = 'temperature'
address = 0x4001204C
format = '<H'
expr = '(x * 3.3 / 4096 - 0.76) / 0.0025 + 25'
Symbol name instead of raw address: Set elf_file in config (or pass --elf on the CLI) to resolve C variable names to addresses automatically:
[[vars]]
name = 'adc_value'
address = 'ADC1->DR' # resolved from ELF/DWARF
format = '<H'
[[vars]]
name = 'system_tick'
address = 'sys_tick_count' # any global variable works
format = '<I'
No need to look up datasheet memory maps or update addresses after firmware changes — the symbol name follows the code. Use ucap sym -e firmware.elf to explore available symbols.
Pre / Post Variables
[[pre_vars]] and [[post_vars]] are single-shot variable groups read before (or after) the continuous acquisition loop. Useful for capturing static configuration or calibration values:
[[pre_vars]]
name = 'device_id'
address = 0xE0042000
format = '<I'
[[post_vars]]
name = 'status_at_end'
address = 0x200000F0
format = '<H'
Pre/post data is saved in metadata.json under pre_data and post_data.
Usage
ucap rw — Continuous Read/Write
Headless batch-mode data acquisition. Reads/writes target variables continuously at the configured frequency. No GUI overhead — the fastest mode. Press Ctrl+C to stop; then saves data and plots with matplotlib.
ucap rw -c path/to/config.toml
You can specify the ELF file via the --elf CLI option or the elf_file config key, so configs can use C variable names in address instead of raw hex:
ucap rw -c path/to/config.toml --elf path/to/firmware.elf
# config.toml
elf_file = 'path/to/firmware.elf'
This makes configs more readable and resilient — addresses update automatically when firmware changes, and there's no need to cross-check linker maps or datasheet memory layouts.
ucap mon — Real-time Monitor
Real-time read/write with live plotting GUI.
ucap mon -c path/to/config.toml
ucap show — Plot Saved Data
Re-plots data previously captured by ucap rw or ucap mon using matplotlib. The config is auto-loaded from the data directory if available.
ucap show -d path/to/data_dir
ucap sym — List ELF Symbols
Lists all global variables (and their types / struct members) from an ELF file. Useful for finding variable addresses when writing configs.
ucap sym -e path/to/firmware.elf
Filter by regex pattern:
ucap sym -e path/to/firmware.elf "TIM|ADC"
Interactive filtering with fzf:
ucap sym -e path/to/firmware.elf | fzf
Shell Completion
Tab completion is supported for bash / zsh / fish / powershell:
# bash
eval "$(ucap completion bash)"
# zsh
eval "$(ucap completion zsh)"
# fish
ucap completion fish | source
# powershell
ucap completion powershell | Out-String | Invoke-Expression
Add the eval line to ~/.bashrc, ~/.zshrc, fish config, or PowerShell $PROFILE to enable permanently.
Backend Support
| Backend | Description | Dependency |
|---|---|---|
pyocd |
Default, versatile, supports many debuggers | pyocd |
pyswd |
Lightweight and fast, ST-Link only | pyswd |
openocd |
Requires a pre-started OpenOCD daemon (TCP) | openocd |
mock |
In-memory simulation for development/testing | (built-in) |
Example Configs
The examples/ directory provides config templates for various scenarios:
| File | Description |
|---|---|
simple.toml |
Minimal config, quick start |
full.toml |
Comprehensive example covering scalar / array / struct / computed / write |
symbol.toml |
ELF symbol resolution — use variable names instead of raw addresses |
plot.toml |
Plotting config (multi-figure / multi-layout / plot / stem / scatter) |
pyocd.toml |
pyOCD backend connecting to a specific target chip |
pyswd.toml |
pySWD backend (ST-Link) |
openocd.toml |
OpenOCD backend, requires manually starting the daemon |
For a full reference of all config options, see docs/config-reference.toml.
Project details
Download files
Download the file for your platform. If you're not sure which to choose, learn more about installing packages.
Source Distribution
Built Distribution
Filter files by name, interpreter, ABI, and platform.
If you're not sure about the file name format, learn more about wheel file names.
Copy a direct link to the current filters
File details
Details for the file python_ucap-0.7.6.tar.gz.
File metadata
- Download URL: python_ucap-0.7.6.tar.gz
- Upload date:
- Size: 116.1 kB
- Tags: Source
- Uploaded using Trusted Publishing? Yes
- Uploaded via: twine/6.1.0 CPython/3.13.12
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
a1fe0ba9fc6f2103506029bc1a0cbf8740f360278bbb446b0a76b6ff8deaa1f8
|
|
| MD5 |
cd10af605243f85f0e9c6034fc2dafb2
|
|
| BLAKE2b-256 |
927a63d2a8eb7fb3617b6bc23738516e4a6111586ac921f64fcae32de9c6e5d1
|
Provenance
The following attestation bundles were made for python_ucap-0.7.6.tar.gz:
Publisher:
release.yml on vaxowt/ucap
-
Statement:
-
Statement type:
https://in-toto.io/Statement/v1 -
Predicate type:
https://docs.pypi.org/attestations/publish/v1 -
Subject name:
python_ucap-0.7.6.tar.gz -
Subject digest:
a1fe0ba9fc6f2103506029bc1a0cbf8740f360278bbb446b0a76b6ff8deaa1f8 - Sigstore transparency entry: 1615112096
- Sigstore integration time:
-
Permalink:
vaxowt/ucap@72bad8cf59e41a8752522a4277140c7634a47a89 -
Branch / Tag:
refs/tags/v0.7.6 - Owner: https://github.com/vaxowt
-
Access:
public
-
Token Issuer:
https://token.actions.githubusercontent.com -
Runner Environment:
github-hosted -
Publication workflow:
release.yml@72bad8cf59e41a8752522a4277140c7634a47a89 -
Trigger Event:
push
-
Statement type:
File details
Details for the file python_ucap-0.7.6-py3-none-any.whl.
File metadata
- Download URL: python_ucap-0.7.6-py3-none-any.whl
- Upload date:
- Size: 38.5 kB
- Tags: Python 3
- Uploaded using Trusted Publishing? Yes
- Uploaded via: twine/6.1.0 CPython/3.13.12
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
972e936b0224efbe64d9e6e602ac7598283db317c4ae4d3a6f8c722b7af808a0
|
|
| MD5 |
0e212dcfb1d43e53af279b267c930879
|
|
| BLAKE2b-256 |
7b01363f7fb3030c3234b4272a81636fc204093ae2a171b0b579b6806007c5e1
|
Provenance
The following attestation bundles were made for python_ucap-0.7.6-py3-none-any.whl:
Publisher:
release.yml on vaxowt/ucap
-
Statement:
-
Statement type:
https://in-toto.io/Statement/v1 -
Predicate type:
https://docs.pypi.org/attestations/publish/v1 -
Subject name:
python_ucap-0.7.6-py3-none-any.whl -
Subject digest:
972e936b0224efbe64d9e6e602ac7598283db317c4ae4d3a6f8c722b7af808a0 - Sigstore transparency entry: 1615112111
- Sigstore integration time:
-
Permalink:
vaxowt/ucap@72bad8cf59e41a8752522a4277140c7634a47a89 -
Branch / Tag:
refs/tags/v0.7.6 - Owner: https://github.com/vaxowt
-
Access:
public
-
Token Issuer:
https://token.actions.githubusercontent.com -
Runner Environment:
github-hosted -
Publication workflow:
release.yml@72bad8cf59e41a8752522a4277140c7634a47a89 -
Trigger Event:
push
-
Statement type: