Rust, Embassy, Zephyr - Ready for Prime Time?

Application is on a Survey drone - Drones are not too big, they use 17" propellers.
X frame configuration so I have about 60cm from the motor to the flight controller, therefore the CANbus solution for clean signals.
T4 for each smartnode is overkill for what the nodes do but I originally tested with Teensy's and bare-metal rust and it works great.
Some of the survey hardware (aka payload) needs mcu control so T4 Smart node.
So no particular reason why I picked T4 for those functions. I find the Teensy products easy to work with and rock solid.
The Teensy 4.1 acts as a companion computer to the flight control and runs a small Nueral Net that learns and aids in Navigation.
For the Nueral Net I did need some power and SDcard for logging - like the T41.

Basically:

ArduPilot alone: standard flight controller stack.
ArduPilot + Snow Owl Companion: standard flight controller stack plus an external AI shadow brain (T41) watching, learning, comparing, and preparing for supervised autonomy (MAVlink injection).
 
Last edited:
ArduPilot alone: standard flight controller stack.
ArduPilot + Snow Owl Companion: standard flight controller stack plus an external AI shadow brain (T41) watching, learning, comparing, and preparing for supervised autonomy (MAVlink injection).
Thanks, that's interesting. It's not clear to me what Rust tools you are using. Have you created your own development environment? What was your starting point?
 
Thanks, that's interesting. It's not clear to me what Rust tools you are using. Have you created your own development environment? What was your starting point?
There isn’t really anything unique or custom about my development environment. I’m mostly using a normal Rust embedded workflow: cargo, rustup, the ARM embedded target, and the existing Teensy / i.MX RT Rust crates where they fit.

The style is mostly no_std bare-metal Rust. I’m not using Arduino, Teensyduino, an RTOS, or a custom IDE. For a lot of the lower-level work I still end up close to the hardware: peripheral registers, CAN setup, UARTs, timers, USB, GPIO, SD card, and so on.

My starting point was already being comfortable with embedded / MCU programming, then applying Rust to that workflow. So for me the Teensy boards are basically solid ARM dev boards with a very convenient bootloader and good hardware, and Rust is just the language I’m using to build the firmware.

On the Teensy 4.1 side, the Snow Owl work is bare-metal Rust for things like MAVLink input, CAN telemetry, SD logging, USB serial / MSC, and eventually the small companion logic. On the STM32 side I’m doing similar bare-metal Rust work for ESC / motor-control experiments.

So I wouldn’t say I created a new development environment. It’s more that I’m using the standard Rust embedded tools, plus direct register-level work where needed, on hardware that PJRC has made very approachable.
 
Quick progress update on a Teensy 4.0 DroneCAN node experiment written in close-to-bare-metal Rust.

The node now shows up in the DroneCAN GUI, responds to GetNodeInfo, publishes NodeStatus, and exposes parameters through uavcan.protocol.param.GetSet. The screenshots show the node being discovered as node 42 and the GUI reading/editing parameters.

One of the trickier parts was persistent parameter storage. Since this is not running on top of Arduino, Teensyduino EEPROM helpers, or a filesystem-style abstraction, saving configuration values meant figuring out a small flash-backed storage path directly from Rust. That is now working well enough for the node parameters to survive reset/power cycling.

Current milestone:

Teensy 4.0
Rust firmware
USB/SLCAN DroneCAN GUI connection
NodeStatus + GetNodeInfo
Parameter enumeration/read/write
Flash-backed persistent parameter storage

This is still an experiment, but it is a useful checkpoint toward a Teensy-based DroneCAN peripheral node.
Screenshot from 2026-07-02 06-49-15.png
Screenshot from 2026-07-02 06-48-40.png
Screenshot from 2026-07-02 06-48-02.png
Screenshot from 2026-07-02 06-46-51.png



PXL_20260702_110648216.jpg
 
Quick progress update on a Teensy 4.0 DroneCAN node experiment written in close-to-bare-metal Rust.

