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