nucleus_trace/lib.rs
1//! The Nucleus trace backend.
2//!
3//! Wires the [`nucleus_itm`] decoder to a WebSocket fan-out so editor/browser
4//! dashboards can subscribe to live, structured trace events:
5//!
6//! ```text
7//! OpenOCD (SWO) ──▶ source ──▶ Decoder ──▶ Translator ──▶ JSON ──▶ WebSocket :7878
8//! ```
9//!
10//! [`translate`] assigns meaning (port 0 = logs, ports 1–7 = typed variables),
11//! [`server`] owns the pipeline and client fan-out, and [`source`] supplies the
12//! bytes (OpenOCD TCP trace port or a captured-file replay). [`run_blocking`] is
13//! the synchronous entry point the CLI calls.
14
15pub mod server;
16pub mod source;
17pub mod translate;
18
19pub use server::TraceServer;
20pub use source::Source;
21pub use translate::{TraceEvent, Translator, VarType, VariableMap};
22
23/// The default WebSocket port (per the README/architecture).
24pub const DEFAULT_WS_PORT: u16 = 7878;
25
26/// Options for [`run_blocking`].
27pub struct TraceOptions {
28 /// Address to bind the WebSocket server on, e.g. `127.0.0.1:7878`.
29 pub ws_addr: String,
30 /// Where SWO bytes come from.
31 pub source: Source,
32 /// Optional OpenOCD telnet setup: `(telnet_addr, trace_port, cpu_hz, swo_hz)`.
33 pub openocd: Option<(String, u16, u32, u32)>,
34 /// Port → variable map from `[[trace.variables]]`.
35 pub variables: VariableMap,
36}
37
38/// Run the trace daemon to completion (until the source ends), blocking on a
39/// fresh Tokio runtime so the caller stays synchronous.
40pub fn run_blocking(opts: TraceOptions) -> std::io::Result<()> {
41 let runtime = tokio::runtime::Builder::new_multi_thread()
42 .enable_all()
43 .build()?;
44 runtime.block_on(async move {
45 let server = TraceServer::new(opts.variables);
46 let (addr, _accept) = server.serve_ws(&opts.ws_addr).await?;
47 eprintln!("nucleus trace: streaming events on ws://{addr}");
48
49 if let Some((telnet, port, cpu, swo)) = &opts.openocd {
50 if let Err(err) = source::openocd_enable(telnet, *port, *cpu, *swo).await {
51 eprintln!("nucleus trace: warning: OpenOCD setup failed ({err}); continuing");
52 }
53 }
54
55 let reader = opts.source.open().await?;
56 eprintln!("nucleus trace: reading SWO from source…");
57 server.run_source(reader).await?;
58 eprintln!("nucleus trace: source ended");
59 Ok(())
60 })
61}