Raspberry Pi PicoのWSL+OpenOCDデバッグにVSCodeを使う

- [Raspberry Pi PicoをWSL(Windows Subsystem for Linux)で使う](https://qiita.com/yunkya2/items/e67996301a2d8d2a5609)
- [Raspberry Pi PicoをWSL+OpenOCDでJTAG(SWD)デバッグする](https://qiita.com/yunkya2/items/4e3d89f08b2237ef551f)

の続きです。Raspberry Pi Pico(以下Pico)をWSLのコマンドラインでgdbを使ってデバッグできるようになったので、今度はこれをVisual Studio Codeから使えるようにします。

実は現時点ではまだ不完全な点があって、事前にブレークポイントを置いてそこに止めることはできる一方で、実行中のプログラムを停止させることができていません(コマンドラインでgdbを使う際は普通にCtrl+Cで止まるのに…)。
とは言え、VSCodeのGUI上でのデバッグができると便利なことは確かなので、不完全ではありますが情報として公開したいと思います。

(実行環境のWSLはWSL2を前提としています。ＷSL1の場合はWindows側のIPアドレスを指定している箇所を削除するなどすれば動くと思います)

#  実行前の準備

- 以下のシェルスクリプトを`gdb-pico`というファイル名でパスの通った箇所に置きます。
([ここ](https://qiita.com/yunkya2/items/4e3d89f08b2237ef551f) で書いたものから少しだけ変わっています)

```shell:gdb-pico
#!/bin/sh
killall -q gdb-multiarch
gdb-multiarch -ex "target remote `tail -1 /etc/resolv.conf|awk '{print $2}'`:3333" $*
```

- Pico SDKで動かすプログラムのあるフォルダをVSCodeのRemote WSLでワークスペースとして開き、そのルートに`.vscode`というフォルダを作成して以下のファイル`launch.json`を置きます。
  - (pico-examplesの場合は pico-examples/.vscode/launch.json)

```json:launch.json
{
    "version": "0.2.0",
    "configurations": [
        {
            "name": "(gdb)",
            "type": "cppdbg",
            "request": "launch",
            "targetArchitecture": "arm",
            "program": "${workspaceFolder}/build/${relativeFileDirname}/${fileBasenameNoExtension}.elf",
            "args": [],
            "stopAtEntry": true,
            "cwd": "${workspaceFolder}",
            "environment": [],
            "MIMode": "gdb",
            "miDebuggerPath": "${env:HOME}/bin/gdb-pico",
            "launchCompleteCommand": "exec-continue",
            "setupCommands": [
                {
                    "text": "load ${workspaceFolder}/build/${relativeFileDirname}/${fileBasenameNoExtension}.elf"
                }
            ]
        }
    ]
}
```

# VSCodeでのデバッグ


- WSLのシェルから以下のコマンドを実行しておきます。

```
openocd.exe -f interface/picoprobe.cfg -f target/rp2040.cfg -c 'bindto 0.0.0.0'
```

- VSCodeでデバッグしたいアプリをビルドしておき、そのソースコード (ここではblink/blink.c) を開きます。
- `main()`の最初の行の行番号の左をクリックして、ブレークポイントを置きます(赤い丸が付く)。
- `F5` または `実行(R)`-`デバッグの開始`で、gdbが動いて事前に実行していたopenocdに接続し、ブレークポイントに止まることでデバッグを開始します。

![pico-debug-vscode.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/642667/e21e09a8-41ef-a4f5-06da-f213e4be27c8.png)

- ブレークポイントを置かずに`続行(F5)`すると止められなくなってしまうことだけ注意が必要ですが、その他通常のデバッグ操作は普通にできます。
  - 続行するとgdbがVSCodeの制御を離れて動きっぱなしになってしまうのですが、停止して再度デバッグを開始する際は、`gdb-pico`スクリプトに入れたkillallで削除されるようにしています。


# (おまけ) cmake/make等を行うtasks.json

Getting StartedではVSCodeを使う際はCMake Tools機能拡張を使うように書いてありますが、私は以下のような`tasks.json`を`.vscode`に置いて使っています。

ソースコードを開いて`Ctrl+Shift+B`または`ターミナル`-`ビルド タスクの実行`で以下の内容を実行することができます。

- cmake
    - プロジェクトのルートにbuild/ディレクトリを掘ってcmakeを実行します
- distclean
    - build/ディレクトリを削除します
- make
- make (verbose)
    - 開いているソースコードのアプリをビルドします
- clean
    - ビルドの生成物を削除します
- install
    - ビルドでできた*.uf2ファイルをPicoにインストールします。以下の記事で説明した`pico-install`スクリプトを用意してパスを通しておく必要があります
        - [【小ネタ】WSL利用時のRaspberry Pi Picoへの書き込みをコマンドラインから行う](https://qiita.com/yunkya2/items/2c8bd3293e834de58d39)

```json:tasks.json
{
    "version": "2.0.0",
    "tasks": [
        {
            "label": "make",
            "type": "shell",
            "command": "make -j4",
            "options": {
                "cwd": "${workspaceFolder}/build/${relativeFileDirname}"
            },
            "presentation": {
                "revealProblems": "onProblem"
            },
            "problemMatcher": [
                "$gcc"
            ],
            "group": "build"
        },
        {
            "label": "make (verbose)",
            "type": "shell",
            "command": "make VERBOSE=1",
            "options": {
                "cwd": "${workspaceFolder}/build/${relativeFileDirname}"
            },
            "presentation": {
                "revealProblems": "onProblem"
            },
            "problemMatcher": [
                "$gcc"
            ],
            "group": "build"
        },
        {
            "label": "clean",
            "type": "shell",
            "command": "make clean",
            "options": {
                "cwd": "${workspaceFolder}/build/${relativeFileDirname}"
            },
            "problemMatcher": [],
            "group": "build"
        },
        {
            "label": "install",
            "type": "shell",
            "command": "pico-install",
            "args": [
                "*.uf2"
            ],
            "options": {
                "cwd": "${workspaceFolder}/build/${relativeFileDirname}"
            },
            "problemMatcher": [],
            "group": "build"
        },
        {
            "label": "distclean",
            "type": "shell",
            "command": "rm -rf ${workspaceFolder}/build",
            "problemMatcher": [],
            "group": "build"
        },
        {
            "label": "cmake",
            "type": "shell",
            "command": "mkdir build; (cd build; cmake .. -DCMAKE_BUILD_TYPE=${input:buildType} -DPICO_DEFAULT_BINARY_TYPE=${input:binaryType})",
            "options": {
                "cwd": "${workspaceFolder}"
            },
            "problemMatcher": [],
            "group": "build"
        },
    ],
    "inputs": [
        {
            "type": "pickString",
            "id": "buildType",
            "description": "Build Type",
            "options": [
                "Release",
                "Debug"
            ],
            "default": "Debug"
        },
                {
            "type": "pickString",
            "id": "binaryType",
            "description": "Binary Type",
            "options": [
                "default",
                "no_flash",
                "copy_to_ram",
                "blocked_ram"
            ],
            "default": "default"
        }
    ]
}
```