PlatformIOにデバッガ(picoprobe)を追加する

2023/3/12追記:
platform以下のファイルを修正しなくても、picoprobeが使えるようになる方法を追記しました。
2023/3/28追記:
デバッガ起動時に、停止する関数を指定する方法を追記しました。
2023/4/14修正:
tool-wizio-picoのURL変更に対応してplatform.jsonの内容を修正しました。

## 1. 概要
rp2040用のソフトをPlatformIO上(platform:raspberrypi、framework:arduino)で開発しています。この環境ではデバッガとしてjlinkなどは使えるのですが、picoprobeは使えません。設定を変えれば使えるのではないかと試したところ、以下の手順で、比較的簡単に動作させることができました。

## 2. まずはpicoprobeが使える環境を作る
去年買った[「Raspberry Pi Pico らくらくデバッグ」](https://booth.pm/ja/items/4086225)にPlatformIOとpicoprobeを使ったデバッグ方法が載っていました。これはhttps://github.com/WizIO/wizio-picoからダウンロードしたplatformパッケージ(以降platform)を使用しています。このplatformの設定を参考に、picoprobeを使えるようにしていきます。

## 3. 修正が必要なファイルをピックアップ
C:\Users\\%USERNAME%\\.platformio\platforms以下にあるwizio-picoとraspberrypi以下のファイルを見比べ、以下のファイル修正が必要そうだと見当を付けました。
+ platform.json
+ platform.py
+ boards\\pico.json

## 4. ファイルを修正
２つの環境を比較しながらファイルを修正します。

2023/3/12追記:
これらのファイルを変更しなくてもよい方法を「5. platformio.iniの変更」に追記しました。この方法を採用する場合、以下のファイル変更は不要です。

2023/4/14修正
tool-wizio-picoのURL変更に対応してplatform.jsonの内容を修正しました。またこの変更をgithub上のコードにも反映しました。

### platform.json
```diff
--- orig/platform.json   2023-02-28 19:49:33.174815600 +0900
+++ new/platform.json      2023-03-10 19:54:50.677106700 +0900
@@ -53,6 +53,15 @@
       "optional": true,
       "owner": "platformio",
       "version": "^1.72000.0"
-    }
+    },
+    "tool-wizio-pico": {
+      "type": "uploader",
+      "version": "https://github.com/Wiz-IO/tool-wizio-pico"
+    },
+    "tool-pico-openocd": {
+      "optional": true,
+      "type": "debugger",
+      "version": "https://github.com/Wiz-IO/tool-pico-openocd"
+    }
   }
 }
```
"tool-wizio-pico"のパッケージはデバッグには不要ですが、参考にしたplatform(wizio-pico )に入っており、[「Raspberry Pi Pico らくらくデバッグ」](https://booth.pm/ja/items/4086225)に記載されているように、pioasmが使えるようになるので追加しています。"type"が"uploader"になっていますが、なぜこのようになっているかはわかりません。

### platform.py
```diff
--- orig/platform.py     2023-02-28 19:49:33.175817200 +0900
+++ new/platform.py        2023-03-10 19:54:50.677106700 +0900
@@ -12,11 +12,17 @@
 # See the License for the specific language governing permissions and
 # limitations under the License.

-import platform
-
+import os, platform, copy
 from platformio.public import PlatformBase
+from os.path import join
+from platform import system, machine

-
+def get_system():
+    sys_dir = system() +'_'+ machine()
+    sys_dir = sys_dir.lower()
+    if 'windows' in sys_dir:
+        sys_dir = 'windows'
+    return sys_dir
 class RaspberrypiPlatform(PlatformBase):

     def is_embedded(self):
@@ -58,7 +64,7 @@
         if "tools" not in debug:
             debug["tools"] = {}

-        for link in ("cmsis-dap", "jlink", "raspberrypi-swd"):
+        for link in ("cmsis-dap", "jlink", "raspberrypi-swd", "picoprobe"):
             if link not in upload_protocols or link in debug["tools"]:
                 continue

@@ -81,6 +87,23 @@
                     },
                     "onboard": link in debug.get("onboard_tools", [])
                 }
+            elif link == "picoprobe":
+                openocd_target = debug.get("openocd_target")
+                assert openocd_target, ("Missing target configuration for %s" % board.id)
+                debug["tools"][link] = {
+                    "server": {
+                        "package"    : "tool-pico-openocd",
+                        "executable" : join(get_system(), "picoprobe"), # EXE
+                        "arguments"  : [
+                            "-s", "$PACKAGE_DIR/share/openocd/scripts",
+                            "-f", "interface/%s.cfg" % link,
+                            "-f", "target/%s" % openocd_target
+                        ]
+                    },
+                    "init_cmds"      : [ ],
+                    "onboard"        : link in debug.get("onboard_tools", []),
+                    "default"        : link == debug.get("default_tool"),
+                }
             else:
                 openocd_target = debug.get("openocd_target")
                 assert openocd_target, ("Missing target configuration for %s" % board.id)
@@ -96,6 +119,7 @@
                     }
                 }

+
         board.manifest["debug"] = debug
         return board
```

### boards\\pico.json
```diff
--- orig/boards/pico.json        2023-02-28 19:49:33.132575500 +0900
+++ new/boards/pico.json   2023-03-10 19:54:50.658568400 +0900
@@ -34,6 +34,7 @@
       "cmsis-dap",
       "jlink",
       "raspberrypi-swd",
+      "picoprobe",
       "picotool"
     ]
   },
```
以上でplatformの修正は完了です。

## 5. platformio.iniの変更
次に個別のプロジェクト設定を変更します。
プロジェクトの設定を変更し、デバッガとしてpicoprobeを使うよう指定します。

```ini
[env:pico]
platform = raspberrypi
board = pico
framework = arduino
; 以下の行を追加
debug_tool = picoprobe
```

2023/3/12追記：
以下のようにplatformを指定することにより、platform以下のファイルを変更することなくpicoprobeが使えるようになります。

```ini
[env:pico]
platform = https://github.com/yasuhirok-git/platform-raspberrypi
board = pico
framework = arduino
debug_tool = picoprobe
```
2023/3/28追記:
以下の様にdebug_init_breakを使用し。起動時に停止する関数を指定することができます。
```ini
[env:pico]
platform = https://github.com/yasuhirok-git/platform-raspberrypi
board = pico
framework = arduino
debug_tool = picoprobe
;; 起動時に停止する関数を指定
debug_init_break = tbreak setup
```

参考URL:
https://docs.platformio.org/en/latest/projectconf/sections/env/options/debug/debug_init_break.html

https://docs.platformio.org/en/latest/projectconf/sections/env/options/debug/debug_init_break.html
## 6. 動作確認
メニューバーから「**実行**(en:Run)]→「**デバッグの開始**(en:Start Debugging)」を選ぶと、ビルド、ダウンロードが行われ、以下の画面が表示されます。これでステップ実行や、変数の表示などができるようになります。![picoprobe-debug.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/193997/ad532be2-1a08-2ea0-1d9c-088cd5fa0548.png)