2
2

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

Rustの組み込み系のハンズオンのDiscoveryをやってみます

ひとまず、環境構築からLEDが光るくらいまでを目標にします

では、ドキュメントを読んでいきます
以下は、後で自分自身が振り返るときに便利なことを書いたメモです

不足や誤りなどありましたら、ご容赦ください

どの開発ボードを使うか

Read the newer book, using a micro:bit

と、あり、micro:bitが入手しやすかったため、micro:bitを使うことにしました

今回は以下から、『micro:bit(マイクロビット) v2.2』を購入しました

micro:bit用のドキュメントはこちらがスタートです

このハンズオンで勉強すること

このドキュメントを勉強することで、
まずは基本的な要素である、ボード向けのソースコードの書き方、ビルドの仕方、ボードへの書き込み方、デバッグの仕方がわかるようです

また、ボードの各機能であるデジタル入出力、PWM、ADC、Serial通信、I2C通信、SPI通信についてや、マルチタスクのコンセプトとかを学べるとかなんとか

準備するもの

開発ボードのmicro:bit v2.2と、開発ボードと開発環境のパソコンをつなぐUSBケーブルです

mircro:bitはUSBマイクロB端子です

最近は、USBマイクロB端子が淘汰されてきましたが、この手の開発ボードや安価なボードはいまだUSBマイクロB端子ですね

なんでだろう、安いのかな

各種ツール

rustc -Vでツールチェインのバージョンを確認しておきます

rustc 1.79.0 (129f3b996 2024-06-10)とのことなので、ドキュメントの1.57.0に比べると多少新しいため、もしかしたら、そのままいかないところもあるかもしれませんが、まあ気にせず進めます

そのほか、ドキュメントにあるとおり、あれこれインストールしました


実行したコマンドは以下のような感じです

$ rustup component add llvm-tools
$ cargo install cargo-binutils --vers 0.3.3
$ cargo size --version

そして、以下にしたがって、probe-rsもインストールします

それから、下記のコマンドです

$ cargo install probe-rs-tools --vers 0.24.0
$ cargo embed --version

また、ハンズオン用のソースコードがあるとのことなので、GitHubからコピーしてきました

基本的に、microbitディレクトリのソースコードを使うっぽいですね


開発環境がWindowsなので、以下も実行します

自分の環境にあったarm-none-eabi-gccをインストールします

これをインストールした後は、IDEを再起動しないとarm-none-eabi-gccコマンドが認識されませんでした


PuTTYも必要らしいので、インストールします

micro:bitに電源をつないでみる

パソコンとmicro:bitをつないでみました

なんか音が鳴って驚きました
後、めちゃくちゃ光ります
製造時に書かれていたプログラムがパリピだったようです

では、認識されているか確認するためにprobe-rs listを実行します

$ probe-rs list
The following debug probes were found:
[0]: BBC micro:bit CMSIS-DAP -- 0d28:0204:9906360200052820AFF95D856A2782CB000000006E052820 (CMSIS-DAP)
[1]: CMSIS-DAP v1 -- 0d28:0204:9906360200052820aff95d856a2782cb000000006e052820 (CMSIS-DAP)

なぜか、2つ認識されていますが、いったん見なかったことにします

続いて、ソースコードをビルドしてみます

$ cargo embed --target thumbv7em-none-eabihf

を実行したところ、

    Finished `dev` profile [unoptimized + debuginfo] target(s) in 0.07s
      Config default
      Target E:\github\rust_embedded\microbit\target\thumbv7em-none-eabihf\debug\rtt-check
       Error The following devices were found:
              [0]: BBC micro:bit CMSIS-DAP -- 0d28:0204:9906360200052820AFF95D856A2782CB000000006E052820 (CMSIS-DAP)
             [1]: CMSIS-DAP v1 -- 0d28:0204:9906360200052820aff95d856a2782cb000000006e052820 (CMSIS-DAP)
              Use '--probe VID:PID'
              You can also set the [default.probe] config attribute (in your Embed.toml) to select which probe to use. For usage examples see https://github.com/probe-rs/probe-rs/blob/master/probe-rs-tools/src/bin/probe-rs/cmd/cargo_embed/config/default.toml .

