1
0
mirror of https://github.com/google/comprehensive-rust.git synced 2025-05-17 08:02:38 +02:00

Add page about type-state pattern.

This commit is contained in:
Andrew Walbran 2023-02-13 02:22:05 +00:00
parent 65749777c9
commit 100341aa9f
5 changed files with 82 additions and 1 deletions

View File

@ -242,8 +242,8 @@
- [Microcontrollers](bare-metal/microcontrollers.md) - [Microcontrollers](bare-metal/microcontrollers.md)
- [PACs](bare-metal/microcontrollers/pacs.md) - [PACs](bare-metal/microcontrollers/pacs.md)
- [HAL crates](bare-metal/microcontrollers/hals.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) - [embedded-hal](bare-metal/microcontrollers/embedded-hal.md)
- [The type state pattern]()
# Day 5A: Afternoon # Day 5A: Afternoon

View File

@ -1,3 +1,5 @@
[workspace]
[package] [package]
name = "microcontroller-examples" name = "microcontroller-examples"
version = "0.1.0" version = "0.1.0"
@ -15,3 +17,6 @@ name = "pac"
[[bin]] [[bin]]
name = "hal" name = "hal"
[[bin]]
name = "typestate"

View File

@ -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<Input<Floating>> = gpioc.pc9;
// let pc9_again = gpioc.pc9; // Error, moved.
if pc9.is_high().unwrap() {
// ...
}
let mut pc9_output: PC9<Output<OpenDrain>> =
pc9.into_open_drain_output(&mut gpioc.config);
pc9_output.set_high().unwrap();
// pc9.is_high(); // Error, moved.
let _pc1: PC1<Output<OpenDrain>> = gpioc.pc1.into_open_drain_output(&mut gpioc.config);
let _pc2: PC2<Output<PushPull>> = gpioc.pc2.into_push_pull_output(&mut gpioc.config);
loop {}
}

View File

@ -7,3 +7,9 @@ from [`embedded-hal`](https://crates.io/crates/embedded-hal).
```rust,editable,compile_fail ```rust,editable,compile_fail
{{#include examples/src/bin/hal.rs:Example}} {{#include examples/src/bin/hal.rs:Example}}
``` ```
<details>
* `split(...)` enables the GPIO port and returns a struct of its pins.
</details>

View File

@ -0,0 +1,20 @@
# The type state pattern
```rust,editable,compile_fail
{{#include examples/src/bin/typestate.rs:Example}}
```
<details>
* 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.
</details>