RustをArduinoで実行するお勉強


Rustのお勉強開始

参考にするサイト

この手のキットを使っていきます。

私は37in1っていうのを買ってたんだけど、放置してていくつかなくしてる気がするのと、売り切れになってたので、予算とかに合わせて買えばよいかと。
wikiに動かすコードのってるので

悲報、参考サイトにアクセスできない。

https://book.avr-rust.com/

このサイトにアクセスしてガイドに従うと良いって上記サイトではかいてあったんだけど、アクセスできへん。
困ったなぁ。

まぁとにかく、サンプルを動かせれば良いのだろう?

https://github.com/avr-rust/blink/blob/master/src/main.rs


サンプルというのはこれ。

#![no_std]
#![no_main]

use ruduino::Pin;
use ruduino::cores::current::{port};

#[no_mangle]
pub extern fn main() {
    port::B5::set_output();

    loop {
        port::B5::set_high();

        ruduino::delay::delay_ms(1000);

        port::B5::set_low();

        ruduino::delay::delay_ms(1000);
    }
}

ruduino…?
rust+duinoってことなんじゃろか。

rustをとりあえずインストール

インストール

ここのサイトが公式で、こっからインストーラーをダウンロード。
WSLの人は

curl --proto '=https' --tlsv1.2 -sSf https://sh.rustup.rs | sh

これで入れられるみたい。WSL2よく知らない。

インストールにこんなのが出たけど、デフォの1を入力してインストール

インストール中…….少し長かった。最後にEnter押してねって表示されたけどスクショ忘れた。すみません。

Rust with AVR supportを入れたい

Rust with AVR supportってやつを入れるといいみたい。
検索しまくって、その結論に至った。
なので入れていく。

ちがうかも。

ここ参考に

$ rustup update
$ rustup toolchain install nightly
$ rustup component add rust-src --toolchain nightly
$ rustup override set nightly
$ rustc -Vv

これを実行していくよ。

rustc -Vv
rustc 1.77.0-nightly (6ae4cfbbb 2024-01-17)
binary: rustc
commit-hash: --------------------------------------
commit-date: 2024-01-17
host: x86_64-pc-windows-msvc
release: 1.77.0-nightly
LLVM version: 17.0.6

なんかいっぱい出てきたよ、ハッシュのところは公開していいかわかんないので伏せたよ。

rustc --print target-spec-json -Z unstable-options --target avr-unknown-gnu-atmega328 > avr-atmega328p.json

これ実行してってことなので実行する。
するとavr-atmega328p.jsonが生成される
ふむふむ…どこに?
私の場合はユーザー名直下にあった。

--target avr-unknown-gnu-atmega328
ですか??
UNO R3って328pじゃないっけ?。


avr-atmega328p.jsonを開いてみるとやっぱり328Pじゃなくて328になってる。

---------
  "cpu": "atmega328"
---------
  "pre-link-args": {
    "gnu-cc": [
      "-mmcu=atmega328"
    ],
    "gnu-lld-cc": [
      "-mmcu=atmega328"
    ]
  },
----------
"llvm-target": "avr-unknown-unknown",

これunknownでいいのかな…?
328は全部328pにしておく。
cpuとpre-linkのところ

{
  "arch": "avr",
  "atomic-cas": false,
  "cpu": "atmega328p",
  "crt-objects-fallback": "false",
  "data-layout": "e-P1-p:16:8-i8:8-i16:8-i32:8-i64:8-f32:8-f64:8-n8-a:8",
  "eh-frame-header": false,
  "exe-suffix": ".elf",
  "is-builtin": true,
  "late-link-args": {
    "gnu-cc": [
      "-lgcc"
    ],
    "gnu-lld-cc": [
      "-lgcc"
    ]
  },
  "linker": "avr-gcc",
  "linker-flavor": "gnu-cc",
  "llvm-target": "avr-unknown-unknown",
  "max-atomic-width": 16,
  "pre-link-args": {
    "gnu-cc": [
      "-mmcu=atmega328p"
    ],
    "gnu-lld-cc": [
      "-mmcu=atmega328p"
    ]
  },
  "relocation-model": "static",
  "target-c-int-width": "16",
  "target-pointer-width": "16"
}