と、怒られました

2つ認識されているため、どちらを使えばいいかわからないらしいですね

Use '--probe VID:PID'と教えてくれているため、そうします

$ cargo embed --target thumbv7em-none-eabihf --probe 
0d28:0204:9906360200052820AFF95D856A2782CB000000006E052820

どこかVID:PIDなのかがわからないため、ひとまずそれっぽいものをまるごとコピペして、実行です

    Finished `dev` profile [unoptimized + debuginfo] target(s) in 0.06s
      Config default
 Terminal
Hello World

おなじみのHello Worldが出たので、よさそうです

開発ボードのMCUについて

micro:bit v2ではNordic nRF52833を使うよと解説してくれています

ここで、今回のチップの基礎的な知識だけでなく、ARMとはなんぞや?みたいな話もしてくれているのは、さすが親切なドキュメントです

用語

以下のような用語が説明されています

  • Peripheral Access Crate (PAC)
  • The Hardware Abstraction Layer (HAL)
  • The Board Support Crate (historically called Board Support Package, or BSP)

HALとBSPは知っていましたが、PACは始めて聞きました

LED Roulette

続いて、ビルド、フラッシュ、デバッグのやり方を実践です


前回と同じく、Embed.tomlのチップのアンコメントします

Embed.toml
[default.general]
chip = "nrf52833_xxAA" # uncomment this line for micro:bit V2
# chip = "nrf51822_xxAA" # uncomment this line for micro:bit V1

[default.reset]
halt_afterwards = true

[default.rtt]
enabled = false

[default.gdb]
enabled = true

クロスコンパイルのターゲット用のライブラリをインストールしておきます
これは一度実行すればOK

# For micro:bit v2
$ rustup target add thumbv7em-none-eabihf

二度目以降は、アップデートの確認が走りました
up to dateは最新という意味だと知った)


ビルドします

# make sure you are in the `src/05-led-roulette` directory
# For micro:bit v2
$ cargo build --features v2 --target thumbv7em-none-eabihf

書きこみます

# For micro:bit v2
$ cargo embed --features v2 --target thumbv7em-none-eabihf

エラーになりました

> cargo embed --features v2 --target thumbv7em-none-eabihf
    Finished `dev` profile [unoptimized + debuginfo] target(s) in 0.10s
      Config default
      Target E:\github\discovery-master\microbit\target\thumbv7em-none-eabihf\debug\led-roulette
       Error The following devices were found:
              [0]: BBC micro:bit CMSIS-DAP -- 0d28:0204:9906360200052820AFF95D856A2782CB000000006E052820 (CMSIS-DAP)
             [1]: CMSIS-DAP v1 -- 0d28:0204:9906360200052820aff95d856a2782cb000000006e052820 (CMSIS-DAP)     
              Use '--probe VID:PID'
              You can also set the [default.probe] config attribute (in your Embed.toml) to select which probe to use. For usage examples see https://github.com/probe-rs/probe-rs/blob/master/probe-rs-tools/src/bin/probe-rs/cmd/cargo_embed/config/default.toml .

デバイスがふたつ認識されているから、困っていますね
--probe VID:PIDオプションをコマンドにつけるか、Embed.tomlに書いてくださいとありますが、今後も--probeをつけるのがめんどうなので、Embed.tomlに書くことにします

Embed.tomlに書くのは以下の通りです
VID、PIDはフラッシュ時のエラー文章を参照しました

[default.probe]
usb_vid = "0d28"
usb_pid = "0204"

そして、実行すると、今度はこうなりました

