Debugger

probe-rs VS Code 拡張機能 は Microsoft Debug Adapter Protocol を使用して、 VS Code と probe-rs ターゲットの間で対話的なデバッグ体験を 実現します。

この拡張機能は現在プレプロダクション/Alpha 段階であり、機能は 限定的です。現在の状態と機能の詳細については、この セクション を参照してください。

インストール

VS Code で probe-rs 拡張機能をインストールするには、Visual Studio の Extension Marketplace から 利用可能な最新バージョン をインストールしてください。 システム上に probe-rs ツールが見つからない場合、拡張機能はそれらを インストールするよう求めます。

使用方法と設定

ビジュアルツアー

VS Code 用の probe-rs 拡張機能を使用するには、ターゲットプロジェクト用の launch.json エントリを設定する必要があります。

まず、 VSCode デバッグプロセス に慣れておくことをお勧めします。特に、 launch リクエストタイプと attach リクエストタイプの 違い を説明しているセクションを確認してください。

設定の選択肢はユースケースに応じて異なる場合があります。以下の例で 示すとおりです。

  • ターゲットデバイス上で 新しいプロセスを起動 してデバッグセッションを開始する。
  • ターゲットデバイス上の 既存のプロセスにアタッチ して、 デバッグセッションを開始する。
  • デバッグセッションを開始し(上記いずれの形式でも)、 特定の TCP/IP アドレスとポートで動作しているサーバー上の リモートデバッグサーバー プロセスを対象にする。
  • RTT を使用 して、データ(例: ログや println)を VSCode とターゲットアプリケーションの間で転送する

launch.json 内のエントリの多くは省略可能で、それぞれの値は ホバー時のヒントで説明されています。あるいは、利用可能なオプションの 完全な一覧を 付録 で確認できます。値が 制限されている場合、許可される値は VS Code の IntelliSense で確認できます。

