chakokuのブログ(rev4)

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

Pico+TinyGo用のデバッグ環境をOpenOCDで構築

目標:コンパイラ型言語で何かモノを作る時はデバッガがないとやってられないと思い、OpenOCDによるデバッグ環境を構築する。
取り組み:ST-Linkで試す、だめなら、RPi4上でOpenOCDを動かしてSWDで接続する
結果:ST-Linkはターゲット(Pico)と接続できなかった。RPi4上に構築したOpenOCDはターゲットと接続できた
課題:RPi上のGDB+OpenOCDの組み合わせではPico上のプログラムのデバッグができそうだった。一方、tinygo gdbによる起動ではエラーが出てgdbが起動できていない。configが不足しているのは明らかだが、なぜエラーなのか?原因が分からない

取り組み:
よくあるのは、PicoでPicoをデバッグするというやつなのだが、、以前買ったST-Link V2コンパチでデバッグできないかやってみた。

$ ./bin-x64/openocd.exe  -f ./scripts/interface/stlink-v2.cfg  -c "adapter_khz 4000"       -c 'set USE_CORE 0'  -f ./scripts/target/rp2040.cfg                  Open On-Chip Debugger 0.10.0
Licensed under GNU GPL v2
For bug reports, read
        http://openocd.org/doc/doxygen/bugs.html
adapter speed: 4000 kHz
0
./scripts/target/rp2040.cfg:43: Error: invalid command name "dap"
in procedure 'script'
at file "embedded:startup.tcl", line 60
at file "./scripts/target/rp2040.cfg", line 43

適当にrp2040.cfgを取ってきて引数に指定してみたが、エラーになる。RP2040はマルチコアなのだが、ST-LINK V2のファームはマルチコアに対応していないのが原因らしい。ファームを更新すれば動くという記事もあり。
https://electronics.stackexchange.com/questions/592979/programming-rp2040-with-st-link
ファーム更新に失敗してST LINKを壊すのは避けたいので、、RPiにOpenOCDを入れてデバッグする方法を検討する。
GitHub - raspberrypi/openocd
RPi4上でOpenOCDを動かして、SWDで接続してPico上のプログラムをデバッグする方法が以下に記載されている。これによると、OpenOCDをビルドするようだ。。
https://datasheets.raspberrypi.com/pico/getting-started-with-pico.pdf

GPIOとボードの接続は以下

GND (Pin 20)    <-> SWD GND
GPIO24 (Pin 18) <-> SWDIO
GPIO25 (Pin 22) <-> SWCLK

以下のオプションでOpenOCDが動くはず

openocd -f interface/raspberrypi-swd.cfg  -f target/rp2040.cfg

結線せずエラー前提で起動してみる。スクリプトの読み込み段階ではエラーがなく、DAP(Debug Adapter Protocol)で初期化エラーとなる(多分結線していないからだろう)

$  /usr/local/bin/openocd  -f /usr/local/share/openocd/scripts/interface/raspberrypi-swd.cfg -f /usr/local/share/openocd/scripts/target/rp2040.cfg

Open On-Chip Debugger 0.11.0-g228ede4-dirty (2022-12-10-18:01)
Licensed under GNU GPL v2
For bug reports, read
        http://openocd.org/doc/doxygen/bugs.html
adapter speed: 1000 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 : BCM2835 GPIO JTAG/SWD bitbang driver
Info : clock speed 1001 kHz
Info : Read incorrect DLIPDR 00000000 (possibly CTRL/STAT value) when selecting coreid 0
Info : DAP init failed

Info : Read incorrect DLIPDR 00000000 (possibly CTRL/STAT value) when selecting coreid 0

RPi4とPicoをSWDで接続してOpenOCDを起動する。以下の通り、3333番ポートでListenしてますと出ているので、ターゲットとは接続できたのだろう

root@raspberrypi:/usr/local/share/openocd/scripts/target# /usr/local/bin/openocd  -f /usr/local/share/openocd/scripts/interface/raspberrypi-swd.cfg -f /usr/local/share/openocd/scripts/target/rp2040.cfg
Open On-Chip Debugger 0.11.0-g228ede4-dirty (2022-12-10-18:01)
Licensed under GNU GPL v2
For bug reports, read
        http://openocd.org/doc/doxygen/bugs.html
adapter speed: 1000 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 : BCM2835 GPIO JTAG/SWD bitbang driver
Info : clock speed 1001 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

GDBからOpenOCDを呼び出してみる。レジスタは表示できた

