Keyboard shortcuts

Press ← or → to navigate between chapters

Press S or / to search in the book

Press ? to show this help

Press Esc to hide this help

Паттерн typestate

// Copyright 2023 Google LLC
// SPDX-License-Identifier: Apache-2.0

#[entry]
fn main() -> ! {
    let p = Peripherals::take().unwrap();
    let gpio0 = p0::Parts::new(p.P0);

    let pin: P0_01<Disconnected> = gpio0.p0_01;

    // let gpio0_01_again = gpio0.p0_01; // Ошибка, значение перемещено.
    let mut pin_input: P0_01<Input<Floating>> = pin.into_floating_input();
    if pin_input.is_high().unwrap() {
        // ...
    }
    let mut pin_output: P0_01<Output<OpenDrain>> = pin_input
        .into_open_drain_output(OpenDrainConfig::Disconnect0Standard1, Level::Low);
    pin_output.set_high().unwrap();
    // pin_input.is_high(); // Ошибка, значение перемещено.

    let _pin2: P0_02<Output<OpenDrain>> = gpio0
        .p0_02
        .into_open_drain_output(OpenDrainConfig::Disconnect0Standard1, Level::Low);
    let _pin3: P0_03<Output<PushPull>> =
        gpio0.p0_03.into_push_pull_output(Level::Low);

    loop {}
}
  • Выводы не реализуют Copy или Clone, поэтому каждый вывод может существовать только в единственном экземпляре. Как только вывод перемещён из структуры порта, никто другой не может его забрать.
  • Изменение конфигурации вывода потребляет старый экземпляр вывода, поэтому после этого старым экземпляром пользоваться нельзя.
  • Тип значения показывает, в каком состоянии оно находится: например, в этом случае — состояние конфигурации GPIO-вывода. Это кодирует конечный автомат в системе типов и гарантирует, что вы не попытаетесь использовать вывод определённым образом, не настроив его должным образом сначала. Недопустимые переходы состояний отлавливаются во время компиляции.
  • Можно вызвать is_high для входного вывода и set_high для выходного, но не наоборот.
  • Многие HAL-крейты следуют этому паттерну.