Rename to "ST"

Name change due to confusion with the common programming verb "set".

Once again I cannot settle on a name.:
This commit is contained in:
Dominic Höglinger 2025-05-15 20:28:16 +02:00
parent 0e068e764d
commit e2523c09d9
4 changed files with 212 additions and 212 deletions

View File

@ -1,23 +1,23 @@
```
▓▓▓▓▓ ░░░ ███████ ███████ ███████
▓ ▓ ▒ ░ ██ ██ ██ Streaming Event Trace
▓ ▓ ▓ ░░ ███████ █████ ██ A tiny signal tracing library
▓ ▓ ▒ ░ ██ ██ ██
▓▓▓▓▓ ░░░ ███████ ███████ ██ Version 1.0.2 Alpha
▓▓▓▓▓ ░░░ ███████ ████████
▓ ▓ ▒ ░ ██ ██ Streaming Trace
▓ ▓ ▓ ░░ ███████ ██ A tiny signal tracing library
▓ ▓ ▒ ░ ██ ██
▓▓▓▓▓ ░░░ ███████ ██ Version 1.0.2 Alpha
```
# Introduction
SET is a small tracing library written in C99.
ST 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.
Signals types supported are almost all 32 bit skalars (integers, floats),
32 bit 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.
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,

View File

@ -1,5 +1,5 @@
/*
* SET: Streaming Event Trace - A tiny tracing library
* ST: Streaming Trace - A tiny tracing library
* Copyright (C) 2025 Dominic Hoeglinger
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
@ -21,16 +21,16 @@
* SOFTWARE.
*/
#include "set.h"
#include "st.h"
#define SET_NIBBLE_TO_HEX(nibble) ((nibble) < 10 ? (nibble) + '0' : (nibble) - 10 + 'A')
#define SET_NIBBLE(value, nibble) ((value >> nibble) & 0xF)
#define SET_BYTE(value, offset) (char)(((value >> (8 * offset)) & 0xFF))
#define SET_ENCODE(value, nibble) (char)(SET_NIBBLE_TO_HEX(SET_NIBBLE(value, nibble)))
#define SET_NELEMS(a) (sizeof(a) / sizeof(a[0]))
#define SET_MACROPACK_FRAME_SIZE (2 * 8)
#define SET_MACROPACK_SIZE(n) (SET_MACROPACK_FRAME_SIZE * n + (SET_MACROPACK_FRAME_SIZE * n) / 254 + 1 + n - 1)
#define SET_MAX_RENDER_SIZE(n) (SET_MACROPACK_SIZE(n) + (SET_MACROPACK_SIZE(n) / 254) + 1)
#define ST_NIBBLE_TO_HEX(nibble) ((nibble) < 10 ? (nibble) + '0' : (nibble) - 10 + 'A')
#define ST_NIBBLE(value, nibble) ((value >> nibble) & 0xF)
#define ST_BYTE(value, offset) (char)(((value >> (8 * offset)) & 0xFF))
#define ST_ENCODE(value, nibble) (char)(ST_NIBBLE_TO_HEX(ST_NIBBLE(value, nibble)))
#define ST_NELEMS(a) (sizeof(a) / sizeof(a[0]))
#define ST_MACROPACK_FRAME_SIZE (2 * 8)
#define ST_MACROPACK_SIZE(n) (ST_MACROPACK_FRAME_SIZE * n + (ST_MACROPACK_FRAME_SIZE * n) / 254 + 1 + n - 1)
#define ST_MAX_RENDER_SIZE(n) (ST_MACROPACK_SIZE(n) + (ST_MACROPACK_SIZE(n) / 254) + 1)
#define FASTLZ1_MAX_COPY 32
#define FASTLZ1_MAX_LEN 264 /* 256 + 8 */
@ -44,43 +44,43 @@
typedef enum
{
set_d1 = 0x11,
set_d2 = 0x12,
set_d4 = 0x14,
set_v1 = 0x21,
set_v2 = 0x22,
set_v4 = 0x24,
set_a1 = 0x31,
set_a2 = 0x32,
set_a4 = 0x34,
set_s4 = 0x44,
set_f4 = 0x54,
set_ev = 0x60,
} set_type_t;
st_d1 = 0x11,
st_d2 = 0x12,
st_d4 = 0x14,
st_v1 = 0x21,
st_v2 = 0x22,
st_v4 = 0x24,
st_a1 = 0x31,
st_a2 = 0x32,
st_a4 = 0x34,
st_s4 = 0x44,
st_f4 = 0x54,
st_ev = 0x60,
} st_type_t;
typedef enum
{
set_packet_z = (1 << 0),
} set_packetflags_t;
st_packet_z = (1 << 0),
} st_packetflags_t;
typedef struct
{
const char* m_tag;
uint16_t m_hash;
} set_hashcache_t;
} st_hashcache_t;
typedef union
{
uint32_t u32value;
#if (!SET_FLOAT_DISABLE)
#if (!ST_FLOAT_DISABLE)
float f32value;
#endif
} set_convert_t;
} st_convert_t;
static bool s_enabled = false;
static uint32_t s_last_time = 0;
set_overflow_policy_t s_policy = set_overwrite;
static set_trace_t* s_tracebuffer;
st_overflow_policy_t s_policy = st_overwrite;
static st_trace_t* s_tracebuffer;
static size_t s_tracebuffer_size = 0;
static size_t s_tracebuffer_head = 0;
static size_t s_tracebuffer_tail = 0;
@ -100,39 +100,39 @@ static uint32_t s_diag_avg_ctime_n = 0;
static uint32_t s_diag_avg_rtime_total = 0;
static uint32_t s_diag_avg_rtime_n = 0;
#if (SET_HASHCACHE_LINES > 0)
static set_hashcache_t s_hashcache[SET_HASHCACHE_LINES] = {0};
#if (ST_HASHCACHE_LINES > 0)
static st_hashcache_t s_hashcache[ST_HASHCACHE_LINES] = {0};
static size_t s_hashcache_index = 0;
#endif
size_t render_macropacket_payload(char buffer[], const size_t buffer_size, size_t n);
static size_t frame_preamble(char buffer[], const size_t buffer_size);
static size_t frame_epilouge(char buffer[], const size_t buffer_size);
static size_t pack_frame(char packet_bytes[], const set_trace_t* const p_packet);
static size_t pack_frame(char packet_bytes[], const st_trace_t* const p_packet);
static size_t ttyize_payload(char packet_buffer[], const size_t packet_size, const size_t buffer_size);
static uint16_t bsd_hash(const char* const str, size_t n);
static bool populate_time_delta_packet(const uint32_t timestamp, set_trace_t* const p_trace);
static void tracebuffer_add(const uint32_t timestamp, const set_type_t type, const uint32_t value, const uint8_t sub, char const *tag);
static bool populate_time_delta_packet(const uint32_t timestamp, st_trace_t* const p_trace);
static void tracebuffer_add(const uint32_t timestamp, const st_type_t type, const uint32_t value, const uint8_t sub, char const *tag);
size_t cobs_encode(uint8_t* dst, size_t dst_buf_len, const uint8_t* ptr, int len, uint8_t delim);
static int fastlz1_compress(const void* input, int length, void* output);
void set_init(set_trace_t tracebuffer[], size_t ntraces)
void st_init(st_trace_t tracebuffer[], size_t ntraces)
{
s_tracebuffer = tracebuffer;
s_tracebuffer_size = ntraces;
}
size_t set_get_buffer_items(void)
size_t st_get_buffer_items(void)
{
return s_tracebuffer_items;
}
void set_tty_mode(const bool enable)
void st_tty_mode(const bool enable)
{
s_tty_enabled = enable;
}
size_t set_tty_rubout(char buffer[], const size_t buffer_size)
size_t st_tty_rubout(char buffer[], const size_t buffer_size)
{
const size_t rubout_packet_size = 3 + s_tty_rubout_len + 3;
size_t buffer_pos = 0;
@ -153,27 +153,27 @@ size_t set_tty_rubout(char buffer[], const size_t buffer_size)
return buffer_pos;
}
size_t set_output(size_t n, const bool compress, const bool rubout)
size_t st_output(size_t n, const bool compress, const bool rubout)
{
const size_t render_number_items = 4;
const size_t render_max_size = SET_MAX_RENDER_SIZE(render_number_items);
char packet_bytes[SET_MAX_RENDER_SIZE(4)] = {0};
const size_t render_max_size = ST_MAX_RENDER_SIZE(render_number_items);
char packet_bytes[ST_MAX_RENDER_SIZE(4)] = {0};
size_t packet_size = 0;
size_t i = 0;
n = (n == 0) ? s_tracebuffer_size : n;
while ((s_tracebuffer_full || (s_tracebuffer_tail != s_tracebuffer_head)) && (i < n))
{
packet_size = set_render(packet_bytes, render_max_size, render_number_items, compress);
packet_size = st_render(packet_bytes, render_max_size, render_number_items, compress);
i += render_number_items;
set_out(packet_bytes, packet_size);
st_out(packet_bytes, packet_size);
}
if (rubout)
{
packet_size = set_tty_rubout(packet_bytes, render_max_size);
set_out(packet_bytes, packet_size);
packet_size = st_tty_rubout(packet_bytes, render_max_size);
st_out(packet_bytes, packet_size);
}
return i;
@ -184,7 +184,7 @@ size_t render_macropacket_payload(char buffer[], const size_t buffer_size, size_
const size_t max_render_size = (8 + 1 + 1) * 2 - 1;
char payload_buffer[8] = {0};
char delimimter = 0x00;
set_trace_t timestamp_pack = {0};
st_trace_t timestamp_pack = {0};
size_t payload_size = 0;
size_t i = 0;
size_t buffer_pos = 0;
@ -223,20 +223,20 @@ size_t render_macropacket_payload(char buffer[], const size_t buffer_size, size_
return buffer_pos;
}
size_t set_render(char buffer[], const size_t buffer_size, const size_t n, const bool compress)
size_t st_render(char buffer[], const size_t buffer_size, const size_t n, const bool compress)
{
const char delimimter = '\033';
size_t n_elems = (n == 0) ? s_tracebuffer_items : n;
n_elems = (s_tty_enabled && (n > 4)) ? 4 : n_elems;
size_t render_max_size = SET_MAX_RENDER_SIZE(n_elems);
uint32_t ticks_render_start = set_timestamp();
size_t render_max_size = ST_MAX_RENDER_SIZE(n_elems);
uint32_t ticks_render_start = st_timestamp();
char *final_payload_buffer = NULL;
size_t final_payload_size = 0;
while ((buffer_size < (1 + (render_max_size * 2))) && (n_elems > 0))
{
n_elems--;
render_max_size = SET_MAX_RENDER_SIZE(n_elems);
render_max_size = ST_MAX_RENDER_SIZE(n_elems);
}
if (n_elems == 0) return 0;
@ -248,11 +248,11 @@ size_t set_render(char buffer[], const size_t buffer_size, const size_t n, const
size_t compressed_size = macropack_payload_size + (macropack_payload_size*15)/100;
char *compressed_buffer = &buffer[buffer_size - compressed_size];
uint32_t ticks_comp_start = set_timestamp();
uint32_t ticks_comp_start = st_timestamp();
compressed_size = fastlz1_compress(buffer, macropack_payload_size, compressed_buffer);
final_payload_buffer = compressed_buffer;
final_payload_size = compressed_size;
s_diag_avg_ctime_total += set_timestamp() - ticks_comp_start;
s_diag_avg_ctime_total += st_timestamp() - ticks_comp_start;
s_diag_avg_ctime_n++;
if (macropack_payload_size > 0)
@ -275,7 +275,7 @@ size_t set_render(char buffer[], const size_t buffer_size, const size_t n, const
size_t out_pos = frame_preamble(buffer, buffer_size);
uint8_t flags = 0;
if (compress) flags |= (uint8_t)set_packet_z;
if (compress) flags |= (uint8_t)st_packet_z;
buffer[out_pos] = flags;
out_pos++;
@ -293,54 +293,54 @@ size_t set_render(char buffer[], const size_t buffer_size, const size_t n, const
out_pos += payload_size;
out_pos += frame_epilouge(&buffer[out_pos], buffer_size - out_pos);
s_diag_avg_rtime_total += set_timestamp() - ticks_render_start;
s_diag_avg_rtime_total += st_timestamp() - ticks_render_start;
s_diag_avg_rtime_n++;
return out_pos;
}
void set_enable(const set_overflow_policy_t policy)
void st_enable(const st_overflow_policy_t policy)
{
s_policy = policy;
s_enabled = true;
}
void set_disable(void)
void st_disable(void)
{
s_enabled = false;
}
void set_clear(void)
void st_clear(void)
{
s_tracebuffer_tail = s_tracebuffer_head;
s_tracebuffer_full = false;
}
void set_diagtrace(void)
void st_diagtrace(void)
{
const uint32_t buffer_health = ((s_tracebuffer_size - s_tracebuffer_items) * 0xFF)/s_tracebuffer_size;
set_u32trace("SET.BufferItems", s_tracebuffer_items, false);
set_u8trace("SET.BufferHealth", (uint8_t)buffer_health, true);
st_u32trace("ST.BufferItems", s_tracebuffer_items, false);
st_u8trace("ST.BufferHealth", (uint8_t)buffer_health, true);
if (s_diag_avg_compression_n > 0)
{
const uint32_t average = s_diag_avg_compression_total / s_diag_avg_compression_n;
set_u8trace("SET.CompressionLevel", (uint8_t)average, true);
st_u8trace("ST.CompressionLevel", (uint8_t)average, true);
s_diag_avg_compression_total = 0;
s_diag_avg_compression_n = 0;
}
if (s_diag_items_sent > 0)
{
set_u32trace("SET.ItemsSent", s_diag_items_sent, true);
st_u32trace("ST.ItemsSent", s_diag_items_sent, true);
s_diag_items_sent = 0;
}
if (s_diag_avg_ctime_n > 0)
{
const uint32_t average = s_diag_avg_ctime_total / s_diag_avg_ctime_n;
set_u8trace("SET.CompressionTime", (uint8_t)average, true);
st_u8trace("ST.CompressionTime", (uint8_t)average, true);
s_diag_avg_ctime_total = 0;
s_diag_avg_ctime_n = 0;
}
@ -349,147 +349,147 @@ void set_diagtrace(void)
if (s_diag_avg_rtime_n > 0)
{
const uint32_t average = s_diag_avg_rtime_total / s_diag_avg_rtime_n;
set_u8trace("SET.RenderTime", (uint8_t)average, true);
st_u8trace("ST.RenderTime", (uint8_t)average, true);
s_diag_avg_rtime_total = 0;
s_diag_avg_rtime_n = 0;
}
}
void set_evtrace(const char* const tag, const bool skip_time)
void st_evtrace(const char* const tag, const bool skip_time)
{
if (s_enabled == true)
{
tracebuffer_add(skip_time ? 0UL : set_timestamp(), set_ev, 1UL, 0U, tag);
tracebuffer_add(skip_time ? 0UL : st_timestamp(), st_ev, 1UL, 0U, tag);
}
}
void set_u8trace(const char* const tag, const uint8_t value, const bool skip_time)
void st_u8trace(const char* const tag, const uint8_t value, const bool skip_time)
{
if (s_enabled == true)
{
tracebuffer_add(skip_time ? 0UL : set_timestamp(), set_v1, (uint32_t)value, 0U, tag);
tracebuffer_add(skip_time ? 0UL : st_timestamp(), st_v1, (uint32_t)value, 0U, tag);
}
}
void set_u16trace(const char* const tag, const uint16_t value, const bool skip_time)
void st_u16trace(const char* const tag, const uint16_t value, const bool skip_time)
{
if (s_enabled == true)
{
tracebuffer_add(skip_time ? 0UL : set_timestamp(), set_v2, (uint32_t)value, 0U, tag);
tracebuffer_add(skip_time ? 0UL : st_timestamp(), st_v2, (uint32_t)value, 0U, tag);
}
}
void set_u32trace(const char* const tag, const uint32_t value, const bool skip_time)
void st_u32trace(const char* const tag, const uint32_t value, const bool skip_time)
{
if (s_enabled == true)
{
tracebuffer_add(skip_time ? 0UL : set_timestamp(), set_v4, (uint32_t)value, 0U, tag);
tracebuffer_add(skip_time ? 0UL : st_timestamp(), st_v4, (uint32_t)value, 0U, tag);
}
}
void set_s8trace(const char* const tag, const int8_t value, const bool skip_time)
void st_s8trace(const char* const tag, const int8_t value, const bool skip_time)
{
if (s_enabled == true)
{
tracebuffer_add(skip_time ? 0UL : set_timestamp(), set_v1, (uint32_t)value, 0U, tag);
tracebuffer_add(skip_time ? 0UL : st_timestamp(), st_v1, (uint32_t)value, 0U, tag);
}
}
void set_s16trace(const char* const tag, const int16_t value, const bool skip_time)
void st_s16trace(const char* const tag, const int16_t value, const bool skip_time)
{
if (s_enabled == true)
{
tracebuffer_add(skip_time ? 0UL : set_timestamp(), set_v2, (uint32_t)value, 0U, tag);
tracebuffer_add(skip_time ? 0UL : st_timestamp(), st_v2, (uint32_t)value, 0U, tag);
}
}
void set_s4trace(const char* const tag, const int32_t value, const bool skip_time)
void st_s4trace(const char* const tag, const int32_t value, const bool skip_time)
{
if (s_enabled == true)
{
tracebuffer_add(skip_time ? 0UL : set_timestamp(), set_v4, (uint32_t)value, 0U, tag);
tracebuffer_add(skip_time ? 0UL : st_timestamp(), st_v4, (uint32_t)value, 0U, tag);
}
}
void set_au8trace(const char* const tag, const uint8_t value[const], const uint8_t size, const bool skip_time)
void st_au8trace(const char* const tag, const uint8_t value[const], const uint8_t size, const bool skip_time)
{
if (s_enabled == true)
{
const size_t ts = skip_time ? 0UL : set_timestamp();
const size_t ts = skip_time ? 0UL : st_timestamp();
for (size_t i = 0; i < size; ++i)
{
tracebuffer_add(ts, set_a1, (uint32_t)value[i], (uint8_t)i, tag);
tracebuffer_add(ts, st_a1, (uint32_t)value[i], (uint8_t)i, tag);
}
}
}
void set_au16trace(const char* const tag, const uint16_t value[const], const uint8_t size, const bool skip_time)
void st_au16trace(const char* const tag, const uint16_t value[const], const uint8_t size, const bool skip_time)
{
if (s_enabled == true)
{
const size_t ts = skip_time ? 0UL : set_timestamp();
const size_t ts = skip_time ? 0UL : st_timestamp();
for (size_t i = 0; i < size; ++i)
{
tracebuffer_add(ts, set_a2, (uint32_t)value[i], (uint8_t)i, tag);
tracebuffer_add(ts, st_a2, (uint32_t)value[i], (uint8_t)i, tag);
}
}
}
void set_au32trace(const char* const tag, const uint32_t value[const], const uint8_t size, const bool skip_time)
void st_au32trace(const char* const tag, const uint32_t value[const], const uint8_t size, const bool skip_time)
{
if (s_enabled == true)
{
const size_t ts = skip_time ? 0UL : set_timestamp();
const size_t ts = skip_time ? 0UL : st_timestamp();
for (size_t i = 0; i < size; ++i)
{
uint16_t sub = (i) | (size << 8);
tracebuffer_add(ts, set_a4, (uint32_t)value[i], (uint8_t)i, tag);
tracebuffer_add(ts, st_a4, (uint32_t)value[i], (uint8_t)i, tag);
}
}
}
void set_as8trace(const char* const tag, const int8_t value[const], const uint8_t size, const bool skip_time)
void st_as8trace(const char* const tag, const int8_t value[const], const uint8_t size, const bool skip_time)
{
if (s_enabled == true)
{
const size_t ts = skip_time ? 0UL : set_timestamp();
const size_t ts = skip_time ? 0UL : st_timestamp();
for (size_t i = 0; i < size; ++i)
{
tracebuffer_add(ts, set_a1, (uint32_t)value[i], (uint8_t)i, tag);
tracebuffer_add(ts, st_a1, (uint32_t)value[i], (uint8_t)i, tag);
}
}
}
void set_as16trace(const char* const tag, const int16_t value[const], const uint8_t size, const bool skip_time)
void st_as16trace(const char* const tag, const int16_t value[const], const uint8_t size, const bool skip_time)
{
if (s_enabled == true)
{
const size_t ts = skip_time ? 0UL : set_timestamp();
const size_t ts = skip_time ? 0UL : st_timestamp();
for (size_t i = 0; i < size; ++i)
{
tracebuffer_add(ts, set_a2, (uint32_t)value[i], (uint8_t)i, tag);
tracebuffer_add(ts, st_a2, (uint32_t)value[i], (uint8_t)i, tag);
}
}
}
void set_as32trace(const char* const tag, const int32_t value[const], const uint8_t size, const bool skip_time)
void st_as32trace(const char* const tag, const int32_t value[const], const uint8_t size, const bool skip_time)
{
if (s_enabled == true)
{
const size_t ts = skip_time ? 0UL : set_timestamp();
const size_t ts = skip_time ? 0UL : st_timestamp();
for (size_t i = 0; i < size; ++i)
{
uint16_t sub = (i) | (size << 8);
tracebuffer_add(ts, set_a4, (uint32_t)value[i], (uint8_t)i, tag);
tracebuffer_add(ts, st_a4, (uint32_t)value[i], (uint8_t)i, tag);
}
}
}
void set_strtrace(const char* const tag, const char* const str, const bool skip_time)
void st_strtrace(const char* const tag, const char* const str, const bool skip_time)
{
if (s_enabled == true)
{
const size_t ts = skip_time ? 0UL : set_timestamp();
const size_t ts = skip_time ? 0UL : st_timestamp();
uint32_t packword = 0;
uint8_t packindex = 0;
for (size_t i = 0; str[i] != '\0'; ++i)
@ -498,24 +498,24 @@ void set_strtrace(const char* const tag, const char* const str, const bool skip_
packword |= (str[i] << (8 * packindex));
if (packindex == 3)
{
tracebuffer_add(ts, set_s4, packword, (uint8_t)str[i + 1] == '\0', tag);
tracebuffer_add(ts, st_s4, packword, (uint8_t)str[i + 1] == '\0', tag);
packword = 0;
}
}
if (packindex != 3)
{
tracebuffer_add(ts, set_s4, packword, (uint8_t)true, tag);
tracebuffer_add(ts, st_s4, packword, (uint8_t)true, tag);
}
}
}
#if (!SET_FLOAT_DISABLE)
void set_f32trace(const char* const tag, const float value, const bool skip_time)
#if (!ST_FLOAT_DISABLE)
void st_f32trace(const char* const tag, const float value, const bool skip_time)
{
set_convert_t converter = {.f32value = value };
st_convert_t converter = {.f32value = value };
if (s_enabled == true)
{
tracebuffer_add(skip_time ? 0UL : set_timestamp(), set_f4, converter.u32value, 0U, tag);
tracebuffer_add(skip_time ? 0UL : st_timestamp(), st_f4, converter.u32value, 0U, tag);
}
}
#endif
@ -544,56 +544,56 @@ static size_t frame_epilouge(char buffer[], const size_t buffer_size)
return pack_pos;
}
static size_t pack_frame(char packet_bytes[], const set_trace_t* const p_packet)
static size_t pack_frame(char packet_bytes[], const st_trace_t* const p_packet)
{
size_t packet_size = 0;
packet_bytes[packet_size++] = (char)p_packet->m_type;
switch ((set_type_t)p_packet->m_type)
switch ((st_type_t)p_packet->m_type)
{
case set_v1:
case set_a1:
case set_d1:
packet_bytes[packet_size++] = SET_BYTE(p_packet->m_value, 0);
case st_v1:
case st_a1:
case st_d1:
packet_bytes[packet_size++] = ST_BYTE(p_packet->m_value, 0);
break;
case set_v2:
case set_a2:
case set_d2:
packet_bytes[packet_size++] = SET_BYTE(p_packet->m_value, 0);
packet_bytes[packet_size++] = SET_BYTE(p_packet->m_value, 1);
case st_v2:
case st_a2:
case st_d2:
packet_bytes[packet_size++] = ST_BYTE(p_packet->m_value, 0);
packet_bytes[packet_size++] = ST_BYTE(p_packet->m_value, 1);
break;
case set_v4:
case set_a4:
case set_s4:
case set_f4:
case set_d4:
packet_bytes[packet_size++] = SET_BYTE(p_packet->m_value, 0);
packet_bytes[packet_size++] = SET_BYTE(p_packet->m_value, 1);
packet_bytes[packet_size++] = SET_BYTE(p_packet->m_value, 2);
packet_bytes[packet_size++] = SET_BYTE(p_packet->m_value, 3);
case st_v4:
case st_a4:
case st_s4:
case st_f4:
case st_d4:
packet_bytes[packet_size++] = ST_BYTE(p_packet->m_value, 0);
packet_bytes[packet_size++] = ST_BYTE(p_packet->m_value, 1);
packet_bytes[packet_size++] = ST_BYTE(p_packet->m_value, 2);
packet_bytes[packet_size++] = ST_BYTE(p_packet->m_value, 3);
break;
}
switch ((set_type_t)p_packet->m_type)
switch ((st_type_t)p_packet->m_type)
{
case set_a1:
case set_a2:
case set_a4:
case set_s4:
case st_a1:
case st_a2:
case st_a4:
case st_s4:
packet_bytes[packet_size++] = (char)p_packet->m_sub;
break;
}
switch ((set_type_t)p_packet->m_type)
switch ((st_type_t)p_packet->m_type)
{
case set_d1:
case set_d2:
case set_d4:
case st_d1:
case st_d2:
case st_d4:
break;
default:
const uint16_t hash_tag = bsd_hash(p_packet->m_tag, SET_MAX_TAG_LEN);
packet_bytes[packet_size++] = SET_BYTE(hash_tag, 0);
packet_bytes[packet_size++] = SET_BYTE(hash_tag, 1);
const uint16_t hash_tag = bsd_hash(p_packet->m_tag, ST_MAX_TAG_LEN);
packet_bytes[packet_size++] = ST_BYTE(hash_tag, 0);
packet_bytes[packet_size++] = ST_BYTE(hash_tag, 1);
break;
}
@ -613,8 +613,8 @@ static size_t ttyize_payload(char packet_buffer[], const size_t packet_size, con
{
value = packet_buffer[(packet_size - i - 1)];
backpos = (packet_size - i - 1) * 2;
packet_buffer[backpos] = SET_ENCODE(value, 0);
packet_buffer[backpos + 1] = SET_ENCODE(value, 4);
packet_buffer[backpos] = ST_ENCODE(value, 0);
packet_buffer[backpos + 1] = ST_ENCODE(value, 4);
}
return tty_packet_size;
@ -625,10 +625,10 @@ static uint16_t bsd_hash(const char* const str, size_t n)
uint32_t checksum = 0;
if (str == NULL) return 0U;
#if (SET_HASHCACHE_LINES > 0)
for (size_t i = 0; i < SET_HASHCACHE_LINES; ++i)
#if (ST_HASHCACHE_LINES > 0)
for (size_t i = 0; i < ST_HASHCACHE_LINES; ++i)
{
size_t hash_index = (i + s_hashcache_index) % SET_HASHCACHE_LINES;
size_t hash_index = (i + s_hashcache_index) % ST_HASHCACHE_LINES;
if (s_hashcache[hash_index].m_tag == str)
{
return s_hashcache[hash_index].m_hash;
@ -641,8 +641,8 @@ static uint16_t bsd_hash(const char* const str, size_t n)
checksum += str[i];
checksum &= 0xFFFF;
}
#if (SET_HASHCACHE_LINES > 0)
s_hashcache_index = (s_hashcache_index + 1) % SET_HASHCACHE_LINES;
#if (ST_HASHCACHE_LINES > 0)
s_hashcache_index = (s_hashcache_index + 1) % ST_HASHCACHE_LINES;
s_hashcache[s_hashcache_index].m_hash = checksum;
s_hashcache[s_hashcache_index].m_tag = str;
#endif
@ -650,7 +650,7 @@ static uint16_t bsd_hash(const char* const str, size_t n)
return checksum;
}
static bool populate_time_delta_packet(const uint32_t timestamp, set_trace_t* const p_trace)
static bool populate_time_delta_packet(const uint32_t timestamp, st_trace_t* const p_trace)
{
const uint32_t dt = timestamp - s_last_time;
uint16_t type = 0;
@ -661,15 +661,15 @@ static bool populate_time_delta_packet(const uint32_t timestamp, set_trace_t* co
{
if (dt > 0xFFFF)
{
type = set_d4;
type = st_d4;
}
else if (dt > 0xFF)
{
type = set_d2;
type = st_d2;
}
else
{
type = set_d1;
type = st_d1;
}
p_trace->m_type = type;
@ -685,18 +685,18 @@ static bool populate_time_delta_packet(const uint32_t timestamp, set_trace_t* co
return false;
}
static void tracebuffer_add(const uint32_t timestamp, const set_type_t type, const uint32_t value, const uint8_t sub, char const *tag)
static void tracebuffer_add(const uint32_t timestamp, const st_type_t type, const uint32_t value, const uint8_t sub, char const *tag)
{
const size_t insertion_pos = s_tracebuffer_head;
uint32_t critical_h = 0UL;
if (s_tracebuffer_full == false || s_policy == set_overwrite)
if (s_tracebuffer_full == false || s_policy == st_overwrite)
{
set_crit_on(&critical_h);
st_crit_on(&critical_h);
s_tracebuffer_head = (s_tracebuffer_head + 1) % s_tracebuffer_size;
s_tracebuffer_full = (s_tracebuffer_head == s_tracebuffer_tail);
s_tracebuffer_items++;
set_crit_off(critical_h);
st_crit_off(critical_h);
s_tracebuffer[insertion_pos].m_type = (uint8_t)type;
s_tracebuffer[insertion_pos].m_value = value;
@ -761,7 +761,7 @@ static uint16_t flz_hash(uint32_t v) {
}
static void set_memcpy(uint8_t* dest, const uint8_t* src, uint32_t count)
static void st_memcpy(uint8_t* dest, const uint8_t* src, uint32_t count)
{
for(size_t i = 0; i < count; ++i)
{
@ -779,14 +779,14 @@ static uint32_t flz_cmp(const uint8_t* p, const uint8_t* q, const uint8_t* r) {
static uint8_t* flz_literals(uint32_t runs, const uint8_t* src, uint8_t* dest) {
while (runs >= FASTLZ1_MAX_COPY) {
*dest++ = FASTLZ1_MAX_COPY - 1;
set_memcpy(dest, src, FASTLZ1_MAX_COPY);
st_memcpy(dest, src, FASTLZ1_MAX_COPY);
src += FASTLZ1_MAX_COPY;
dest += FASTLZ1_MAX_COPY;
runs -= FASTLZ1_MAX_COPY;
}
if (runs > 0) {
*dest++ = runs - 1;
set_memcpy(dest, src, runs);
st_memcpy(dest, src, runs);
dest += runs;
}
return dest;

View File

@ -1,5 +1,5 @@
/*
* SET: Streaming Event Trace - A tiny tracing library
* ST: Streaming Trace - A tiny tracing library
* Copyright (C) 2025 Dominic Hoeglinger
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
@ -21,28 +21,28 @@
* SOFTWARE.
*/
#ifndef SET_H_INCLUDED_
#define SET_H_INCLUDED_
#ifndef ST_H_INCLUDED_
#define ST_H_INCLUDED_
#include <stddef.h>
#include <stdbool.h>
#include <stdint.h>
/** Maxmum signal name / tag length considered for the identifying hash */
#define SET_MAX_TAG_LEN (126)
#define ST_MAX_TAG_LEN (126)
/** Number of cached hashes */
#define SET_HASHCACHE_LINES (64)
#define ST_HASHCACHE_LINES (64)
/** Switch to enable or disable floating point support */
#define SET_FLOAT_DISABLE (false)
#define ST_FLOAT_DISABLE (false)
/** Overflow policy for the tracebuffer */
typedef enum
{
set_overwrite, /**< Overwrite oldest samples */
set_drop /**< Drop newest samples */
} set_overflow_policy_t;
st_overwrite, /**< Overwrite oldest samples */
st_drop /**< Drop newest samples */
} st_overflow_policy_t;
/** Element used to allocate the tracebuffer */
typedef struct
@ -52,51 +52,51 @@ typedef struct
uint32_t m_value;
uint8_t m_type;
uint8_t m_sub;
} set_trace_t;
} st_trace_t;
/** @brief Integration hook writing out a packet to the desired interface
* @param[in] str Packet data
* @param[in] len Packet data length
* @return None
*/
void set_out(const char* const str, size_t len);
void st_out(const char* const str, size_t len);
/** @brief Integration hook for retrieving a timestamp
* @return Timestamp value
*/
uint32_t set_timestamp(void);
uint32_t st_timestamp(void);
/** @brief Integration hook which locks the tracebuffer
* This can be for instance a mutex or interrupt lock.
* @param[out] h handle value which will be passed to the #set_crit_off function
*/
void set_crit_on(uint32_t *h);
void st_crit_on(uint32_t *h);
/** @brief Integration hook which unlocks the tracebuffer
* @param[in] h handle value set by #set_crit_on
*/
void set_crit_off(const uint32_t h);
void st_crit_off(const uint32_t h);
/** @brief Initializes PET with the provided trace buffer
* @param[in] str Trace buffer array
* @param[in] len Trace buffer array length
* @return None
*/
void set_init(set_trace_t tracebuffer[], size_t ntraces);
void st_init(st_trace_t tracebuffer[], size_t ntraces);
/** @brief Returns the current trace buffer utilization
* @return Number of items used in the trace buffer
*/
size_t set_get_buffer_items(void);
size_t st_get_buffer_items(void);
/** @brief Enables or disables TTY mode
* TTY mode esures packet output is friendly for interactive console usage without a client.
* This means that at most 4 packets are sent at once, the data is encoded as hex digits
* and position is restored with each transmit. To erase a transmitted packet, see set_tty_rubout.
* and position is restored with each transmit. To erase a transmitted packet, see st_tty_rubout.
* @param[in] enable If true, enable TTY mode
* @return None
*/
void set_tty_mode(const bool enable);
void st_tty_mode(const bool enable);
/** @brief Creates a rubout packet clearing the maximum amount of data transmitted in TTY mode.
* This consists of a ANSI store, enough spaces to overwrite sent data and an ANSI restore.
@ -104,32 +104,32 @@ void set_tty_mode(const bool enable);
* @param[in] buffer_size the size of the output buffer
* @return The packet size written to the buffer
*/
size_t set_tty_rubout(char buffer[], const size_t buffer_size);
size_t st_tty_rubout(char buffer[], const size_t buffer_size);
/** @brief Enables tracing with the provided overflow policy
* @param[in] policy Either overwrite to overwrite oldest trace, or drop to drop the newest sample
* @return None
*/
void set_enable(const set_overflow_policy_t policy);
void st_enable(const st_overflow_policy_t policy);
/** @brief Disables tracing
* @return None
*/
void set_disable(void);
void st_disable(void);
/** @brief Clears the trace buffer deleting all captures samples
* @return None
*/
void set_clear(void);
void st_clear(void);
/** @brief Render a set amount of tracebuffer items and write them out using set_out
/** @brief Render a set amount of tracebuffer items and write them out using st_out
* This function is for basic usage where the output function writes into a managed stream such as stdout
* @param[in] n Number of tracebuffer items to render, or 0 for the current size of the tracebuffer
* @param[in] compress if true, render the packets compressed
* @param[in] rubout if true, sends a rubout packet at the end clearing the trace output on a terminal
* @return None
*/
size_t set_output(size_t n, const bool compress, const bool rubout);
size_t st_output(size_t n, const bool compress, const bool rubout);
/** @brief Render a set amount of tracebuffer items and store them in the provided buffer
* This advanced function is intended to be used with DMA buffers.
@ -139,26 +139,26 @@ size_t set_output(size_t n, const bool compress, const bool rubout);
* @param[in] compress if true, render the packets compressed
* @return None
*/
size_t set_render(char buffer[], const size_t buffer_size, const size_t n, const bool compress);
size_t st_render(char buffer[], const size_t buffer_size, const size_t n, const bool compress);
/** @brief Adds diagnostic samples to the tracebuffer
* Signals include:
* - SET.BufferItems:u32 - The current amount of tracebuffer items
* - SET.BufferHealth:u8 - The buffer utilization, zero means that the buffer is full while 255 means the buffer is free
* - SET.CompressionLevel:u8 - The average compression level if packets are rendered compressed
* - SET.CompressionTime:u32 - The average compression time spent for one packet render
* - SET.RenderTime:u32 - The average render time for one packet
* - SET.ItemsSent:u32 - The number of items sent since the last call to this function
* - ST.BufferItems:u32 - The current amount of tracebuffer items
* - ST.BufferHealth:u8 - The buffer utilization, zero means that the buffer is full while 255 means the buffer is free
* - ST.CompressionLevel:u8 - The average compression level if packets are rendered compressed
* - ST.CompressionTime:u32 - The average compression time spent for one packet render
* - ST.RenderTime:u32 - The average render time for one packet
* - ST.ItemsSent:u32 - The number of items sent since the last call to this function
* @return None
*/
void set_diagtrace(void);
void st_diagtrace(void);
/** @brief Trace an event
* @param[in] tag Signal name of the trace
* @param[in] skip_time Use last recorded timestamp for this trace
* @return None
*/
void set_evtrace(const char* const tag, const bool skip_time);
void st_evtrace(const char* const tag, const bool skip_time);
/** @brief Trace an u8 value
* @param[in] tag Signal name of the trace
@ -166,7 +166,7 @@ void set_evtrace(const char* const tag, const bool skip_time);
* @param[in] skip_time Use last recorded timestamp for this trace
* @return None
*/
void set_u8trace(const char* const tag, const uint8_t value, const bool skip_time);
void st_u8trace(const char* const tag, const uint8_t value, const bool skip_time);
/** @brief Trace an u16 value
* @param[in] tag Signal name of the trace
@ -174,7 +174,7 @@ void set_u8trace(const char* const tag, const uint8_t value, const bool skip_tim
* @param[in] skip_time Use last recorded timestamp for this trace
* @return None
*/
void set_u16trace(const char* const tag, const uint16_t value, const bool skip_time);
void st_u16trace(const char* const tag, const uint16_t value, const bool skip_time);
/** @brief Trace an u32 value
* @param[in] tag Signal name of the trace
@ -182,7 +182,7 @@ void set_u16trace(const char* const tag, const uint16_t value, const bool skip_t
* @param[in] skip_time Use last recorded timestamp for this trace
* @return None
*/
void set_u32trace(const char* const tag, const uint32_t value, const bool skip_time);
void st_u32trace(const char* const tag, const uint32_t value, const bool skip_time);
/** @brief Trace an s8 value
* @param[in] tag Signal name of the trace
@ -190,7 +190,7 @@ void set_u32trace(const char* const tag, const uint32_t value, const bool skip_t
* @param[in] skip_time Use last recorded timestamp for this trace
* @return None
*/
void set_s8trace(const char* const tag, const int8_t value, const bool skip_time);
void st_s8trace(const char* const tag, const int8_t value, const bool skip_time);
/** @brief Trace an s16 value
* @param[in] tag Signal name of the trace
@ -198,7 +198,7 @@ void set_s8trace(const char* const tag, const int8_t value, const bool skip_time
* @param[in] skip_time Use last recorded timestamp for this trace
* @return None
*/
void set_s16trace(const char* const tag, const int16_t value, const bool skip_time);
void st_s16trace(const char* const tag, const int16_t value, const bool skip_time);
/** @brief Trace an s32 value
* @param[in] tag Signal name of the trace
@ -206,7 +206,7 @@ void set_s16trace(const char* const tag, const int16_t value, const bool skip_ti
* @param[in] skip_time Use last recorded timestamp for this trace
* @return None
*/
void set_s32trace(const char* const tag, const int32_t value, const bool skip_time);
void st_s32trace(const char* const tag, const int32_t value, const bool skip_time);
/** @brief Trace an array of u8 values
* @param[in] tag Signal name of the trace
@ -215,7 +215,7 @@ void set_s32trace(const char* const tag, const int32_t value, const bool skip_ti
* @param[in] skip_time Use last recorded timestamp for this trace
* @return None
*/
void set_au8trace(const char* const tag, const uint8_t value[const], const uint8_t size, const bool skip_time);
void st_au8trace(const char* const tag, const uint8_t value[const], const uint8_t size, const bool skip_time);
/** @brief Trace an array of u16 values
* @param[in] tag Signal name of the trace
@ -224,7 +224,7 @@ void set_au8trace(const char* const tag, const uint8_t value[const], const uint8
* @param[in] skip_time Use last recorded timestamp for this trace
* @return None
*/
void set_au16trace(const char* const tag, const uint16_t value[const], const uint8_t size, const bool skip_time);
void st_au16trace(const char* const tag, const uint16_t value[const], const uint8_t size, const bool skip_time);
/** @brief Trace an array of u32 values
* @param[in] tag Signal name of the trace
@ -233,7 +233,7 @@ void set_au16trace(const char* const tag, const uint16_t value[const], const uin
* @param[in] skip_time Use last recorded timestamp for this trace
* @return None
*/
void set_au32trace(const char* const tag, const uint32_t value[const], const uint8_t size, const bool skip_time);
void st_au32trace(const char* const tag, const uint32_t value[const], const uint8_t size, const bool skip_time);
/** @brief Trace an array of s8 values
@ -243,7 +243,7 @@ void set_au32trace(const char* const tag, const uint32_t value[const], const uin
* @param[in] skip_time Use last recorded timestamp for this trace
* @return None
*/
void set_as8trace(const char* const tag, const int8_t value[const], const uint8_t size, const bool skip_time);
void st_as8trace(const char* const tag, const int8_t value[const], const uint8_t size, const bool skip_time);
/** @brief Trace an array of s16 values
* @param[in] tag Signal name of the trace
@ -252,7 +252,7 @@ void set_as8trace(const char* const tag, const int8_t value[const], const uint8_
* @param[in] skip_time Use last recorded timestamp for this trace
* @return None
*/
void set_as16trace(const char* const tag, const int16_t value[const], const uint8_t size, const bool skip_time);
void st_as16trace(const char* const tag, const int16_t value[const], const uint8_t size, const bool skip_time);
/** @brief Trace an array of s32 values
* @param[in] tag Signal name of the trace
@ -261,7 +261,7 @@ void set_as16trace(const char* const tag, const int16_t value[const], const uint
* @param[in] skip_time Use last recorded timestamp for this trace
* @return None
*/
void set_as32trace(const char* const tag, const int32_t value[const], const uint8_t size, const bool skip_time);
void st_as32trace(const char* const tag, const int32_t value[const], const uint8_t size, const bool skip_time);
/** @brief Trace a string
* @param[in] tag Signal name of the trace
@ -269,9 +269,9 @@ void set_as32trace(const char* const tag, const int32_t value[const], const uint
* @param[in] skip_time Use last recorded timestamp for this trace
* @return None
*/
void set_strtrace(const char* const tag, const char* const str, const bool skip_time);
void st_strtrace(const char* const tag, const char* const str, const bool skip_time);
#if (!SET_FLOAT_DISABLE)
#if (!ST_FLOAT_DISABLE)
/** @brief Trace an f32 value
* @param[in] tag Signal name of the trace
@ -279,7 +279,7 @@ void set_strtrace(const char* const tag, const char* const str, const bool skip_
* @param[in] skip_time Use last recorded timestamp for this trace
* @return None
*/
void set_f32trace(const char* const tag, const float value, const bool skip_time);
void st_f32trace(const char* const tag, const float value, const bool skip_time);
#endif
#endif