> cargo embed --features v2 --target thumbv7em-none-eabihf
    Finished `dev` profile [unoptimized + debuginfo] target(s) in 0.09s
      Config default
      Target E:\github\discovery-master\microbit\target\thumbv7em-none-eabihf\debug\led-roulette
      Erasing ✔ [00:00:00] [####################################] 16.00 KiB/16.00 KiB @ 33.13 KiB/s (eta 0s )
  Programming ✔ [00:00:00] [####################################] 16.00 KiB/16.00 KiB @ 17.30 KiB/s (eta 0s )
    Finished in 1.444s
 WARN probe_rs::util::rtt: No RTT header info was present in the ELF file. Does your firmware run RTT?       
    GDB stub listening at 127.0.0.1:1337
During the execution of GDB an error was encountered:
通常、各ソケット アドレスに対してプロトコル、ネットワーク アドレス、またはポートのどれか 1 つのみを使用できます。 (os error 10048)

Caused by:
    通常、各ソケット アドレスに対してプロトコル、ネットワーク アドレス、またはポートのどれか 1 つのみを使用できます。 (os error 10048)
        Done processing config default

127.0.0.1:1337が既に使用済みか何かのようです

コマンドプロンプトで``netstat -a`を実行しみてみると、確かに使われていました

  TCP         127.0.0.1:1337         myPC:0               LISTENING

こちらを参考にして、何が使っているか確かめてみました

$netstat -ano | find "1337"

  TCP         127.0.0.1:1337         0.0.0.0:0              LISTENING       6808

PID6808が使っているらしいです

このままコマンドプロンプトを使っても調べられそうですが、めんどうくさいのでタスクマネージャーを開き、「詳細」タブから6808を探します

image.png

Razer Chromaが使っているらしいです
Razerには心当たりがあるため、このプロセスをkillするのはやめて、ポート番号を変える方向にします


Embed.tomldefault.tomlにhost:portの設定がありました

[default.gdb]
# Whether or not a GDB server should be opened after flashing.
enabled = false
# The connection string in host:port format wher the GDB server will open a socket.
gdb_connection_string = "127.0.0.1:1337"

と、ありましたので、以下のようにしたいと思います
ポート番号は適当です

[default.gdb]
enabled = true
gdb_connection_string = "127.0.0.1:1338"

これでもう一度フラッシュコマンドを実行します

$ cargo embed --features v2 --target thumbv7em-none-eabihf

    Finished `dev` profile [unoptimized + debuginfo] target(s) in 0.08s
      Config default
      Target E:\github\discovery-master\microbit\target\thumbv7em-none-eabihf\debug\led-roulette
      Erasing ✔ [00:00:00] [####################################] 16.00 KiB/16.00 KiB @ 34.23 KiB/s (eta 0s )
  Programming ✔ [00:00:00] [####################################] 16.00 KiB/16.00 KiB @ 19.40 KiB/s (eta 0s )
    Finished in 1.332s
 WARN probe_rs::util::rtt: No RTT header info was present in the ELF file. Does your firmware run RTT?       
    GDB stub listening at 127.0.0.1:1338

よさそうです

Debug

上記のフラッシュコマンドを実行した状態で、別ターミナルを開き、arm-none-eabi-gdbをインストールしたので、以下のコマンドを実行します

# For micro:bit v2
$ arm-none-eabi-gdb target/thumbv7em-none-eabihf/debug/led-roulette

以下が出力されました

GNU gdb (Arm GNU Toolchain 13.3.Rel1 (Build arm-13.24)) 14.2.90.20240526-git
Copyright (C) 2023 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=i686-w64-mingw32 --target=arm-none-eabi".
Type "show configuration" for configuration details.
For bug reporting instructions, please see:
--Type <RET> for more, q to quit, c to continue without paging--c
<https://bugs.linaro.org/>.
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"...
target/thumbv7em-none-eabihf/debug/led-roulette: No such file or directory.
(gdb)

no such file or directoryと言われているため、以下のコマンドを実行し直します
(GDBを抜けるときは、quitを入力します)

arm-none-eabi-gdb ../../target/thumbv7em-none-eabihf/debug/led-roulette

warningが出ていますが、それを無視すると、よさそうです
作業を進めます

> arm-none-eabi-gdb ../../target/thumbv7em-none-eabihf/debug/led-roulette
GNU gdb (Arm GNU Toolchain 13.3.Rel1 (Build arm-13.24)) 14.2.90.20240526-git
Copyright (C) 2023 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=i686-w64-mingw32 --target=arm-none-eabi".
Type "show configuration" for configuration details.
For bug reporting instructions, please see:
--Type <RET> for more, q to quit, c to continue without paging--
<https://bugs.linaro.org/>.
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 ../../target/thumbv7em-none-eabihf/debug/led-roulette...

warning: could not convert 'main' from the host encoding (CP1252) to UTF-32.
This normally should not happen, please file a bug report.
(gdb)

ポート番号を変えたので、接続先のポート番号を変えて、コマンドを入力します

(gdb) target remote :1338
Remote debugging using :1338
0x00000100 in cortex_m::delay::Delay::delay_us (self=0x9e8280c9, us=4291676149)
    at src/delay.rs:57
57                  self.syst.clear_current();
(gdb) 

続いて、break mainです

(gdb) break main
Breakpoint 1 at 0x15c: file src\05-led-roulette\src/main.rs, line 9.
Note: automatically using hardware breakpoints for read-only addresses.

そして、continueをすると、

(gdb) c
Continuing.

Program received signal SIGINT, Interrupt.
led_roulette::__cortex_m_rt_main () at src\05-led-roulette\src/main.rs:11
11      fn main() -> ! {

よさそうですね


breakpointの一覧はinfo breakで表示され、delete <breakpoint-num>で削除できます

(gdb) info break
Num     Type           Disp Enb Address    What
1       breakpoint     keep y   0x0000015c in led_roulette::__cortex_m_rt_main_trampoline at src\05-led-roulette\src/main.rs:9
        breakpoint already hit 1 time
(gdb) delete 1
(gdb) info break
No breakpoints or watchpoints.

次はlayout srcが出てきますが、Windows環境にはないため、飛ばします
break <ブレイクポイントを置きたい行数>でブレイクポイントを貼ります

指示にあるとおり、main.rsの13行目にブレイクポイントを貼ろうとしましたが、どうもずれてしまいます
未使用変数だから、最適化されているのか?

disassemble /mで確認してみると、下記のようになっていました
_y = x;に対応するアセンブリが存在していないようです
最適化か……?

(gdb) disassemble /m
Dump of assembler code for function _ZN12led_roulette18__cortex_m_rt_main17h515d3c049099b5e4E:
10      fn main() -> ! {
=> 0x00000160 <+0>:     sub     sp, #8
   0x00000162 <+2>:     movs    r0, #42 @ 0x2a

11          let _y;
12          let x = 42;
   0x00000164 <+4>:     str     r0, [sp, #0]
   0x00000166 <+6>:     str     r0, [sp, #4]
--Type <RET> for more, q to quit, c to continue without paging-- 

13          _y = x;
14
15          // infinite loop; just so we don't leave this stack frame
16          loop {}
   0x00000168 <+8>:     b.n     0x16a <_ZN12led_roulette18__cortex_m_rt_main17h515d3c049099b5e4E+10>
   0x0000016a <+10>:    b.n     0x16a <_ZN12led_roulette18__cortex_m_rt_main17h515d3c049099b5e4E+10>

--Type <RET> for more, q to quit, c to continue without paging--

でもビルドする際に、unoptimizedと出ています……?

で、よく見てみると、

11          let _y;
12          let x = 42;
   0x00000164 <+4>:     str     r0, [sp, #0]
   0x00000166 <+6>:     str     r0, [sp, #4]

とあって、どうもx_y両方に値がストアされていそうですね

だから、13行目の_y = x;に対応する直接的な処理がないみたい?

ということみたいなので、まあよしとしましょう

後は、stepimonitor resetなどがありました

Light it up

では、実際にLEDを光らせてみます

main.rsを書き換えて、実行したところ、LEDがひとつ光りました

まとめ

ということで、Rust DiscoveryのLEDがひとつ光るまでをやりました

環境構築はめんどうくさいし、つまずくと厄介な作業栄えある第一位だと思いますが、なんとかなってよかったです

もし似たようなところで、つまずいた方がいたら、ご参考になれば幸いです

この後の部分もちょいちょいとやっていきたいと思います
記事にしたほうがよさそうだったら、そうします

以上、ご清聴ありがとうございました

2
2
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
2
2

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?