RustでPro Microのキーボードのファームウェアをつくりたい(車輪の再発明したい)と思ったため、前準備としてLチカさせました。
環境構築
avr-halを使用しますので、こちらを見ながら、環境構築しました。
テンプレート
cargo generate --git https://github.com/Rahix/avr-hal-template.git
こちらでテンプレートのプロジェクトを作成。
ボードはSparkFun ProMicro
を選択してあります。
動かし方
cargo run
でビルド、書き込みを行うのですが、環境によるかもしれませんが、わたしのケースではポートを指定する必要がありました。
ravedudeへポートを情報を渡す必要があるため、cargo run -- -P COM5
という形式で実行しました。
今回はPro Micro本体のみで試しているため、ドライバーでGNDとRSTピンをショートさせて、書き込み待機状態にさせます。
PS E:\github\temp> cargo run -- -P COM5
Finished `dev` profile [optimized + debuginfo] target(s) in 0.22s
Running `ravedude promicro target\avr-atmega32u4\debug\temp.elf -P COM5`
Board SparkFun Pro Micro
Warning: this board cannot reset itself.
Reset the board by quickly pressing the reset button **twice**.
Once reset, press ENTER here:
Programming target\avr-atmega32u4\debug\temp.elf => COM5
Reading 328 bytes for flash from input file temp.elf
Writing 328 bytes to flash
Writing | ################################################## | 100% 0.03 s
Reading | ################################################## | 100% 0.00 s
328 bytes of flash verified
Avrdude done. Thank you.
Programmed target\avr-atmega32u4\debug\temp.elf
ポートを指定しなかった場合は以下のエラーになりました。
ポートを指定しなかった場合のログ
Finished `dev` profile [optimized + debuginfo] target(s) in 0.27s
Running `ravedude promicro target\avr-atmega32u4\debug\temp.elf`
Board SparkFun Pro Micro
Warning: this board cannot reset itself.
Reset the board by quickly pressing the reset button **twice**.
Once reset, press ENTER here:
Error: no matching serial port found, use -P or set RAVEDUDE_PORT in your environment
Caused by: Serial port not found.
error: process didn't exit successfully: `ravedude promicro target\avr-atmega32u4\debug\temp.elf` (exit code: 1)
ポート番号は環境依存な気がするので、お試しする方はご自分の環境のものを調べてください。
Windows11環境であれば、デバイスマネージャーの「ポート(COMとLPT)」を見ながら、ボードをリセットして、出現するポートを指定するといいと思います。
これで、サンプルコードでのLチカに成功しました。
Arduinoを使用しないようにする
テンプレートではarduino_hal
を使用しているため、次にatmega_hal
を使用するケースを試して見ます。
Cargo.tomlを以下のようにモジュールを追加したり、書き換えたりします。
[dependencies]
panic-halt = "0.2.0"
ufmt = "0.2.0"
nb = "1.1.0"
embedded-hal = "1.0"
+ avr-device-macros = "0.7.0"
- [dependencies.arduino-hal]
+ [dependencies.atmega-hal]
git = "https://github.com/rahix/avr-hal"
rev = "3c089795cadbbc7fa83f45958128689fee7ba1e4"
- features = ["arduino-leonardo"]
+ features = ["atmega32u4"]
ソースコード本体は、試行錯誤した結果、以下のようになりました。
#![no_std]
#![no_main]
use atmega_hal::delay::Delay;
use embedded_hal::delay::DelayNs;
type Clock = atmega_hal::clock::MHz16;
use panic_halt as _;
fn delay(ms: u32) {
let mut delay = Delay::<Clock>::new();
delay.delay_ms(ms);
}
#[avr_device_macros::entry]
fn main() -> ! {
let dp = atmega_hal::Peripherals::take().unwrap();
let pins = atmega_hal::pins!(dp);
let mut led = pins.pb0.into_output();
loop {
led.toggle();
delay(500);
}
}
これで同様に書きこんで実行すると、無事Lチカに成功しました。
他のLEDも光らせる
スイッチサイエンスさんで確認できる回路図を確認すると、LED二つはPB0とPD5につながっていることが確認できます。
この情報を元にして、以下のようにすると二つのLEDが交互に光りました。
fn main() -> ! {
let dp = atmega_hal::Peripherals::take().unwrap();
let pins = atmega_hal::pins!(dp);
let mut led1 = pins.pb0.into_output();
let mut led2 = pins.pd5.into_output();
led1.toggle();
loop {
led1.toggle();
led2.toggle();
delay(500);
}
}
終わりに
以上で簡単ですがLチカ作業完了です。
ネットでググっていると、arduino_halベースで書いているケースは多く見られましたが、atmega_halベースのものは少なかったため、今回書いてみました。
続いて、USBデバイス作成に取りかかりたいと思います。