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_DEVICE_HEADER  stm32g474xx.h
#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 setting without a default is the device header. Put it in va_config.h too (the Zephyr module supplies it automatically):

#define VA_DEVICE_HEADER stm32g474xx.h

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

Master switches

RAM metadata is enabled by default for direct DROP-mode RAM-buffer recording without a snapshot tee. Use a compatible ViewAlyzer-RS host and the matching firmware ELF. Set VA_METADATA=0 for setup-bundle capture.

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_TRANSPORTRAM_BUFFERARM_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), except VA_TRACE_TASK_STATES, which follows VA_TRACE_TASKS, and VA_TRACE_TIMER_CALLBACKS, which follows VA_TRACE_TIMERS. 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_STATESReady/blocked/sleep/suspend states, wait reasons and runtime priorities
VA_TRACE_STREAM_BUFFERSFreeRTOS stream/message-buffer operations and byte counts
VA_TRACE_MEM_SLABSZephyr slab usage, capacity, allocation failures
VA_TRACE_CONDVARS, VA_TRACE_POLLZephyr condition-variable and poll waits/results/signals
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, stop
VA_TRACE_TIMER_CALLBACKSZephyr expiry/stop handler spans; also requires VA_TRACE_TIMERS
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

For fixed-coverage benchmarks and HIL baselines, explicitly set VA_TRACE_TASK_STATES=0 and VA_TRACE_TIMER_CALLBACKS=0 to retain task switches and timer lifecycle events without the newer state/priority and callback packets. VA_TRACE_DEFAULT=0 alone does not disable subcategories of enabled parents. In Zephyr, use CONFIG_VIEWALYZER_TRACE_TASK_STATES=n and CONFIG_VIEWALYZER_TRACE_TIMER_CALLBACKS=n. Callback spans are currently automatic only on Zephyr kernels that expose the stock handler entry/exit hooks. Enabling this flag adds no automatic events on FreeRTOS or older Zephyr kernels; FreeRTOS timer-expiry events still follow VA_TRACE_TIMERS.

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_METADATA1 for direct DROP-mode RAM without a snapshot tee; 0 otherwiseELF-assisted attachment; set 0 for setup bundles
VA_METADATA_SIZE2048uMetadata table capacity in bytes, plus a 64-byte descriptor and service state
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, control blocks and metadata, 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 of at least 64 bytes
VA_DRAIN_MAX_BYTES256Maximum bytes offered to the sink per VA_Drain() call; at least 1

Pass the matching firmware ELF with --elf for default RAM metadata capture. With VA_METADATA=0, the host can also locate the ring by scanning RAM (--rambuf-scan-start, --rambuf-scan-size). On cached cores, use linker/MPU configuration to put the ring, descriptors and metadata in non-cacheable RAM.

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; allowed 4–255)
VA_MAX_LOG_STRING_LEN100 (allowed 0–1024; 0 suppresses string payloads)

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.

Session, clock, OS and error metadata use a separate fixed capacity, so short display names do not truncate control messages. Custom transport packet capacity is derived from both names and logs; neither setting imposes a minimum on the other. The current ViewAlyzer-RS decoder accepts names up to 64 characters; larger recorder settings are memory-safe but need corresponding viewer support.

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

Timestamped events automatically track counter rollover. During quiet periods, call VA_TickOverflowCheck() more often than the source timer wraps. It also services idle attachment requests and time/sequence checkpoints. Example service intervals (allow for scheduling delays; see API reference):

SOURCE RATE WRAP PERIOD CALL CADENCE
DWT, 32-bit170 MHz25 s100 ms
DWT, 32-bit48 MHz89 s100 ms
Custom, 16-bit1 MHz65 ms10 ms
Custom, 32-bit1 MHz72 min100 ms

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_MS2000Full setup retransmission interval when metadata is disabled; ignored with VA_METADATA=1. Service from an unmasked thread using VA_TickOverflowCheck()
VA_RAMBUF_SETUP_ON_ATTACH1With metadata disabled, request one setup bundle when a host starts draining the RAM ring; not used in WRAP mode
VA_RAMBUF_HOST_IDLE_MS1000A host that leaves pending ring data unconsumed this long counts as detached; the next drain is a new attach

FreeRTOS stack tracing uses a word scanner with the same high-water accuracy and sampling schedule. It needs aligned, downward-growing 32-bit stacks with known bounds and the standard 0xA5 fill. Unsupported layouts, unknown bounds or a scan that exhausts its bound use uxTaskGetStackHighWaterMark() instead. There is no scanner-selection setting; VA_TRACE_STACK_USAGE=0 disables stack measurements. Other RTOSes are unaffected. See FreeRTOS stack scanning.

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), metadata (_METADATA, _METADATA_SIZE), 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.