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

Recorder configuration

Every knob is a preprocessor macro with a default in core/ViewAlyzerConfig.h. That file includes nothing (no CMSIS, no RTOS header), so it is safe to include from anywhere, FreeRTOSConfig.h included. You never edit it in place: a package update would overwrite the edit.

Three ways to set a knob

In order of precedence:

  1. Your own header, named on the command line as a bare token (no quotes, no angle brackets):
add_definitions(-DVA_CONFIG_HEADER=va_config.h)
/* va_config.h: only what differs from the defaults */
#define VA_TRANSPORT      RAM_BUFFER
#define VA_RAMBUF_SIZE    16384u
#define VA_TRACE_DEFAULT  0          /* opt in below */
#define VA_TRACE_TASKS    1
#define VA_TRACE_ISRS     1
#define VA_TRACE_MUTEX_CONTENTION 1
#define VA_TRACE_USER_VALUES 1
  1. **-D on the command line** (every knob is #ifndef-guarded).
  2. Editing ViewAlyzerConfig.h (lost on update; do not).

Warning: the configuration must reach every translation unit, the RTOS kernel included, so that the kernel hooks and ViewAlyzer.c agree on the layout. Use a directory-wide add_definitions() or a global -D, not target_compile_definitions() on the app target only, and never define VA_* knobs inside FreeRTOSConfig.h (invisible to ViewAlyzer.c).

The only knob without a default is the device header:

-DVA_DEVICE_HEADER=stm32g474xx.h      # Zephyr: cmsis_core.h (set by the module)

core/va_config_template.h lists every knob, commented out, as a starting point.

Master switches

KNOB DEFAULT MEANING
VA_ENABLED10 compiles the whole API out (every call becomes an argument-discarding macro)
VA_RTOS_SELECTVA_RTOS_NONEVA_RTOS_NONE (0), VA_RTOS_FREERTOS (1), VA_RTOS_ZEPHYR (2); VA_RTOS_THREADX (3) is reserved
VA_DEVICE_HEADERnone, requiredThe CMSIS device header, bare token
VA_TRANSPORTARM_ITMARM_ITM (1), JLINK_RTT (2), CUSTOM_TRANSPORT (3), RAM_BUFFER (4)

Categories

Each category is 0 or 1 and defaults to VA_TRACE_DEFAULT (1), so the usual pattern is either "everything on" or VA_TRACE_DEFAULT 0 plus an opt-in list. Turning a category off removes its packets from the wire and its functions from the binary.

CATEGORY TRACES
VA_TRACE_TASKSTask switches, creation, deletion, renames (RTOS)
VA_TRACE_TASK_NOTIFICATIONSFreeRTOS task notifications
VA_TRACE_STACK_USAGEPer-task stack high-water marks, every VA_STACK_USAGE_HEARTBEAT_MS
VA_TRACE_ISRSVA_LogISRStart/End lanes
VA_TRACE_MUTEXES, VA_TRACE_MUTEX_CONTENTIONMutex take/give, and who waited on whom (priority inversion analysis)
VA_TRACE_SEMAPHORES, VA_TRACE_QUEUES, VA_TRACE_EVENT_FLAGSSemaphores, queues and message queues, event groups / k_event
VA_TRACE_WORKZephyr k_work submit, schedule, cancel
VA_TRACE_SLEEP, VA_TRACE_PMTask delays and suspends; tickless idle and power-management suspend
VA_TRACE_TIMERSKernel timers: arm, expiry, callbacks
VA_TRACE_RTOS_HEAPSKernel heap alloc, free, failures, capacity
VA_TRACE_USER_VALUESVA_LogTrace, VA_LogTraceFloat, VA_LogToggle
VA_TRACE_USER_EVENTSVA_LogEvent spans
VA_TRACE_STRINGSVA_LogString markers
VA_TRACE_GPIO, VA_TRACE_COUNTERS, VA_TRACE_HEAP_METRICSGPIO lanes, counters, the manual heap gauge

Transport

KNOB DEFAULT MEANING
VA_ITM_PORT1ITM stimulus port the stream rides (0 to 31); the host's --itm-port must match. Port 0 stays free for printf
VA_RTT_CHANNEL0RTT up-channel index; the host finds the channel named ViewAlyzer, else this index
VA_CONFIGURE_RTT1The recorder configures the channel itself (VA_RTT_BUFFER_SIZE, VA_RTT_MODE)
VA_RTT_BUFFER_SIZE4096uRTT up-buffer size
VA_RTT_MODESEGGER_RTT_MODE_NO_BLOCK_SKIPDrop rather than block when the host is not draining
VA_RAMBUF_SIZE8192uRAM ring size in bytes (16 KB is comfortable on an RTOS with several tasks)
VA_RAMBUF_MODEVA_RAMBUF_MODE_DROPDROP (0): drop the newest packet when full; BLOCK (1): spin until the probe drains; WRAP (2): overwrite the oldest, a post-mortem window
VA_RAMBUF_ATTRIBUTESemptyAttributes for the ring, for instance __attribute__((section(".va_rambuf"))) to place it in non-cacheable RAM on a cached part
VA_RAMBUF_BUSY_IDLE1Keep the core out of WFI while the RAM buffer is active: some probe and MCU combinations return garbage for debug memory reads while the core sleeps. 1 spins in the idle path (interrupts still serviced), 0 sleeps normally. Consumed by the Zephyr adapter; bare metal and FreeRTOS keep the core awake themselves when their probe misreads during sleep
VA_TRANSPORT_BUFFERED0Stage packets in a RAM ring and flush with VA_Drain() (ITM, RTT, custom); not combinable with RAM_BUFFER
VA_BUFFER_SIZE4096The staging ring, a power of two

The host locates a RAM ring by the _VA_RAMBUF ELF symbol (pass --elf) or by scanning RAM for its magic tag (--rambuf-scan-start, --rambuf-scan-size). No linker script change is needed; the ring is ordinary .bss unless you give it attributes.

Post-mortem snapshot

KNOB DEFAULT MEANING
VA_SNAPSHOT0Keep a second, wrap-around ring of the last events alongside the live transport
VA_SNAPSHOT_SIZE4096uIts size
VA_SNAPSHOT_SETUP_SIZE1024uRoom reserved for the setup bundle so names survive with the window
VA_SNAPSHOT_ATTRIBUTESemptyPlacement attributes, as for the RAM buffer

VA_SnapshotFreeze() stops the ring; viewalyzer-cli snapshot reads it without resetting the target. See Transports and snapshots.

Registries

KNOB DEFAULT
VA_MAX_TASKS16
VA_MAX_SYNC_OBJECTS64
VA_MAX_USER_EVENTS16
VA_MAX_USER_TRACES16
VA_MAX_GPIOS16
VA_MAX_HEAPS8
VA_MAX_TASK_NAME_LEN16 (including the terminator; also the length of every registered name)
VA_MAX_LOG_STRING_LEN100

Raise VA_MAX_TASKS on a Zephyr system with many threads (the Zephyr demo uses 28) and VA_MAX_TASK_NAME_LEN when your names are longer than 15 characters.

Timestamps

KNOB DEFAULT MEANING
VA_TIMESTAMP_SOURCEDWT_CYCCNTThe Cortex-M cycle counter; CUSTOM_TIMER for a free-running timer you supply to VA_Init
VA_TIMER_BITS32Width of the custom timer, 16 or 32

Wire timestamps are 32-bit; a software extension tracks wraps. The wrap period sets how often VA_TickOverflowCheck() must run during quiet stretches (see API reference):

SOURCE RATE WRAP PERIOD CALL CADENCE
DWT, 32-bit170 MHz25 severy 1 to 10 s
DWT, 32-bit48 MHz89 severy 1 to 10 s
Custom, 16-bit1 MHz65 msevery main-loop pass, or a 20 to 50 ms timer
Custom, 32-bit1 MHz72 minrarely, but keep it

VA_TIMESTAMP_BITS is 32 and not a knob; VA_SEQ_COUNTER (the per-packet sequence byte that lets the host count losses) is always on.

Timing and wire

KNOB DEFAULT MEANING
VA_ALLOWED_TO_DISABLE_INTERRUPTS1The recorder masks interrupts around a packet write; set 0 when your latency budget forbids it and log only from one context
VA_STACK_USAGE_HEARTBEAT_MS500Stack high-water sampling period
VA_AUTO_SETUP_INTERVAL_MS2000Automatic re-emission of the setup bundle (names), so a host can attach at any time

Zephyr: the same knobs as Kconfig

The Zephyr module maps CONFIG_VIEWALYZER_* options onto these macros (zephyr/CMakeLists.txt): transport (CONFIG_VIEWALYZER_TRANSPORT_ITM / _RTT / _RAMBUF), timestamp (CONFIG_VIEWALYZER_TS_DWT / _TS_CUSTOM_TIMER, CONFIG_VIEWALYZER_TIMER_BITS), every category (CONFIG_VIEWALYZER_TRACE_THREADS, _ISRS, _MUTEXES, _MUTEX_CONTENTION, _SEMAPHORES, _MESSAGE_QUEUES, _EVENT_FLAGS, _WORK, _SLEEP, _TIMERS, _HEAPS, _PM, _USER_VALUES, _USER_EVENTS, _STRINGS, _GPIO, _COUNTERS, _HEAP_METRICS), CONFIG_VIEWALYZER_STACK_USAGE, the registry sizes (_MAX_TASKS, _MAX_SYNC_OBJECTS, _MAX_USER_EVENTS, _MAX_USER_TRACES, _MAX_GPIOS, _MAX_HEAP_GAUGES, _MAX_TASK_NAME_LEN), the RTT and RAM-buffer knobs (_RTT_CHANNEL, _CONFIGURE_RTT, _RTT_BUFFER_SIZE, _RAMBUF_SIZE, _RAMBUF_BLOCK, _RAMBUF_WRAP, _RAMBUF_BUSY_IDLE), the snapshot (_SNAPSHOT, _SNAPSHOT_SIZE, _SNAPSHOT_SETUP_SIZE), _BUFFERED / _BUFFER_SIZE, _ALLOW_DISABLE_INTERRUPTS, _AUTO_SETUP_INTERVAL_MS, _STACK_USAGE_HEARTBEAT_MS. Two things are fixed by the module: VA_DEVICE_HEADER=cmsis_core.h and task notifications off. CUSTOM_TRANSPORT is not selectable from Kconfig.