SVD Register Decoding
The SVDManager subsystem integrates CMSIS-SVD metadata with live hardware reads. Given an SVD file describing a microcontroller’s peripheral registers, it can read a register from the target and decode its raw value into named bitfields — turning opaque hex values into human-readable output.
Access it through the session:
# Asyncsession.svd
# Syncsync_session.svdPrerequisites
Section titled “Prerequisites”The SVD subsystem requires the cmsis-svd package, which is included in the default dependencies:
uv add openocd-pythonLoading an SVD file
Section titled “Loading an SVD file”load(svd_path) parses an SVD XML file and indexes its peripherals and registers. The file parse runs in a background thread (via asyncio.to_thread) to avoid blocking the event loop on large SVD files.
import asynciofrom pathlib import Pathfrom openocd import Session
async def main(): async with await Session.connect() as session: await session.svd.load(Path("STM32F103.svd")) print(f"SVD loaded: {session.svd.loaded}")
asyncio.run(main())from pathlib import Pathfrom openocd import Session
with Session.connect_sync() as session: session.svd.load(Path("STM32F103.svd")) print(f"SVD loaded: {session.svd.loaded}")Raises SVDError if the file is not found or cannot be parsed.
Browsing peripherals and registers
Section titled “Browsing peripherals and registers”After loading, enumerate what is available. Both list_peripherals() and list_registers() are synchronous methods (no await needed) since they operate on in-memory data.
async with await Session.connect() as session: await session.svd.load(Path("STM32F103.svd"))
# List all peripherals peripherals = session.svd.list_peripherals() print(f"Found {len(peripherals)} peripherals:") for name in peripherals[:10]: print(f" {name}")
# List registers in a specific peripheral regs = session.svd.list_registers("GPIOA") print(f"\nGPIOA registers: {', '.join(regs)}")with Session.connect_sync() as session: session.svd.load(Path("STM32F103.svd"))
peripherals = session.svd.list_peripherals() print(f"Found {len(peripherals)} peripherals:") for name in peripherals[:10]: print(f" {name}")
regs = session.svd.list_registers("GPIOA") print(f"\nGPIOA registers: {', '.join(regs)}")Reading and decoding a register
Section titled “Reading and decoding a register”read_register(peripheral, register) is the primary method. It computes the register’s memory-mapped address from the SVD metadata, reads 32 bits from that address on the target, and decodes the raw value into named bitfields.
async with await Session.connect() as session: await session.svd.load(Path("STM32F103.svd")) await session.target.halt()
decoded = await session.svd.read_register("GPIOA", "ODR") print(decoded)with Session.connect_sync() as session: session.svd.load(Path("STM32F103.svd")) session.target.halt()
decoded = session.svd.read_register("GPIOA", "ODR") print(decoded)The DecodedRegister.__str__ method formats the output:
GPIOA.ODR @ 0x4001080C = 0x00000001 [ 0:0] ODR0 = 0x1 Port output data bit 0 [ 1:1] ODR1 = 0x0 Port output data bit 1 [ 2:2] ODR2 = 0x0 Port output data bit 2 ...Each line shows the bit range, field name, extracted value, and the description from the SVD metadata.
Reading an entire peripheral
Section titled “Reading an entire peripheral”read_peripheral(peripheral) reads and decodes every register in a peripheral, returning a dict keyed by register name.
async with await Session.connect() as session: await session.svd.load(Path("STM32F103.svd")) await session.target.halt()
all_regs = await session.svd.read_peripheral("GPIOA") for name, decoded in all_regs.items(): print(f"\n{decoded}")with Session.connect_sync() as session: session.svd.load(Path("STM32F103.svd")) session.target.halt()
all_regs = session.svd.read_peripheral("GPIOA") for name, decoded in all_regs.items(): print(f"\n{decoded}")Decoding without hardware
Section titled “Decoding without hardware”decode(peripheral, register, value) decodes a raw integer value using SVD metadata without performing any hardware read. Useful when you already have the value from a log file, a previous read, or a known reset value.
async with await Session.connect() as session: await session.svd.load(Path("STM32F103.svd"))
# Decode a known value -- no target read needed decoded = session.svd.decode("RCC", "CR", 0x0300_0083) print(decoded)with Session.connect_sync() as session: session.svd.load(Path("STM32F103.svd"))
decoded = session.svd.decode("RCC", "CR", 0x0300_0083) print(decoded)decode() is synchronous in both APIs — it operates purely on in-memory data.
Data types
Section titled “Data types”DecodedRegister
Section titled “DecodedRegister”| Field | Type | Description |
|---|---|---|
peripheral | str | Peripheral name (e.g. GPIOA) |
register | str | Register name (e.g. ODR) |
address | int | Memory-mapped address |
raw_value | int | Raw 32-bit value read from hardware |
fields | list[BitField] | Decoded bitfields, sorted by bit offset |
BitField
Section titled “BitField”| Field | Type | Description |
|---|---|---|
name | str | Field name from the SVD (e.g. ODR0) |
offset | int | Bit offset within the register |
width | int | Field width in bits |
value | int | Extracted field value |
description | str | Description from the SVD metadata |
Error handling
Section titled “Error handling”from openocd import SVDError
try: session.svd.list_peripherals()except SVDError as e: print(f"No SVD loaded: {e}")
try: decoded = await session.svd.read_register("NONEXISTENT", "REG")except SVDError as e: print(f"Lookup failed: {e}")Common SVDError cases:
- No SVD file loaded (call
load()first) - Peripheral name not found in the SVD
- Register name not found within the peripheral
- SVD file does not exist or is malformed
Hardware read failures from read_register and read_peripheral raise TargetError, not SVDError.
Method reference
Section titled “Method reference”| Method | Return Type | Description |
|---|---|---|
load(svd_path) | None | Parse an SVD XML file |
loaded (property) | bool | Whether an SVD is loaded |
list_peripherals() | list[str] | Sorted peripheral names |
list_registers(peripheral) | list[str] | Sorted register names for a peripheral |
read_register(peripheral, register) | DecodedRegister | Read from hardware and decode |
read_peripheral(peripheral) | dict[str, DecodedRegister] | Read all registers in a peripheral |
decode(peripheral, register, value) | DecodedRegister | Decode without hardware read |