ARM embedded tooling: feature discussion on `itm` crate


#1

I am working on a Rust-based microcontroller project using ARM ITM, and want to add some extra tooling around the read side to @japaric 's itm crate. I thought it may be useful to have a quick discussion in one place about extra features to avoid duplicate or irrelevant work.

Ideas:

  1. Support for ports / stimuli other than 0. We could perhaps write data from different ports to different files (which could be pipes for further chaining), or use structured output as discussed below.
  2. Structured output. Currently any bytes received are written to stdout, which is fine for reading a log. My team want to output machine-readable tracing data, and this is fairly easy to glue together with some shell pipes if packets are output in a more structured way, e.g. one per line as white separated values, or as JSON.
  3. Split functionality into a re-usable library, as already proposed in itm issue 1.

#2

Hey there!

First off, thanks for looking into the itm crate. I believe that having better ITM / SWO support is pretty important to improve embedded Rust tooling story. There are several commercial tools that use ITM / SWO to provide profiling and tracking functionality but they cost $$$ and are not open source. It would be great to have open source tooling that offers similar functionality. (cf. https://github.com/rust-embedded/rfcs/issues/28)

That being said, I’m not quite sure how to proceed with creating / developing the tooling. But one of things I would do if I had time to work at this would be to look at existing solutions like orbuculum for ideas about the architecture. The other thing I’d like to do is to keep, or actually make, itm as / into a library. Eventually, I think itmdump should be its own crate and itm should be the library that supports all the ITM related tooling.


#3

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. orbuculum's 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.


#4

The bincode crate has a closed issue about no_std support.

However, ssmarshal mentioned there seems to essentially be bincode for no_std, zero-allocation environments. Sounds perfect.