VS Code + platformIOを使ってESP32のデバッグをやってみた

#はじめに
ESP32 DevKitC用のソフトウェアを作成しているのですが（[例えばこんなもの](https://qiita.com/YSFT_KOBE/items/aec4a3ad95240fdf9fab)）、プログラムが正常に動作しないときなどは、デバッグログ出力処理をいたるところに埋め込んで、ログを見ながらデバッグしてました。しかし、この方法では、ログを仕込む度にビルドを行う必要があるため、非常に非効率で疲れます。なので、コードをステップ実行しながらデバッグできないかと思っていたところ、VS Code + platformIOを使って安価かつ比較的お手軽にできる方法が見つかりました。
本記事はVS Code + platformIOでの開発環境構築からデバッグ手順までを備忘録としてまとめたものです。

#platformIOとは
Arduino IDEなどのように、さまざまなMCUやそれら開発ボード用のソフトウェアを統一的に開発できるツールで、ボードの種類とプラットフォームなどを指定するだけで自動で開発環境が整います。まさに至れり尽くせりのツールです。

#開発環境構築
##構成
開発環境を構築するにあたって、以下の構成としました。

+ 環境構築PC：Ubuntu 20.04LTS
+ ソフトウェア：VS Code + platformIO(VS Code拡張機能)
+ ターゲットボード：ESP32-DevKitC ESP-WROOM-32<br>
秋月電子通商さんで売っている[こちら](https://akizukidenshi.com/catalog/g/gM-11819/)のボードを使用します。<br>
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/307872/2bb40dbb-cab9-a129-b705-8b730135f9ff.png)
+ JTAGアダプタ：Adafruit FT232H Breakout<br>
[こちら](https://www.switch-science.com/catalog/5740/)のボードを使用しました。FTDI社のFT232HというUSB-シリアル変換チップを搭載した商品です。USB-シリアル変換チップはいろいろありますが、すべてがJTAGとして使用できるわけではなく、FT232HはJTAGとして使用できるチップの１つです。<br>
スイッチサイエンスさんから購入できます。<br>
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/307872/64813d86-e5dc-3ceb-b47b-33f7a6a01d48.png)

##開発環境構築手順
以下に構築手順を示します。

###VS Codeのインストール
[マイクロソフトの公式ドキュメント](https://code.visualstudio.com/docs/setup/linux#_debian-and-ubuntu-based-distributions)にインストール方法がありますので、そちらを参照してください。

###VS CodeへのplatformIO拡張機能の追加
platformIO拡張機能をVS Codeへ追加します。こちらは特に詰まることは無いと思いますので、詳細は割愛します。
[こちらのページ](http://kunsen.net/2018/07/28/post-618/)などを参考にしてください。



###ターゲットボードとJTAGアダプタを接続
ここまでできたら、ターゲットボードとJTAGアダプタの端子同士を接続します。

以下の表に従って、端子同士をつなぎます。

|FT232H|信号名|ESP32|
|:----:|:----:|:----:|
|AD0|TCK|GPIO13|
|AD1|TDI|GPIO12|
|AD2|TDO|GPIO15|
|AD3|TMS|GPIO14|
|AC1|RST|EN|
|GND|GND|GND|

物は若干違いますが、[こちらのページ](https://reinventor192909088.wordpress.com/2018/03/27/esp32-visualgdb-jtag-debugging/)にわかりやすい図があります。
AC1とENは接続しなくてもよかったり、そもそも接続の記載がないサイトもありますが、私の環境では接続しないとうまく動作しませんでした。

この後、ターゲットボードとJTAGアダプタ共にPCに接続するのですが、そのまま繋ぐとJTAGアダプタをシリアル通信デバイス（Windowsで言うCOMポート）としてしか認識してもらえません。そこで、次に記載のMPSSEセットアップを実施して、JTAGボードとして認識してもらえるようにします。

###MPSSEセットアップ
FT232HはUSBからJTAG、GPIO、SPI、I2C等へ変換できるのですが、マルチプロトコル同期シリアルエンジン（MPSSE）によって、SPI等の通信を利用することが可能となっています。そのため、PCからマルチプロトコル同期シリアルエンジン（MPSSE）として認識できるようにPC側のセットアップを行う必要があります。

**1. libusb-1.0のインストール**
libusb-1.0をインストールします。

```cmd:コマンド
user@host:~$ sudo apt-get install libusb-1.0
```

**2. /etc/udev/rules.d/11-ftdi.rulesの作成**
/etc/udev/rules.d/11-ftdi.rulesファイルを新規に作成し、以下の内容を保存します。

```file:/etc/udev/rules.d/11-ftdi.rules
# /etc/udev/rules.d/11-ftdi.rules
SUBSYSTEM=="usb", ATTR{idVendor}=="0403", ATTR{idProduct}=="6001", GROUP="plugdev", MODE="0666"
SUBSYSTEM=="usb", ATTR{idVendor}=="0403", ATTR{idProduct}=="6011", GROUP="plugdev", MODE="0666"
SUBSYSTEM=="usb", ATTR{idVendor}=="0403", ATTR{idProduct}=="6010", GROUP="plugdev", MODE="0666"
SUBSYSTEM=="usb", ATTR{idVendor}=="0403", ATTR{idProduct}=="6014", GROUP="plugdev", MODE="0666"
SUBSYSTEM=="usb", ATTR{idVendor}=="0403", ATTR{idProduct}=="6015", GROUP="plugdev", MODE="0666"
```

[このページ](https://learn.adafruit.com/circuitpython-on-any-computer-with-ft232h/linux)に詳細が書かれてます。ただし、Pythonでボードを制御する手順が続きますので、そのあたりはご注意ください。


###ターゲットボードとJTAGアダプタをPCに接続
USBケーブルで2つのボードを接続します。接続はJTAGアダプタ → ESP32ターゲットボードの順番で行います。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/307872/5bb4eb7a-9f9d-be49-b3ca-bac632641889.png)
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/307872/51a1eb26-1f48-8cf5-e183-d204d0cff6e8.png)

接続ができたら、platformIOで確認します。

左端のplatformIOアイコンをクリックし、Openをクリックします。しばらくするとホーム画面が出てきます。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/307872/94d42dda-f069-f846-9be4-f2a90f7af8fa.png)

ホーム画面の左端にあるメニューのDevicesアイコンをクリックします。
シリアルデバイスが表示されますので、図にあるように、JTAGアダプタが/dev/ttyUSB0に、ESP32ターゲットボードが/dev/ttyUSB1に割り当てられていることを確認してください。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/307872/70899840-ae2f-e99e-fc5c-c51d3fc2f64b.png)

:::note info
デバイスの割当に関しては気にする必要はないかもしれませんが、上記の割り当てでないと私の環境では正しく動作しませんでした。
:::

問題なければ、/dev/ttyUSBxに読み込み・書き込み権限を設定します。これをやっておかないと各ボードへのアクセスができなくなります。

```cmd:コマンド
user@host:~$ sudo chmod 666 /dev/ttyUSB0
user@host:~$ sudo chmod 666 /dev/ttyUSB1
```

これで開発環境の構築は完了です。

#ソースコード作成からデバッグまで
ここからは、ソースコードの作成からデバッグ実行までの手順を記載します。

###プロジェクトの作成
まずはplatformIOのプロジェクトを作成します。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/307872/027c861a-65a8-c307-4b44-7772e1c80343.png)
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/307872/973a765c-7c1b-c906-171a-6d5fb335409a.png)

