手元にはArmボードとして、STM32F103C8T6やSTM32L476RGがあるが、、まずはSTM32F103C8T6(通称BluePill)を使ってLチカしてみる。
STM32F103C8T6は、ARM Cortex-M3であった。演算コプロ(FPU)付きらしいけど。
Cortex-M3なので、入れるライブラリは、thumbv7m-none-eabi
WIndows環境でRustを動かすには、、どうやらまずVisual Studioを入れる必要があるようだ。C++が必要*1だから?? とりあえず、C++, .Net, Pythonを指定してVisual Studioを入れてみる。
以下の手順は「Interface誌 5月号 C/C++後継モダン言語の研究」でRustでArm用Lチカビルドの紹介があったのでそれに沿って作業
■Windows環境にRust開発ツールを入れる。(Armクロス開発用)
$ ./rustup-init.exe $ /cygdrive/c/Users/<UserName>/.cargo/bin/rustup.exe target add thumbv7em-none-eabi $ /cygdrive/c/Users/<UserName>/.cargo/bin/cargo.exe install cargo-generate $ /cygdrive/c/Users/<UserName>/.cargo/bin/cargo.exe install cargo-binutils $ /cygdrive/c/Users/<UserName>/.cargo/bin/rustup component add llvm-tools-preview
GitHubからcortex-m用サンプルを取得、ビルドしてみるとエラー
$ /cygdrive/c/Users/<UserName>/.cargo/bin/cargo generate --git https://github.com/rust-embedded/cortex-m-quickstart.git Project Name: cortex-m-quickstart Creating project called `cortex-m-quickstart`... Done! New project created C:\cygwin64\home\xxxx\lang\rust\cortex-m-quickstart $ /cygdrive/c/Users/<UserName>/.cargo/bin/cargo build --example hello *略* error[E0463]: can't find crate for `core` | = note: the `thumbv7m-none-eabi` target may not be installed error: aborting due to previous error For more information about this error, try `rustc --explain E0463`. error: could not compile `stable_deref_trait`.
Cortex-M3用のパッケージを入れる
$ /cygdrive/c/Users/<UserName>/.cargo/bin/rustup.exe target add thumbv7m-none-eabi
もう一度ビルドしてみる。バイナリはできた
$ /cygdrive/c/Users/<UserName>/.cargo/bin/cargo build --example hello $ file target/thumbv7m-none-eabi/debug/examples/hello target/thumbv7m-none-eabi/debug/examples/hello: ELF 32-bit LSB executable, ARM, EABI5 version 1 (SYSV), statically linked, with debug_info, not stripped
メモリマップがあっていないので、修正して再ビルド
$ diff memory.x_org memory.x 6,7c6,7 < FLASH : ORIGIN = 0x00000000, LENGTH = 256K < RAM : ORIGIN = 0x20000000, LENGTH = 64K --- > FLASH : ORIGIN = 0x08000000, LENGTH = 64K > RAM : ORIGIN = 0x20000000, LENGTH = 20K
gdb用に変更
$ diff .cargo/config_org .cargo/config 9c9 < # runner = "gdb-multiarch -q -x openocd.gdb" --- > runner = "arm-none-eabi-gdb.exe -q -x openocd.gdb"
hello.rs中の、 debug::exit(...)もコメント
何も考えずに、run を実行するとエラー (事前にopnocdを走らせる必要あり。それにボードも接続してないし)
$ /cygdrive/c/Users/<UserName>/.cargo/bin/cargo run --example hello warning: unused import: `debug` --> examples\hello.rs:9:28 | 9 | use cortex_m_semihosting::{debug, hprintln}; | ^^^^^ | = note: `#[warn(unused_imports)]` on by default Finished dev [unoptimized + debuginfo] target(s) in 0.08s Running `gdb-multiarch -q -x openocd.gdb target\thumbv7m-none-eabi\debug\examples\hello` error: could not execute process `gdb-multiarch -q -x openocd.gdb target\thumbv7m-none-eabi\debug\examples\hello` (never executed)
前回、Windows(Cygwin)環境で、openocd+gdbでデバッグしたメモを再度確認
ST LinkV2(互換品)を使ってOpenOCDと評価ボード(STM32F103C8T6)を接続してみる - chakokuのブログ(rev4)
openocdを起動
directory: /usr/local/openocd-0.10.0 $ ./bin-x64/openocd -f ./scripts/interface/stlink-v2.cfg -f ./scripts/target/stm32f1x.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 : auto-selecting first available session transport "hla_swd". To override u se 'transport select <transport>'. Info : The selected transport took over low-level target control. The results mi ght differ compared to plain JTAG/SWD adapter speed: 1000 kHz adapter_nsrst_delay: 100 none separate Info : Unable to match requested speed 1000 kHz, using 950 kHz Info : Unable to match requested speed 1000 kHz, using 950 kHz Info : clock speed 950 kHz Info : STLINK v2 JTAG v29 API v2 SWIM v7 VID 0x0483 PID 0x3748 Info : using stlink api v2 Info : Target voltage: 3.170428 Info : stm32f1x.cpu: hardware has 6 breakpoints, 4 watchpoints
gdbを起動して接続
dir:/usr/local $ ./GNUToolsARMEmbedded/4.8_2013q4/bin/arm-none-eabi-gdb.exe GNU gdb (GNU Tools for ARM Embedded Processors) 7.6.0.20131129-cvs Copyright (C) 2013 Free Software Foundation, Inc. License GPLv3+: GNU GPL version 3 or later <http://gnu.org/licenses/gpl.html> This is free software: you are free to change and redistribute it. There is NO WARRANTY, to the extent permitted by law. Type "show copying" and "show warranty" for details. This GDB was configured as "--host=i586-mingw32 --target=arm-none-eabi". For bug reporting instructions, please see: <http://www.gnu.org/software/gdb/bugs/>. (gdb) target remote localhost:3333 Remote debugging using localhost:3333 0x00000000 in ?? () (gdb) monitor reset halt target halted due to debug-request, current mode: Thread xPSR: 0x01000000 pc: 0x080002b4 msp: 0x20005000 (gdb) info register r0 0x0 0 r1 0x0 0 r2 0x0 0 r3 0x0 0 r4 0x0 0 r5 0x0 0 r6 0x0 0 r7 0x0 0 r8 0x0 0 r9 0x0 0 r10 0x0 0 r11 0x0 0 r12 0x0 0 sp 0x0 0x0 lr 0x0 0 pc 0x0 0x0 xPSR 0x0 0 (gdb) continue Continuing. Program received signal SIGINT, Interrupt. 0x080009e4 in ?? () (gdb) info register r0 0x0 0 r1 0x0 0 r2 0x0 0 r3 0x1 1 r4 0x0 0 r5 0x0 0 r6 0x0 0 r7 0x20000aa0 536873632 r8 0x0 0 r9 0x0 0 r10 0x0 0 r11 0x0 0 r12 0x0 0 sp 0x20000aa0 0x20000aa0 lr 0x80009e1 134220257 pc 0x80009e4 0x80009e4 xPSR 0x61000000 1627389952
openocdでgdbの接続は確認できたとして、、次はデバッグをやっている。
openocdとgdbを接続してファイルをロードする
$ /usr/local/GNUToolsARMEmbedded/4.8_2013q4/bin/arm-none-eabi-gdb.exe (gdb) !ls hello hello.d hello-9f32306224ddede2 hello-9f32306224ddede2.d (gdb) file hello Reading symbols from C:\cygwin64\home\XXXX\lang\rust\cortex-m-quickstart\target\ thumbv7m-none-eabi\debug\examples\hello...done. (gdb) target extended-remote:3333 Remote debugging using :3333 main () at examples\hello.rs:11 11 #[entry] (gdb) b main Breakpoint 1 at 0x8000470: file examples\hello.rs, line 11. (gdb) run The program being debugged has been started already. Start it from the beginning? (y or n) y Starting program: C:\cygwin64\home\XXXX\lang\rust\cortex-m-quickstart\target\thu mbv7m-none-eabi\debug\examples\hello Note: automatically using hardware breakpoints for read-only addresses. main () at examples\hello.rs:11 11 #[entry] (gdb) l 6 extern crate panic_halt; 7 8 use cortex_m_rt::entry; 9 use cortex_m_semihosting::{debug, hprintln}; 10 11 #[entry] 12 fn main() -> ! { 13 hprintln!("Hello, world!").unwrap(); 14 15 // exit QEMU
実行を継続すると割り込みが発生する。syscallの所。semihostingの整合が取れていないのかも。
(gdb) syscall1 (_nr=1, _arg=536891116) at C:\Users\XXXX\.cargo\registry\src\github.com-1ecc6299db9ec823\cortex-m-se mihosting-0.3.5\src\lib.rs:216 216 () => __syscall(_nr, _arg), (gdb) Program received signal SIGTRAP, Trace/breakpoint trap. 0x08000b98 in __syscall () (gdb)
デバッグ再確認
OpenOCDを起動する
(cd /usr/local/openocd-0.10.0/; ./bin-x64/openocd -f ./scripts/interface/stlink-v2.cfg -f ./scripts/target/stm32f1x.cfg)
gdbのパスを切る
export PATH=/usr/local/GNUToolsARMEmbedded/4.8_2013q4/bin/:$PATH
cargo runでgdbを起動
$ /cygdrive/c/Users/<UserName>/.cargo/bin/cargo run --example hello warning: unused import: `debug` --> examples\hello.rs:9:28 | 9 | use cortex_m_semihosting::{debug, hprintln}; | ^^^^^ | = note: `#[warn(unused_imports)]` on by default Finished dev [unoptimized + debuginfo] target(s) in 0.09s Running `arm-none-eabi-gdb.exe -q -x openocd.gdb target\thumbv7m-none-eabi\ debug\examples\hello` Reading symbols from C:\cygwin64\home\XXXX\lang\rust\cortex-m-quickstart\target\ thumbv7m-none-eabi\debug\examples\hello...done. main () at examples\hello.rs:11 11 #[entry] Breakpoint 1 at 0x80011c8: file C:\Users\XXXX\.cargo\registry\src\github.com-1ec c6299db9ec823\cortex-m-rt-0.6.12\src\lib.rs, line 562. Breakpoint 2 at 0x800138c: file C:\Users\XXXX\.cargo\registry\src\github.com-1ec c6299db9ec823\cortex-m-rt-0.6.12\src\lib.rs, line 552. Breakpoint 3 at 0x8001014: file C:\Users\XXXX\.cargo\registry\src\github.com-1ec c6299db9ec823\panic-halt-0.2.0\src\lib.rs, line 32. Breakpoint 4 at 0x8000470: file examples\hello.rs, line 11. semihosting is enabled Loading section .vector_table, size 0x400 lma 0x8000000 Loading section .text, size 0xfa0 lma 0x8000400 Loading section .rodata, size 0x304 lma 0x80013a0 Start address 0x800117e, load size 5796 Transfer rate: 13 KB/sec, 1932 bytes/write. Note: automatically using hardware breakpoints for read-only addresses. 0x08001180 in Reset () at C:\Users\XXXX\.cargo\registry\src\github.com-1ecc6299db9ec823\cortex-m-rt -0.6.12\src\lib.rs:489 489 pub unsafe extern "C" fn Reset() -> ! { (gdb) l main 6 extern crate panic_halt; 7 8 use cortex_m_rt::entry; 9 use cortex_m_semihosting::{debug, hprintln}; 10 11 #[entry] 12 fn main() -> ! { 13 hprintln!("Hello, world!").unwrap(); 14 15 // exit QEMU (gdb) i b Num Type Disp Enb Address What 1 breakpoint keep y 0x080011c8 in DefaultHandler_ at C:\Users\XXXX\.cargo\registry\src\ github.com-1ecc6299db9ec823\cortex-m-rt-0.6.12\src\lib.rs:562 2 breakpoint keep y 0x0800138c in HardFault_ at C:\Users\XXXX\.cargo\registry\src\ github.com-1ecc6299db9ec823\cortex-m-rt-0.6.12\src\lib.rs:552 3 breakpoint keep y 0x08001014 in rust_begin_unwind at C:\Users\XXXX\.cargo\registry\src\ github.com-1ecc6299db9ec823\panic-halt-0.2.0\src\lib.rs:32 4 breakpoint keep y 0x08000470 in main at examples\hello.rs:11 (gdb) b main Note: breakpoint 4 also set at pc 0x8000470. Breakpoint 5 at 0x8000470: file examples\hello.rs, line 11. (gdb) run The program being debugged has been started already. Start it from the beginning? (y or n) y Starting program: C:\cygwin64\home\XXXX\lang\rust\cortex-m-quickstart\target\thu mbv7m-none-eabi\debug\examples\hello Breakpoint 4, main () at examples\hello.rs:11 11 #[entry] (gdb)
OpenOCD側のWindowにデバッグ出力がなされた
Hello, world!
■参考URL
IDEを使わずに、素でビルド、gdbを使う解説
Blink, the HelloWorld of Hardware -- Chuck's Robotics Notebook
■追記
Lチカするには、GPIOを叩く必要があり、IO用のレジスタを番地指定で操作する必要があるのだが、、Cだとポインタでサクッと書けるが、Rustだとどう書いたらいいのか全く分からず、BluePill用のサンプル集がリリースされているので、以下からもらってきてBluePill専用のサンプルを走らせてみる予定
GitHub - lupyuen/stm32-blue-pill-rust: Rust for STM32 Blue Pill with Visual Studio Code
git clone https://github.com/lupyuen/stm32-blue-pill-rust.git cd stm32-blue-pill-rust/
cargo buildでblinkyをビルドしてみると、エラーが
/cygdrive/c/Users/<UserName>/.cargo/bin/cargo build --example blinky
error[E0557]: feature has been removed --> C:\Users\<UserName>\.cargo\registry\src\github.com-1ecc6299db9ec823\panic-semihosting-0.3.0\src\lib.rs:59:12 | 59 | #![feature(panic_implementation)] | ^^^^^^^^^^^^^^^^^^^^ feature has been removed | = note: subsumed by `#[panic_handler]` error: cannot find attribute `panic_implementation` in this scope --> C:\Users\<UserName>\.cargo\registry\src\github.com-1ecc6299db9ec823\panic-semihosting-0.3.0\src\lib.rs:71:3 | 71 | #[panic_implementation] | ^^^^^^^^^^^^^^^^^^^^ error[E0554]: `#![feature]` may not be used on the stable release channel --> C:\Users\<UserName>\.cargo\registry\src\github.com-1ecc6299db9ec823\panic-semihosting-0.3.0\src\lib.rs:59:1 | 59 | #![feature(panic_implementation)] | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error: aborting due to 3 previous errors
パッケージ関連でエラーがでていてどういう手順が正しい解決策かわからず。。
公式ライブラリから取ってくるソースがビルドエラーになって、gitから取ってきたのをCopyPasteで張り付けた。
panic-semihosting/lib.rs at master · rust-embedded/panic-semihosting · GitHub
815 /cygdrive/c/Users/<UserName>/.cargo/bin/cargo install cargo-edit 816 /cygdrive/c/Users/<UserName>/.cargo/bin/cargo add cortex_m_rtfm
cortex_m_rtfm (RealTime Frame Work)のcrateが解決できず。。
$ /cygdrive/c/Users/<UserName>/.cargo/bin/cargo add cortex_m_rtfm WARN: Added `cortex-m-rtfm` instead of `cortex_m_rtfm` Updating 'https://github.com/rust-lang/crates.io-index' index Adding cortex-m-rtfm v0.5.1 to dependencies <UserName>@DESKTOP-TRNV8F8 ~/lang/rust/stm32-blue-pill-rust $ /cygdrive/c/Users/<UserName>/.cargo/bin/cargo build --example blinky Compiling stm32-blue-pill-rust v0.3.2 (C:\cygwin64\home\<UserName>\lang\rust\stm32-blue-pill-rust) error[E0463]: can't find crate for `cortex_m_rtfm` --> examples\blinky.rs:9:1 | 9 | extern crate cortex_m_rtfm as rtfm; | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ can't find crate error: aborting due to previous error For more information about this error, try `rustc --explain E0463`. error: could not compile `stm32-blue-pill-rust`. To learn more, run the command again with --verbose.
Rustは言語仕様も難しいらしいが、、パッケージ管理上も解決できない旨のエラーが出る。どうやって解決させたらいいのかよくわからず。パッケージ管理ツールを使いこなしてないからか。。
stm32-blue-pill-rustでexampleをbuildしようとしてはまっていたので、そっちはあきらめて、Readme通りに、 cargo check --release を実行。すると、set_low\set_highの関数がdeprecatedなので digital::v2を使え?というエラーが出る。
dir:~/lang/rust/stm32-blue-pill-rust $ cargo check --release *略* Checking stm32-blue-pill-rust v0.3.2 (C:\cygwin64\home\<UserName>\lang\rust\stm32-blue-pill-rust) error: use of deprecated item 'bluepill_hal::prelude::_embedded_hal_digital_OutputPin::set_high': Deprecated because the method s cannot return errors. Users should use the traits in digital::v2. --> src\main.rs:70:13 | 70 | led.set_high(); | ^^^^^^^^ | note: the lint level is defined here --> src\main.rs:3:9 | 3 | #![deny(warnings)] // If the Rust compiler generates a warning, | ^^^^^^^^ = note: `#[deny(deprecated)]` implied by `#[deny(warnings)]` error: use of deprecated item 'bluepill_hal::prelude::_embedded_hal_digital_OutputPin::set_low': Deprecated because the methods cannot return errors. Users should use the traits in digital::v2. --> src\main.rs:77:13 | 77 | led.set_low(); | ^^^^^^^ error: aborting due to 2 previous errors error: could not compile `stm32-blue-pill-rust`. To learn more, run the command again with --verbose.
Rustの言語仕様は複雑としてまぁそっちは勉強する意味ありそうだが、、仕様もどんどん変わって整合が取れないライブラリのエラーも潰しながら実装を進めるってのはどうしたものか。。Rustに燃えている人、または、言語仕様、ライブラリ管理まで熟知している人ならすぐに直せるのだろうけど。。うーーん、(自分のアホさ加減はおいといて)学習曲線のカーブが確かにかなり角度が緩やかすぎて。。
根本原因をつぶすべきだが、、とりあえずwarningを無視するように修正、再度ビルド
file:stm32-blue-pill-rust/src/main.rs
//#![deny(warnings)] // If the Rust compiler generates a warning, // // stop the compilation with an error.
今度は、rust-lldコマンドで引数エラー (no start file... はぁ。。statup がないとかそういうことかも)
$ cargo build --release error: linking with `rust-lld` failed: exit code: 1 | = note: "rust-lld" "-flavor" "gnu" "-L" *略* 4148bc4a9441.rlib" "-nostartfiles" "-Wl,-Tlink.x" "-Bdynamic" = note: rust-lld: error: unknown argument '-nostartfiles' rust-lld: error: unknown argument '-Wl,-Tlink.x'
回避方法が以下にあり
Rust Embedded Working Group
上記ブログの修正案Bに従いconfigを修正、再度ビルド
"-C", "link-arg=-Tlink.x", # CHANGED # "-C", "link-arg=-nostartfiles", # REMOVED
なんとかビルドは通った。。
configのrunnerを修正
runner = "arm-none-eabi-gdb.exe -q -x openocd.gdb"
(cd /usr/local/openocd-0.10.0/; ./bin-x64/openocd -f ./scripts/interface/stlink-v2.cfg -f ./scripts/target/stm32f1x.cfg) # exec another window export PATH=/usr/local/GNUToolsARMEmbedded/4.8_2013q4/bin:$PATH cp ../cortex-m-quickstart/openocd.gdb . cargo run
OpenOCD + GDBの組み合わせでバイナリを転送、Lチカできた。。なんとかコンパイルを通しただけで内容は全く理解できておらず。Rustでは安全なコードを作成するための機構がいろいろ働いていて、適当にコードを組むと通してくれないというのはわかった。
試しに、st-flashでBluePillのflashに焼いてみた。サイズがおかしいのかエラーになった。
$ pwd ~/tech/arm/stm32/stlink $ ./st-flash.exe write ~/lang/rust/stm32-blue-pill-rust/target/thumbv7m-none-eabi/release/stm32-blue-pill-rust 0x08000000 st-flash 1.3.1 2020-04-28T13:03:09 INFO src/common.c: Loading device parameters.... 2020-04-28T13:03:09 INFO src/common.c: Device connected is: F1 Medium-density device, id 0x20036410 2020-04-28T13:03:09 INFO src/common.c: SRAM size: 0x5000 bytes (20 KiB), Flash: 0x10000 bytes (64 KiB) in pages of 1024 bytes 2020-04-28T13:03:09 INFO src/common.c: Attempting to write 173948 (0x2a77c) bytes to stm32 address: 134217728 (0x8000000) 2020-04-28T13:03:09 ERROR src/common.c: addr too high stlink_fwrite_flash() == -1
デバッグ情報等がまずいのか?と思い、stripツールでbinaryを抜き出して再度書き込み実行、coreIDがおかしいとエラー。これは過去にも出くわしているので、、st-flashのconfigを修正すればOKなはず
/usr/local/GNUToolsARMEmbedded/4.8_2013q4/bin/arm-none-eabi-strip.exe stm32-blue-pill-rust -o test.bin $ ./st-flash.exe write ~/lang/rust/stm32-blue-pill-rust/target/thumbv7m-none-eabi/release/text.bin 0x08000000 st-flash 1.3.1 2020-04-28T13:14:59 INFO src/common.c: Loading device parameters.... 2020-04-28T13:14:59 INFO src/common.c: Device connected is: F1 Medium-density device, id 0x20036410 2020-04-28T13:14:59 INFO src/common.c: SRAM size: 0x5000 bytes (20 KiB), Flash: 0x10000 bytes (64 KiB) in pages of 1024 bytes 2020-04-28T13:14:59 INFO src/common.c: Attempting to write 12840 (0x3228) bytes to stm32 address: 134217728 (0x8000000) Flash page at addr: 0x08003000 erased 2020-04-28T13:14:59 INFO src/common.c: Finished erasing 13 pages of 1024 (0x400) bytes 2020-04-28T13:14:59 INFO src/common.c: Starting Flash write for VL/F0/F3 core id 2020-04-28T13:14:59 ERROR src/flash_loader.c: unknown coreid, not sure what flash loader to use, aborting! coreid: 2ba01477, chipid: 410 2020-04-28T13:14:59 WARN src/flash_loader.c: Failed to write flash loader to sram! 2020-04-28T13:14:59 ERROR src/common.c: stlink_flash_loader_init() == -1 stlink_fwrite_flash() == -1
st-flash.exeに再度手パッチを当ててエラー回避、書き込み実施
./st-flash.exe write ~/lang/rust/stm32-blue-pill-rust/target/thumbv7m-none-eabi/release/aho.bin 0x08000000 st-flash 1.3.1 2020-04-28T14:29:09 INFO src/common.c: Loading device parameters.... 2020-04-28T14:29:09 INFO src/common.c: Device connected is: F1 Medium-density device, id 0x20036410 2020-04-28T14:29:09 INFO src/common.c: SRAM size: 0x5000 bytes (20 KiB), Flash: 0x10000 bytes (64 KiB) in pages of 1024 bytes 2020-04-28T14:29:09 INFO src/common.c: Attempting to write 12840 (0x3228) bytes to stm32 address: 134217728 (0x8000000) Flash page at addr: 0x08003000 erased 2020-04-28T14:29:10 INFO src/common.c: Finished erasing 13 pages of 1024 (0x400) bytes 2020-04-28T14:29:10 INFO src/common.c: Starting Flash write for VL/F0/F3 core id 2020-04-28T14:29:10 INFO src/flash_loader.c: Successfully loaded flash loader in sram 12/12 pages written 2020-04-28T14:29:10 INFO src/common.c: Starting verification of write complete 2020-04-28T14:29:10 INFO src/common.c: Flash written and verified! jolly good!
書き込みはできた。電源投入しただけではLED点滅しない。gdbからだと動くがリセットでは動かないので、スタートアップルーチンあたりが何かおかしいように思える。組み込み+Rustはやはり敷居が高い。。
■追記
RustでLチカネタは大量に投稿されていて、あちこちで試されているようなんですが、、他の方々はすんなり動いたのだろうか。一度自分で手を動かさないと他人の試作レポートもよく理解できないので、まずは泥沼に足を突っ込んだわけなんだが。。最終的にはスタンドアローンでは動かず。。
読み直してみたい他人様のレポート
ようこそ Japaric Park へ – GitHub 出張所 – プログラム関係のブログはここに