类型状态模式

  1. #[entry]
  2. fn main() -> ! {
  3. let p = Peripherals::take().unwrap();
  4. let gpio0 = p0::Parts::new(p.P0);
  5. let pin: P0_01<Disconnected> = gpio0.p0_01;
  6. // let gpio0_01_again = gpio0.p0_01; // Error, moved.
  7. let pin_input: P0_01<Input<Floating>> = pin.into_floating_input();
  8. if pin_input.is_high().unwrap() {
  9. // ...
  10. }
  11. let mut pin_output: P0_01<Output<OpenDrain>> = pin_input
  12. .into_open_drain_output(OpenDrainConfig::Disconnect0Standard1, Level::Low);
  13. pin_output.set_high().unwrap();
  14. // pin_input.is_high(); // Error, moved.
  15. let _pin2: P0_02<Output<OpenDrain>> = gpio0
  16. .p0_02
  17. .into_open_drain_output(OpenDrainConfig::Disconnect0Standard1, Level::Low);
  18. let _pin3: P0_03<Output<PushPull>> =
  19. gpio0.p0_03.into_push_pull_output(Level::Low);
  20. loop {}
  21. }
  • 引脚无法实现 CopyClone,因此,每个引脚只能存在一个实例。一旦某个引脚从端口结构体移出,任何人都无法再使用它。
  • 更改引脚的配置会使旧的引脚实例失效,因此您无法再继续使用旧实例。
  • 值的类型表示其所处状态:例如,在本例中,表示 GPIO 引脚的配置状态。通过这种方式,可将状态机编码成类型系统,并确保在未正确完成引脚配置之前,不会尝试以某种方式使用引脚。编译时捕获了非法状态转换。
  • 您可以在输入引脚上调用 is_high,在输出引脚上调用 set_high,反之则不行。
  • 许多 HAL crate 都遵循此模式。