111 lines
4.9 KiB
Markdown
111 lines
4.9 KiB
Markdown

|
|
|
|
# Introduction
|
|
|
|
ST is a small tracing library written in C99.
|
|
It is 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.
|
|
|
|
Signal types supported are all integers up to 64 bit, integer arrays up to 32 bit, floats, doubles, events and strings.
|
|
|
|

|
|
|
|
# How to use
|
|
|
|
ST 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 "st.h"
|
|
|
|
// Basic implementation of output and timestamp retrieval
|
|
void st_out(const char* const str, size_t len) { Serial.write(str, len); }
|
|
uint32_t st_timestamp(void) { return micros(); }
|
|
|
|
// No concurrency protection needed
|
|
void st_crit_on(uint32_t *h) {}
|
|
void st_crit_off(const uint32_t h) {}
|
|
|
|
static const size_t s_tracesize = 256;
|
|
static st_trace_t s_tracebuf[256];
|
|
|
|
void setup()
|
|
{
|
|
st_init(s_tracebuf, s_tracesize);
|
|
st_enable(st_drop); // drop traces on full buffer
|
|
|
|
st_u8trace("Serial.Ready", 0, false);
|
|
Serial.begin(2000000);
|
|
while (!Serial);
|
|
st_u8trace("Serial.Ready", 1, false);
|
|
}
|
|
|
|
void loop()
|
|
{
|
|
static unsigned sawtooth = 0;
|
|
|
|
if (sawtooth < 0xFFFF) sawtooth++;
|
|
else sawtooth = 0;
|
|
st_u32trace("Main.Sawtooth", sawtooth, false);
|
|
|
|
if (sawtooth == 4711) Serial.println("I can still be used with regular text.");
|
|
|
|
st_output(0, true, true); //send unlimited traces, compressed and clear console
|
|
st_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 statically accessible strings as they are later hashed when rendering traces.
|
|
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 put 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 "picocom -b 921600 /dev/ttyUSB0" | \
|
|
./st_record.py -d trace.vcd -s ./Sources -t "1 us" --diagnostics
|
|
````
|
|
|
|
The resulting VCD can be inspected with dedicated programs such as GTKwave.
|
|
|
|
This script also features a TUI mode, displaying live diagnostic information.
|
|
TUI mode requires the "rich" package in order to work.
|
|
|
|
|
|
# Special Thanks
|
|
|
|
This repository uses code by the following people, so a thanks goes out to them!
|
|
- COBS algorithm with nonzero delimiter based on [this Wren library](https://rosettacode.org/wiki/Consistent_overhead_byte_stuffing#Wren) by unknown
|
|
- [FastLZ](https://github.com/ariya/FastLZ) by ariya
|
|
- [FastLZ Python native implementation](https://github.com/dargor0/pyfastlz-native/blob/main/src/fastlz_native/decompress.py) by Oscar Diaz
|