Skip to content

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:

# Async
session.svd
# Sync
sync_session.svd

The SVD subsystem requires the cmsis-svd package, which is included in the default dependencies:

Terminal window
uv add openocd-python

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 asyncio
from pathlib import Path
from 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())

Raises SVDError if the file is not found or cannot be parsed.

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)}")

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)

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.

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}")

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)

decode() is synchronous in both APIs — it operates purely on in-memory data.

FieldTypeDescription
peripheralstrPeripheral name (e.g. GPIOA)
registerstrRegister name (e.g. ODR)
addressintMemory-mapped address
raw_valueintRaw 32-bit value read from hardware
fieldslist[BitField]Decoded bitfields, sorted by bit offset
FieldTypeDescription
namestrField name from the SVD (e.g. ODR0)
offsetintBit offset within the register
widthintField width in bits
valueintExtracted field value
descriptionstrDescription from the SVD metadata
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.

MethodReturn TypeDescription
load(svd_path)NoneParse an SVD XML file
loaded (property)boolWhether 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)DecodedRegisterRead from hardware and decode
read_peripheral(peripheral)dict[str, DecodedRegister]Read all registers in a peripheral
decode(peripheral, register, value)DecodedRegisterDecode without hardware read