diff --git a/src/SUMMARY.md b/src/SUMMARY.md index f0c3972..060849d 100644 --- a/src/SUMMARY.md +++ b/src/SUMMARY.md @@ -24,12 +24,9 @@ more information and coordination - [The Borrow Checker](./peripherals/borrowck.md) - [Singletons](./peripherals/singletons.md) - [Peripherals in Rust](./peripherals/rusty.md) -- [Typestate Programming](./typestate-programming/typestate-programming.md) - - [Peripherals as State Machines](./typestate-programming/state-machines.md) - - [Design Contracts](./typestate-programming/design-contracts.md) - - [Zero Cost Abstractions](./typestate-programming/zero-cost-abstractions.md) +- [Static Guarantees](./static-guarantees/static-guarantees.md) + - [Portability](./portability/portability.md) - - [The Trait System](./portability/traits.md) - [Concurrency](./concurrency/concurrency.md) diff --git a/src/portability/portability.md b/src/portability/portability.md index 26fb9c2..bc2e273 100644 --- a/src/portability/portability.md +++ b/src/portability/portability.md @@ -1,14 +1,3 @@ # Portability -> ❌: This section has not yet been written. Please refer to [embedded-wg#119](https://github.com/rust-lang-nursery/embedded-wg/issues/119) for discussion of this section. - -## Building something bigger - -> drivers that work for more than one chip - -![](./../assets/embedded-hal.svg) - -* Device Crates (one per chip) -* HAL Implementation Crates (one per chip) -* `embedded-hal` (only one) -* Driver Crates (one per external component) +> ❌: This section has not yet been written. Please refer to [embedded-wg#119](https://github.com/rust-lang-nursery/embedded-wg/issues/119) for discussion of this section. \ No newline at end of file diff --git a/src/portability/traits.md b/src/portability/traits.md deleted file mode 100644 index 2fbf2ff..0000000 --- a/src/portability/traits.md +++ /dev/null @@ -1,50 +0,0 @@ -# The Trait System - -```rust -/// Single digital push-pull output pin -pub trait OutputPin { - /// Drives the pin low - fn set_low(&mut self); - - /// Drives the pin high - fn set_high(&mut self); -} -``` - -[rust-embedded/embedded-hal](https://github.com/rust-embedded/embedded-hal/blob/master/src/digital.rs) - -```rust -impl OutputPin for OutputGpio { - fn set_low(&mut self) { - self.set_pin_low() - } - - fn set_high(&mut self) { - self.set_pin_high() - } -} -``` - -> this goes in your chip crate - - -```rust -impl L3gd20 -where - SPI: Transfer + Write, - CS: OutputPin, -{ - /// Creates a new driver from a SPI peripheral - /// and a NCS (active low chip select) pin - pub fn new(spi: SPI, cs: CS) -> Result { - // ... - } - // ... -} -``` - -[japaric/l3gd20](https://github.com/japaric/l3gd20/blob/master/src/lib.rs) - -## N\*M >>> N+M - -> to re-use a driver, just implement the embedded-hal interface \ No newline at end of file diff --git a/src/typestate-programming/design-contracts.md b/src/typestate-programming/design-contracts.md deleted file mode 100644 index e6f7bbf..0000000 --- a/src/typestate-programming/design-contracts.md +++ /dev/null @@ -1,48 +0,0 @@ -# Design Contracts - -In - -```rust -use gpio::{InputGpio, OutputGpio}; - -struct GpioPin; - -impl GpioPin { - fn into_input(self) -> InputGpio { - self.set_input_mode(); - InputGpio - } - fn into_output(self) -> OutputGpio { - self.set_output_mode(); - OutputGpio - } -} -``` - -* Use type transitions to enforce setup steps -* Like the builder pattern in "normal" Rust - -```rust -impl LedPin { - fn new(pin: OutputGpio) -> Self { ... } - fn toggle(&mut self) -> bool { ... } -} - -fn main() { - let gpio_1 = unsafe { PERIPHERALS.take_gpio_1() }; - // This won't work, the types are wrong! - // let led_1 = LedPin::new(gpio_1); - let mut led_1 = LedPin::new(gpio_1.into_output()); - let _ = led_1.toggle(); -} -``` - -* You have to have the right types to have the interfaces you want - -## Enforce design contracts - -> entirely at compile time -> -> no runtime cost -> -> no room for human error diff --git a/src/typestate-programming/state-machines.md b/src/typestate-programming/state-machines.md deleted file mode 100644 index f7c8f81..0000000 --- a/src/typestate-programming/state-machines.md +++ /dev/null @@ -1,5 +0,0 @@ -# Peripherals as State Machines - -The peripherals of a microcontroller can be thought of as set of state machines. For example, a simplified [GPIO pin] - -[GPIO pin]: https://en.wikipedia.org/wiki/General-purpose_input/output \ No newline at end of file diff --git a/src/typestate-programming/typestate-programming.md b/src/typestate-programming/typestate-programming.md deleted file mode 100644 index 9f21150..0000000 --- a/src/typestate-programming/typestate-programming.md +++ /dev/null @@ -1,63 +0,0 @@ -# Typestate Programming - -The concept of [typestates] describes the encoding of information about the current state of an object into the type of that object. Although this can sound a little arcane, if you have used the [Builder Pattern] in Rust, you have already started using Typestate Programming! - -[typestates]: https://en.wikipedia.org/wiki/Typestate_analysis -[Builder Pattern]: https://doc.rust-lang.org/1.0.0/style/ownership/builders.html - -```rust -#[derive(Debug)] -struct Foo { - inner: u32, -} - -struct FooBuilder { - a: u32, - b: u32, -} - -impl FooBuilder { - pub fn new(starter: u32) -> Self { - Self { - a: starter, - b: starter, - } - } - - pub fn double_a(self) -> Self { - Self { - a: self.a * 2, - b: self.b, - } - } - - pub fn into_foo(self) -> Foo { - Foo { - inner: self.a + self.b, - } - } -} - -fn main() { - let x = FooBuilder::new(10) - .double_a() - .into_foo(); - - println!("{:#?}", x); -} -``` - -In this example, there is no direct way to create a `Foo` object. We must create a `FooBuilder`, and properly initialize it before we can obtain the `Foo` object we want. - -This minimal example encodes two states: - -* `FooBuilder`, which represents an "unconfigured", or "configuration in process" state -* `Foo`, which represents a "configured", or "ready to use" state. - -## Strong Types - -Because Rust has a [Strong Type System], there is no easy way to magically create an instance of `Foo`, or to turn a `FooBuilder` into a `Foo` without calling the `into_foo()` method. Additionally, calling the `into_foo()` method consumes the original `FooBuilder` structure, meaning it can not be reused without the creation of a new instance. - -[Strong Type System]: https://en.wikipedia.org/wiki/Strong_and_weak_typing - -This allows us to represent the states of our system as types, and to include the necessary actions for state transitions into the methods that exchange one type for another. By creating a `FooBuilder`, and exchanging it for a `Foo` object, we have walked through the steps of a basic state machine. \ No newline at end of file diff --git a/src/typestate-programming/zero-cost-abstractions.md b/src/typestate-programming/zero-cost-abstractions.md deleted file mode 100644 index 89c142e..0000000 --- a/src/typestate-programming/zero-cost-abstractions.md +++ /dev/null @@ -1,78 +0,0 @@ -# Zero Cost Abstractions - -## "no runtime cost"? - -```rust -use core::mem::size_of; - -let _ = size_of::(); // == 0 -let _ = size_of::(); // == 0 -let _ = size_of::(); // == 0 -let _ = size_of::<()>(); // == 0 -``` - -## Zero Sized Types - -```rust -struct GpioPin; -``` - -> acts real at compile time -> -> doesn't exist in the binary -> -> no RAM, no CPU, no space -> -> Evaporates at compile time - -## What if our `OutputGpio` has multiple modes? - -> (it does) - ---- - -```rust -pub struct PushPull; // good for general usage -pub struct OpenDrain; // used when multiple devices could drive a bus - -pub struct OutputGpio { - _mode: MODE -} - -impl OutputGpio { - fn default() -> OutputGpio { ... } - fn into_push_pull(self) -> OutputGpio { ... } - fn into_open_drain(self) -> OutputGpio { ... } -} -``` - ---- - -```rust -/// This kind of LED only works with OpenDrain settings -struct DrainLed { - pin: OutputGpio, -} - -impl DrainLed { - fn new(pin: OutputGpio) -> Self { ... } - fn toggle(&self) -> bool { ... } -} -``` - ---- - -```rust -/// This kind of LED works with any output -struct LedDriver { - pin: OutputGpio, -} - -/// Generically support any OutputGpio variant! -impl LedDriver { - fn new(pin: OutputGpio) -> LedDriver { ... } - fn toggle(&self) -> bool { ... } -} -``` - -* Nested zero sized types are still zero sized, no matter how deep you nest them \ No newline at end of file