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:
- 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
- **
-Don the command line** (every knob is#ifndef-guarded). - 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_ENABLED | 1 | 0 compiles the whole API out (every call becomes an argument-discarding macro) |
VA_RTOS_SELECT | VA_RTOS_NONE | VA_RTOS_NONE (0), VA_RTOS_FREERTOS (1), VA_RTOS_ZEPHYR (2); VA_RTOS_THREADX (3) is reserved |
VA_DEVICE_HEADER | none, required | The CMSIS device header, bare token |
VA_TRANSPORT | ARM_ITM | ARM_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_TASKS | Task switches, creation, deletion, renames (RTOS) |
VA_TRACE_TASK_NOTIFICATIONS | FreeRTOS task notifications |
VA_TRACE_STACK_USAGE | Per-task stack high-water marks, every VA_STACK_USAGE_HEARTBEAT_MS |
VA_TRACE_ISRS | VA_LogISRStart/End lanes |
VA_TRACE_MUTEXES, VA_TRACE_MUTEX_CONTENTION | Mutex take/give, and who waited on whom (priority inversion analysis) |
VA_TRACE_SEMAPHORES, VA_TRACE_QUEUES, VA_TRACE_EVENT_FLAGS | Semaphores, queues and message queues, event groups / k_event |
VA_TRACE_WORK | Zephyr k_work submit, schedule, cancel |
VA_TRACE_SLEEP, VA_TRACE_PM | Task delays and suspends; tickless idle and power-management suspend |
VA_TRACE_TIMERS | Kernel timers: arm, expiry, callbacks |
VA_TRACE_RTOS_HEAPS | Kernel heap alloc, free, failures, capacity |
VA_TRACE_USER_VALUES | VA_LogTrace, VA_LogTraceFloat, VA_LogToggle |
VA_TRACE_USER_EVENTS | VA_LogEvent spans |
VA_TRACE_STRINGS | VA_LogString markers |
VA_TRACE_GPIO, VA_TRACE_COUNTERS, VA_TRACE_HEAP_METRICS | GPIO lanes, counters, the manual heap gauge |
Transport
| KNOB | DEFAULT | MEANING |
|---|---|---|
VA_ITM_PORT | 1 | ITM stimulus port the stream rides (0 to 31); the host's --itm-port must match. Port 0 stays free for printf |
VA_RTT_CHANNEL | 0 | RTT up-channel index; the host finds the channel named ViewAlyzer, else this index |
VA_CONFIGURE_RTT | 1 | The recorder configures the channel itself (VA_RTT_BUFFER_SIZE, VA_RTT_MODE) |
VA_RTT_BUFFER_SIZE | 4096u | RTT up-buffer size |
VA_RTT_MODE | SEGGER_RTT_MODE_NO_BLOCK_SKIP | Drop rather than block when the host is not draining |
VA_RAMBUF_SIZE | 8192u | RAM ring size in bytes (16 KB is comfortable on an RTOS with several tasks) |
VA_RAMBUF_MODE | VA_RAMBUF_MODE_DROP | DROP (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_ATTRIBUTES | empty | Attributes for the ring, for instance __attribute__((section(".va_rambuf"))) to place it in non-cacheable RAM on a cached part |
VA_RAMBUF_BUSY_IDLE | 1 | Keep 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_BUFFERED | 0 | Stage packets in a RAM ring and flush with VA_Drain() (ITM, RTT, custom); not combinable with RAM_BUFFER |
VA_BUFFER_SIZE | 4096 | The 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_SNAPSHOT | 0 | Keep a second, wrap-around ring of the last events alongside the live transport |
VA_SNAPSHOT_SIZE | 4096u | Its size |
VA_SNAPSHOT_SETUP_SIZE | 1024u | Room reserved for the setup bundle so names survive with the window |
VA_SNAPSHOT_ATTRIBUTES | empty | Placement 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_TASKS | 16 |
VA_MAX_SYNC_OBJECTS | 64 |
VA_MAX_USER_EVENTS | 16 |
VA_MAX_USER_TRACES | 16 |
VA_MAX_GPIOS | 16 |
VA_MAX_HEAPS | 8 |
VA_MAX_TASK_NAME_LEN | 16 (including the terminator; also the length of every registered name) |
VA_MAX_LOG_STRING_LEN | 100 |
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_SOURCE | DWT_CYCCNT | The Cortex-M cycle counter; CUSTOM_TIMER for a free-running timer you supply to VA_Init |
VA_TIMER_BITS | 32 | Width 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-bit | 170 MHz | 25 s | every 1 to 10 s |
| DWT, 32-bit | 48 MHz | 89 s | every 1 to 10 s |
| Custom, 16-bit | 1 MHz | 65 ms | every main-loop pass, or a 20 to 50 ms timer |
| Custom, 32-bit | 1 MHz | 72 min | rarely, 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_INTERRUPTS | 1 | The 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_MS | 500 | Stack high-water sampling period |
VA_AUTO_SETUP_INTERVAL_MS | 2000 | Automatic 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.