[Raspberry Pi PicoをWSL(Windows Subsystem for Linux)で使う]
(https://qiita.com/yunkya2/items/e67996301a2d8d2a5609)の続きです。WSL上でRaspberry Pi PicoのJTAGデバッグをやってみました。
接続の概要
Raspberry Pi Picoが2枚ある場合は、1枚を**Picoprobe**というアプリでJTAG(SWD)デバッグプローブにすることで、もう1枚のRaspberry Pi Pico上のアプリのデバッグに使うことができます。
具体的なやり方は Getting started with Raspberry Pi Pico の Appendix A: Using Picoprobe に載っているのですが、WSLを利用する場合、WSLからはPicoprobeのつながったUSBが見えないため、以下のような接続になります。
- OpenOCDはWindowsアプリとして動作させ、USBの先のPicoprobeに接続する
- gdbはLinuxアプリとしてWSL上で動作させ、Windows側のOpenOCDにTCP/IPで接続する
OpenOCDのビルド
まず、PicoprobeとつながるWindows側のOpenOCDをビルドします。A.1.2. Windows のやり方に従って、WSLでなくMSYS2を使用します。
こちら (https://github.com/yunkya2/openocd-win64) にMSYS2上でOpenOCDをビルドしてWSL環境用のtarballを作るためのMakefileを用意しました。
また、私の環境でビルドしたバイナリをこちら に置いてありますので、ダウンロードして使っていただくこともできます(動作の保証は致しかねますので自己責任で)。
ビルドもしくはダウンロードしたtarballは、WSL環境側で展開してopenocd-w64/binにパスを通しておきます。bashからopenocd.exeが実行できることを確認します。
$ openocd.exe
Open On-Chip Debugger 0.11.0-rc2+dev-gabbf03b09 (2021-01-30-21:57)
Licensed under GNU GPL v2
For bug reports, read
http://openocd.org/doc/doxygen/bugs.html
embedded:startup.tcl:26: Error: Can't find openocd.cfg
in procedure 'script'
at file "embedded:startup.tcl", line 26
Info : Listening on port 6666 for tcl connections
Info : Listening on port 4444 for telnet connections
Error: Debug Adapter has to be specified, see "adapter driver" command
embedded:startup.tcl:26: Error:
in procedure 'script'
at file "embedded:startup.tcl", line 26
$
Raspberry Pi Pico (デバッグプローブ用)の環境準備
デバッグプローブとなる Raspbberry Pi Pico にpicoprobeをインストールします。
方法は A.2. Build and flash picoprobe にありますが、Raspberry Pi公式でビルド済みのpicoprobeバイナリが用意されていますので、ここ からダウンロードした picoprobe.uf2 を BOOTSELボタンを押しながら起動したRaspbberry Pi Picoにドラッグ&ドロップするだけでOKです。
結線
A.3. Picoprobe Wiring の通りです。
picoprobe自体にUSBシリアル変換の機能がありますので、Raspberry PiのUART同士をつないでやることで、picoprobeを接続したWindows PC側からデバッグターゲットのUARTを見ることができます。
Windows側のドライバインストール
A.4. Install Picoprobe driver (only needed on Windows) の通り…かと思ったのですが、ドキュメント通りにZadig (http://zadig.akeo.ie) からlibusb-win32をインストールしてもOpenOCDがクラッシュしてしまいます。いろいろ試したところ、ここでWinUSBをインストールしたら動作するようになりました(このあたりのドライバの違いが良く分からん…)。
デバッグの実行
WSL側には事前にgdb-multiarchをインストールしておきます。
$ sudo apt install gdb-multiarch
また、デバッグ対象のアプリのビルド時には、5.1. Build "Hello World" debug version にあるように、cmakeに-DCMAKE_BUILD_TYPE=Debugを指定してデバッグ情報が入るようにします。
$ cd ~/pico/pico-examples/
$ rm -rf build
$ mkdir build
$ cd build
$ cmake -DCMAKE_BUILD_TYPE=Debug ..
$ cd hello_world
$ make -j4
この後、WindowsアプリであるOpenOCDを起動して、WSL上で動かすgdbからこれに接続する必要があるのですが、この手順はWSL1とWSL2とで大きく異なります。WSL2はVMのLinuxカーネル上で動作しているため、WSL環境とWindows環境が異なるIPアドレスとして扱われるためです。
WSL1の場合
5.4. Use GDB and OpenOCD to debug Hello World と同じ手順でできます。WSL上から以下のコマンドラインでOpenOCDを実行します。
$ openocd.exe -f interface/picoprobe.cfg -f target/rp2040.cfg
Open On-Chip Debugger 0.11.0-rc2+dev-00014-gabbf03b09-dirty (2021-01-28-13:19)
Licensed under GNU GPL v2
For bug reports, read
http://openocd.org/doc/doxygen/bugs.html
Info : only one transport option; autoselect 'swd'
Warn : Transport "swd" was already selected
adapter speed: 5000 kHz
Info : Hardware thread awareness created
Info : Hardware thread awareness created
Info : RP2040 Flash Bank Command
Info : Listening on port 6666 for tcl connections
Info : Listening on port 4444 for telnet connections
Info : clock speed 5000 kHz
Info : SWD DPIDR 0x0bc12477
Info : SWD DLPIDR 0x00000001
Info : SWD DPIDR 0x0bc12477
Info : SWD DLPIDR 0x10000001
Info : rp2040.core0: hardware has 4 breakpoints, 2 watchpoints
Info : rp2040.core1: hardware has 4 breakpoints, 2 watchpoints
Info : starting gdb server for rp2040.core0 on 3333
Info : Listening on port 3333 for gdb connections
OpenOCDを実行したのとは別のターミナルを開いて、デバッグ対象のELFファイルを指定してgdb-multiarchを実行し、target remoteコマンドでOpenOCDに接続します。
$ gdb-multiarch hello_world.elf
:
(gdb) target remote localhost:3333
loadコマンドでフラッシュにELFファイルをロードし、monitor reset initコマンド実行後、continueコマンドで実行を開始します。
(gdb) load
Loading section .boot2, size 0x100 lma 0x10000000
Loading section .text, size 0x49c8 lma 0x10000100
Loading section .rodata, size 0xd88 lma 0x10004ac8
Loading section .binary_info, size 0x24 lma 0x10005850
Loading section .data, size 0x9ec lma 0x10005874
Start address 0x10000104, load size 25184
Transfer rate: 6 KB/sec, 4197 bytes/write.
(gdb) monitor reset init
target halted due to debug-request, current mode: Thread
xPSR: 0xf1000000 pc: 0x000000ee msp: 0x20041f00
target halted due to debug-request, current mode: Thread
xPSR: 0xf1000000 pc: 0x000000ee msp: 0x20041f00
(gdb) continue
Continuing.
WSL2の場合
以下のコマンドラインでOpenOCDを実行します。bindtoコマンドの実行を追加することで、OpenOCDを実行しているホスト以外からの接続を受け入れるようにします。
$ openocd.exe -f interface/picoprobe.cfg -f target/rp2040.cfg -c 'bindto 0.0.0.0'
初回の接続の場合のみ、以下のようなファイアウォールの警告が出ます。WSL2から接続できるようにするためには、「パブリック ネットワーク」の方にもチェックを入れてアクセスを許可する必要があります。
もしチェックを入れ忘れてダイアログを閉じてしまった場合は、コントロールパネルの「Windows Defenderファイアウォール」→「Windows Defenderファイアウォールを介したアプリまたは機能の許可」を選択し、openocd.exe に対して「プライベート」「パブリック」の両方にチェックが入っている状態にします。
更に、OpenOCDの接続先となる、WSLから見たWindows側のIPアドレスを知る必要があります。/etc/resolv.confでnameserverが指定されているアドレスがそれになるので、事前に調べておきます。
$ cat /etc/resolv.conf
# This file was automatically generated by WSL. To stop automatic generation of this file, add the following entry to /etc/wsl.conf:
# [network]
# generateResolvConf = false
nameserver 172.xx.xx.xx <=== このアドレスを覚えておく
gdbのリモート接続時にはこのアドレスを指定します。
$ gdb-multiarch hello_world.elf
:
(gdb) target remote 172.xx.xx.xx:3333 <=== 先ほど調べたアドレスを指定する
この後の実行手順は同じです。
(追記)WSL2用gdb起動スクリプト
以下のようなスクリプトを用意しておくと、いちいちアドレスを調べる手間が省けて便利です。
# !/bin/sh
gdb-multiarch -ex "target remote `tail -1 /etc/resolv.conf|awk '{print $2}'`:3333" $*
上のスクリプトをgdb-picoという名前で保存しておけば、実行したいELFファイルを指定して
$ gdb-pico hello_world.elf
これだけで、OpenOCDに接続するところまでやってくれます。