うまく行ってればこれで環境はOKみたい。

サンプルを動かすよ

フォルダ構成から見直すよ

.
├── Cargo.toml
├── src
│   └── main.rs
└── avr-atmega328p.json

こうなってればいいのね?
avr-atmega328p.jsonはさっき作った。
Cargo.tomlってなに。

なるほど、この中にあるやつね。はいはい。
っつーか、JSONもはいってるやんけ。
ダウンロード…

ここまできたらコンパイル


$ export AVR_CPU_FREQUENCY_HZ=16000000
$ cargo build -Z build-std=core --target avr-atmega328p.json --release

この2つを実行するとコンパイルできるみたい。
さて上を実行…

詰まったよ

'export' は、内部コマンドまたは外部コマンド、
操作可能なプログラムまたはバッチ ファイルとして認識されていません。

(°д°)まじか。
最後の最後ので詰まるじゃん…
とりあえずGPTに聞いてみよか。

このエラーメッセージ「'export' は、内部コマンドまたは外部コマンド、操作可能なプログラムまたはバッチ ファイルとして認識されていません。」は、Windowsのコマンドプロンプトやバッチファイル内でUnix系システムのコマンドを使用しようとしたときに発生します。

export はUnixやLinux、macOSなどのUnix系オペレーティングシステムで環境変数を設定するために使用されるコマンドです。Windowsでは、同様の機能は set コマンドを使用して行います。

ほう。setにすればいいんじゃな?

$ set AVR_CPU_FREQUENCY_HZ=16000000
$ cargo build -Z build-std=core --target avr-atmega328p.json --release

こうですかね?

上は行けるけど、下が行けない。
調査します。
error: linker `avr-gcc` not found
|
= note: program not found

そんなことある??
avr-gccがないらしい…?
いやArduinoIDEはいってるからavr-gccっていうのも入ってると思うんだけど…


とりあえずEverythingとかいう神検索ソフトで
C:\Program Files (x86)\Arduino\hardware\tools\avr\bin
C:\Users\UserName\AppData\Local\Arduino15\packages\arduino\tools\avr-gcc\7.3.0-atmel3.6.1-arduino7\bin
どっちかにありそうなことがわかったので環境変数に入れてみた。


できた。

\target\avr-atmega328p\release
みたいなところに.elfがあればおっけー。
今回はblink.elfだね。

.elfを書き込む方法は色々調べてavrdudeからやるみたい。

GPTに聞くよ。


Rustで生成したELFファイルをArduinoに書き込むには、通常、AVRプログラマーやArduino IDEの書き込みツールを使用します。ここでは一般的なステップを説明しますが、具体的な手順は使用しているArduinoのモデルや環境によって異なる場合があります。

必要なツール
AVRDUDE: AVRDUDEはAVRマイクロコントローラ向けのプログラム書き込みツールです。Arduino IDEにはこのツールが含まれているため、Arduino IDEを既にインストールしている場合は、AVRDUDEも利用可能です。

USBケーブル: Arduinoをコンピュータに接続するためのUSBケーブル。

書き込み手順
ArduinoをPCに接続: ArduinoをUSBケーブルを使ってPCに接続します。

コマンドラインからAVRDUDEを実行: 以下のコマンドラインを実行します。このコマンドは、Arduinoのモデルと使用しているポートに応じて変更する必要があります。

avrdude -p [arduino_model] -P [port] -c [programmer] -U flash:w:[your_elf_file].elf:e
[arduino_model]: Arduinoのモデル。例えば、Arduino Unoの場合は m328p。
[port]: Arduinoが接続されているポート。Windowsでは COM3 のようになることが多く、LinuxやmacOSでは /dev/ttyACM0 のようになります。
[programmer]: 使用しているプログラマー。Arduino Unoの場合は arduino。
[your_elf_file]: 書き込むELFファイルのパス。
実行: 上記のコマンドを実行すると、ELFファイルがArduinoに書き込まれます。

