Visual Studio Code で ESP32 の JTAG debug 環境を構築 (Ubuntu 版)

Ubuntu 上の Visual Studio Code 上で、ESP32 の JTAG debug 環境を構築するまでの手順です。
以前に書いた [Windows10 向けの記事](https://qiita.com/ain1084/items/6b6451ca44234c6cc628)の Ubuntu 版になります。

# 記事を作成した理由

* 忘れないための作業メモです。
* GUI 環境構築のため、図が多めです。

# 前提環境 / 用意するもの

* Ubuntu 22.04 x64
  * 物理PCへのインストールではなく、VMware 上に作成した仮想マシン。
  * Visual Studio Code はインストール済み。
* ESP32-DevKitC
  * ESP32-WROOM-32 を搭載したボードです。
* FT2232H 搭載ボード (JTAG 接続に使用)
  * 1ch だけ使います。FT232H でも可です(多分)。

# 作業の流れ

1. Espressif IDF extension インストール前の準備
1. Espressif IDF extension をインストール
1. テスト用ワークスペースとアプリケーションの作成と書き込み
1. モニタ用 UART デバイスの変更
1. デバッグの開始

# Espressif IDF extension インストール前の準備

インストールした後で良い作業もありますが、まとめて最初に行います。

## python3-pip & libpython2.7-dev のインストール

```shell
sudo apt-get install python3-pip libpython2.7-dev
```

### dialout group へ User を追加

```shell
$ sudo gpasswd -a <User名> dialout
ユーザー <User名> をグループ dialout に追加
``` 
ログアウトか再起動が必要です。
id コマンドで dialout が含まれている事を確認します。
```shell
$ id
uid=XXXX(ユーザー名)....groups=....20(dialout),24(cdrom),
```

参考記事: [[小ネタ]Ubuntu でttyUSB0(USBシリアル変換)が権限関連で使えない場合の対処方法](https://qiita.com/chromabox/items/b3ceaab6efa6edde2bda)

# Espressif IDF extension をインストール

1. 拡張機能を「IDF」等のキーワードで検索して、「Espressif IDF」をインストールします。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/553718/092df2bc-91d7-4be9-6595-fc2013bf60aa.png)
2. インストールが終わるとウィンドウの左下にアイコンが増えます。それをクリックします。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/553718/47ddd535-fad9-8840-7367-6ea6ad4614ac.png)
3. 特にこだわりはないので EXPRESS を押します。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/553718/e20ad7fb-78b0-95ad-7c1c-c95005116837.png)
4. Select ESP-IDF version から 最新版 (画像では v4.4.2) を選択します。
**仮想環境で使用する場合は v5 系 (master 含む)を選択した方が良さそうです。master 版の方が、明らかに JTAG 動作が安定します。**
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/553718/44ac8c1d-f31e-9dde-7f07-809119318b45.png)
5. 下の方にある Install ボタンをクリックします。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/553718/b2e2e8b3-4a82-eeec-0dbc-6ff611d8a55f.png)
6. ダウンロードとインストール完了まで待ちます。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/553718/7e438fde-189c-1a98-aa53-09a0af3629b0.png)
7. 出力に Python requirements has been installed が表示されたら成功です。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/553718/528324ef-2d88-c713-c5ec-64d8423f9f1d.png)
8. ターミナルから OpenOCD に必要なファイルのコピーを行います。
```shell
sudo cp -n /home/ain/.espressif/tools/openocd-esp32/v0.11.0-esp32-20220411/openocd-esp32/share/openocd/contrib/60-openocd.rules /etc/udev/rules.d
```
※ 「v.0.11.0-esp32-20220411」の部分はバージョンによって異なります。正確な内容は完了画面に表示されています。選択/コピーして実行すれば確実です(以下の赤枠内)。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/553718/4456dca0-ff28-d255-11dd-f0109c51bbc7.png)


# テスト用ワークスペースとアプリケーションの作成
1. ホームディレクトリ等へ適当なフォルダを作成します(ここでは ~/esp_test/ とします)。
2. VSCode から作成したフォルダを開きます。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/553718/04aa7cf4-b142-3f1a-679d-4e270c50383b.png)
3. コマンドパレット (Ctrl+Shift+P) を開きます。「ESP-IDF」等と入力します。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/553718/586565e7-d0eb-9299-5fe3-e5a212e06f4c.png)
4. ESP-IDF: Create project from extension template を選択します。
5. Select a directory use と表示が変わったら「Use current folder」を選択します。
6. Select a template to use と表示が変わったら「template-app」を選択します。
4. VSCode の新しいウィンドウが開きます。

## モニタ用 UART デバイスの確認と設定

1. ESP32 の出力をモニタするための USB UART のデバイス名 dmesg コマンド等で確認します。
ここでは CP210x チップの ttyUSB0 が ESP32 です。
    ```shell
    $ sudo dmesg | grep ttyUSB
    [ 2700.650108] usb 3-2: cp210x converter now attached to ttyUSB0
    [ 2710.889532] usb 3-4.1: FTDI USB Serial Device converter now attached to ttyUSB1
    [ 2710.889952] usb 3-4.1: FTDI USB Serial Device converter now attached to ttyUSB2
    ```

