chakokuのブログ(rev4)

テック・コミック・DTM・・・ごくまれにチャリ

WSL上にArm開発環境を構築->ビルドはできるがデバッグが困難

結論:

  • WSL環境でArm用バイナリのビルドは可能(ここまでは予想通り)
  • gdbデバッグする際、OpenOCDとST-Linkに接続するのはデバイス仮想化の影響によるのか正常に動作しない。ワークアラウンドとして、Windows環境でOpenOCDを走らせて、WSLからはポートで接続する
  • st-link tool (st-flash等)も正常に動作しない。ファームを焼くのはOpenOCDのtelnetで行う

詳細:
これまではWindows上にArm開発環境を構築してどうにかこうにかビルドしていたが、、実際はCygwinから使っており、どうも場当たり的でたまたま動いている観が強い。標準インストール手順はLinuxで紹介されていることも多いのだが、VMWare等の仮想環境にUbuntuを入れて作業するのも結構手間だった。幸い、Windows環境にはWSL(Windows Subsystem for Linux)が提供されていて、WIndows環境で下位レイヤーが仮想化されており、軽くUbuntu等を走らせてLinuxのパッケージも使えるとのことで、WSL上にUbuntuを走らせてArm環境をいれてみることにした。

Arm用ビルド環境
developer.arm.comから Arm用クロスコンパイラをDL
https://developer.arm.com/tools-and-software/open-source-software
https://developer.arm.com/tools-and-software/open-source-software/developer-tools/gnu-toolchain/gnu-rm/downloads

Arm用コンパイルはいけそうだが、、WSL環境でOpenOCDはエラーになる

$ openocd  -f stlink-v2.cfg   -f ./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 use 'transport select <transport>'.
Info : The selected transport took over low-level target control. The results might 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
Error: open failed
in procedure 'init'
in procedure 'ocd_bouncer'

st-linkツール類も動作しない。USB経由でst-linkが見えない。デバイス仮想化と、usblibあたりがうまくいっていないのかも。
本来はWSL上のUbuntuで完結させたいけど、デバイスレイヤー仮想化の影響をどう回避したらいいのか詳細わかっておらず。。逃げの手として、物理デバイスを操作するアプリ(OpenOCD)はWIndows環境で走らせて、gdbはWSL上で走らせる手がある。
gdbを起動するとライブラリ(libcurses)がないと言われる

$  /usr/local/gcc-arm-none-eabi-9-2019-q4-major/bin/arm-none-eabi-gdb
/usr/local/gcc-arm-none-eabi-9-2019-q4-major/bin/arm-none-eabi-gdb: error while loading shared libraries: libncurses.so.5: cannot open shared object file: No such file or directory

libcursesを入れる

$ apt-cache search libncurses
libncurses-dev - developer's libraries for ncurses
libncurses5-dev - transitional package for libncurses-dev
libncurses6 - shared libraries for terminal handling
libncursesw5-dev - transitional package for libncurses-dev
libncursesw6 - shared libraries for terminal handling (wide character support)
libtinfo-dev - transitional package for libncurses-dev
libncurses-gst - Ncurses bindings for GNU Smalltalk
libncurses5 - shared libraries for terminal handling (legacy version)
libncursesada-doc - Ada binding to the ncurses text interface library: documentation
libncursesada6.2.20180127.1 - Ada binding to the ncurses text interface library: shared library
libncursesada7-dev - Ada binding to the ncurses text interface library: development
libncursesw5 - shared libraries

$ sudo apt-get install libncurses5

デバッグ環境を動かしてみる。まず、Windows側でOpenOCDを走らせる

 (cd /usr/local/openocd-0.10.0/; ./bin-x64/openocd  -f ./scripts/interface/stlink-v2.cfg -f ./scripts/target/stm32f1x.cfg)

WSLでgdbを走らせる。以下はWSLのUbuntu上でgdbを起動した例。動いた。

$ /usr/local/gcc-arm-none-eabi-9-2019-q4-major/bin/arm-none-eabi-gdb miniblink.elf
GNU gdb (GNU Tools for Arm Embedded Processors 9-2019-q4-major) 8.3.0.20190709-git
Copyright (C) 2019 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=x86_64-linux-gnu --target=arm-none-eabi".
Type "show configuration" for configuration details.
For bug reporting instructions, please see:
<http://www.gnu.org/software/gdb/bugs/>.
Find the GDB manual and other documentation resources online at:
    <http://www.gnu.org/software/gdb/documentation/>.