プロジェクトの作成が完了すると、platform.iniファイルが開かれた状態になりますので、設定を追加します。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/307872/c113d80a-0d5e-7a9d-246b-fec382997816.png)

以下のように変更します。(下3行を追加しました。)

```ini:platform.ini
[env:esp-wrover-kit]
platform = espressif32
board = esp-wrover-kit
framework = espidf
monitor_speed = 115200
debug_tool = ftdi
upload_port = /dev/ttyUSB1
```

:::note info
debug_toolの設定値として”minimodule”を設定する手順が書かれているサイトが多いですが、私の環境ではJTAGアダプタを正常に認識できませんでした。
:::

ここまでできたら、ビルドを実施します。

###ビルド
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/307872/a8a0dd62-3d1b-9553-eb5b-2511b3f03ef4.png)
platformIOアイコンをクリックして、「PROJECT TASK」-「esp-wrover-kit」の”Build”をクリックするとビルドが始まります。
画像のようにSUCCESSが出ると完了です。

###アップロード
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/307872/a2160e5a-0369-16a4-3bdb-58a56c9f1fa4.png)
ターゲットボードにビルドしたプログラムをアップロードします。
アップロードする前に、JTAGアダプタをPCから外しておきます。私の環境では、こうしておかないとUploadがうまく出来ませんでした。
platformIOアイコンをクリックして、「PROJECT TASK」-「esp-wrover-kit」の”Upload”をクリックするとアップロードが始まります。
画像のようにSUCCESSが出ると完了です。

###デバッグ開始
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/307872/28d3628e-48d0-31f5-c5cd-93925a7c58bc.png)
JTAGアダプタをPCに接続します。
platformIOアイコンをクリックして、「QUICK ACCESS」-「esp-wrover-kit」の”Start Debgugging”をクリックするとデバッグが始まります。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/307872/a4703bcb-984c-7069-b772-3c8a339b19e7.png)
画像のようにSUCCESSが出たあと、しばらくしてapp_main関数でブレイクされます。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/307872/cfb74838-d868-0a86-f2ec-7e2a8dc95ea9.png)
デバッグを開始すると、DEBUG_CONSOLE上にデバッグログも出力されるようになります。

これで、ブレイクポイントの設定やステップ実行などでデバッグを行う事が出来ます。

#まとめ
VS Code + platformIOを使って安価かつ比較的お手軽にできることがわかってもらえたかと思います。
今回はplatformIOでプロジェクトを新規作成しましたが、サンプルのプロジェクトが用意されているので、そちらを利用してアプリケーションを作成していくこともお薦めです。