The node now shows up in the DroneCAN GUI, responds to GetNodeInfo, publishes NodeStatus, and exposes parameters through uavcan.protocol.param.GetSet. The screenshots show the node being discovered as node 42 and the GUI reading/editing parameters.

One of the trickier parts was persistent parameter storage. Since this is not running on top of Arduino, Teensyduino EEPROM helpers, or a filesystem-style abstraction, saving configuration values meant figuring out a small flash-backed storage path directly from Rust. That is now working well enough for the node parameters to survive reset/power cycling.

Current milestone:

Teensy 4.0
Rust firmware
USB/SLCAN DroneCAN GUI connection
NodeStatus + GetNodeInfo
Parameter enumeration/read/write
Flash-backed persistent parameter storage

This is still an experiment, but it is a useful checkpoint toward a Teensy-based DroneCAN peripheral node.
View attachment 39564View attachment 39565View attachment 39566View attachment 39567


View attachment 39563
I looked at some of your code on GitHub. I am impressed at what you have accomplished.

Access to hardware registers looks cleaner than in C++.

I am just learning rust. I started trying to read documents and doing simple examples. This didn't work for me so I switched to trying to implement low level access to an SD card using async DMA SPI and Embassy.

This was really painful but it forced me to learn what I needed. I have managed to init an SD and read/write blocks.

Looks like it will be about 10-20 times faster than crates like embedded_sdmmc which use blocking SPI. I get about 3 MB/sec with the Pico 2 I am using.
 
I looked at some of your code on GitHub. I am impressed at what you have accomplished.

Access to hardware registers looks cleaner than in C++.

I am just learning rust. I started trying to read documents and doing simple examples. This didn't work for me so I switched to trying to implement low level access to an SD card using async DMA SPI and Embassy.

This was really painful but it forced me to learn what I needed. I have managed to init an SD and read/write blocks.

Looks like it will be about 10-20 times faster than crates like embedded_sdmmc which use blocking SPI. I get about 3 MB/sec with the Pico 2 I am using.
Thanks Bill, that means a lot.

I am still feeling my way through Rust on the embedded side, but access to registers has been one of the parts I have really enjoyed. Once the register layout is understood, the code can stay pretty direct and readable.
Your SD card work sounds familiar in spirit. A lot of this has been painful in the same way: not because the individual pieces are impossible, but because doing it close to bare metal forces me to actually understand the peripheral, the timing, the buffers, and the failure modes.

A small update from my side: I now have a 3-node bench CAN setup working. The G431 ESC board is sending raw CAN telemetry, a Teensy 4.1 is being brought up as a DroneCAN node, and a Teensy 4.0 is acting as the SLCAN/DroneCAN GUI bridge.

The G431 firmware is not DroneCAN-enabled yet. It is still raw/classical CAN telemetry for now. The Teensy 4.1 is close: it shows up as node 41 in DroneCAN GUI and publishes stable NodeStatus, but my GetNodeInfo response still needs more work.

I also wrote a small terminal dashboard for bring-up. It reads the Teensy serial output and gives me a live view of raw CAN frames, decoded ESC telemetry, frame rates, bus/error state, FC UART/MAVLink status, and power/health notes. It has been useful as a bench tool for learning what is really happening on the wire before wrapping the ESC telemetry into proper DroneCAN messages.

The setup is running at 500 kbit/s for now. The wiring is still very temporary, with no soldered harnesses yet, and I measured 63.1 ohms across CANH/CANL with the bus unpowered, so termination looks reasonable. Honestly, I am a little surprised how stable it is already on the bench.

I have several Teensy-side updates in progress as well. Once they are cleaned up a bit more, I will post the details and share the GitHub repo links.
PXL_20260705_143231223.jpg
Screenshot from 2026-07-03 13-41-50.png
Screenshot from 2026-07-05 10-18-27.png
 
Back
Top