For help, type "help".
Type "apropos word" to search for commands related to "word"...
Reading symbols from miniblink.elf...

(gdb) target extended-remote:3333
Remote debugging using :3333
reset_handler () at ../../cm3/vector.c:67
67              for (src = &_data_loadaddr, dest = &_data;

(gdb) mon reset halt
target halted due to debug-request, current mode: Thread
xPSR: 0x01000000 pc: 0x08000224 msp: 0x20005000, semihosting

(gdb) load
Loading section .text, size 0x2b0 lma 0x8000000
Start address 0x8000224, load size 688
Transfer rate: 3 KB/sec, 688 bytes/write.

(gdb) b main
Breakpoint 1 at 0x8000150: file miniblink.c, line 37.

(gdb) run
The program being debugged has been started already.
Start it from the beginning? (y or n) y
Starting program: /home/xxxx/stm32/miniblink/miniblink.elf
Note: automatically using hardware breakpoints for read-only addresses.

Breakpoint 1, main () at miniblink.c:37
37              gpio_setup();

(gdb) l
32
33      int
34      main(void) {
35              int i;
36
37              gpio_setup();
38
39              for (;;) {
40                      gpio_clear(GPIOC,GPIO13);       /* LED on */
41                      for (i = 0; i < 1500000; i++)   /* Wait a bit. */
(gdb)

OpenOCDではファームを焼く機能もある。OpenOCDにターミナルソフトから接続すると以下の手順でファームが焼ける

$ telnet localhost 4444
> reset halt
> flash write_image erase ${elf_file_absolute_path}

WSLからでも、telnet localhost 4444でOpenOCDに接続できるので、バッチで操作できればファームを焼くのも可能。


■参考URL
以下のブログのように、wslでopneocdを走らせた人もいるので、、usblibを適切にコンパイルするとうまくいくのかも
OpenOCDをwslでWindows用にクロスコンパイルする - Qiita
st-link support ( usb problem ) · Issue #3803 · microsoft/WSL · GitHub
Programming STM32 on Linux - Olayiwola Ayinde - Medium

■追記
workaroundながらビルドまではOKということで、WSL環境にRustを入れてみる。WSL用のスクリプトが提示されていて、それを実行
https://www.rust-lang.org/tools/install

Windows Subsystem for Linux

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

するとcurgoのビルドでpanicで中断

info: installing component 'cargo'
thread 'main' panicked at 'assertion failed: `(left == right)`
  left: `22`,

https://github.com/rust-lang/rustup/issues/2293
他の人も同じようで、sleep関連で問題が出ているとか?

どこまでやれるかわからないけど、、WSL環境は実際のLinuxとほぼ同じとのことで、、VMware上のUbuntuでrust環境を構築して、出来上がったバイナリ一式をtarで固めてWSLにコピーした。

cd ~
tar cvfz rust.tgz .rustup/  .cargo/

結果、WSLでcargo等は動くようになった。VMware上のUbuntuとWSL上のUbuntuではバージョンが少し違うのでライブラリの整合性とか、かなり怪しい。

cargo install cargo-generate

ビルド途中でエラー発生

   Compiling miniz_oxide v0.3.6
error: failed to run custom build command for `openssl-sys v0.9.55`

Could not find directory of OpenSSL installation, and this `-sys` crate cannot
proceed without this knowledge. If OpenSSL is installed and this crate had
trouble finding it,  you can set the `OPENSSL_DIR` environment variable for the
compilation process.

openssl自体はインストールされている。もう少し読むと、pkg-configでエラーが出ていると判断して追加。

sudo apt install pkg-config

やはりopenssl関連のエラーであった

error: failed to run custom build command for `openssl-sys v0.9.55`

Caused by:
  process didn't exit successfully: 
 `/tmp/cargo-installx4ZcZL/release/build/openssl-sys-f3f76be6d73ab789/build-script-main` (exit code: 101)
--- stdout
cargo:rustc-cfg=const_fn
cargo:rerun-if-env-changed=X86_64_UNKNOWN_LINUX_GNU_OPENSSL_LIB_DIR
X86_64_UNKNOWN_LINUX_GNU_OPENSSL_LIB_DIR unset
cargo:rerun-if-env-changed=OPENSSL_LIB_DIR
OPENSSL_LIB_DIR unset
cargo:rerun-if-env-changed=X86_64_UNKNOWN_LINUX_GNU_OPENSSL_INCLUDE_DIR
X86_64_UNKNOWN_LINUX_GNU_OPENSSL_INCLUDE_DIR unset
cargo:rerun-if-env-changed=OPENSSL_INCLUDE_DIR
OPENSSL_INCLUDE_DIR unset
cargo:rerun-if-env-changed=X86_64_UNKNOWN_LINUX_GNU_OPENSSL_DIR
X86_64_UNKNOWN_LINUX_GNU_OPENSSL_DIR unset
cargo:rerun-if-env-changed=OPENSSL_DIR
OPENSSL_DIR unset

run pkg_config fail: `"pkg-config" "--libs" "--cflags" "openssl"` did not exit successfully: exit code: 1

--- stderr
Package openssl was not found in the pkg-config search path.
Perhaps you should add the directory containing `openssl.pc\'
to the PKG_CONFIG_PATH environment variable
No package \'openssl\' found"
--- stderr
thread 'main' panicked at '

Could not find directory of OpenSSL installation, and this `-sys` crate cannot
proceed without this knowledge. If OpenSSL is installed and this crate had
trouble finding it,  you can set the `OPENSSL_DIR` environment variable for the
compilation process.

Make sure you also have the development packages of openssl installed.
For example, `libssl-dev` on Ubuntu or `openssl-devel` on Fedora.

If you're in a situation where you think the directory *should* be found
automatically, please open a bug at https://github.com/sfackler/rust-openssl
and include information about your system as well as this message.

$HOST = x86_64-unknown-linux-gnu
$TARGET = x86_64-unknown-linux-gnu
openssl-sys = 0.9.55

', /home/xxxx/.cargo/registry/src/github.com-1ecc6299db9ec823/openssl-sys-0.9.55/build/find_normal.rs:155:5
note: run with `RUST_BACKTRACE=1` environment variable to display a backtrace

warning: build failed, waiting for other jobs to finish...
error: failed to compile `cargo-generate v0.5.0`, intermediate artifacts can be found at `/tmp/cargo-installx4ZcZL`

Caused by:
  build failed

pkg-configでエラーが出ているのが原因のようで、これを解決させる必要がある。

$ pkg-config --libs --cflags openssl

Package openssl was not found in the pkg-config search path.
Perhaps you should add the directory containing `openssl.pc'
to the PKG_CONFIG_PATH environment variable
No package 'openssl' found
sudo apt-get install libssl-dev

pkg-configコマンドはエラー解消された

$ pkg-config --libs --cflags openssl
-lssl -lcrypto

再度 cargo-generateをインストール、インストールできた。

cargo install cargo-generate


RustでArm用バイナリをビルドできるように手当実施

rustup target add thumbv7em-none-eabi
rustup target add thumbv7m-none-eabi
cargo install cargo-binutils
rustup component add llvm-tools-preview
$ rustup target list | grep thumbv7
thumbv7em-none-eabi
thumbv7em-none-eabihf
thumbv7m-none-eabi
thumbv7neon-linux-androideabi
thumbv7neon-unknown-linux-gnueabihf

ビルドしてみると、coreのcrateがない??

$ cargo build --example hello
   Compiling stable_deref_trait v1.1.1
   Compiling vcell v0.1.2
   Compiling r0 v0.2.2
   Compiling panic-halt v0.2.0
error[E0463]: can't find crate for `core`
  |
  = note: the `thumbv7m-none-eabi` target may not be installed

error[E0463]: can't find crate for `core`
  |
  = note: the `thumbv7m-none-eabi` target may not be installed

error: aborting due to previous error

再確認すると、target addがエラーを起こしていた

$ rustup target add thumbv7m-none-eabi
info: downloading component 'rust-std' for 'thumbv7m-none-eabi'
info: installing component 'rust-std' for 'thumbv7m-none-eabi'
thread 'main' panicked at 'assertion failed: `(left == right)`
  left: `22`,
 right: `4`', src/libstd/sys/unix/thread.rs:166:21
note: run with `RUST_BACKTRACE=1` environment variable to display a backtrace.
info: rolling back changes

エラー発生までのバックトレースを表示させる

$ export RUST_BACKTRACE=full

$ rustup target add thumbv7m-none-eabi
info: downloading component 'rust-std' for 'thumbv7m-none-eabi'
info: installing component 'rust-std' for 'thumbv7m-none-eabi'
thread 'main' panicked at 'assertion failed: `(left == right)`
  left: `22`,
 right: `4`', src/libstd/sys/unix/thread.rs:166:21
stack backtrace:
   0:     0x7f1c836dbc9c - backtrace::backtrace::libunwind::trace::h65597d255cb1398b
                               at /cargo/registry/src/github.com-1ecc6299db9ec823/backtrace-0.3.40/src/backtrace/libunwind.rs:88
   1:     0x7f1c836dbc9c - backtrace::backtrace::trace_unsynchronized::hd4f479d7150ec4a0
                               at /cargo/registry/src/github.com-1ecc6299db9ec823/backtrace-0.3.40/src/backtrace/mod.rs:66
   2:     0x7f1c836dbc9c - std::sys_common::backtrace::_print_fmt::h015072984a2b172c
                               at src/libstd/sys_common/backtrace.rs:77
   3:     0x7f1c836dbc9c - <std::sys_common::backtrace::_print::DisplayBacktrace as core::fmt::Display>::fmt::h6df05d3335f32194
                               at src/libstd/sys_common/backtrace.rs:61
   4:     0x7f1c833ba81c - core::fmt::write::h1f444f4312eb6c27
                               at src/libcore/fmt/mod.rs:1028
   5:     0x7f1c836db526 - std::io::Write::write_fmt::h8d147888220078ef
                               at src/libstd/io/mod.rs:1412
   6:     0x7f1c836db19e - std::sys_common::backtrace::_print::h8a6df0fa81d6af62
                               at src/libstd/sys_common/backtrace.rs:65
   7:     0x7f1c836db19e - std::sys_common::backtrace::print::h6f05b4733407e509
                               at src/libstd/sys_common/backtrace.rs:50
   8:     0x7f1c836db19e - std::panicking::default_hook::{{closure}}::h0d0a23bd02315dd8
                               at src/libstd/panicking.rs:188
   9:     0x7f1c836da943 - std::panicking::default_hook::h8d15a9aecb4efac6
                               at src/libstd/panicking.rs:205
  10:     0x7f1c836da943 - std::panicking::rust_panic_with_hook::hbe174577402a475d
                               at src/libstd/panicking.rs:464
  11:     0x7f1c836da4be - std::panicking::continue_panic_fmt::h4d855dad868accf3
                               at src/libstd/panicking.rs:373
  12:     0x7f1c836da450 - std::panicking::begin_panic_fmt::ha0f013e3301a9528
                               at src/libstd/panicking.rs:328
  13:     0x7f1c836aae86 - <rustup::diskio::threaded::Threaded as rustup::diskio::Executor>::join::hf33124263a81d2a4
  14:     0x7f1c8369cd40 - rustup::dist::component::package::unpack_without_first_dir::h352b57d236248e9a
  15:     0x7f1c836762f6 - rustup::dist::manifestation::Manifestation::update::h8c800deec8167b5b
  16:     0x7f1c836cc138 - rustup::toolchain::Toolchain::add_component::h9456367278c4c593
  17:     0x7f1c832e7454 - rustup_init::rustup_mode::main::h2c97a39c05d9bf7c
  18:     0x7f1c83323b1c - rustup_init::run_rustup_inner::ha545371fd2dc19a6
  19:     0x7f1c83322d64 - rustup_init::main::hba9a23e308c96901
  20:     0x7f1c832b7a03 - std::rt::lang_start::{{closure}}::h1778d9ce6385bef5
  21:     0x7f1c8332c458 - main
  22:     0x7f1c82d970b3 - __libc_start_main
  23:     0x7f1c832b4029 - <unknown>
info: rolling back changes