RustでAVR microcontrollerを使いたい
Rustの環境構築
avr-gcc
https://github.com/osx-cross/homebrew-avr に従ってセットアップを行う
$ brew tap osx-cross/avr
$ brew install avr-gcc
クロスコンパイラ環境の準備
https://github.com/avr-rust/rust-legacy-fork#notes-for-macos に従ってセットアップを行う
sudo mkdir /usr/local/avr-rust && sudo chown ${USER}:admin /usr/local/avr-rust
# Grab the avr-rust sources
git clone https://github.com/avr-rust/rust.git --recursive
# Create a directory to place built files in
mkdir build && cd build
# Generate Makefile using settings suitable for an experimental compiler
../rust/configure \
--enable-debug \
--disable-docs \
--enable-llvm-assertions \
--enable-debug-assertions \
--enable-optimize \
--enable-llvm-release-debuginfo \
--experimental-targets=AVR \
--prefix=/usr/local/avr-rust
# Build the compiler, install it to /usr/local/avr-rust
make
brew install cmake
make install
# Register the toolchain with rustup
# rustup toolchain link avr-toolchain /usr/local/avr-rust
rustup toolchain link avr-toolchain $(realpath $(find . -name 'stage1'))
# Optionally enable the avr toolchain globally
rustup default avr-toolchain
info: default toolchain set to 'avr-toolchain'
info: note that the toolchain 'nightly-aarch64-apple-darwin' is currently in use (directory override for '/Users/denham/Documents/selfmade-rtos/avr-rust')
Malefileの作成にはpython2が必要
下記よりインストールするRust実行バイナリ(.elf)を書き込むためのツールをインストール
brew install avrdude
サンプルコードをビルドする
$ git clone https://github.com/avr-rust/blink.git
$ rustup override set nightly
info: using existing install for 'nightly-aarch64-apple-darwin'
info: override toolchain for '/Users/denham/Documents/selfmade-rtos/avr-rust' set to 'nightly-aarch64-apple-darwin'
nightly-aarch64-apple-darwin unchanged - rustc 1.64.0-nightly (23e21bdd2 2022-07-15)
$ cargo build -Z build-std=core --target avr-atmega328p.json --release
Compiling blink v0.1.0 (/Users/denham/Documents/selfmade-rtos/avr-rust/blink)
Finished release [optimized] target(s) in 0.20s
$ avrdude -patmega328p -carduino -P/dev/tty.usbmodem11101 -b115200 -D -Uflash:w:target/avr-atmega328p/release/blink.elf:e
avrdude: AVR device initialized and ready to accept instructions
Reading | ################################################## | 100% 0.00s
avrdude: Device signature = 0x1e950f (probably m328p)
avrdude: reading input file "target/avr-atmega328p/release/blink.elf"
avrdude: writing flash (930 bytes):
Writing | ################################################## | 100% 0.16s
avrdude: 930 bytes of flash written
avrdude: verifying flash memory against target/avr-atmega328p/release/blink.elf:
Reading | ################################################## | 100% 0.13s
avrdude: 930 bytes of flash verified
avrdude done. Thank you.
環境構築(改)
下記に沿って行う
- nightlyとrust-srcのインストール
$ rustup toolchain install nightly
$ rustup component add rust-src --toolchain nightly
- homebrew-avr のインストール
https://github.com/osx-cross/homebrew-avr からosx-cross/avr tap
をセットアップし、各パッケージをインストールする
$ brew tap osx-cross/avr
$ brew install avr-binutils avr-gcc avrdude
- AVR の実行可能なクレートをコンパイルしてリンクする
cargo build -Z build-std=core --target avr-unknown-gnu-atmega328 --release
-Z build-std=core
オプションでターゲットをAVRに設定しクレートをビルドする
- Rustターゲット仕様のJSONファイルを生成する
rustc --print target-spec-json -Z unstable-options --target avr-unknown-gnu-atmega328 > my-custom-avr-unknown-gnu-atmega328.json
my-custom-avr-unknown-gnu-atmega328.json
が生成される
atmega328以外のマイコンをターゲットに指定したいときは、JSONの以下の項目を次のものに置き換える
"cpu": "atmega328"
→"cpu": "YOUR-AVR-VARIANT-NAME"
"-mmcu=atmega328"
→"-mmcu=YOUR-AVR-VARIANT-NAME"
ターゲットリストは下記のコマンドで確認できる
$ rustc --print target-list
リストにコンパイラ組込みのターゲットがない場合、ターゲットとするシステムに近いコンパイラ組込みターゲットを上記コマンドから取得し、それをカスタムする方法が推奨されている。
参考
例 blinkAVR用プログラムをビルドする
# fetch and prepare the blink crate (only needs to be done once).
$ git clone https://github.com/avr-rust/blink.git
$ cd blink
$ rustup override set nightly
# Configure the 'ruduino' crate with a MCU frequency of 16MHz
$ export AVR_CPU_FREQUENCY_HZ=16000000
# compile the blink crate to an ELF file targeting atmega328p.
$ cargo build -Z build-std=core --target avr-atmega328p.json --release
コンパイル後、
$ file target/avr-atmega328p/release/blink.elf
target/avr-atmega328p/release/blink.elf: ELF 32-bit LSB executable, Atmel AVR 8-bit, version 1 (SYSV), statically linked, with debug_info, not stripped
Arduino Uno 向けにelfファイルをフラッシュする
$ avrdude -patmega328p -carduino -P/dev/tty.usbmodem11301 -b115200 -D -Uflash:w:target/avr-atmega328p/release/blink.elf:e
avrdude: AVR device initialized and ready to accept instructions
Reading | ################################################## | 100% 0.00s
avrdude: Device signature = 0x1e950f (probably m328p)
avrdude: reading input file "target/avr-atmega328p/release/blink.elf"
avrdude: writing flash (930 bytes):
Writing | ################################################## | 100% 0.16s
avrdude: 930 bytes of flash written
avrdude: verifying flash memory against target/avr-atmega328p/release/blink.elf:
Reading | ################################################## | 100% 0.13s
avrdude: 930 bytes of flash verified
avrdude done. Thank you.
AVR atmega328pをビルドターゲットとする場合のテンプレート
curl "https://codeload.github.com/avr-rust/template-bin/tar.gz/master" | tar xvzf -
sed 's/template-bin/$YOUR_CRATE_NAME/g' template-bin-master/Cargo.toml
mv template-bin-master $YOUR_CRATE_NAME
cd $YOUR_CRATE_NAME
rustup override set nightly-2020-12-25
rustup component add rust-src
用途別のクレートリストリポジトリ
can-busのクレート
CAN-BUS-Shield
HAL(avr-hul)でAtmega328P(Arduino Unoボード)を動かす
テンプレートを使う
のcargo install cargo-generate
cargo install ravedude
cargo generate --git https://github.com/Rahix/avr-hal-template.git
# Build and run it on a connected board
# src/main.rs
cargo run
# src/bin/uno-blink.rs
cargo run --bin uno-blink
unoのサンプルコードは下記にまとまっている
nightlyのバージョンは
nightly-2022-07-10
SPI通信
OSの実装
nostd, alloc対応
no_std環境ではBoxもVecも使えない
メモリのヒープ領域の管理をどうするか?
Rustでメモリアロケータを管理するために
core libraryの中ではcore::allocがメモリアロケータに関連する
GlobalAlloc traitを実装し、#[global_allocator]をつけることで、デフォルトアロケータを登録する
linked_list_allocator = "0.10.4"
は1.64.0-nightlyでビルドできなさそう?
Compiling scopeguard v1.1.0
Compiling lock_api v0.4.9
error[E0432]: unresolved import `core::sync::atomic::AtomicUsize`
--> /Users/denham/.cargo/registry/src/github.com-1ecc6299db9ec823/lock_api-0.4.9/src/remutex.rs:19:20
|
19 | sync::atomic::{AtomicUsize, Ordering},
| ^^^^^^^^^^^ no `AtomicUsize` in `sync::atomic`
For more information about this error, try `rustc --explain E0432`.
代わりに
を使う通常、コレクション利用には、グローバルメモリアロケータの実装が必須です (メモリアロケータ参照)。heaplessクレートは、グローバルメモリアロケータがなくても利用できるコレクションです。
これでVecが使える