real actual dragon (θΔ). follow for weird photography stuff and the occasional rawr


spending like 3 days figuring out all the completely undocumented things the Teensy imxrt1062 core does that the chip Absolutely Will Not Fucking Work Without sucked ass BUT now i have figured those things out we are once again rolling

currently very pleased with a combination of the log, serde, postcard, and heapless crates that's let me implement structured logging and a command-response interface over USB serial. works like this:


  • run a command on the computer connected to the device. it takes a serial port path and a JSON string encoding the message to send
  • host-side program parses the message (serde_json) to a native Rust representation (shared with the device-side code via a common crate), then re-encodes it using an efficient wire format (postcard)
  • host-side program opens the serial port (serialport) and sends the encoded command
  • device-side program reads the command (imxrt-usbd) and parses it (postcard and the shared type crate again), passes it off to a completely type-safe command handler
  • device-side program does stuff with the hardware (imxrt-hal, custom DMA GPIO abstraction layer)
  • device-side program produces log messages (log), which get encoded as response values (postcard), sent back up the pipe, and reassembled into complete Unicode strings on the host side (std), since log lines get split sometimes because I'm running the USB interface in direct packet mode and there is a MTU (i.e. from the device side it does not actually look like a serial port)
  • device-side program produces structured data, which gets encoded (postcard), sent back up the pipe, decoded on the host side (postcard again), and passed off to type-safe response handlers

the data formats are all auto-generated from Rust type definitions through serde, so instead of having to think about any of the encoding details myself I can (for instance) read 85 samples from the CCD (each sample is six bytes long on the wire and MTU is 512 bytes, so I can fit 85 of them in a packet and have exactly two bytes left over for encoding overhead), stick 'em in a heapless::Vec<Sample, 85>, send that over USB, and get the exact same heapless::Vec<Sample, 85> back out (which I then can convert to a "normal" Vec<Sample> since I can heap-allocate on the host side). from my perspective the data never leaves a Rust-native format.

also since it's all just going through serde, a lot of the code involved here is actually the same code you use to implement, say, a HTTP REST interface. everything outside the transport layer can't tell the difference between whether the data is getting encoded as packed binary and sent over USB CDC or whether it's getting turned into JSON and sent over a network. it's fucking awesome. all computer programming should be like this


You must log in to comment.