1. VSCode のステータスバーにある /dev/ttyUSB? の部分をクリックします。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/553718/59e31d63-c2a1-4e12-ac35-458add91c5fa.png)
1. ウィンドウ上部のコマンドパレットのあたりにデバイス一覧が表示されるので、ESP32 の ttyUSB (ここでは /dev/ttyUSB0)を選択します。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/553718/146406cb-d702-d8ef-eae8-ca4af342bcbd.png)

## ビルドと書き込み

1. ステータスバーの「ESP-IDF Build, Flash and Monitor」をクリックします。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/553718/85381b4f-9284-5b60-afdf-8e53cd516ea3.png)
2. ビルドが完了するとコマンドパレットのあたりに書き込み方法の選択が表示されます。ここでは UART を選択します。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/553718/53780503-1555-c9cf-7df5-e4f54823bf7c.png)
3. 書き込みが正常に完了すると ESP32 がリセットされ、ターミナルで起動ログを確認できます。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/553718/615b2e24-ee9a-1ecd-8990-34b3f6c9a034.png)

## デバッグの開始

### 接続確認

FT2232H と ESP32 を JTAG で結線して、FT2232H を PC と接続します。結線については、以前に書いた[Windows 10 の記事](https://qiita.com/ain1084/items/6b6451ca44234c6cc628#jtag-%E3%81%AE%E7%B5%90%E7%B7%9A)等を参照して下さい。
1. Visual Studio Code のメニュー: 実行 -> デバッグの開始を選択します。
app_main 関数で自動的に break します。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/553718/f31353ac-129e-7166-02d5-4af7a83ec897.png)
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/553718/b388b9c8-81a4-7017-d220-040173e5c562.png)
1. 赤枠の「切断」ボタンを押して一旦デバッグを終了します。

### 設定した break point で停止させる

1. main/main.c を開いて、以下の様に変更してみます(コードに特に意味はありません)。

    ```c++:main/main.c
    #include <stdio.h>

    void app_main(void)
    {
        int total = 0;
        for (int i = 1; i <= 100; ++i) {
            total += i;
        }
        printf("total = %d\n", total);
    }
    ```
1. 9行目の左側をクリックして break point を設定します。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/553718/b7c8e251-68ef-14f5-1230-c1f8ef64da63.png)
1. ステータスバーの「ESP-IDF Build, Flash and Monitor」をクリックします。
※ ファイル変更でビルドは自動的に行われない様です。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/553718/85381b4f-9284-5b60-afdf-8e53cd516ea3.png)
1. ビルド、書き込みが完了すると、ターミナルに実行結果が表示されます
    ```
    --- (省略) ---
    I (284) spi_flash: detected chip: generic
    I (288) spi_flash: flash io: dio
    I (293) cpu_start: Starting scheduler on PRO CPU.
    I (0) cpu_start: Starting scheduler on APP CPU.
    total = 5050
    ```
1. 再度 Visual Studio Code のメニュー: 実行 -> デバッグの開始を選択します。
1. app_main() の最初の行で break したら、F5 キー(続行)を押します。
先に設定した9行目で break します。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/553718/d59b97e0-6a82-2301-6fa3-7c8bcfa46c58.png)
変数やレジスタ、コールスタックを確認できます。
レジスタが見れるならば逆アセンブラやメモリダンプは? と思って探したのですが、現状はまだない様です。

## うまく動かない場合

### フラッシュへ書き込みできない

1. ESP32 の ttyUSB? を dmesg コマンド等で確認します。
2. ステータスバーにある接続先が正しいかを確認します。
3. dialout グループへ USER が追加されているかを id コマンド等で確認します。

### デバッグ開始できない、エラーメッセージが表示される

launch.json の logLevel を上げてログを確認します。デフォルトは 2 です。
設定の反映には openocd の再起動が必要です。コマンドパレットから ESP-IDF OpenOCD Manager で Stop するか、単にプロセスを kill します。
```json:.vscode/launch.json
{
  "version": "0.2.0",
  "configurations": [
    {
      "type": "espidf",
      "name": "Launch",
      "request": "launch",
      "logLevel": 4
    }
  ]
}
```
https://github.com/espressif/vscode-esp-idf-extension/blob/master/docs/DEBUGGING.md

### 動作が不安定(仮想マシン特有?)

**v4.4.2 よりも master 版の方が仮想環境上での JTAG 動作が安定する様です。**

書き込み、デバッグ開始、break まで機能すれば環境構築としては成功と言えます。
ただ、仮想マシン環境特有なのかどうか分かりませんが、動作がいまいち安定していません。ESP32 のモニタが開けない、突然デバッグ開始できなくなる、といった現象が発生します。大抵は以下で解決できました。
1. 再度 debug 開始を行う。
1. ESP Monitor device を開いてから、debug 開始。
赤枠が ESP Monitor device です。 
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/553718/969bcda9-917c-5b28-ba68-fc89107b31af.png)
1. Visual Studio Code 再起動してから、debug 開始。
1. openocd プロセスを kill してから、debug 開始。
   * コマンドパレットの ESP-IDF OpenOCD Manager から Start/Stop ができますが、debug 開始に失敗してしまうと機能しない場合があります。
   * pkill openocd 等で行う方が確実です。
1. ESP32 と FT2232H (JTAG Adapter)を一度 USB から外す。再度 1 から試す。