Transports and snapshots
The recorder writes one packet stream; VA_TRANSPORT picks how it leaves the chip, and the host's connection file (.vacf) names the matching reader. This page pairs them up and covers the post-mortem ring.
Which transport
| VA_TRANSPORT | NEEDS ON THE TARGET | HOST TRANSPORT (.VACF) | THROUGHPUT | WHEN |
|---|---|---|---|---|
RAM_BUFFER (default) | RAM for the ring (8 KB default); any Cortex-M | stlink-rambuf, jlink-rambuf | Limited by the probe's SWD memory reads and the SWD clock; the throughput/ examples measure it per probe | Every board; no pins beyond SWD; the only choice on M0/M0+/M23 |
ARM_ITM | An ITM and the SWO pin wired to the probe (Cortex-M3/M4/M7/M33) | stlink-swo, jlink-swo | The SWO rate: 2 MHz is 200 KB/s, a STLINK-V3 takes up to 24 MHz | Highest bandwidth, and the only transport that also carries hardware trace (PC samples, exception trace, data watches) on the same pin |
JLINK_RTT | SEGGER RTT (SEGGER_RTT.c in the build) | stlink-rtt, jlink-rtt | Similar to the RAM buffer | Projects that already use RTT for logging |
CUSTOM_TRANSPORT | A byte pipe of your own (UART, USB CDC, radio) and core/viewalyzer_cobs.c | serial, udp | Your link's rate | No debug probe at run time, or a remote target |
Every probe transport also takes --target-device, --speed-khz and, with several probes attached, --stlink-serial or --jlink-serial.
RAM buffer
#define VA_TRANSPORT RAM_BUFFER
#define VA_RAMBUF_SIZE 16384u
#define VA_RAMBUF_MODE VA_RAMBUF_MODE_DROP /* DROP | BLOCK | WRAP */
The recorder keeps a ring with a control block in RAM; the probe reads it over SWD while the core runs, so the firmware never waits on a pin. The host finds the ring by the _VA_RAMBUF symbol when you pass --elf, or by scanning RAM for the magic tag:
{
"transport": "stlink-rambuf",
"target-device": "STM32G474RE",
"speed-khz": 24000,
"rambuf-scan-start": "0x20000000",
"rambuf-scan-size": 131072
}
$ viewalyzer-cli capture --config nucleo_g474_rambuf.vacf --elf build/rambuf/Nucleo_G474_VA.elf --output run.vadb --duration 10
Modes: DROP loses the newest packet when the ring is full (the sequence byte tells the host how many); BLOCK spins in the writer until the probe drains, which keeps every event at the cost of timing; WRAP overwrites the oldest, turning the ring into a post-mortem window (below). On a part with a data cache place the ring in non-cacheable memory with VA_RAMBUF_ATTRIBUTES and a matching linker section; otherwise nothing is needed.
ITM over SWO
#define VA_TRANSPORT ARM_ITM
#define VA_ITM_PORT 1 /* port 0 stays free for printf */
The host programs the ITM, the TPIU and the trace clock through the probe on connect (init-swo, on by default), so the firmware does not touch the trace registers. The two sides must agree on the core clock and the SWO rate:
{
"transport": "stlink-swo",
"target-device": "STM32G474RE",
"cpu-clock-hz": 170000000,
"swo-freq-hz": 2000000,
"itm-port": 1
}
The rate is bounded by the probe's receiver (2 MHz on a V2 ST-LINK and a J-Link over probe-rs, 24 MHz on a STLINK-V3) and must divide the core clock in whole numbers. When nobody drains the pin the ITM FIFO fills; the recorder detects the stall and drops rather than blocks, then re-arms from VA_TickOverflowCheck() once a host appears. Hardware trace (--dwt, --dwt-pc, --dwt-watch, the hardware-trace block) rides the same pin; see the CLI reference.
RTT
#define VA_TRANSPORT JLINK_RTT
#define VA_RTT_CHANNEL 0
#define VA_CONFIGURE_RTT 1 /* the recorder sizes the channel itself */
{ "transport": "stlink-rtt", "target-device": "STM32F446RE", "rtt-channel": 0 }
The host finds _SEGGER_RTT in RAM (or --rtt-address / --elf pins it) and drains the up-channel named ViewAlyzer, else the configured index. Works over an ST-LINK too: the RTT control block is ordinary memory.
Custom transport
#define VA_TRANSPORT CUSTOM_TRANSPORT
static void uart_send(const uint8_t *data, uint32_t length)
{
HAL_UART_Transmit_DMA(&huart2, data, (uint16_t) length); /* one COBS frame per call */
}
VA_RegisterTransportSend(uart_send); /* before VA_Init */
VA_Init(SystemCoreClock);
Packets arrive COBS-framed and zero-delimited (core/viewalyzer_cobs.c does the framing); ship each buffer as is. On the host, the serial transport reads a port, udp listens on a socket; both expect COBS ("cobs": true by default):
{ "transport": "serial", "serial-port": "COM7", "baud": 921600 }
{ "transport": "udp", "udp-port": 17200 }
Buffered mode
VA_TRANSPORT_BUFFERED=1 stages packets in a RAM ring (VA_BUFFER_SIZE, a power of two) and ships them when you call VA_Drain() from the idle loop, so an ISR-heavy system never blocks on the pipe. Applies to ITM, RTT and custom transports; the RAM buffer transport is already a ring.
Post-mortem snapshots
Two ways to keep the last events across a crash:
VA_RAMBUF_MODE_WRAP: the live RAM buffer itself overwrites the oldest packets, so it always holds the most recent window.VA_SNAPSHOT=1: a second ring (VA_SNAPSHOT_SIZE, withVA_SNAPSHOT_SETUP_SIZEreserved for the names) alongside any live transport.
In both cases call VA_SnapshotFreeze() from the fault or assert handler; the ring stops and the window is preserved through the handler, a reset loop, or a halted core. The host reads it without resetting the target:
$ viewalyzer-cli snapshot --config nucleo_g474_rambuf.vacf --elf firmware.elf --output crash.vadb
The envelope reports ring (post-mortem or live-drop), events, window_bytes, discarded_packets, wrapped, frozen; the recording opens like any other, with the last seconds before the freeze. viewalyzer-cli reset resets the target afterwards.
Sizing the transport
A packet is 7 bytes for an ISR edge or a task switch (type, sequence, id, 32-bit timestamp), 11 for a value, 12 plus the text for a marker. As a rule of thumb at 100 KB/s: a 1 kHz task switch rate with a few values per millisecond fits in a RAM buffer; a 10 kHz ISR with entry and exit traced (140 KB/s by itself) does not, and belongs on the SWO pin or should be sampled. The capture summary's lost_events and the sequence gaps tell you when the transport fell behind; VA_RAMBUF_MODE_BLOCK trades timing for completeness while you find out where.