Thanks for the pointers,
orbuculum looks great.
On my team’s project we need sensor data from each of 3 ADC’s for a motor control application. We will probably start by outputting 1 data point for each sensor over ITM and then using
orbcat to turn that into a CSV or hopefully
sigrok (signal analyser with TPIU/ITM/ETM support) can graph that directly.
On the microcontroller we probably want Rust support for:
- TPIU configuration (multiplexes and encodes debug data)
- ITM (transfers application data)
- ETM (instruction-level tracing)
- DWT (profiling, breakpoints, watchpoints)
I see TPIU, ITM, DWT code in the
cortex-m crate. I’ll try to add anything appropriate I come up with there. I think ETM code should live there too. Perhaps it should be behind a feature flag, as the ARM v7-M architecture reference manual indicates ETM is optional.
For profiling we would probably configure the peripherals with Rust, but then other tools probably do most/all of the host-side work.
orbstat converts PC samples for KCachegrind (screenshots), which has a source code view annotated with time per line and call tree graph. Converting lines of PC samples for other tools should be very easy, including FlameGraph.
Before stumbling upon sigrok’s features we brainstormed on application-level tracing and I’ll probably work on that today for fun and future-proofing. I’m imagining multiple streams of strongly-typed structs going from microcontroller to host, with an opinionated Rust library at each end. It might fit in the
itm crate, or perhaps a new one. ITM only supports 1, 2 or 4 byte packets, so framing arbitrary length payloads on top of that would be nice (see the
framed-serial crate, which supports
no_std; [Consistent Overhead Byte Stuffing] algorithm wiki page and crate). On top of byte arrays structs could be serialised and deserialised, perhaps with serde (supports
no_std) and the bincode crate (needs
std currently, but I hope adding
no_std support would be relatively painless). I think ITM already includes a 5-bit stimulus (source) ID in every header byte of its wire protocol so we could re-use that for efficiency. Stream 0 could support printf-style output, streams 1-31 application defined structs.