harden USB telemetry transport

This commit is contained in:
Jay
2026-08-17 14:51:12 -04:00
parent 1cf0a9ac77
commit 3c95f3d7be
17 changed files with 709 additions and 114 deletions
+39 -15
View File
@@ -14,6 +14,8 @@
#include "freertos/task.h"
#include "l3g4200d.h"
#include "trikke_protocol.h"
#include "trikke_transport.h"
#include "trikke_usb_transport.h"
// Seeed Studio XIAO ESP32-C3: D4/SDA = GPIO6, D5/SCL = GPIO7.
#define TRIKKE_I2C_PORT I2C_NUM_0
@@ -54,6 +56,8 @@ typedef struct {
QueueHandle_t sample_queue;
atomic_uint_least32_t dropped_sample_count;
atomic_uint_least32_t loop_overrun_count;
trikke_transport_t transport;
trikke_usb_transport_t usb_transport;
} trikke_context_t;
static trikke_context_t s_context;
@@ -157,22 +161,26 @@ static void acquisition_task(void *argument)
}
}
static bool write_binary_packet(const uint8_t *packet, size_t packet_size)
{
const size_t written = fwrite(packet, 1, packet_size, stdout);
const int flush_result = fflush(stdout);
const bool complete = written == packet_size && flush_result == 0;
if (!complete) {
clearerr(stdout);
}
return complete;
}
static void write_binary_packet_until_sent(
trikke_context_t *context,
trikke_transport_sender_t *sender,
const uint8_t *packet,
size_t packet_size)
{
while (!write_binary_packet(packet, packet_size)) {
while (true) {
const trikke_transport_status_t status =
trikke_transport_sender_step(
sender, &context->transport, packet, packet_size);
if (status == TRIKKE_TRANSPORT_COMPLETE) {
return;
}
if (status == TRIKKE_TRANSPORT_FATAL) {
// Preserve the in-flight packet and stop consuming the queue. A
// fatal backend invariant is not safely recoverable or retryable.
while (true) {
vTaskDelay(portMAX_DELAY);
}
}
vTaskDelay(pdMS_TO_TICKS(TRIKKE_TRANSPORT_RETRY_DELAY_MS));
}
}
@@ -185,12 +193,14 @@ static void output_task(void *argument)
uint8_t packet[TRIKKE_WIRE_MAX_PACKET_SIZE] = {0};
uint32_t packet_sequence = 0;
uint32_t sample_packet_count = 0;
trikke_transport_sender_t sender;
trikke_transport_sender_init(&sender);
size_t packet_size = trikke_encode_metadata_packet(
packet, sizeof(packet), packet_sequence++, esp_timer_get_time(),
atomic_load(&context->dropped_sample_count),
atomic_load(&context->loop_overrun_count), &TRIKKE_METADATA);
write_binary_packet_until_sent(packet, packet_size);
write_binary_packet_until_sent(context, &sender, packet, packet_size);
while (true) {
trikke_wire_sample_t samples[TRIKKE_WIRE_MAX_RECORDS] = {0};
@@ -227,14 +237,15 @@ static void output_task(void *argument)
packet, sizeof(packet), packet_sequence++, esp_timer_get_time(),
atomic_load(&context->dropped_sample_count),
atomic_load(&context->loop_overrun_count), &TRIKKE_METADATA);
write_binary_packet_until_sent(packet, packet_size);
write_binary_packet_until_sent(
context, &sender, packet, packet_size);
}
packet_size = trikke_encode_sample_packet(
packet, sizeof(packet), packet_sequence++,
atomic_load(&context->dropped_sample_count),
atomic_load(&context->loop_overrun_count), samples, sample_count);
write_binary_packet_until_sent(packet, packet_size);
write_binary_packet_until_sent(context, &sender, packet, packet_size);
++sample_packet_count;
}
}
@@ -324,6 +335,17 @@ void app_main(void)
// binary frames whenever a payload byte equals LF.
usb_serial_jtag_vfs_set_tx_line_endings(ESP_LINE_ENDINGS_LF);
err = trikke_usb_transport_init(
&s_context.usb_transport, &s_context.transport);
if (err != ESP_OK) {
ESP_LOGE(TAG, "USB transport initialization failed: %s",
esp_err_to_name(err));
l3g4200d_deinit(&s_context.gyroscope);
adxl345_deinit(&s_context.accelerometer);
i2c_del_master_bus(bus);
return;
}
s_context.sample_queue =
xQueueCreate(TRIKKE_SAMPLE_QUEUE_DEPTH, sizeof(trikke_wire_sample_t));
if (s_context.sample_queue == NULL) {
@@ -331,6 +353,7 @@ void app_main(void)
l3g4200d_deinit(&s_context.gyroscope);
adxl345_deinit(&s_context.accelerometer);
i2c_del_master_bus(bus);
trikke_usb_transport_deinit(&s_context.usb_transport);
return;
}
@@ -351,6 +374,7 @@ void app_main(void)
l3g4200d_deinit(&s_context.gyroscope);
adxl345_deinit(&s_context.accelerometer);
i2c_del_master_bus(bus);
trikke_usb_transport_deinit(&s_context.usb_transport);
return;
}