ViewAlyzer Recorder
The recorder is the firmware side of ViewAlyzer: a small C library you compile into your target that writes a compact binary event stream (task switches, interrupts, sync objects, your own values and markers) to a transport the host reads. The host is any of the ViewAlyzer front ends: the desktop app, the headless CLI, the Python SDK, the BKPT Debug extension. This section is the user-facing API: what you call, what you configure, what each transport needs.
What it covers
| ADAPTER | WHAT IS TRACED FOR FREE | YOUR CALLS |
|---|---|---|
Bare metal (VA_RTOS_SELECT=VA_RTOS_NONE) | Nothing automatic: no kernel, no hooks | Values, events, markers, ISR entry and exit, GPIO, counters, heap gauge |
| FreeRTOS (v9.0 to 11.x) | Task switches, creation and deletion, stack usage, queues, semaphores, mutexes and their contention, notifications, event groups, timers, heap, tickless idle | The same value and marker API, plus ISR entry and exit in your handlers |
| Zephyr (Cortex-M) | Threads, mutexes, semaphores, message queues, k_event, k_work, k_timer, sleep, power management, heaps | The same value and marker API |
Three transports carry the stream, chosen at build time with VA_TRANSPORT: ITM over the SWO pin, SEGGER RTT, or a RAM ring buffer the probe reads over SWD (the default; works on every core, including Cortex-M0/M0+/M23 that have no ITM). A fourth, CUSTOM_TRANSPORT, hands COBS-framed packets to a function you supply (UART, USB, radio). See Transports and snapshots.
Five minutes to a first trace
- Add
core/ViewAlyzer.c(and the adapter file for your RTOS) to the build,core/(andfreertos/or the Zephyr module) to the include path. - Define the build knobs. The only mandatory one is the device header:
add_definitions(
-DVA_ENABLED=1
-DVA_RTOS_SELECT=VA_RTOS_NONE # VA_RTOS_FREERTOS or VA_RTOS_ZEPHYR
-DVA_DEVICE_HEADER=stm32g4xx.h # your CMSIS device header, bare token
-DVA_TRANSPORT=RAM_BUFFER) # ARM_ITM | JLINK_RTT | RAM_BUFFER | CUSTOM_TRANSPORT
- Start the recorder once clocks are up, register what you will log, then log from anywhere:
#include "ViewAlyzer.h"
enum { TRACE_SINE = 1, TRACE_LED = 2, EVENT_WORK = 1 };
int main(void)
{
SystemClock_Config();
VA_Init(SystemCoreClock); /* before any VA_Register* */
VA_RegisterUserTrace(TRACE_SINE, "Sine Wave", VA_USER_TYPE_GRAPH);
VA_RegisterUserTrace(TRACE_LED, "LED Toggle", VA_USER_TYPE_TOGGLE);
VA_RegisterUserEvent(EVENT_WORK, "Work Block");
for (;;) {
VA_EVENT_START(EVENT_WORK);
int32_t v = process_sample();
VA_EVENT_END(EVENT_WORK);
VA_LogTrace(TRACE_SINE, v);
VA_LogToggle(TRACE_LED, led_state);
VA_TickOverflowCheck(); /* housekeeping, see the API reference */
}
}
- Capture from the host:
viewalyzer-cli capture --config board.vacf --elf firmware.elf --output run.vadb --duration 10, or press Record in the app. The.vacfnames the matching transport (stlink-rambuffor a RAM buffer over an ST-LINK, and so on): Transports and snapshots pairs them up.
Note: VA_Init resets every registry, so register after it, never before. It also checks that the timestamp source is counting and refuses to start (the host sees ERR:TS_*) when it is not, which catches a vendor-omitted DWT before you chase ghosts.
Where things are
- Integration: build steps per adapter, the FreeRTOS hook header, the Zephyr module and Kconfig.
- Configuration: every
VA_*knob, its default, and theva_config.hcontract. - API reference: every function and macro you call, including the housekeeping calls (
VA_TickOverflowCheck,VA_EmitSetupBundle,VA_Drain,VA_SnapshotFreeze). - Transports and snapshots: ITM, RTT, RAM buffer, custom transports, the post-mortem ring, and the host configuration that goes with each.
Worked examples for every adapter and transport live in the ViewAlyzer-Examples repository (baremetal/, freertos/, zephyr/, each with its .vacf).
Versions
The recorder reports two numbers. VA_RECORDER_VERSION (1.1.0, from VA_RECORDER_VERSION_MAJOR/MINOR/PATCH in core/ViewAlyzer.h) is the library release; it is sent to the host in the setup bundle and shown in the recording's metadata. VA_WIRE_VERSION (1) is the stream format, encoded in the sync marker; it changes only on a breaking framing change, so a host that understands wire version 1 reads every 1.x recorder. The recorder and the host app are released together as a pair.