さぁ、それではLチカをやっていきましょう!
Lチカのソースコード
いきなりですが、ソースコードを示します。低レベルな記述が好きな僕ですが、Rust でそれをやると unsafe
な物となってしまうので、今回ばかりは HAL を使います。。。
fn main() {
let cp = cortex_m::Peripherals::take().unwrap();
let p = hal::stm32f30x::Peripherals::take().unwrap();
let mut flash = p.FLASH.constrain();
let mut rcc = p.RCC.constrain();
let clocks = rcc.cfgr.freeze(&mut flash.acr);
// Systickベースでディレイするオブジェクト
let mut delay = Delay::new(cp.SYST, clocks);
// PA5 for Output
let mut gpioa = p.GPIOA.split(&mut rcc.ahb);
let mut pa0 = gpioa.pa5.into_push_pull_output(&mut gpioa.moder, &mut gpioa.otyper);
loop {
pa0.set_high();
delay.delay_ms(500_u16);
pa0.set_low();
delay.delay_ms(100_u16);
}
}
ざっと説明
各ブロックで説明をします。僕自身理解が不十分ですが...
let cp = cortex_m::Peripherals::take().unwrap();
let p = hal::stm32f30x::Peripherals::take().unwrap();
こちらで cortex_m のコア部と STM32F303 用の HAL の設定用インスタンスを生成します。変数はイミュータブルでいいっぽいです。
let mut flash = p.FLASH.constrain();
let mut rcc = p.RCC.constrain();
let clocks = rcc.cfgr.freeze(&mut flash.acr);
// Systickベースでディレイするオブジェクト
let mut delay = Delay::new(cp.SYST, clocks);
ごちゃごちゃやっていますが、このブロックは Systick タイマを用いて Delay をさせることを目的としています。そのために色々と必要なのです。なおここでは動作クロックをデフォの 8MHz としています。
// PA5 for Output
let mut gpioa = p.GPIOA.split(&mut rcc.ahb);
let mut pa0 = gpioa.pa5.into_push_pull_output(&mut gpioa.moder, &mut gpioa.otyper);
ここでは GPIOA の情報を取得、gpioa.pa5.into_push_pull_output
で PA5 をプッシュプルの出力動作としています。いずれも変更を加えるものですので、ミュータブルな参照が必要となっています。
loop {
pa0.set_high();
delay.delay_ms(500_u16);
pa0.set_low();
delay.delay_ms(100_u16);
}
こちらがプログラムのメイン部です。動作は見てわかると思いますが、delay_ms
の引数渡すべき型は unsigned でなければいけません。よって末尾に _u16
を付けています。付け忘れると「そんな型に対応した関数なんかねぇよ」って思いっきり怒られます。
生成バイナリの書き込み
プロジェクト内の target/thumbv7em-none-eabihf/debug/
に ELF バイナリがあるはず。こちらを OpenOCD やシリアル書き込みによってターゲットに焼きます。
例えば OpenOCD なら次のコマンドとか。
$ echo target/thumbv7em-none-eabihf/debug/blinky | xargs -I {} openocd -f interface/cmsis-dap.cfg -f target/stm32f3x.cfg -c "adapter_khz 5000;program {};reset;exit"
お疲れ様でした。動いた方はおめでとうございます。あとはドキュメント読んでね!!!!!!(丸投げ)
LED ボヤァもやってみたのでソースコード
チカチカするだけでは野暮ったいと思い疑似 PWM のLEDのボヤァを実装した所、見事にハマりましたので呈示します。ご査収ください。なお動画は上手く取れなかったので取ってません。
#![no_std]
extern crate cortex_m;
extern crate stm32f30x_hal as hal;
use hal::prelude::*;
// Systickを用いたディレイ
use hal::delay::Delay;
const I_MAX: u16 = 30;
fn main() {
let cp = cortex_m::Peripherals::take().unwrap();
let p = hal::stm32f30x::Peripherals::take().unwrap();
let mut flash = p.FLASH.constrain();
let mut rcc = p.RCC.constrain();
let clocks = rcc.cfgr.freeze(&mut flash.acr);
// Systickベースでディレイするオブジェクト
let mut delay = Delay::new(cp.SYST, clocks);
// PA5 for Output
let mut gpioa = p.GPIOA.split(&mut rcc.ahb);
let mut pa0 = gpioa.pa5.into_push_pull_output(&mut gpioa.moder, &mut gpioa.otyper);
// let mut i: u16 = 100;
let mut i: u16 = 0;
loop {
pa0.set_high();
delay_ms(&mut delay, i);
pa0.set_low();
delay_ms(&mut delay, I_MAX - i);
i += 1;
i %= I_MAX;
}
}
// For avoiding lock up on ms == 0.
fn delay_ms(delay: &mut hal::delay::Delay, ms: u16) {
if ms != 0_u16 {
(*delay).delay_ms(ms);
}
}
何を変えたか
delay_ms
なんですが、どうやら引数に0を渡すとロックアップするっぽいです。ですのでコード下部の関数を作って workaroud としました。これを言いたかったがためにLEDボヤァのコードを載せました。以上。
〆
まだ割り込みが出来ていないのでやりたい。