$ gdb
GNU gdb (Debian 10.1-1.7) 10.1.90.20210103-git
Copyright (C) 2021 Free Software Foundation, Inc.
License GPLv3+: GNU GPL version 3 or later <http://gnu.org/licenses/gpl.html>

(gdb) target remote localhost:3333
Remote debugging using localhost:3333
warning: No executable has been specified and target does not support
determining executable automatically.  Try using the "file" command.
warning: multi-threaded target stopped without sending a thread-id, using first non-exited thread
0x10001a4c in ?? ()
(gdb) i r
r0             0x1cf99f64          486121316
r1             0x1                 1
r2             0x1                 1
r3             0x7a120             500000
r4             0x7a11d             499997
r5             0x40054010          1074085904
r6             0x1                 1
r7             0x20000b38          536873784
r8             0xffffffff          -1
r9             0xffffffff          -1
r10            0xffffffff          -1
r11            0xffffffff          -1
r12            0x4001801c          1073840156
sp             0x200007f8          0x200007f8
lr             0x10001a45          268442181
pc             0x10001a4c          0x10001a4c
xPSR           0x1000000           16777216
msp            0x200007f8          0x200007f8
psp            0x20001384          0x20001384
primask        0x0                 0
basepri        0x0                 0
faultmask      0x0                 0
control        0x0                 0

(gdb) x/i $pc
=> 0x10001a4c:  ldr     r5, [sp, #4]

今は、[GDB]--->[OpenODC]--->[RPi Pico] の形式で接続しているので、GDBをtinyGo版のGDBに置き換える必要があるのだろう。。多分

と思ったら違っていて、 コマンドプロンプトから tinygo gdb と打ち込むと、PATH上にある、gdbが起動されるようであった。しかし、どうやってプローブと接続指定をするのか不明。自分の環境だと、コンパイルWindows上で、OpenOCDはRPi4上なので、IPとPortを指定してGDBを起動する必要があるのだが。。
解説本を参考にtinygoからGDBを起動しようとするがエラーになる

$ tinygo.exe gdb --target pico
error: no gdb found configured in the target specification (gdb-multiarch, arm-n
one-eabi-gdb)

$ cat /usr/local/tinygo0.26.0.windows-amd64/tinygo/targets/rp2040.json
{
    "inherits": ["cortex-m0plus"],
    "build-tags": ["rp2040", "rp"],
    "flash-1200-bps-reset": "true",
    "flash-method": "msd",
    "serial": "usb",
    "msd-volume-name": "RPI-RP2",
    "msd-firmware-name": "firmware.uf2",
    "binary-format": "uf2",
    "uf2-family-id": "0xe48bff56",
    "rp2040-boot-patch": true,
    "extra-files": [
        "src/device/rp/rp2040.s"
    ],
    "openocd-interface": "picoprobe",
    "openocd-transport": "swd",
    "openocd-target": "rp2040"
}

openocd-interfaceがpicoprobeってのも気になる。tinygo gdb で単にGDBが起動されているだけなら、手動でODBを起動してもOKなのだが。

Gitにソースコードが公開されているので、gdbを指定した時の動きを見てみたい。gdbが見つけられないのか、あるいは、gdbは見つけたが、ターゲットをデバッグできる条件を満たさないのか。。
GitHub - tinygo-org/tinygo: Go compiler for small places. Microcontrollers, WebAssembly (WASM/WASI), and command-line tools. Based on LLVM.

RPi上でtinygoの環境を構築してgdbを起動してみた。gdbが無いとか怒られることなく動いたが、ターゲット制御?でエラーが出ている。

$ tinygo gdb --target pico
GNU gdb (Debian 10.1-1.7) 10.1.90.20210103-git
Copyright (C) 2021 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 "aarch64-linux-gnu".
Type "show configuration" for configuration details.
For bug reporting instructions, please see:
<https://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 /tmp/tinygo4028570371/main...

warning: Section .debug_aranges in /tmp/tinygo4028570371/main has duplicate debug_info_offset 0xee3, ignoring .debug_aranges.
:3333: Connection timed out.
"monitor" command not supported by this target.
You can't do that when your target is `exec'
"monitor" command not supported by this target.
(gdb) l
DW_FORM_rnglistx index pointing outside of .debug_rnglists offset array [in module /tmp/tinygo4028570371/main]
(gdb) list
error: failed to run gdb-multiarch with /tmp/tinygo4028570371/main: signal: aborted