概要
組み込み系でRustを使ってみたいなと思っていろいろやってたらNucleo-f401reで動かせるサンプルがあったので試してみました。ここまでたどり着くのに時間はかかりましたが、これ自体はサクッと動いてくれました。
環境
- Ubuntu 18.04
- rustc 1.38.0
- VSCode 1.38.1
参考
開発環境は以下の3つのサイトを参考に構築しています。
UbuntuにRustをインストールする
UbuntuのVSCodeでRustの開発環境を作る
The Embedded Rust Book
クレートのGitHub
他のボード
Rustで組み込みプログラミングの第一歩、LチカとHello Worldを試してみた
クロスコンパイラ
Nucleo-f401reに搭載されているのはCortex-M4Fなのでそれ用にコンパイルできるthumbv7em-none-eabihf
をインストールしてきます。
$ rustup target add thumbv7em-none-eabihf
info: downloading component 'rust-std' for 'thumbv7em-none-eabihf'
info: installing component 'rust-std' for 'thumbv7em-none-eabihf
こんな感じの状態です。
$ rustup show
Default host: x86_64-unknown-linux-gnu
rustup home: /home/yoshi/.rustup
installed targets for active toolchain
--------------------------------------
thumbv7em-none-eabihf
x86_64-unknown-linux-gnu
active toolchain
----------------
stable-x86_64-unknown-linux-gnu (default)
rustc 1.38.0 (625451e37 2019-09-23)
クローン
$ git clone https://github.com/jkristell/nucleo-f401re.git
ビルド
$ cargo build --example gpio_hal_blinky
Updating crates.io index
Compiling semver-parser v0.7.0
Compiling typenum v1.11.2
Compiling proc-macro2 v0.4.30
Compiling unicode-xid v0.1.0
Compiling rand_core v0.4.2
Compiling syn v0.15.44
Compiling stable_deref_trait v1.1.1
Compiling cortex-m-rt v0.6.10
Compiling vcell v0.1.2
Compiling byteorder v1.3.2
Compiling cortex-m v0.6.1
Compiling r0 v0.2.2
Compiling stm32f4 v0.7.1
Compiling heapless v0.4.4
Compiling nb v0.1.2
Compiling void v1.0.2
Compiling cortex-m-semihosting v0.3.5
Compiling cortex-m v0.5.10
Compiling cast v0.2.2
Compiling cortex-m-rtfm v0.4.3
Compiling aligned v0.2.0
Compiling rand_core v0.3.1
Compiling semver v0.9.0
Compiling volatile-register v0.2.0
Compiling embedded-hal v0.2.3
Compiling rand v0.5.6
Compiling tpa2016d2 v0.2.0
Compiling segment-display v0.1.0
Compiling hd44780-driver v0.3.0
Compiling rustc_version v0.2.3
Compiling hash32 v0.1.0
Compiling quote v0.6.13
Compiling bare-metal v0.2.5
Compiling generic-array v0.12.3
Compiling generic-array v0.11.1
Compiling as-slice v0.1.0
Compiling aligned v0.3.1
Compiling panic-semihosting v0.5.3
Compiling cortex-m-rt-macros v0.1.5
Compiling owned-singleton-macros v0.1.0
Compiling cortex-m-rtfm-macros v0.4.3
Compiling owned-singleton v0.1.0
Compiling stm32f4xx-hal v0.5.0
Compiling nucleo-f401re v0.2.0 (/home/yoshi/rust/nucleo-f401re)
warning: use of deprecated item 'embedded_hal::digital::v1::OutputPin::set_low': Deprecated because the methods cannot return errors. Users should use the traits in digital::v2.
--> examples/gpio_hal_blinky.rs:19:9
|
19 | led.set_low();
| ^^^^^^^
|
= note: `#[warn(deprecated)]` on by default
warning: use of deprecated item 'embedded_hal::digital::v1::OutputPin::set_high': Deprecated because the methods cannot return errors. Users should use the traits in digital::v2.
--> examples/gpio_hal_blinky.rs:31:13
|
31 | led.set_high();
| ^^^^^^^^
warning: use of deprecated item 'embedded_hal::digital::v1::OutputPin::set_low': Deprecated because the methods cannot return errors. Users should use the traits in digital::v2.
--> examples/gpio_hal_blinky.rs:38:13
|
38 | led.set_low();
| ^^^^^^^
Finished dev [unoptimized + debuginfo] target(s) in 43.36s
JTAG
openOCDで接続しておきます。
$ openocd -f discovery.cfg
Open On-Chip Debugger 0.10.0
Licensed under GNU GPL v2
For bug reports, read
http://openocd.org/doc/doxygen/bugs.html
Info : The selected transport took over low-level target control. The results might differ compared to plain JTAG/SWD
adapter speed: 2000 kHz
adapter_nsrst_delay: 100
none separate
srst_only separate srst_nogate srst_open_drain connect_deassert_srst
Info : Unable to match requested speed 2000 kHz, using 1800 kHz
Info : Unable to match requested speed 2000 kHz, using 1800 kHz
Info : clock speed 1800 kHz
Info : STLINK v2 JTAG v29 API v2 SWIM v18 VID 0x0483 PID 0x374B
Info : using stlink api v2
Info : Target voltage: 3.250593
Info : stm32f4x.cpu: hardware has 6 breakpoints, 4 watchpoints
実行
OpenOCDを接続した端末とは別の端末から実行します。arm-none-eabi-gdb
がないと怒られます。
$ cargo run --example gpio_hal_blinky
Finished dev [unoptimized + debuginfo] target(s) in 0.03s
Running `arm-none-eabi-gdb -q -x openocd.gdb target/thumbv7em-none-eabihf/debug/examples/gpio_hal_blinky`
error: could not execute process `arm-none-eabi-gdb -q -x openocd.gdb target/thumbv7em-none-eabihf/debug/examples/gpio_hal_blinky` (never executed)
Caused by:
No such file or directory (os error 2)
修正
.cargo/config
を修正します。デフォルトではarm-none-eabi-gdb
を使用するようになっていますが、Ubuntu18.04はgdb-multiarch
に変更になっているので修正します。
- runner = 'arm-none-eabi-gdb -q -x openocd.gdb'
+ runner = 'gdb-multiarch -q -x openocd.gdb'
再実行
$ cargo run --example gpio_hal_blinky
Finished dev [unoptimized + debuginfo] target(s) in 0.03s
Running `gdb-multiarch -q -x openocd.gdb target/thumbv7em-none-eabihf/debug/examples/gpio_hal_blinky`
Reading symbols from target/thumbv7em-none-eabihf/debug/examples/gpio_hal_blinky...done.
0x00000000 in ?? ()
Breakpoint 1 at 0x80041d4: file /home/yoshi/.cargo/registry/src/github.com-1ecc6299db9ec823/cortex-m-rt-0.6.10/src/lib.rs, line 555.
Function "UserHardFault" not defined.
Breakpoint 2 at 0x80036a2: file /home/yoshi/.cargo/registry/src/github.com-1ecc6299db9ec823/panic-semihosting-0.5.3/src/lib.rs, line 78.
semihosting is enabled
Loading section .vector_table, size 0x194 lma 0x8000000
Loading section .text, size 0x414e lma 0x8000194
Loading section .rodata, size 0x10b8 lma 0x80042f0
Start address 0x8004178, load size 21402
Transfer rate: 2 KB/sec, 5350 bytes/write.
Note: automatically using hardware breakpoints for read-only addresses.
LEDチカチカが無事できました。
感想
nucleo-f401reクレートは他のクレートをインポートしているだけみたいです。ボード依存のクレートといったところでしょうか。チップ依存(チップ=stm32f401)のクレートとしてstm32f4xx-halクレートを使用しています。参考に上げたサイト(Rustで組み込みプログラミングの第一歩、LチカとHello Worldを試してみた)ではボード依存に相当するクレートは使用せず、チップ依存に相当するクレート(stm32f1xx-hal)を使用しています。
記事には書いてないですが、stableでコンパイルできるようになったのは嬉しいけど、クレートの依存関係って意外とめんどくさいかったり、rustcのバージョンが上がるとnightly必要なかったり、使っていないオプション-Z
だったり、まだ過渡的な時期だから仕方ないのでしょうかね。