Open16

RustでAVR microcontrollerを使いたい

0Yu0Yu

クロスコンパイラ環境の準備

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')
0Yu0Yu

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.
0Yu0Yu

環境構築(改)

下記に沿って行う
https://book.avr-rust.com/

  1. nightlyとrust-srcのインストール
$ rustup toolchain install nightly
$ rustup component add rust-src --toolchain nightly
  1. 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
  1. AVR の実行可能なクレートをコンパイルしてリンクする
cargo build -Z build-std=core --target avr-unknown-gnu-atmega328 --release

-Z build-std=core オプションでターゲットをAVRに設定しクレートをビルドする

  1. 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

リストにコンパイラ組込みのターゲットがない場合、ターゲットとするシステムに近いコンパイラ組込みターゲットを上記コマンドから取得し、それをカスタムする方法が推奨されている。
参考
https://tomoyuki-nakabayashi.github.io/embedded-rust-techniques/04-tools/compiler.html#target-specification

例 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をビルドターゲットとする場合のテンプレート

https://book.avr-rust.com/006-new-crate-template-quickstart.html

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
0Yu0Yu

HAL(avr-hul)でAtmega328P(Arduino Unoボード)を動かす

https://github.com/Rahix/avr-hal
テンプレートを使う

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のサンプルコードは下記にまとまっている
https://github.com/Rahix/avr-hal/tree/main/examples/arduino-uno/src/bin

nightlyのバージョンは
nightly-2022-07-10

0Yu0Yu

https://github.com/rust-osdev/linked-list-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`.

代わりに
https://docs.rs/heapless/latest/heapless/struct.Vec.html
を使う

通常、コレクション利用には、グローバルメモリアロケータの実装が必須です (メモリアロケータ参照)。heaplessクレートは、グローバルメモリアロケータがなくても利用できるコレクションです。

https://tomoyuki-nakabayashi.github.io/embedded-rust-techniques/05-library/heapless.html

これでVecが使える