106 lines
4.5 KiB
Markdown
106 lines
4.5 KiB
Markdown
```
|
|
▓▓▓▓▓ ░░░ ███████ ███████ ████████
|
|
▓ ▓ ▒ ░ ██ ██ ██ Streaming Event Trace
|
|
▓ ▓ ▓ ░░ ███████ █████ ██ A tiny signal tracing library
|
|
▓ ▓ ▒ ░ ██ ██ ██
|
|
▓▓▓▓▓ ░░░ ███████ ███████ ██ Version 1.0.2 Alpha
|
|
```
|
|
|
|
# Introduction
|
|
|
|
SET is a small tracing library written in C99.
|
|
It is highly optimized for minimal data usage and aims to be easy to use
|
|
while also being flexible enough to be integrated in hard real time systems.
|
|
|
|
Signals types supported are almost all skalars (integers, floats),
|
|
integer arrays, events and strings.
|
|
|
|
# How to use
|
|
|
|
SET requires the integrator to implement a few functions such as the timestamp and output functions in order to work.
|
|
Apart from that, it is up to the specific use case how to stream data.
|
|
In its simplest form, traces are processed with no real time demands on a dedicated interface.
|
|
For more advanced usage, this library allows packets to be written, as the time budget allows,
|
|
into any given buffer to send its contents via DMA to for instance a serial output.
|
|
Due to its packet format, the output interface can still be utilitzed as is unless
|
|
the text sent contains the packet preamble or epilouge, which are "\033[s" and "\033[u" respectively.
|
|
|
|
## Simple example on Arduino
|
|
````c
|
|
#include "set.h"
|
|
|
|
// Basic implementation of output and timestamp retrieval
|
|
void set_out(const char* const str, size_t len) { Serial.write(str, len); }
|
|
uint32_t set_timestamp(void) { return micros(); }
|
|
|
|
// No concurrency protection needed
|
|
void set_crit_on(uint32_t *h) {}
|
|
void set_crit_off(const uint32_t h) {}
|
|
|
|
static const size_t s_tracesize = 256;
|
|
static set_trace_t s_tracebuf[256];
|
|
|
|
void setup()
|
|
{
|
|
set_init(s_tracebuf, s_tracesize);
|
|
set_enable(set_drop); // drop traces on full buffer
|
|
|
|
set_u8trace("Serial.Ready", 0, false);
|
|
Serial.begin(2000000);
|
|
while (!Serial);
|
|
set_u8trace("Serial.Ready", 1, false);
|
|
}
|
|
|
|
void loop()
|
|
{
|
|
static unsigned sawtooth = 0;
|
|
|
|
if (sawtooth < 0xFFFF) sawtooth++;
|
|
else sawtooth = 0;
|
|
set_u32trace("Main.Sawtooth", sawtooth, false);
|
|
|
|
if (sawtooth == 4711) Serial.println("I can still be used with regular text.");
|
|
|
|
set_output(0, true, true); //send unlimited traces, compressed and clear console
|
|
set_diagtrace(); // add diagnostic traces
|
|
}
|
|
````
|
|
|
|
# Basic operating principle
|
|
|
|
Traces are identified by a signal name, which may be hierarchical such as `ExampleModule.Function.Value`.
|
|
These must be constant C strings as their pointers are stored in the trace buffer.
|
|
Once a trace is rendered, the signal name is hashed using the BSD sum function.
|
|
This allows a client to identify a trace packet according to the source tree scanned.
|
|
|
|
For sending the traces to a client, they are rendered into a packet.
|
|
A packet consist of a preamble, a flag byte, frame data and an epilouge.
|
|
The preamble and epilouge are chosen to be the ANSI escape sequences for storing the current position, and restoring it.
|
|
|
|
The frame data may be compressed using fastlz, which is indicated by the Z flag in the packet.
|
|
Regardless of compression, it is COBS encoded with delimiter 0033 to not interfere with the preamble or epilouge.
|
|
|
|
Frame data consists of multiple frames, COBS encoded with delimiter 0 and delimited with the same value.
|
|
Each frame contains the signal hash, its type and depending on it a value ranging from 1-4 bytes and indexing information.
|
|
Timestamps are sent in increments to conserve bandwidth.
|
|
All trace functions feature a parameter which enables timestamp capture, if it is omitted this means no time delta is sent,
|
|
making the trace appear to coincide with the last trace which captured a timestamp.
|
|
|
|
# The recorder utility
|
|
|
|
The repository contains an example client application which captures packages and outputs the traces in a Value Change Dump.
|
|
This script uses the PyVCD package which is the only dependency.
|
|
Apart from that, this utility has every function integrated it'll need to decode a trace stream.
|
|
It expects data via stdin, and displays any non-tracing traffic.
|
|
|
|
Example usage tracing remotely via SSH:
|
|
````bash
|
|
# Open /dev/ttyUSB0 via SSH and record to "trace.vcd"
|
|
# with timescale of 1 microsecond with diagnostics enabled
|
|
ssh user@host -C "picocom -b 921600 /dev/ttyUSB0" | \
|
|
./set_record.py -d trace.vcd -s ./Sources -t "1 us" --diagnostics
|
|
````
|
|
|
|
The resulting VCD can be inspected with dedicated programs such as GTKwave.
|
|
|