embedded_platform/lib.rs
1//! # Embedded platform
2//!
3//! This crate defines a rich platform on top of which embedded device drivers and applications can
4//! be written.
5//!
6//! The idea is to add device and peripheral support to complement [`embedded-hal`]-based crates.
7//! This makes it possible to plug-and-play and mix-and-match different crates that adhere to common
8//! specs. For example, if you have a `nrf52840`-based MCU as well as a `ili9341`-based device, and
9//! both adhere to the [Adafruit Feather spec] (pin layout, voltage levels, ...), you can connect
10//! them up and all the wiring will be done for you.
11//!
12//! The ambition is that `embedded-platform` should be to `embedded-hal` what `tokio` is to `mio`.
13//!
14//! ## Design
15//!
16//! Some design trade-offs that have been made:
17//!
18//! * `#![forbid(unsafe_code)]`; that belongs in `-pac` or `-hal` crates.
19//! * Don't require `alloc`.
20//! * Do some compatibility checks at runtime during startup instead of at compile time, for
21//! example to check that a pin is used only once. It turns out to be super tricky to do
22//! granular ownership mapping of device registers at compile time (this has been done in
23//! [`drone-os`](https://www.drone-os.com/)), and instead we opt to do some checks at runtime
24//! (e.g. `Option::take`). This wastes a dozen or so instructions at startup, which is a
25//! one-time cost.
26//! * All APIs are async-first, so that code won't have to block and we can be power efficient.
27//! This does require an executor, and one can be made that doesn't require `alloc`, yet to be
28//! written.
29//! * The crate uses its own HAL-like traits for e.g. `OutputPin` or `I2cRead` to enable async
30//! APIs as well as smooth over any incompatibilities between `embedded_hal::gpio::v1` and
31//! `embedded_hal::gpio::v2` etc.
32//! * All platform crates should be maintained in this repository so that changes like the last
33//! bullet point can be made in lock-step.
34//! * Don't expose interrupts to the user. `mypin.changes()` should return an async
35//! `futures::Stream` when the pin changes. In the background, we stash away a `Waker` that
36//! gets called from the interrupt handler.
37//!
38//! ## Stack
39//! You can think about the intended stack like this:
40//!
41//! ```text
42//! ┌─────────────────────────────────────────┐
43//! │ Peripheral Access Crate │
44//! │ e.g. nrf52840-pac │
45//! ├─────────────────────────────────────────┤
46//! │ Hardware Abstraction Layer │
47//! │ e.g. nrf52840-hal │
48//! ├─────────────────────────────────────────┤
49//! │ Platform Implementation │
50//! │ e.g. nrf52840-platform │
51//! │ ┌─────────────────────────────────────┐ │
52//! │ │ Specific Product │ │
53//! │ │ e.g. Particle Argon │ │
54//! │ ├─────────────────────────────────────┤ │
55//! │ │ Common Spec │ │
56//! │ │ e.g. Adafruit Feather │ │
57//! │ │ or Arduino Shield │ │
58//! │ ├─────────────────────────────────────┤ │
59//! │ │ Adapter │ │
60//! │ │ e.g. "Main SPI bus" on │ │
61//! │ │ specific Feather pins │ │
62//! │ └─────────────────────────────────────┘ │
63//! ├─────────────────────────────────────────┤
64//! │ Device Driver │
65//! │ e.g. ili9341 │
66//! └─────────────────────────────────────────┘
67//! ```
68//!
69//! [`embedded-hal`]: https://crates.io/crates/embedded-hal
70//! [Adafruit Feather spec]: https://learn.adafruit.com/adafruit-feather/feather-specification
71#![no_std]
72#![deny(
73 // missing_docs,
74 missing_debug_implementations,
75 missing_copy_implementations,
76 trivial_casts,
77 trivial_numeric_casts,
78 unstable_features,
79 unused_import_braces,
80 unused_qualifications,
81 clippy::all
82)]
83#![forbid(unsafe_code)]
84
85pub mod gpio;
86pub mod i2c;
87pub mod io;
88pub mod platform;
89pub mod specs;
90pub mod spi;
91pub mod time;
92
93pub use platform::Platform;