Visual Studio Code で ESP32 の JTAG debug 環境を構築

Windows10 上の Visual Studio Code 上で ESP32 の JTAG debug 環境を構築するまでの手順です。

# 記事を作成した理由

- Visual Studio Code の Extenstion のみで環境構築を説明されている情報が少ない。
- printf やコンソール出力での確認ではなく、breakpoint を貼りたい。
- GUI のみで操作を完結させたい。

# 用意するもの
- ESP32-DevKitC
色々な種類がありますが、この記事で確認したのは[秋月電子通商](https://akizukidenshi.com/)から購入した  ESP-WROOM-32 開発ボード (通販コードM-11819)です。シリアル変換チップとして CP2102 を使用しています。多分、ESP32 WROOM-32 搭載ボードでは一般的なものだと思います。

- FT2232H 搭載ボード
これも ESP32 搭載ボードと同じく色々な種類がありますが、ここでは [FT2232H(2ch)高速USBシリアル変換モジュールキット(Strawberry Linux)](https://strawberry-linux.com/catalog/items?code=50028)を使用しました。JTAG として 1ch だけを使用するので、[FT232H (Strawberry Linux)](https://strawberry-linux.com/catalog/items?code=50032)や、秋月電子通商の FT232H 搭載ボード(通販コード M-08942)の方でも大丈夫です。

- Visual Studio Code がインストール済みの Windows10 PC 環境

# 作業の流れ

1. Visual Stduio Code へ ESP-IDF Extension をインストール
2. Zadig で FT2232H のドライバを変更(OpenOCD から使用できる様にするため)
3. ESP32 の接続確認
3. テスト用アプリケーションの動作確認
3. デバッグ実行前の準備
3. デバッグの開始

## ESP-IDF Extension をインストール

1. Visual Studio Code 上で Ctrl+Shift+X を押下して、Extension 検索キーワードへ「ESP-IDF」と入力します。<br>![00-search-extension.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/553718/807760c0-c5cf-03c9-8b64-e13ef856a18d.png)
2. Install (下の画像では Install 済みなので Uninstall となっていますが)を押します。<br>![010-Espressif-IDF.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/553718/d8a7fbdf-e31a-4854-1bfc-4ddf8fa25358.png)
2. Setup mode は EXPRESS を選択します。<br>![01-setup-mode.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/553718/b88fa7a0-7012-1854-4910-07c150431622.png)
2. インストール先等は変更できます。Install ボタンを押下します。<br>![02-install.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/553718/2d896fa4-d518-aa22-2f38-5f07c1a9c20e.png)
2. インストールが始まります。数分は掛かるのでしばらく待ちます。![04-install.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/553718/c1cd6d71-ca77-0213-134e-a049370e051e.png)
2. インストール完了。<br>![05-configured.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/553718/517b67c2-658d-e36f-d48a-8a818c5c78a2.png)

## Zadig で FT2232H のドライバを変更

1. FT2232H 基板を PC と USB 接続します。
1. Zadig を以下からダウンロードします。<br>https://zadig.akeo.ie/
1. Zadig を起動して、メニューの Options -> List All Devices を選択します。<br>![06-Zadig.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/553718/de76f0ec-9ad3-944d-f414-9c4eaeae7db6.png)
1. Dual RS232+HS (Interface 0)を選択します。これは FT2232H の 1ch 目です。FT232H では **Single** RS232+HS 等の名前になります。<br>![07-select-device.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/553718/752747bd-1eef-0c2e-0b0d-5874e12a4666.png)
1. 緑の矢印の右側が「WinUSB」となっている事を確認して、「Replace Driver」ボタンを押下します。<br>![08-replace-driver.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/553718/816fe4cd-b07d-f5b9-6db2-2f6290963d68.png)

1. ドライバーのインストールが終了するまで待ちます。

## ESP32 の接続確認

1. ESP32 を USB で接続します。<br>今回使用したボードでは以下の様に CP2102 の COM ポートがデバイスマネージャ上に表れます。デバイスが認識されない場合は、[CP210x USB to UART Bridge VCP Drivers](https://www.silabs.com/developers/usb-to-uart-bridge-vcp-drivers) からドライバをダウンロード、インストールします。<br>![10-connect-esp32.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/553718/4b08737e-f098-3627-16e6-21f84d9b06b3.png)
1. Visual Studio Code を起動し、画像の赤い四角のアイコンをクリックして ESP-IDF Explorer を表示します。<br>![09-ESP-IDF-Explorer.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/553718/62e200e9-f741-54d2-ecd1-38e1052c1a9f.png)


1. 左下の「COM1」を押下して、デバイスマネージャで確認した ESP32 の COM ボートへ変更します。<br>次に、EFUSE EXPLORER (スクロールした下の方にあります)の「Connect your board first ...」クリックします。<br>![11-efuse-explorer.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/553718/1d109a1b-2500-fc55-7bf2-89f5fc60ef67.png)

1. EFUSE EXPLORER が更新されます。エラーが表示された場合、COM ポートの指定が正しいか、ESP32 ボードのピンに余計な配線が接続されていないかを確認します。後述しますが、FT2232H と JTAG 結線している状態ではエラーになる場合があります。<br>![11-efuse-readed.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/553718/f9daa761-7c88-ec42-1373-6cab73143dfc.png)

## テストアプリケーションの動作確認

1. 適当な作業フォルダを作成します。Visual Studio Code の File -> Open Folder を選択、その作成したフォルダを選択します。<br>![12-open-folder.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/553718/f1160dff-41a2-0000-35ce-cc1eb626d0b5.png)
1. F1 を押下して、以下の画像の様に「ESP-IDF: Create project from extension template」を選択します。<br>「Temp」等と入力すれば候補に出ると思います。<br>![13-create-project.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/553718/3959398f-2de8-d15b-19a8-d8a519cadbd8.png)
1. 「Select a directory to use」は Use current folder を選択します。<br>![140-directory-to-use.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/553718/3f7b60c8-38de-ea63-5670-d91930baa850.png)
1. [Select a template to use」は template-app を選択します。<br>![14-template-app.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/553718/79e914f9-e7d2-4b23-5b48-29d35ff53e67.png)
1. template-app が作成され、新しいウィンドウが開きます。<br>![15-template-app-created.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/553718/8c9b6d6e-9503-0865-fc18-eb5d3d3421c9.png)
1. ステータスバーにある build アイコンを押下してビルドします。<br>(もし、何らかのエラーになってしまった場合、作業フォルダを削除して .1 からやり直してみて下さい)。<br>しばらく時間が掛かるので待ちます。![16-build.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/553718/c02d7d25-5b23-43d1-dbda-88d0775215e4.png)
1. flash アイコンを押下して ESP32 へ書き込みます。<br>![17-flash.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/553718/cb28dfe9-943b-656d-2fce-21f0e2f43f91.png)
1. 書き込み方法の選択ですが、まだ JTAG を準備していないため、ここでは UART を選択します。<br>![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/553718/ecb313d3-cf71-dbc3-6695-0ef69899920e.png)<br>書き込みが正しく完了すると以下の様な出力があります。![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/553718/ff1bc34a-4955-ad6b-7fbc-c44ff6094381.png)
1. Monitor アイコンを押すと、ESP32 からの printf の出力を確認できます。<br>![18-monitor.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/553718/c18eb985-870e-1c7e-3874-379b61eb8fbf.png)<br>![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/553718/9529ba7a-6b77-8413-dc4b-1caeb9d59ff3.png)<br>書いている時に気付いたのですが…以下のボタン押下でビルド～Monitor を実行できます。![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/553718/85b280ae-b1bc-2e3b-0182-4ce1d3530fb9.png)

## JTAG の結線

FT2232H と ESP32 の JTAG 信号を結線します。

|FT2232H 信号名(機能)|ESP32-DevKitC 信号名(機能)|
|---|---|
|ADBUS0 (TCK/SK)|GPIO13 (MTCK)|
|ADBUS1 (TDI/DO)|GPIO12 (MTDI)|
|ADBUS2 (TDO/DI)|GPIO15 (MTDO)|
|ADBUS3 (TMS/CS)|GPIO14 (MTMS)|
|GND|GND|

基板によってピン配置は異なるため、実物の説明書等を参照して下さい。
ESP32-DevKitC のピン配置は[公式サイトから参照](https://docs.espressif.com/projects/esp-idf/en/latest/esp32/hw-reference/esp32/get-started-devkitc.html#pin-layout)できます。

## デバッグ実行前の準備

ESP32 開発ボードと FT2232H 搭載ボードの両方を PC へ接続し、Visual Studio Code で先に作成したテスト用アプリケーションのフォルダを開きます。

### settings.json の変更
.vscode/settings.json へ 以下の様に idf.openOcdConfigs を追加します。これを行わないと、ESP32 と FT2232H を結線した状態で ESP32 の Flash へ書き込みできなくなります(失敗するのは毎回ではなく、問題なくできる場合もあります)。詳細は [ESP32: GPIO12 is dangerous! Can brick a board by using it](https://github.com/micropython/micropython/issues/6149) 等にも書かれていますが、FT2232H を接続すると ESP32 の power on 時に GPIO12 が pull up 状態となって、内蔵 Flash へアクセスできなくなる様です。

```&#x2e;vscode/settings.json
  "C_Cpp.intelliSenseEngine": "Tag Parser",
  "idf.openOcdConfigs": [
    "interface/ftdi/esp32_devkitj_v1.cfg",
    "board/esp32-wrover-kit-3.3v.cfg"
  ]
```

なお、コマンドパレットには ESP-IDF: Select OpenOCD Board Configuration があり、こちらを使用しても idf.openOcdConfigs の設定が可能なのですが、以下の様になぜか不完全な内容(board のパスが違う、interface/... が無い)が追加されてしまいます。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/553718/5f849479-e719-0b23-ee57-20a06f364daa.png)

```&#x2e;vscode/settings.json
    "idf.openOcdConfigs": [
        "boards/esp32-wrover-kit-3.3v.cfg"
    ]
```
(ユーザーの settings.json へ追加される内容)

この状態でデバッグを開始すると、以下の様に OpenOCD のエラーとなってしまいます。

```
Open On-Chip Debugger  v0.10.0-esp32-20210401 (2021-04-01-15:46)
Licensed under GNU GPL v2
For bug reports, read
	http://openocd.org/doc/doxygen/bugs.html
debug_level: 2

❌ embedded:startup.tcl:26: Error: Can't find boards/esp32-wrover-kit-3.3v.cfg
in procedure 'script' 
at file "embedded:startup.tcl", line 26
[Stopped] : OpenOCD Server
```



## デバッグの開始

Visual Studio Code の左端にある「Run and Debug」ボタンを押下してから、メニューバー下の Launch の横のボタン押下でデバッグが開始されます。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/553718/96b98800-7a6e-f663-466f-64ea9b789d63.png)

正常に動作していれば app_main の最初の行で Break します。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/553718/245c089f-0299-88a8-4518-9dbe1b6b0b50.png)

うまく動かなかった場合は、ESP32 と FT2232H を PC から外して再度接続して試してみて下さい。

## ビルド、デバッグ作業の流れ

1. コードを変更した後は前述したステータスバーの build アイコンをクリックして build します。<br>![16-build.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/553718/c02d7d25-5b23-43d1-dbda-88d0775215e4.png)
1. 前述の「デバッグ開始」手順でデバッグを開始します。以下の様な表示が出ますので、Build ボタンを押下します。Flash への書き込みが行われます。<br>![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/553718/a1c9ea75-2353-e4d4-9228-a7c7bc1593bf.png)
1. 再度デバッグ開始を行います。前述の様に app_main の最初の行で break します。

...何だか手数が多いです。Run and debug ボタン押下だけでビルド、デバッグの一連の動作ができて欲しい気がします。別の正しい方法があるか、設定等で可能なのかも知れませんが、今のところ分かっていません。

## うまく動かない場合

### Flash 書き込み時のエラー

Flash への書き込み時にエラーが発生する場合があります。
以下は Compressed の表示後、しばらく停止して A fatal error occurred となった時の出力です。

```
  :
(省略)
  :
Uploading stub...
Running stub...
Stub running...
Changing baud rate to 460800
Changed.
Configuring flash size...
Warning: Could not auto-detect Flash size (FlashID=0xffffff, SizeID=0xff), defaulting to 4MBFlash will be erased from 0x00010000 to 0x00037fff...
Flash will be erased from 0x00001000 to 0x00007fff...
Flash will be erased from 0x00008000 to 0x00008fff...
Compressed 162800 bytes to 85436...

A fatal error occurred: Timed out waiting for packet content
```

前述の settings.json の変更を行っているか確認します。

### デバッグ開始で Flash への書き込みが行われない

変更がない場合は Flash への書き込みは行わない様です。変更があっても書き込みがスキップされてしまう場合、ソースコードの一部を変更(空行等を挿入)して、build を行ってからデバッグ開始すると、強制的に書き込む事ができます。

### 突然デバッグできなくなった

flash 書き込み -> デバッグ開始で大抵は復旧できますが、それでもダメな場合は以下を試します。

1. Visual Studio Code を終了し、ESP32 と FT2232H を PC から一旦外して再び接続します。
2. EFUSE EXPLORER で ESP32 の接続を確認。
2. ステータスバーの Monitor アイコンを押下して ESP32 の動作状況を確認。
2. ソースコードの一部に空行等を挿入して build -> flash 書き込み -> デバッグ開始を行う。

## その他

### ビルドの度に書き込みサイズが異なる

オブジェクト内にビルドした日時を含んでいるためです。削除する事はできます。気にしなくても大丈夫です。

# おわりに

筆者はこの記事を作成するまで ESP32 の使用/開発経験は全くありません。Visual Studio Code も普段は単なるテキストエディタとして適当にしか使えていません。間違い、もっと良い方法等がありましたら、ご指摘お願いします。

## 参考記事

- [ESP32 を FT232H でつないで OpenOCD+GDBでデバッグ](https://qiita.com/rukihena/items/f5585436c16f74d0f01d)