Welcome to my collection of posts! Dive in and explore articles on everything from 3D printing and modelling, embedded prototyping with PCBs, breadboards, and building things of all shapes and sizes, to writing workflows in Obsidian, crafting software (especially in Rust), and the occasional software engineering deep-dive. If you like making, tinkering, or just reading about creative projects, you’re in the right place. Hopefully someone, somewhere finds them useful (or at least entertaining)!
Creating a multi platform Rust Driver: FT232H Breakout Board
In the previous part of the series we explored the embedded-hal traits and how they can be used to create platform agnostic drivers in Rust. In this part, we will focus on how we can use the FT232H breakout board to interact with our I2C device from a desktop environment.

An ordinary laptop or desktop computer does not have native I2C support, so we need to use a USB to I2C bridge to communicate with our device. The FT232H breakout board made by adafruit is a popular choice for this purpose, as it provides a simple and reliable way to interface with I2C devices from a computer. It also provides GPIO, SPI and has a STEMMA QT connector for easy wiring. Allowing us to chain a bunch of I2C devices together.
Creating a multi platform Rust Driver: Embedded Hal
In this first part of the series, we’ll focus on the Embedded HAL (Hardware Abstraction Layer) and Embedded HAL Async—the foundation for writing portable Rust drivers.
What is it?

The Embedded HAL provides a set of traits that let you write platform-agnostic code, making it much easier to support multiple hardware platforms. It doesn’t just cover GPIO, I²C, and SPI—there are also traits for:
- embedded-hal-bus - provides traits for shared bus access, allowing multiple devices to share the same bus without conflicts.
- embedded-can - provides traits for Controller Area Network (CAN) communication, commonly used in automotive and industrial applications.
- And many more systems…
It’s a set of official traits maintained by the Rust Embedded Working Group that provide standardised interfaces for embedded protocols. Instead of everyone reimplementing read/write functions for I²C, SPI, or GPIO, there’s one common interface. There are two flavours: embedded-hal for blocking/synchronous operations, and embedded-hal-async for non-blocking/asynchronous ones.
Creating a multi platform Rust Driver: Overview
Writing drivers that work consistently across microcontrollers, embedded Linux boards, and desktop operating systems is deceptively hard. Different HALs, conflicting abstractions, and platform-specific quirks often lead to duplicated code or forests of #ifdef blocks.

In this blog series, we’ll explore how to design and implement a multi-platform Rust driver that avoids all of that — one codebase, many targets. We’ll look at how Rust’s trait system, strong type guarantees, built-in testing support, and CI-friendly workflow make this not only possible, but pleasant.