BKPT LabsDOCS/VIEWALYZER RECORDER VIEWALYZER · FIRMWARE RECORDER
VIEWALYZER · RECORDER API

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 hooksValues, 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 idleThe 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, heapsThe 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

  1. Add core/ViewAlyzer.c (and the adapter file for your RTOS) to the build, core/ (and freertos/ or the Zephyr module) to the include path.
  2. Copy core/va_config_template.h into your project as va_config.h. Set your CMSIS device header there; the defaults already enable the recorder, select bare metal, and use the RAM buffer:
/* va_config.h */
#define VA_DEVICE_HEADER stm32g4xx.h

Add the directory containing va_config.h to your include path, then point the entire build at it with one definition:

add_definitions(-DVA_CONFIG_HEADER=va_config.h)

Keep va_config.h to settings that differ from the defaults. FreeRTOS users also select VA_RTOS_FREERTOS there; Zephyr users configure the module through Kconfig. The configuration reference lists every option.

  1. 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 registering user channels */
    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 */
    }
}
  1. Capture from the host: viewalyzer-cli capture --config board.vacf --elf firmware.elf --output run.vadb --duration 10, or select the matching ELF File and press Record in ViewAlyzer-RS. Default RAM capture requires an ELF and a host with RAM metadata support; see RAM metadata. The .vacf names the matching transport (stlink-rambuf for 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, so check the timer configuration if initialization fails.

For optional buffered ITM, RTT or custom output, schedule VA_Drain() from an application loop, task or FreeRTOS idle hook and budget its caller's stack. The default RAM transport does not need it. See Scheduling the drain.

Using a custom timer

Use a custom timer when your core has no DWT cycle counter (Cortex-M0/M0+/M23) or the device does not implement one. Add two settings to va_config.h:

#define VA_TIMESTAMP_SOURCE CUSTOM_TIMER
#define VA_TIMER_BITS       32              /* 16 or 32 */

Provide a cheap, lock-free reader for a free-running hardware timer, start the timer, and pass its exact frequency to the three-argument form of VA_Init:

static uint32_t read_trace_ticks(void)
{
    return TIM2->CNT;
}

/* Start TIM2 before this call; this example assumes a 1 MHz timer. */
VA_Init(SystemCoreClock, read_trace_ticks, 1000000u);

The reader must be safe from any context, including interrupts. During quiet periods, call VA_TickOverflowCheck() at least once per timer-wrap period. A 16-bit timer at 1 MHz wraps about every 65 ms, so prefer a 32-bit timer when one is available.

Where things are

  • RAM metadata: attach to running firmware with its ELF, configure table capacity, or select setup-bundle capture.
  • Integration: build steps per adapter, the FreeRTOS hook header, the Zephyr module and Kconfig.
  • Configuration: every VA_* knob, its default, and the va_config.h contract.
  • 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 (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. RAM metadata attachment additionally requires a host that supports its descriptor protocol. Set VA_METADATA=0 when using older viewers. The recorder and the host app are released together as a pair.