ステートマシンとしてのペリフェラル

マイクロコントローラのペリフェラルは、一連のステートマシンとして考えることができます。 例えば、簡略化されたGPIOピンの設定は、次の状態ツリーとして表すことができます。

  • 無効
  • 有効
    • 出力として設定
      • 出力:ハイ
      • 出力:ロー
    • 入力として設定
      • 入力:高抵抗(訳注:ハイインピーダンス)
      • 入力:プルダウン
      • 入力:プルアップ

このペリフェラルが無効モードから始まるとすると、入力:高抵抗モードに移行するには、次のステップを踏みます。

  1. 無効
  2. 有効
  3. 入力として設定
  4. 入力:高抵抗

入力:高抵抗から入力:プルダウンへと移る場合、次のステップを実行しなければなりません。

  1. 入力:高抵抗
  2. 入力:プルダウン

同じように、入力:プルダウンと設定されているGPIOピンを、出力:ハイにするには、次のステップを実行しなければなりません。

  1. 入力:プルダウン
  2. 入力として設定
  3. 出力として設定
  4. 出力:ハイ

ハードウェアの表現

通常、上記の状態は、GPIOペリフェラルに割り当てられたレジスタに値を書き込むことで設定できます。 これを説明するために、架空のGPIO設定レジスタを定義しましょう。

名前 ビットフィールド 意味 説明
有効 0 0 無効 GPIOを無効にする
1 有効 GPIOを有効にする
方向 1 0 入力 方向を入力に設定する
1 出力 方向を出力に設定する
入力モード 2..3 00 hi-z 入力を高抵抗に設定する
01 プルダウン 入力ピンはプルダウンになる
10 プルアップ 入力ピンはプルアップになる
11 n/a 無効な状態。設定しないこと。
出力モード 4 0 ロー 出力ピンをローにする
1 ハイ 出力ピンをハイにする
入力状態 5 x 入力値 入力が1.5Vより低ければ0、1.5V以上であれば1

このGPIOを制御するために、次のようなRustの構造体を公開することが できます

# /// GPIO interface
/// GPIOインタフェース
struct GpioConfig {
#     /// GPIO Configuration structure generated by svd2rust
    /// svd2rustで生成されたGPIO設定構造体
    periph: GPIO_CONFIG,
}

impl Gpio {
    pub fn set_enable(&mut self, is_enabled: bool) {
        self.periph.modify(|_r, w| {
            w.enable().set_bit(is_enabled)
        });
    }

    pub fn set_direction(&mut self, is_output: bool) {
        self.periph.modify(|r, w| {
            w.direction().set_bit(is_output)
        });
    }

    pub fn set_input_mode(&mut self, variant: InputMode) {
        self.periph.modify(|_r, w| {
            w.input_mode().variant(variant)
        });
    }

    pub fn set_output_mode(&mut self, is_high: bool) {
        self.periph.modify(|_r, w| {
            w.output_mode.set_bit(is_high)
        });
    }

    pub fn get_input_status(&self) -> bool {
        self.periph.read().input_status().bit_is_set()
    }
}

しかし、この実装では、筋が通らないレジスタの修正が可能になってしまいます。例えば、GPIOを入力に設定している時に、出力モードを設定すると、どうなるのでしょう?

通常、この構造体を利用すると、上のステートマシンで定義されていない状態に到達できてしまいます。 例えば、プルダウンの出力や、ハイに設定された入力、です。

このインタフェースは書き込みには便利ですが、ハードウェア実装によって定められた設計の契約を強制しません。