From 100341aa9fcc6f3f703b57b4143460beee774e52 Mon Sep 17 00:00:00 2001 From: Andrew Walbran Date: Mon, 13 Feb 2023 02:22:05 +0000 Subject: [PATCH] Add page about type-state pattern. --- src/SUMMARY.md | 2 +- .../microcontrollers/examples/Cargo.toml | 5 ++ .../examples/src/bin/typestate.rs | 50 +++++++++++++++++++ src/bare-metal/microcontrollers/hals.md | 6 +++ src/bare-metal/microcontrollers/type-state.md | 20 ++++++++ 5 files changed, 82 insertions(+), 1 deletion(-) create mode 100644 src/bare-metal/microcontrollers/examples/src/bin/typestate.rs create mode 100644 src/bare-metal/microcontrollers/type-state.md diff --git a/src/SUMMARY.md b/src/SUMMARY.md index 597f35cc..0e802c4d 100644 --- a/src/SUMMARY.md +++ b/src/SUMMARY.md @@ -242,8 +242,8 @@ - [Microcontrollers](bare-metal/microcontrollers.md) - [PACs](bare-metal/microcontrollers/pacs.md) - [HAL crates](bare-metal/microcontrollers/hals.md) + - [The type state pattern](bare-metal/microcontrollers/type-state.md) - [embedded-hal](bare-metal/microcontrollers/embedded-hal.md) - - [The type state pattern]() # Day 5A: Afternoon diff --git a/src/bare-metal/microcontrollers/examples/Cargo.toml b/src/bare-metal/microcontrollers/examples/Cargo.toml index a46fa5cb..7c8e8145 100644 --- a/src/bare-metal/microcontrollers/examples/Cargo.toml +++ b/src/bare-metal/microcontrollers/examples/Cargo.toml @@ -1,3 +1,5 @@ +[workspace] + [package] name = "microcontroller-examples" version = "0.1.0" @@ -15,3 +17,6 @@ name = "pac" [[bin]] name = "hal" + +[[bin]] +name = "typestate" diff --git a/src/bare-metal/microcontrollers/examples/src/bin/typestate.rs b/src/bare-metal/microcontrollers/examples/src/bin/typestate.rs new file mode 100644 index 00000000..7a37fa0a --- /dev/null +++ b/src/bare-metal/microcontrollers/examples/src/bin/typestate.rs @@ -0,0 +1,50 @@ +// Copyright 2023 Google LLC +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +// ANCHOR: Example +#![no_main] +#![no_std] + +extern crate panic_halt as _; + +use cortex_m_rt::entry; +use gd32f1x0_hal::{ + gpio::{ + gpioc::{PC1, PC2, PC9}, + Floating, Input, OpenDrain, Output, PushPull, + }, + pac::Peripherals, + prelude::*, +}; + +#[entry] +fn main() -> ! { + let p = Peripherals::take().unwrap(); + let mut rcu = p.RCU.constrain(); + let mut gpioc = p.GPIOC.split(&mut rcu.ahb); + let pc9: PC9> = gpioc.pc9; + // let pc9_again = gpioc.pc9; // Error, moved. + if pc9.is_high().unwrap() { + // ... + } + let mut pc9_output: PC9> = + pc9.into_open_drain_output(&mut gpioc.config); + pc9_output.set_high().unwrap(); + // pc9.is_high(); // Error, moved. + + let _pc1: PC1> = gpioc.pc1.into_open_drain_output(&mut gpioc.config); + let _pc2: PC2> = gpioc.pc2.into_push_pull_output(&mut gpioc.config); + + loop {} +} diff --git a/src/bare-metal/microcontrollers/hals.md b/src/bare-metal/microcontrollers/hals.md index 1cad0d61..051df58b 100644 --- a/src/bare-metal/microcontrollers/hals.md +++ b/src/bare-metal/microcontrollers/hals.md @@ -7,3 +7,9 @@ from [`embedded-hal`](https://crates.io/crates/embedded-hal). ```rust,editable,compile_fail {{#include examples/src/bin/hal.rs:Example}} ``` + +
+ + * `split(...)` enables the GPIO port and returns a struct of its pins. + +
diff --git a/src/bare-metal/microcontrollers/type-state.md b/src/bare-metal/microcontrollers/type-state.md new file mode 100644 index 00000000..5829b171 --- /dev/null +++ b/src/bare-metal/microcontrollers/type-state.md @@ -0,0 +1,20 @@ +# The type state pattern + +```rust,editable,compile_fail +{{#include examples/src/bin/typestate.rs:Example}} +``` + +
+ + * Pins don't implement `Copy` or `Clone`, so only one instance of each can exist. Once a pin is + moved out of the port struct nobody else can take it. + * Changing the configuration of a pin consumes the old pin instance, so you can’t keep use the old + instance afterwards. + * The type of a value indicates the state that it is in: e.g. in this case, the configuration state + of a GPIO pin. This encodes the state machine into the type system, and ensures that you don't + try to use a pin in a certain way without properly configuring it first. Illegal state + transitions are caught at compile time. + * You can call `is_high` on an input pin and `set_high` on an output pin, but not vice-versa. + * Many HAL crates follow this pattern. + +