---
# System prepended metadata

title: '卒研経過報告 #12'

---

# 卒研経過報告 #12
Rustによる組み込みプログラミング
マイコンWio terminalを用いたRustとC言語の信頼性，安全性の比較検証、考察

[先週のレジュメ](https://hackmd.io/@Fteam/Syll3sEdY)

### 型状態プログラミング
何すればいいかわからなかったので，言語化して課題を明確にする．
#### 実現したいこと
Rustの型状態プログラミングの利点の確認．
#### 主張の流れ
1. 構造体を用いGPIOの状態を管理する -> 無効から出力のような例が作成可能
```graphviz
digraph hierarchy {
    GPIO->{無効 有効}
    有効->{出力 入力}
    出力->{high low}
    入力->{高抵抗 プルダウン プルアップ}
}
```
2. 全ての動作でifで状態チェック -> 実行コスト
3. Rustの型システム
#### わかっていること
- 組み込み -> wioを使うといい
- 簡単な例でも可
-> ボタンを押してLEDを点灯する例を流用するのが最適か
#### 実現
3.のRustの型システムについて
先週のコードを構造体を使った例に変更(組込みRustから抜粋)
:::spoiler コード
```rust=
#![no_std]
#![no_main]
#![allow(dead_code)] // 使用しないメソッドでコンパイラが警告を出さないようにする

use panic_halt as _;
use wio_terminal as wio;

use wio::entry;
use wio::hal::gpio::*; // GPIOの構造体やトレイトをインポートする
use wio::pac::Peripherals;
use wio::prelude::*; // 主要な構造体やトレイトをインポートする

#[entry]
fn main() -> ! {
    let peripherals = Peripherals::take().unwrap();
    let mut pins = wio::Pins::new(peripherals.PORT);

    // TODO: ボタン1を押している間、LEDが点灯するコードを書く
    let mut led = Led::new(pins.user_led, &mut pins.port);
    let button1 = Button1::new(pins.button1, &mut pins.port);

    loop {
        if button1.is_pressed(){
            led.turn_on();
        }else{
            led.turn_off();
        }
    }
}

// Wio Terminalのボタン1ドライバ
struct Button1{
    pin: Pc26<Input<Floating>>,
}
impl Button1 {
    // PC26 ピンを入力モードに設定する
    fn new(pin: Pc26<Input<Floating>>, port: &mut Port) -> Button1 {
        Button1 {
            pin: pin.into_floating_input(port),
        }
    }
    // ボタンが押されていれば trueを返す
    fn is_pressed (&self) -> bool {
        self.pin.set_low().unwrap()  // error
    }
    // ボタンが押されていなければtrue を返す
    fn is_released (&self) -> bool {
        self.pin.is_high().unwrap()
    }
}

// Wio TerminalのユーザーLEDドライバ
struct Led {
    pin: Pa15<Output<PushPull>>,
}
impl Led {
    // デフォルトモードの PA15 ピンを、出力モードに移行する
    fn new(pin: Pa15<Input<Floating>>, port: &mut Port) -> Led {
        Led {
            pin: pin.into_push_pull_output(port),
        }
    }
    // LEDを点灯する
    fn turn_on(&mut self) {
        self.pin.set_high().unwrap();
    }
    // LEDを消灯する
    fn turn_off(&mut self) {
        self.pin.set_low().unwrap();
    }
    // LEDが点灯しているときは消灯し、消灯しているときは点灯する
    fn toggle(&mut self) {
        self.pin.toggle();
    }
}
```
:::
`use wio::hal::gpio::*;`：GPIOの構造体やトレイトのインポート

---

**ifを使って実行時にチェックを行う例**
* set_enable関数は条件なしでenableを1(有効)に
* set_direction関数はenableが1(有効)の時のみ使えてset_bit()で方向を1（出力）に変更する
* set_output_statusはenableが有効かつdirectionが出力の時に使えて、出力モードを1にする

result型よくわからん


```=rust
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) -> Result<(), ()> {
        if self.periph.read().enable().bit_is_clear() {
            // 方向を設定するには、有効化されてなければなりません
            return Err(());
        }

        self.periph.modify(|r, w| {
            w.direction().set_bit(is_output)
        });

        Ok(())
    }
    
    pub fn set_output_status(&mut self, is_high: bool) -> Result<(), ()> {
        if self.periph.read().enable().bit_is_clear() {
            // 出力状態を設定するためには、有効化されてなければなりません
            return Err(());
        }

        if self.periph.read().direction().bit_is_clear() {
            // 方向は出力でなければなりません
            return Err(());
        }

        self.periph.modify(|_r, w| {
            w.output_mode.set_bit(is_high)
        });

        Ok(())
    }
```
簡単な例➡同じように構造体を作り
bool型で1か0(入力か出力/有効か無効)かをif文でチェックする簡単なコードを作ればいい？（まだできてないしよくわからん）

set_enableは条件なしでenabledをtrueに
set_directionはenabledが(1)でなければ処理を抜ける
(1)ならdirectionをtrueに


```=rust
struct Gpio{
    enabled:bool,
    direction:bool,
    output:bool,
    //periph:GPIO_CONFIG,
}

impl Gpio{
    pub fn set_enable(&mut self){
        self.enabled=true;
    }

    pub fn set_direction(&mut self){
        if self.enabled!=true{
            return;
        }
        self.direction=true;
    }

    pub fn set_output_status(&mut self){
        if self.enabled!=true{
            return;
        }
        if self.direction!=true{
            return;
        }
        self.output=true;
    }
}

fn main(){
    let mut pin=Gpio{
        enabled:false,
        direction:false,
        output:false,
    };
    println!("{}",pin.enabled); //false
    pin.set_enable();
    println!("{}",pin.enabled); //true
}
```
そもそも構造体がまだよくわかってない



## 参考文献
[1] rustプログラミング入門　オーム社
[２] 基礎から学ぶ組込みRust C&R研究所
[公式ドキュメント](https://doc.rust-jp.rs/book-ja/ch08-02-strings.html)
[The Embedded Rust Book](https://tomoyuki-nakabayashi.github.io/book/static-guarantees/index.html)
[seeed:ユーザー定義ボタン](https://wiki.seeedstudio.com/jp/Wio-Terminal-Buttons/)
[](https://tomo-wait-for-it-yuki.hatenablog.com/entry/2019/01/30/163235)