最小構成は次のようになります(必須のカスタマイズ箇所には //!MODIFY タグ が付いています)

最小構成でデバッグセッションを開始する

{
"version": "0.2.0",
"configurations": [
{
"preLaunchTask": "${defaultBuildTask}",
"type": "probe-rs-debug",
"request": "launch",
"name": "probe_rs 実行ファイルテスト",
"flashingConfig": {
"flashingEnabled": true,
},
//!MODIFY
"chip": "STM32H745ZITx",
"coreConfigs": [
{
//!MODIFY
"programBinary": "programBinary への相対パスまたは完全修飾パス"
}
]
}
]
}

以下の完全な設定例は、使い始める際の参考として利用できます (自身のプロジェクトとチップに合わせてカスタマイズしてください)。

launch リクエストタイプを使用する

{
"version": "0.2.0",
"configurations": [
{
"type": "probe-rs-debug",
"request": "launch",
"name": "probe_rs 実行ファイル起動の例",
"cwd": "${workspaceFolder}",
//!MODIFY(または削除)
"speed": 24000,
//!MODIFY(または削除)
"probe": "VID:PID:<Serial>",
"runtimeExecutable": "probe-rs",
"runtimeArgs": ["dap-server"],
//!MODIFY
"chip": "STM32H745ZITx",
"flashingConfig": {
"flashingEnabled": true,
"haltAfterReset": false,
"formatOptions": {
//!MODIFY(または削除)。有効な値: 'bin'、'hex'、'elf'(デフォルト)、'idf'
"binaryFormat": "elf"
}
},
"coreConfigs": [
{
"coreIndex": 0,
//!MODIFY
"programBinary": "programBinary への相対パスまたは完全修飾パス",
//!MODIFY
"svdFile": "ターゲットコア用 CMSIS-SVD ファイルへの相対パスまたは完全修飾パス"
}
],
"env": {
//!MODIFY(または削除)
// この変数を設定した場合は、ログファイルの場所について VSCode コンソールログウィンドウを確認してください。
"RUST_LOG": "info"
},
// Info、Debug
"consoleLogLevel": "Console"
}
]
}

attach リクエストタイプを使用する

{
"version": "0.2.0",
"configurations": [
{
"type": "probe-rs-debug",
"request": "attach",
"name": "probe_rs 実行ファイル起動の例",
"cwd": "${workspaceFolder}",
//!MODIFY(または削除)
"speed": 24000,
//!MODIFY
"chip": "STM32H745ZITx",
//!MODIFY(または削除)
"probe": "VID:PID:<Serial>",
"coreConfigs": [
{
"coreIndex": 0,
//!MODIFY
"programBinary": "programBinary への相対パスまたは完全修飾パス",
//!MODIFY
"svdFile": "ターゲットコア用 CMSIS-SVD ファイルへの相対パスまたは完全修飾パス"
}
],
"env": {
//!MODIFY(または削除)
// この変数を設定した場合は、ログファイルの場所について VSCode コンソールログウィンドウを確認してください。
"RUST_LOG": "info"
},
// Info、Debug
"consoleLogLevel": "Console"
}
]
}

スタンドアロンの probe-rs dap-server サーバーに接続する

probe-rs をスタンドアロンサーバーとして起動するには:

probe-rs dap-server --port 50000 # 50000 は利用可能な任意の TCP ポート番号に置き換えてください

次に、以下の launch.json を使用して接続します:

{
"version": "0.2.0",
"configurations": [
{
// 'cargo build' のデフォルトのビルドタスクを設定します
"preLaunchTask": "${defaultBuildTask}",
"type": "probe-rs-debug",
"request": "launch",
"name": "probe_rs サーバーアタッチの例",
//!MODIFY ... VSCode セッションからはリモートでも、probe に対してはローカルなサーバーを指定できます
"server": "127.0.0.1:50001",
"cwd": "${workspaceFolder}",
//!MODIFY(または削除)
"speed": 24000,
//!MODIFY
"chip": "STM32H745ZITx",
//!MODIFY(または削除)
"probe": "VID:PID:<Serial>",
"coreConfigs": [
{
"coreIndex": 0,
//!MODIFY
"programBinary": "programBinary への相対パスまたは完全修飾パス",
//!MODIFY
"svdFile": "ターゲットコア用 CMSIS-SVD ファイルへの相対パスまたは完全修飾パス"
}
],
//!これは有効になりません。環境変数は `probe-rs dap-server` を起動する前に設定してください。
"env": {},
// Info、Debug
"consoleLogLevel": "Console"
}
]
}

データ転送のために RTT を設定する

probe-rs と VS Code 拡張機能は、ターゲット アプリケーションで RTT を使用することをサポートしています。

ターゲットアプリケーションで RTT を使用するための設定方法の詳細については、 このガイドの cargo-embed セクションの手順を参照してください。 VSCode 拡張機能で RTT 出力をキャプチャするには、 アプリケーションの launch.json エントリに追加の項目を指定する必要があります。次の 例を使用し、チャネル情報をアプリケーション内の rtt-target チャネル設定に合わせて変更できます。

{
"version": "0.2.0",
"configurations": [
{
"type": "probe-rs-debug",
"request": "launch",
"name": "probe_rs rtt-target example",
// ... <snip> ...
"coreConfigs": [
{
"coreIndex": 0,
// ... <snip> ...
"rttEnabled": true,
"rttChannelFormats": [
{
"channelNumber": 0,
// RTT データを文字列データとしてフォーマットする
"dataFormat": "String",
// ターゲットの RTT 出力から転送されるデータの各行にホスト側のタイムスタンプを含める
"showTimestamps": true
},
{
"channelNumber": 1,
// データを生のバイナリデータとして扱い、いかなる方法でもフォーマットしない
"dataFormat": "BinaryLE"
}
]
}
]
}
]
}

RTT チャネルを rtt-target でサポートしていることに 加えて、defmt もサポートしています(これは リソース制約のあるデバイス向けの非常に効率的なロギングフレームワークで、 複雑なフォーマットと RUST_LOG のようなロギングをサポートします。)

defmt を使用する場合は、アプリケーションでキャプチャされる内容に基づいて クライアント側を設定でき、launch.json に必要なのは最小限の追加 設定だけです。

{
"version": "0.2.0",
"configurations": [
{
"type": "probe-rs-debug",
"request": "launch",
"name": "probe_rs rtt-target example",
// ... <snip> ...
"coreConfigs": [
{
"coreIndex": 0,
"rttEnabled": true
}
]
}
]
}

注: RTT を低電力モードと併用する場合には、 いくつかの制限事項 があります。embassyrtic のようなフレームワークはデフォルトで 低電力を使用するため、一部のデバイスでは RTT がまったく出力されなくなることがあります。場合によっては、 低電力モードに入る前に RCC DMA クロックを有効にするようデバイスを設定することで、 これを回避できます。

注: defmt RTT を使用する場合は、次の制限事項に注意してください。

  • defmt crate の動作方式により、現在のところ 1 つのアプリケーション内で defmtrtt-target のチャネルを混在させることはできません。
  • defmt crate は、その出力に常にチャネル番号 0 を使用します。
  • defmt crate には、ログ文を ビルド時 に除外する新しいログフィルターが 導入されました。defmt ロギングがデフォルトで error レベルに フィルタされないようにするには、環境変数を .cargo/config ファイルに追加するか、tasks.jsonoptions 設定に追加して(下記を参照)、 ターゲット上で希望するロギングレベルに合わせてください。

DEFMT_LOG.cargo/config.toml に追加する

[env]
DEFMT_LOG = "info"

DEFMT_LOGtasks.json に追加する

// ... <snip> ...
"options": {
"env": {
//!MODIFY: 削除するか、サポートされている DEFMT_LOG オプションのいずれかを使用してください。
"DEFMT_LOG": "info"
}
},
"tasks": [
// ... <snip> ...

ヒント: RTT を使用する場合、データはチャネルごとにターミナルウィンドウへ ストリームされます。アプリケーションで複数の RTT チャネルを使用している場合は、新しい VSCode Terminal tabs 設定の使用を検討するとよいでしょう。

現在動作している機能と既知の制限事項

  • 起動: ターゲットファームウェアを(必要に応じて)フラッシュして、 ターゲット上でデバッグセッションを開始します。
  • アタッチ: デフォルトでは、VSCode が probe-rs dap-server プロセスを管理(開始/停止)し、ターゲット プロセスに対するデバッグセッションを容易にします。ユーザーが probe-rs dap-server をスタンドアロンプロセスとして管理し、その後 TCIP/IP ポートを使用して VSCode から接続することもできます。
  • probe-rs を使用してターゲットに接続
    • 一部のターゲットで connect-under-reset をサポートします。
    • 以下のアーキテクチャでテスト済みです:
      • STM32H745 を使用する Cortex-M7
      • nRF52833_xxAA を使用する Cortex-M4
      • Raspberry PICO を使用する Cortex-M0
      • ESP32-C3 を使用する RISC-V
  • 独自のバイナリでチップをフラッシュ
    • full-chip-eraserestore-unwritten-bytes をサポートします
    • halt-after-reset をサポートします。これにより、 main() 関数にブレークポイントを設定できます。
    • 以下のバイナリタイプのフラッシュをサポートします:
      • bin - 「ターゲットバイナリファイルには、フラッシュの内容が 1:1 で含まれます。」
      • hex - 「ターゲットバイナリファイルは Intel HEX 形式に準拠しています。」
      • elf - 「ターゲットバイナリファイルは ELF 形式に準拠しています。」
      • idf - 「ターゲットバイナリファイルは ESP-IDF bootloader 形式に準拠しています。」
  • ハードウェアブレークポイントの設定、解除、無効化、有効化
    • VSCode の Source view では、ブレークポイントの位置は自動的に、 関数のプロローグとエピローグの間に安全に収まるコード境界へ調整されます。
    • VSCode の Disassembly view では、ブレークポイントの設定もステップ実行も 「命令」レベルで行われます
  • 更新: ステップ実行 によるデバッグ中の実行コードの追跡:
    • Step OverStep IntoStep Out による「文」レベルのステップ実行をサポートします。 ステップ先は自動的に、関数のプロローグとエピローグの間に安全に収まるコード 境界へ調整されます。
    • VSCode の ‘Disassembly view` を開いている間は、すべてのステップ実行が自動的に 「命令」粒度で行われ、関数のプロローグやエピローグ内の命令を含む任意の ターゲット位置へステップ実行できます。
  • 変数ビュー
    • コアレジスタの値と、コード実行中の変化を表示
    • Locals および Statics 変数の値を表示し、コード実行中に値を 更新できます。
      • 以下の Rust データ型について、データ型と値を表示します。
        • &str を含む基本型
        • 列挙型
        • 構造体
        • ポインタ
        • バリアント
        • 配列
        • 共用体
        • OptionResult
        • ユニット型
        • 関数の仮引数
      • TODO: Generics など、追加の型のサポートを追加する
      • VSCode の Set Variable コマンドを使用して変数値を更新します。
      • VSCode の View Binary Data コマンドを使用して、ターゲットデバイス上のメモリを バイナリ編集します。
  • コールスタックビュー
    • チップの単一コアに対する単一スレッドをサポートしますが、現在のスレッド内の 任意のフレームを選択できます
    • VSCode の Dissambly ビューと SetInstructionBreakpoints をサポートします
    • TODO: 複数スレッドをサポートする
    • TODO: 複数コアを持つチップをサポートする
  • ウォッチビュー 選択した変数の値を監視します。
  • RTT - RTT チャネルを設定し、その出力を VSCode Integrated Terminal でキャプチャします
    • VSCode Terminal ウィンドウへのデータログ出力をサポートする RTT チャネル
  • Debug Console の REPL コマンドラインを使用して変数を評価する
  • SVD Peripheral レジスタを参照して監視する

VS Code でのデバッグ拡張機能のビルドとテスト

拡張機能のビルドとデプロイの最新手順については、 リポジトリの README.md ファイル を 参照してください。

実装済み機能のビジュアルガイド

基本事項と RTT データの表示

更新

Set Variable コマンドを使用して、デバッグ中に変数値を更新する

更新

View Binary Data を使用して、ターゲットメモリを表示しバイナリエディットを行う

更新

Disassembly を使用して、ターゲット上で実行されるアセンブリコードを確認し、このビューで命令ブレークポイントを設定する

更新

CMSIS-SVD 定義を使用して、デバイスのペリフェラルレジスタを参照・監視する

更新

付録: サポートされているすべての設定オプション

launch.json で利用できるこれらのオプションは、 probe-rs library の設定オプションに基づいており、VSCode の要件に適合するよう、名前が camelCase に変換されています。launch または attach 構成でサポートされるオプションには若干の違いがあり、その内容は以下に 示されています。詳細については、 公式の MS DAP ドキュメント の「Launching and Attaching」セクションを参照してください。

Launch: サポートされている設定オプション

```json
"launch": {
"required": [
"chip",
"coreConfigs"
],
"properties": {
"server": {
"type": "string",
"description": "必要に応じて、IP とポート上の既存の `probe-rs dap-server` セッションに接続します。例: '127.0.0.1:50000'",
"default": "127.0.0.1:50000"
},
"logFile": {
"type": "string",
"description": "ログファイルへのパスです。このオプションは、`server` または `runtimeArgs` のいずれかが指定されている場合は無視されます。保存場所が指定されていない場合の動作は、`--log-to-folder\" に依存します"
},
"logToFolder": {
"type": "boolean",
"description": "デフォルトのフォルダーへのログ出力を有効にします。このオプションは、`logFile` または `runtimeArgs` のいずれかが指定されている場合は無視されます。`"
},
"consoleLogLevel": {
"type": "string",
"description": "コンソールに出力されるログ情報のレベルです。これは `env` プロパティで定義された RUST_LOG には影響しません。",
"enum": [
"Console",
"Info",
"Debug"
],
"enumDescriptions": [
"コンソールには、エラーメッセージとプロセスステータスメッセージのみが含まれます。",
"コンソールログには、拡張機能とデバッグアダプター間のやり取りに関する高レベルの情報も含まれます。",
"コンソールログには、拡張機能とデバッグアダプター間のやり取りに関する詳細情報も含まれます。"
],
"default": "Console"
},
"runtimeExecutable": {
"type": "string",
"description": "Probe-rs デバッガー実行ファイルへの、OS が解決可能なパスです。",
"default": "probe-rs"
},
"runtimeArgs": {
"type": "array",
"items": {
"type": "string"
},
"description": "Probe-rs デバッガー実行ファイルの起動引数として渡す引数の文字列配列です。",
"default": [
"dap-server"
]
},
"env": {
"additionalProperties": {
"type": "string"
},
"default": {},
"description": "キーと値のペアとして定義される環境変数です。'key' は環境変数名で、'value' はその環境変数の値です。",
"type": "object"
},
"cwd": {
"type": "string",
"description": "デバッガーの作業ディレクトリです。通常は RUST クレートのルートです",
"default": "${workspaceFolder}"
},
"probe": {
"type": "string",
"description": "リスト内の特定のプローブを選択するには、このフラグを使用します。同じ VID:PID を持つプローブが複数ある場合は、'--probe VID:PID' または '--probe VID:PID:Serial' を使用してください。"
},
"chip": {
"type": "string",
"description": "`probe-rs chip list` を実行して報告されるサポート対象チップの一覧から、適切なチップを指定してください。"
},
"chipDescriptionPath": {
"type": "string",
"description": "ファイルからカスタムターゲットチップを追加するには、このオプションを使用します。"
},
"connectUnderReset": {
"type": "boolean",
"description": "このオプションを指定すると、アタッチ操作中にターゲットのリセットピンがハイのまま保持されます。",
"default": false
},
"speed": {
"type": "number",
"description": "プロトコル速度を kHz 単位で指定します。"
},
"wireProtocol": {
"type": "string",
"description": "使用する正しいワイヤプロトコルです。",
"enum": [
"Swd",
"Jtag"
],
"enumDescriptions": [
"Serial Wire Debug (SWD) プロトコルを使用します。",
"Joint Test Action Group (JTAG) プロトコルを使用します。"
]
},
"allowEraseAll": {
"type": "boolean",
"description": "セッションでチップのすべてのメモリを消去したり、工場出荷時のデフォルトにリセットしたりできるようにします。",
"default": false
},
"flashingConfig": {
"type": "object",
"additionalProperties": false,
"description": "これらのオプションは、1 つ以上の `program_binary` ファイルをターゲットメモリにフラッシュする際に適用されます。",
"properties": {
"flashingEnabled": {
"type": "boolean",
"description": "デバッグ前にターゲットを書き込みます。",
"default": false
},
"haltAfterReset": {
"type": "boolean",
"description": "リセット後にターゲット上のすべてのコアを停止します。",
"default": false
},
"fullChipErase": {
"type": "boolean",
"description": "ページ単位の消去ではなく、チップ全体を消去します。",
"default": false
},
"restoreUnwrittenBytes": {
"type": "boolean",
"description": "ELF から再書き込みされない消去済みバイトを復元します。",
"default": false
},
"formatOptions": {
"type": "object",
"additionalProperties": false,
"properties": {
"binaryFormat": {
"type": "string",
"description": "ターゲットバイナリの書き込みに probe-rs が使用する、サポート対象のバイナリ形式のいずれかです。",
"enum": [
"bin",
"hex",
"elf",
"idf"
],
"enumDescriptions": [
"ターゲットバイナリファイルには、フラッシュの内容そのものが含まれます。",
"ターゲットバイナリファイルは [Intel HEX](https://en.wikipedia.org/wiki/Intel_HEX) 形式に準拠しています。",
"ターゲットバイナリファイルは [ELF](https://en.wikipedia.org/wiki/Executable_and_Linkable_Format) 形式に準拠しています。",
"ターゲットバイナリファイルは [ESP-IDF bootloader](https://docs.espressif.com/projects/esp-idf/en/latest/esp32/api-reference/system/app_image_format.html#app-image-structures) 形式に準拠しています"
],
"default": "elf"
},
"baseAddress": {
"type": "number",
"description": "バイナリが書き込まれるメモリ上のアドレスです。"
},
"skip": {
"type": "number",
"description": "バイナリファイルの先頭でスキップするバイト数です。"
},
"idf_bootloader": {
"type": "string",
"description": "ESP-IDF bootloader へのパス(`cwd` からの相対パス、または絶対パス)です。"
},
"idf_partition_table": {
"type": "string",
"description": "ESP-IDF パーティションテーブルへのパス(`cwd` からの相対パス、または絶対パス)です。"
}
}
}
}
},
"coreConfigs": {
"type": "array",
"description": "各 MCU コアには必須の `programBinary` があり、それに加えていくつかのオプションプロパティがあります。",
"items": {
"type": "object",
"additionalProperties": false,
"required": [
"programBinary"
],
"properties": {
"coreIndex": {
"type": "number",
"description": "このセッションにおける MCU コアの 0 始まりのインデックスです",
"default": 0
},
"programBinary": {
"type": "string",
"description": "ターゲットファームウェア用バイナリへのパス(`cwd` からの相対パス、または絶対パス)です"
},
"svdFile": {
"type": "string",
"description": "ターゲットコア用 CMSIS-SVD ファイルへのパス(`cwd` からの相対パス、または絶対パス)です"
},
"rttEnabled": {
"type": "boolean",
"description": "true の場合、デバッガーはターゲット上の各アクティブチャネルに対して RTT Terminal タブを開きます。",
"default": false
},
"rttChannelFormats": {
"type": "array",
"description": "RTT チャネル設定です。一覧にないアクティブチャネルは、`dataFormat=String' および 'showTimestamps=true'` で設定されます。",
"items": {
"type": "object",
"required": [
"channelNumber"
],
"properties": {
"channelNumber": {
"type": "number",
"description": "このデータ形式が適用されるチャネル番号です。"
},
"dataFormat": {
"type": "string",
"description": "RTT チャネルでサポートされるデータ形式のいずれかです。",
"enum": [
"String",
"BinaryLE",
"Defmt"
],
"enumDescriptions": [
"String(テキスト)形式。",
"Binary Little Endian 形式。",
"defmt(参照: https://defmt.ferrous-systems.com)。"
],
"default": "String"
},
"mode": {
"type": "string",
"description": "RTT 動作モードです。",
"enum": [
"NoBlockSkip",
"NoBlockTrim",
"BlockIfFull"
],
"enumDescriptions": [
"ターゲットは、データが完全に収まる場合にのみチャネルにデータを追加し、そうでない場合はそのデータをスキップします。",
"ターゲットは、ブロックせずに可能な限り多くのデータをチャネルに追加します。",
"ターゲットは、データを追加するのに十分な空き領域がチャネルにできるまでブロックします。"
]
},
"showTimestamps": {
"type": "boolean",
"description": "`dataFormat=String` の RTT 出力にタイムスタンプを含めることを有効にします。"
},
"showLocation": {
"type": "boolean",
"description": "`dataFormat=Defmt` の RTT 出力に defmt の位置情報を含めることを有効にします。"
},
"logFormat": {
"type": "string",
"description": "defmt ログのデコードに使用するデフォルトのフォーマット文字列です。"
}
}
}
}
}
}
}
}
}

Attach: サポートされている設定オプション。

"attach": {
"required": [
"chip",
"coreConfigs"
],
"properties": {
"server": {
"type": "string",
"description": "必要に応じて、IP とポート上の既存の `probe-rs dap-server` セッションに接続できます。例: '127.0.0.1:50000'",
"default": "127.0.0.1:50000"
},
"logFile": {
"type": "string",
"description": "ログファイルへのパスです。`server` または `runtimeArgs` のいずれかが指定されている場合、このオプションは無視されます。場所が指定されていない場合の動作は `--log-to-folder"
},
"logToFolder": {
"type": "boolean",
"description": "デフォルトのフォルダーへのログ出力を有効にします。`logFile` または `runtimeArgs` のいずれかが指定されている場合、このオプションは無視されます.`"
},
"consoleLogLevel": {
"type": "string",
"description": "コンソールに出力されるログ情報のレベルです。これは `env` プロパティで定義された RUST_LOG には影響しません。",
"enum": [
"Console",
"Info",
"Debug"
],
"enumDescriptions": [
"コンソールにはエラーメッセージとプロセスステータスメッセージのみが表示されます。",
"コンソールログには、拡張機能とデバッグアダプター間のやり取りに関する高レベルな情報も含まれます。",
"コンソールログには、拡張機能とデバッグアダプター間のやり取りに関する詳細情報も含まれます。"
],
"default": "Console"
},
"runtimeExecutable": {
"type": "string",
"description": "OS から解決可能な Probe-rs デバッガー実行ファイルへのパスです。",
"default": "probe-rs"
},
"runtimeArgs": {
"type": "array",
"items": {
"type": "string"
},
"description": "Probe-rs デバッガー実行ファイルの起動引数として渡す引数の文字列配列です。",
"default": [
"dap-server"
]
},
"env": {
"additionalProperties": {
"type": "string"
},
"default": {},
"description": "キーと値のペアとして定義する環境変数です。'key' は環境変数名で、'value' は環境変数の値です。",
"type": "object"
},
"cwd": {
"type": "string",
"description": "デバッガーの作業ディレクトリで、通常は RUST クレートのルートです",
"default": "${workspaceFolder}"
},
"probe": {
"type": "string",
"description": "このフラグを使用して、一覧から特定のプローブを選択します。同じ VID:PID のプローブが複数ある場合は、'--probe VID:PID' または '--probe VID:PID:Serial' を使用してください。"
},
"chip": {
"type": "string",
"description": "`probe-rs chip list` を実行して表示されるサポート対象チップの一覧から、適切なチップを指定してください。"
},
"chipDescriptionPath": {
"type": "string",
"description": "このオプションを使用して、ファイルからカスタムターゲットチップを追加します。"
},
"connectUnderReset": {
"type": "boolean",
"description": "このオプションを指定すると、アタッチ操作中にターゲットのリセットピンがハイに保持されます。",
"default": false
},
"speed": {
"type": "number",
"description": "プロトコル速度を kHz 単位で指定します。"
},
"wireProtocol": {
"type": "string",
"description": "使用する適切なワイヤプロトコルです。",
"enum": [
"Swd",
"Jtag"
],
"enumDescriptions": [
"Serial Wire Debug (SWD) プロトコルを使用します。",
"Joint Test Action Group (JTAG) プロトコルを使用します。"
]
},
"allowEraseAll": {
"type": "boolean",
"description": "セッションでチップの全メモリを消去すること、または工場出荷時の状態にリセットすることを許可します。",
"default": false
},
"coreConfigs": {
"type": "array",
"description": "各 MCU コアには必須の `programBinary` と、その他いくつかの任意プロパティがあります。",
"items": {
"type": "object",
"additionalProperties": false,
"properties": {
"required": [
"programBinary"
],
"coreIndex": {
"type": "number",
"description": "このセッションにおける MCU コアの 0 ベースのインデックスです",
"default": 0
},
"programBinary": {
"type": "string",
"description": "ターゲットファームウェアのバイナリへのパスです(`cwd` からの相対パスまたは絶対パス)。"
},
"svdFile": {
"type": "string",
"description": "ターゲットコアの CMSIS-SVD ファイルへのパスです(`cwd` からの相対パスまたは絶対パス)。"
},
"rttEnabled": {
"type": "boolean",
"description": "true の場合、デバッガーはターゲット上の各アクティブチャネルに対して RTT Terminal タブを開きます。",
"default": false
},
"rttChannelFormats": {
"type": "array",
"description": "RTT チャネルの設定です。一覧にないアクティブチャネルは、`dataFormat=String' および 'showTimestamps=true' で設定されます。",
"items": {
"type": "object",
"additionalProperties": false,
"required": [
"channelNumber"
],
"properties": {
"channelNumber": {
"type": "number",
"description": "このデータ形式が適用されるチャネル番号です。"
},
"dataFormat": {
"type": "string",
"description": "RTT チャネルでサポートされているデータ形式の 1 つです。",
"enum": [
"String",
"BinaryLE",
"Defmt"
],
"enumDescriptions": [
"String(テキスト)形式です。",
"バイナリのリトルエンディアン形式です。",
"defmt(参照: https://defmt.ferrous-systems.com)。"
],
"default": "String"
},
"mode": {
"type": "string",
"description": "RTT の動作モードです。",
"enum": [
"NoBlockSkip",
"NoBlockTrim",
"BlockIfFull"
],
"enumDescriptions": [
"ターゲットは、データが完全に収まる場合にのみチャネルにデータを追加し、そうでない場合はそのデータをスキップします。",
"ターゲットは、ブロックせずに可能な限り多くのデータをチャネルに追加します。",
"ターゲットは、データを追加するのに十分な空きがチャネルにできるまでブロックします。"
]
},
"showTimestamps": {
"type": "boolean",
"description": "`dataFormat=String` の RTT 出力にタイムスタンプを含めるようにします。"
},
"showLocation": {
"type": "boolean",
"description": "`dataFormat=Defmt` の RTT 出力に defmt の位置情報を含めるようにします。"
},
"logFormat": {
"type": "string",
"description": "defmt ログのデコードに使用するデフォルトのフォーマット文字列です。"
}
}
}
}
}
}
}
}
}

その他のエディタ

VSCode が好みではありませんか? 問題ありません!

probe-rs は Debug Adapter Protocol を実装しているため、Vimspector のような他の エディタ、IDE、ビジュアルデバッガ を使用できます…

Dape を使った Emacs

Dape は、DAP デバッガ向けによく作り込まれた Emacs パッケージです。Dape は launch.json 構成をサポートしていないため、設定構文に転記する必要があり、Dape でのセットアップは少し厄介になることがあります。さらに、RTT ロギングをサポートするには、いくつかのイベント処理メソッドが必要です。ただし、設定してしまえば、うまく動作します。

Dape について詳しくはこちら。ドキュメントや、describe-functiondescribe-variablecustomize など Emacs に組み込まれている通常のヘルプ機能に加えて、さまざまな DAP デバッガ向けのより多くの例については、Dape wiki ページ を参照することもできます。

dape がすでにインストールされているとすると、probe-rs 用に dape を次のように設定できます。

;; これらのメソッドは、probe-rs からの RTT データイベントを設定してから
;; それをインターセプトし、REPL に直接ログ出力を提供します。
(cl-defmethod dape-handle-event (conn (_event (eql probe-rs-rtt-data)) body)
"When Probe.rs sends RTT messages, insert them into the REPL.
CONN is the `dape-connection'.
BODY is the contents of the event."
(let ((data (plist-get body :data)))
(dape--repl-insert (format "%s\n" data))))
(cl-defmethod dape-handle-event (conn (_event (eql probe-rs-rtt-channel-config)) body)
"When Probe.rs sends channel config info, send a request to let it know the 'terminal window' is open.
CONN is the `dape-connection'.
BODY is the contents of the event."
(dape-request conn "rttWindowOpened"
'((channelNumber . 0)(windowIsOpen . t))))
(setq target-binary "embassy-blinky"
target-architecture-triple "thumbv7em-none-eabihf"
target-chip "STM32WB55RG"
target-chip-svd-path
(expand-file-name "res/STM32WB55_CM4.svd"
(project-root (project-current)))
target-binary-path
(expand-file-name
(format "target/%s/debug/%s"
target-architecture-triple
target-binary)
(project-root (project-current))))
(add-to-list 'dape-configs
'(probe-rs modes (rust-mode)
command "probe-rs"
command-args ("dap-server" "--port" :autoport)
host "localhost"
port :autoport
compile "cargo build"
:chip target-chip
:coreConfigs [(
:programBinary target-binary-path
:coreIndex 0
:svdFile target-chip-svd-path
:rttEnabled t
:rttChannelFormats [(:channelNumber 0 :dataFormat "String" :showTimestamps t)])]
:flashingConfig (:flashingEnabled t)
:type "probe-rs-debug"
:consoleLogLevel "Console"
:type "probe-rs-debug"
:request "launch"))

nvim-dap を使った NVIM

nvim-dap は、dap デバッガで作業するための人気のある nvim プラグインです。probe-rs 向けの nvim-dap のセットアップは基本的には簡単で、多くのことは最小限の設定で動作します。RTT メッセージや probe-rs からのその他のメッセージは、“probe-rs-show-messages”、“probe-rs-rtt-data”、“probe-rs-rtt-channel-config” のような DAP イベントを介して実装されています。最後のものでは、RTT データを有効にするために応答を返す必要があります。

これらのメッセージを受け取るためのハンドシェイクをサポートし、それらを dap-repl に表示し、さらに cwd のファイルにログ出力する設定スニペットを、nvim-dap の wiki で見つけることができます。これは好みに合わせて変更できます。dapui-console に表示するなど、よりよい方法を見つけた場合は、wiki を拡充してください。

nvim-dap は .vscode/launch.json の読み込みをサポートしています。設定内容はプロジェクトごとに大きく異なるため、この設定スニペットには構成は含まれていません。プロジェクト内の launch.json をインポートする必要があります。astronvim のような nvim ディストリビューションを使用している場合は、launch.json の自動インポートはあらかじめ設定されています。そうでない場合は、自分で設定するか、:lua require('dap.ext.vscode').load_launchjs() を実行する必要があります。アダプタと rust の関連付けは、設定スニペット内ですでに設定されています。

プラグインマネージャとして lazy.nvim を使用している場合は、次の lua モジュールを追加することでセットアップできます:

/path/to/your/lua/plugins/nvim-dap-probe-rs.lua
```lua
return {
"mfussenegger/nvim-dap",
opts = function()
local dap = require "dap"
if not dap.adapters then dap.adapters = {} end
dap.adapters["probe-rs-debug"] = {
type = "server",
port = "${port}",
executable = {
command = vim.fn.expand "$HOME/.cargo/bin/probe-rs",
args = { "dap-server", "--port", "${port}" },
},
}
-- probe-rs-debug を Rust ファイルに関連付けます。デバッガーの設定は project_folder/.vscode/launch.json を通じて行います
require("dap.ext.vscode").type_to_filetypes["probe-rs-debug"] = { "rust" }
-- RTT と probe-rs のメッセージ用のハンドラーを設定します。
-- nvim-dap-ui に加えて、メッセージをプロジェクトフォルダー内の probe-rs.log に書き込みます
-- RTT が有効な場合、probe-rs はチャネルの初期化後にイベントを送信します。これを確認しないと、probe-rs は RTT データを送信しません。
dap.listeners.before["event_probe-rs-rtt-channel-config"]["plugins.nvim-dap-probe-rs"] = function(session, body)
local utils = require "dap.utils"
utils.notify(
string.format('probe-rs: Opening RTT channel %d with name "%s"!', body.channelNumber, body.channelName)
)
local file = io.open("probe-rs.log", "a")
if file then
file:write(
string.format(
'%s: Opening RTT channel %d with name "%s"!\n',
os.date "%Y-%m-%d-T%H:%M:%S",
body.channelNumber,
body.channelName
)
)
end
if file then file:close() end
session:request("rttWindowOpened", { body.channelNumber, true })
end
-- RTT ウィンドウが開いていることを確認すると、rtt-data-events を受け取るようになります。
-- これらを dap-repl に出力しています。これは一つの方法ではありますが、分離はされていません。
-- もっとよいアイデアがあれば教えてください。
dap.listeners.before["event_probe-rs-rtt-data"]["plugins.nvim-dap-probe-rs"] = function(_, body)
local message =
string.format("%s: RTT-Channel %d - Message: %s", os.date "%Y-%m-%d-T%H:%M:%S", body.channelNumber, body.data)
local repl = require "dap.repl"
repl.append(message)
local file = io.open("probe-rs.log", "a")
if file then file:write(message) end
if file then file:close() end
end
-- Probe-rs はメッセージを送信でき、それらはこのリスナーで処理されます。
dap.listeners.before["event_probe-rs-show-message"]["plugins.nvim-dap-probe-rs"] = function(_, body)
local message = string.format("%s: probe-rs message: %s", os.date "%Y-%m-%d-T%H:%M:%S", body.message)
local repl = require "dap.repl"
repl.append(message)
local file = io.open("probe-rs.log", "a")
if file then file:write(message) end
if file then file:close() end
end
end,
}