初心者が組み込みRustやってみる - その4

初心者が組み込みRustやってみる - その3 - 雨垂れ石を穿つ
のつづき。

8. LED、再び

tomoyuki-nakabayashi.github.io

これまでは初期設定済みのペリフェラルが提供されていたが、今度は自分で初期設定する。

ほとんどのペリフェラルは、電源が入っていない状態で起動する。そのため、RCC (Reset and Clock Control) を使ってペリフェラルの電源をオンにしないといけないらしい。

さらに、GPIOは電源を入れた後の初期状態だとデジタル入力として設定されている。デジタル出力として使うよ、の設定をしないといけない。

マニュアルやrustdocと格闘して、なんとか解答例を見ずに自力でLEDを点灯させることができた。
今は「マニュアルのここに書いてあるよ」が与えられているが、それも自分で探すのは相当大変そう。。。
でも苦労の末、思った通りに動くと楽しい。

9. クロックと時間

tomoyuki-nakabayashi.github.io

今まで与えられていたdelay関数を自分で実装する。

9.1. forループで遅延

  • forループによる遅延は、マイクロコントローラ内のプロセッサのクロック数に依存する。
  • 空のfor文はコンパイラによる最適化で削除されるため、releaseモードで実行すると遅延しなくなってしまう。

9.2. NOP

  • 最適化によってdelay関数が壊れないようにするには、 cortex_m クレートの cortex_m::asm::nop を呼び出す。

9.3. ワンショットタイマ

  • forループの代わりに、ハードウェアタイマを使って遅延を実装する。
  • ハードウェアタイマは、マイクロコントローラから利用できるペリフェラルの1つ。レジスタを使って制御できる。
    • TIM6 というのが使えるらしい。マニュアルを読むと、内部的にはDAC(Digital to Analog Converter)にも繋がっていて、DACをdriveする(駆動する?動かす?)のにも使われているらしい。

マニュアルを読みつつ、分からないところは手順に従いつつ、最終的なコードは以下。

#![no_main]
#![no_std]

use aux9::{entry, tim6};

#[inline(never)]
fn delay(tim6: &tim6::RegisterBlock, ms: u16) {
    // ms tick後にオフになるようにタイマを設定
    tim6.arr.write(|w| w.arr().bits(ms));
    // タイマを有効化
    tim6.cr1.write(|w| w.cen().set_bit());
    // 更新イベントが発生するまで待つ
    while !tim6.sr.read().uif().bit_is_set() {}
    // 更新イベントフラグをクリアする
    tim6.sr.modify(|_, w| w.uif().clear_bit());
}

#[entry]
fn main() -> ! {
    let (mut leds, rcc, tim6) = aux9::init();

    // TIM6の電源を入れる
    rcc.apb1enr.modify(|_, w| w.tim6en().set_bit());
    // OPM (One Pulse Mode) に設定する
    tim6.cr1.write(|w| w.opm().set_bit().cen().clear_bit());
    // カウンタが1KHzで動作するようにプリスケーラを設定する
    let psc = 7999;
    tim6.psc.write(|w| w.psc().bits(psc));

    let ms = 50;
    loop {
        for curr in 0..8 {
            let next = (curr + 1) % 8;

            leds[next].on();
            delay(tim6, ms);
            leds[curr].off();
            delay(tim6, ms);
        }
    }
}

まとめ

  • ペリフェラルを使うには、電源を入れるところから。
  • 電源の入れ方や使い方(どのレジスタにどんな値をセットするか)はマニュアルを頑張って読む。
    • とにかくマニュアルをよく読んで理解することが重要だと感じた。
  • ハードウェアタイマを利用することで、正確なタイミングで処理を実行できる。
  • 苦労して作ったものが動くと、楽しい。