There are already some embedded Rust projects such as tock-os or zync-rs. They all (AFAIK) took the path to a monolithic API in the sense that they provide everything as a single (potentially) heavy crate that includes all ports and their drivers.

A single dependency to all your projects can look appealing, but it has downsides that (IMHO) make it unworthy. It greatly impairs maintainability and slows down the release pace because it makes the crate heavier (in features and targets):

Decoupling

Splitting the framework in a “galaxy” of lightweight crates allows adoption of updates of the main APIs to be propagated in some sort of waterfall way. A team responsible for maintaining a certain set of targets can use semantic versioning to only update the release when it is ready. It adds latency between the main API & the target implementation updates but it prevents :

This would also help :

This diagram is here to give you a rough idea of what could be achieved. This would of course be extended by more crates dedicated to others tasks such has file system drivers, motor/sensor control (loops?)…

kind of UML diagram

For example here is how things could be spread :

Features

Rust’s Features are a nice & clean replacement for what used to be done with #define in C.
They could be used to select a specific implementation of a given feature.
The most obvious use case that comes to my mind is a bootloader application requiring that ‘no-os’ is provided to get the smallest footprint possible while another app would require a full featured ‘RTOS’ with system calls, os aware synchronisation primitive implementations primitives. Both apps would depend on the same target crate (e.g. silica_arduino_mega2560) but with slightly different implementations.


  1. silica-rs is something I initiated few years ago. It is inspired by something I realized with Makefiles & C in my first company. I wanted a framework that is target, os, ip stack […] agnostic.