注意点
正しいモデルとポートを指定する: ArduinoのモデルとPCに接続されているポートを正確に指定することが重要です。間違ったモデルやポートを指定すると、書き込みが失敗するか、他のデバイスに影響を与える可能性があります。

Arduino IDEとの互換性: Rustで生成したプログラムがArduinoのハードウェアと互換性があることを確認してください。特に、使用しているライブラリや機能がArduinoのハードウェアでサポートされている必要があります。

これらのステップを踏めば、Rustで生成したELFファイルをArduinoに書き込むことができるはずです。もし問題が発生した場合は、エラーメッセージを確認し、必要に応じてArduinoのドキュメントやRustのコミュニティに支援を求めると良いでしょう。

avrdude -p [arduino_model] -P [port] -c [programmer] -U flash:w:[your_elf_file].elf:e
[arduino_model]: Arduinoのモデル。例えば、Arduino Unoの場合は m328p。
[port]: Arduinoが接続されているポート。Windowsでは COM3 のようになることが多く、LinuxやmacOSでは /dev/ttyACM0 のようになります。
[programmer]: 使用しているプログラマー。Arduino Unoの場合は arduino。
[your_elf_file]: 書き込むELFファイルのパス。

これがもし正しいならかなりいい情報を得た。
確かに、

sudo avrdude -p m328p -c atmelice_isp -P usb -U \
flash:w:target/avr-atmega328p/release/blink.elf:e

というコマンドを打ってる人いる。
ってことは
windowsなら

avrdude -p m328p -c arduino -P usb -U [FILEPATH]

というような書き方になるのか?

ってかavrdude helpとかで検索すればいいじゃんね。

avrdude -p m328p -c arduino -P usb -U flash:w:blink.elf:e

バチクソ怖いけどこれを打ってみるよ。

動かん。じゃなくて多分書き込めてない

avrdude -p m328p -c arduino -P usb -U flash:w:blink.elf:e

avrdude.exe: can't open config file "": Invalid argument
avrdude.exe: error reading system wide configuration file ""

ふむ…
elfファイルを直接書き込む記事があんまり出てこないし、hexにするという古い記事もある。
もしかしたらhexにしたら行けるかも。

ここ、USBって指定が良くなかったかも。


avr-objcopy -O ihex -R .eeprom blink.elf blink.hex

これでhexに変換できる。
まじか簡単だ。

ということはこうでしょうか
いやまて、./を忘れてるとかないか?

avrdude -p m328p -c arduino -P usb -U flash:w:./blink.elf:e

avrdude.exe: can't open config file "": Invalid argument
avrdude.exe: error reading system wide configuration file ""

同じや。

じゃあhexを書き込んでみる

ここらへん全部失敗。 最終的にelfでも書き込みできることがわかった。

多分…

avrdude -p m328p -c arduino -P usb -U flash:w:blink.hex:i

いや、こんな書き込み発見


コマンドはArduino IDEの環境設定→ より詳細な情報を表示する:書き込み にチェックを入れてFlashすると Arduino IDEがavrdudeに渡すコマンドが表示できるのでそれを参考にした.


これを参考にしてみよう。
avrdude.confの場所が必要だったかも。

avrdude -C C:\Users\USERNAME\AppData\Local\Arduino15\packages\arduino\tools\avrdude\6.3.0-arduino17/etc/avrdude.conf -v -V -b115200 -p atmega328p -c arduino -P COM7 -U flash:w:blink.elf:e

書き込みできた!

流石にconfの場所を毎回やるのめんどいのでこれ参考に。

以上!

おまけ


ほんとにかけた?書き込めた?ってことでdelayを早くします。

#![no_std]
#![no_main]

use ruduino::Pin;
use ruduino::cores::current::{port};

#[no_mangle]
pub extern fn main() {
    port::B5::set_output();

    loop {
        port::B5::set_high();

        ruduino::delay::delay_ms(100);

        port::B5::set_low();

        ruduino::delay::delay_ms(100);
    }
}

これで書き込みして、点滅が早くなれば、書き込みちゃんとできてて、コンパイルも出来てるはず。。。
頑張ってやってみましょう。ありがとうございました。

この記事が気に入ったらサポートをしてみませんか?